C++ Builder
| Главная | Уроки | Статьи | FAQ | Форум | Downloads | Литература | Ссылки | RXLib | Диски |

 
API-аналог функции SelectDirectory
** pasha
Отправлено: 23.11.2005, 12:34


Не зарегистрирован







Как известно многие функции C++Builder построена на функциях API.
Подскажите API-аналог функции SelectDirectory().

На какой API-функции построена SelectDirectory ?
** pasha
Отправлено: 23.11.2005, 12:36


Не зарегистрирован







Может быть SHBrowseForFolder ???
Gedeon
Отправлено: 23.11.2005, 14:14


Ветеран

Группа: Модератор
Сообщений: 1742



Она не на апи написана — это борландовкое диалоговое окно TSelectDirDlg
BreakPointMAN
Отправлено: 23.11.2005, 23:39


Станционный диспетчер

Группа: Участник
Сообщений: 86



Gedeon, позвольте немного не согласиться с Вами.
Все зависит от того, каким образом вызывается функция SelectDirectory(). Если формат её вызова такой:
CODE

WideString Root="";
AnsiString Caption="Caption";
AnsiString Dir;
SelectDirectory(Caption,Root,Dir);

ShowMessage("Selected directory is: "+Dir);

то компилятор генерирует код, по которому видно, что в данном случае Builder'овская SelectDirectory() инкапсулировала вызов WinAPI.

QUOTE

.text:00402154 ; --------------- S U B R O U T I N E ---------------------------------------
.text:00402154
.text:00402154 ; Attributes: library function bp-based frame
.text:00402154
.text:00402154 __fastcall Filectrl::SelectDirectory(const System::AnsiString,const System::WideString,System::AnsiString &) proc near
.text:00402154                                         ; CODE XREF: sub_4019C0+69p
.text:00402154
.text:00402154 var_4C          = dword ptr -4Ch
.text:00402154 var_48          = dword ptr -48h
.text:00402154 var_44          = dword ptr -44h
.text:00402154 var_40          = dword ptr -40h
.text:00402154 var_3C          = dword ptr -3Ch
.text:00402154 var_38          = dword ptr -38h
.text:00402154 var_34          = dword ptr -34h
.text:00402154 var_2C          = dword ptr -2Ch
.text:00402154 var_28          = dword ptr -28h
.text:00402154 var_24          = dword ptr -24h
.text:00402154 var_20          = dword ptr -20h
.text:00402154 var_1C          = dword ptr -1Ch
.text:00402154 var_18          = dword ptr -18h
.text:00402154 uMode           = dword ptr -14h
.text:00402154 var_10          = dword ptr -10h
.text:00402154 var_C           = dword ptr -0Ch
.text:00402154 var_5           = byte ptr -5
.text:00402154 var_4           = dword ptr -4
.text:00402154
.text:00402154                 push    ebp
.text:00402155                 mov     ebp, esp
.text:00402157                 add     esp, 0FFFFFFB4h
.text:0040215A                 push    ebx
.text:0040215B                 push    esi
.text:0040215C                 xor     ebx, ebx
.text:0040215E                 mov     [ebp+var_20], ebx
.text:00402161                 mov     [ebp+var_24], ebx
.text:00402164                 mov     [ebp+var_4], ecx
.text:00402167                 mov     ebx, edx
.text:00402169                 mov     esi, eax
.text:0040216B                 xor     eax, eax
.text:0040216D                 push    ebp
.text:0040216E                 push    offset loc_40232C
.text:00402173                 push    dword ptr fs:[eax]
.text:00402176                 mov     fs:[eax], esp
.text:00402179                 mov     [ebp+var_5], 0
.text:0040217D                 mov     eax, [ebp+var_4]
.text:00402180                 mov     eax, [eax]
.text:00402182                 call    sub_40233C
.text:00402187                 test    al, al
.text:00402189                 jnz     short loc_402193
.text:0040218B                 mov     eax, [ebp+var_4]
.text:0040218E                 call    System::__linkproc__ LStrClr(System::AnsiString &)
.text:00402193
.text:00402193 loc_402193:                             ; CODE XREF: Filectrl::SelectDirectory(System::AnsiString,System::WideString,System::AnsiString &)+35j
.text:00402193                 lea     eax, [ebp+var_4C]
.text:00402196                 xor     ecx, ecx
.text:00402198                 mov     edx, 20h
.text:0040219D                 call    System::__linkproc__ FillChar(void)
.text:004021A2                 lea     eax, [ebp+var_20]
.text:004021A5                 push    eax
.text:004021A6                 call    SHGetMalloc
.text:004021AB                 test    eax, eax
.text:004021AD                 jnz     loc_40230E
.text:004021B3                 cmp     [ebp+var_20], 0
.text:004021B7                 jz      loc_40230E
.text:004021BD                 push    104h
.text:004021C2                 mov     eax, [ebp+var_20]
.text:004021C5                 push    eax
.text:004021C6                 mov     eax, [eax]
.text:004021C8                 call    dword ptr [eax+0Ch]
.text:004021CB                 mov     [ebp+var_10], eax
.text:004021CE                 xor     eax, eax
.text:004021D0                 push    ebp
.text:004021D1                 push    offset loc_402307
.text:004021D6                 push    dword ptr fs:[eax]
.text:004021D9                 mov     fs:[eax], esp
.text:004021DC                 xor     eax, eax
.text:004021DE                 mov     [ebp+var_18], eax
.text:004021E1                 mov     eax, ebx
.text:004021E3                 xor     edx, edx
.text:004021E5                 call    System::__linkproc__ WStrCmp(void)
.text:004021EA                 jz      short loc_40221F
.text:004021EC                 lea     eax, [ebp+var_24]
.text:004021EF                 push    eax
.text:004021F0                 call    SHGetDesktopFolder
.text:004021F5                 lea     eax, [ebp+var_2C]
.text:004021F8                 push    eax
.text:004021F9                 lea     eax, [ebp+var_18]
.text:004021FC                 push    eax
.text:004021FD                 lea     eax, [ebp+var_28]
.text:00402200                 push    eax
.text:00402201                 mov     eax, ebx
.text:00402203                 call    System::__linkproc__ WStrToPWChar(System::WideString)
.text:00402208                 push    eax
.text:00402209                 push    0
.text:0040220B                 mov     eax, off_46CA64
.text:00402210                 mov     eax, [eax]
.text:00402212                 mov     eax, [eax+30h]
.text:00402215                 push    eax
.text:00402216                 mov     eax, [ebp+var_24]
.text:00402219                 push    eax
.text:0040221A                 mov     eax, [eax]
.text:0040221C                 call    dword ptr [eax+0Ch]
.text:0040221F
.text:0040221F loc_40221F:                             ; CODE XREF: Filectrl::SelectDirectory(System::AnsiString,System::WideString,System::AnsiString &)+96j
.text:0040221F                 mov     eax, off_46CA64
.text:00402224                 mov     eax, [eax]
.text:00402226                 mov     eax, [eax+30h]
.text:00402229                 mov     [ebp+var_4C], eax
.text:0040222C                 mov     eax, [ebp+var_18]
.text:0040222F                 mov     [ebp+var_48], eax
.text:00402232                 mov     eax, [ebp+var_10]
.text:00402235                 mov     [ebp+var_44], eax
.text:00402238                 mov     eax, esi
.text:0040223A                 call    System::__linkproc__ LStrToPChar(void)
.text:0040223F                 mov     [ebp+var_40], eax
.text:00402242                 mov     [ebp+var_3C], 1
.text:00402249                 mov     eax, [ebp+var_4]
.text:0040224C                 cmp     dword ptr [eax], 0
.text:0040224F                 jz      short loc_402265
.text:00402251                 mov     [ebp+var_38], offset FileCtrl::_16501
.text:00402258                 mov     eax, [ebp+var_4]
.text:0040225B                 mov     eax, [eax]
.text:0040225D                 call    System::__linkproc__ LStrToPChar(void)
.text:00402262                 mov     [ebp+var_34], eax
.text:00402265
.text:00402265 loc_402265:                             ; CODE XREF: Filectrl::SelectDirectory(System::AnsiString,System::WideString,System::AnsiString &)+FBj
.text:00402265                 xor     eax, eax
.text:00402267                 call    sub_43FEAC
.text:0040226C                 mov     [ebp+var_C], eax
.text:0040226F                 push    1               ; uMode
.text:00402271                 call    SetErrorMode
.text:00402276                 mov     [ebp+uMode], eax
.text:00402279                 xor     eax, eax
.text:0040227B                 push    ebp
.text:0040227C                 push    offset loc_4022B2
.text:00402281                 push    dword ptr fs:[eax]
.text:00402284                 mov     fs:[eax], esp
.text:00402287                 lea     eax, [ebp+var_4C]
.text:0040228A                 push    eax
.text:0040228B                 call    SHBrowseForFolderA
.text:00402290                 mov     [ebp+var_1C], eax
.text:00402293                 xor     eax, eax
.text:00402295                 pop     edx
.text:00402296                 pop     ecx
.text:00402297                 pop     ecx
.text:00402298                 mov     fs:[eax], edx
.text:0040229B                 push    offset loc_4022B9
.text:004022A0
.text:004022A0 loc_4022A0:                             ; CODE XREF: Filectrl::SelectDirectory(System::AnsiString,System::WideString,System::AnsiString &)+163j
.text:004022A0                 mov     eax, [ebp+uMode]
.text:004022A3                 push    eax             ; uMode
.text:004022A4                 call    SetErrorMode
.text:004022A9                 mov     eax, [ebp+var_C]
.text:004022AC                 call    sub_43FF60
.text:004022B1                 retn


Отредактировано BreakPointMAN — 23/11/2005, 23:40
Gedeon
Отправлено: 24.11.2005, 08:56


Ветеран

Группа: Модератор
Сообщений: 1742



Да, согласен, совсем забыл что она перегруженная и говорил именно про тот вариант, который
CODE

SelectDirectory(AnsiString &Directory, TSelectDirOpts Options, int HelpCtx);

точнее посмотрел в исходниках
CODE

function SelectDirectory(var Directory: string;
 Options: TSelectDirOpts; HelpCtx: Longint): Boolean;
var
 D: TSelectDirDlg;
begin
 D := TSelectDirDlg.Create(Application);
 try
   D.Directory := Directory;
   D.AllowCreate := sdAllowCreate in Options;
   D.Prompt := sdPrompt in Options;

   { scale to screen res }
   if Screen.PixelsPerInch <> 96 then
   begin
     D.ScaleBy(Screen.PixelsPerInch, 96);
     D.FileList.ParentFont := True;
     D.Left := (Screen.Width div 2) — (D.Width div 2);
     D.Top := (Screen.Height div 2) — (D.Height div 2);
     D.FileList.Font.Color := clGrayText;
   end;

   if HelpCtx = 0 then
   begin
     D.HelpButton.Visible := False;
     D.OKButton.Left := D.CancelButton.Left;
     D.CancelButton.Left := D.HelpButton.Left;
   end
   else D.HelpContext := HelpCtx;

   Result := D.ShowModal = mrOK;
   if Result then
   begin
     Directory := D.Directory;
     if sdPerformCreate in Options then
       ForceDirectories(Directory);
   end;
 finally
   D.Free;
 end;
end;

а если вспомнить про второй
CODE

SelectDirectory(const AnsiString Caption, const WideString Root, AnsiString &Directory);

то да совершенно верно SHBrowseForFolder
CODE

function SelectDirectory(const Caption: string; const Root: WideString;
 var Directory: string): Boolean;
var
 WindowList: Pointer;
 BrowseInfo: TBrowseInfo;
 Buffer: PChar;
 OldErrorMode: Cardinal;
 RootItemIDList, ItemIDList: PItemIDList;
 ShellMalloc: IMalloc;
 IDesktopFolder: IShellFolder;
 Eaten, Flags: LongWord;
begin
 Result := False;
 if not DirectoryExists(Directory) then
   Directory := '';
 FillChar(BrowseInfo, SizeOf(BrowseInfo), 0);
 if (ShGetMalloc(ShellMalloc) = S_OK) and (ShellMalloc <> nil) then
 begin
   Buffer := ShellMalloc.Alloc(MAX_PATH);
   try
     RootItemIDList := nil;
     if Root <> '' then
     begin
       SHGetDesktopFolder(IDesktopFolder);
       IDesktopFolder.ParseDisplayName(Application.Handle, nil,
         POleStr(Root), Eaten, RootItemIDList, Flags);
     end;
     with BrowseInfo do
     begin
       hwndOwner := Application.Handle;
       pidlRoot := RootItemIDList;
       pszDisplayName := Buffer;
       lpszTitle := PChar(Caption);
       ulFlags := BIF_RETURNONLYFSDIRS;
       if Directory <> '' then
       begin
         lpfn := SelectDirCB;
         lParam := Integer(PChar(Directory));
       end;
     end;
     WindowList := DisableTaskWindows(0);
     OldErrorMode := SetErrorMode(SEM_FAILCRITICALERRORS);
     try
       ItemIDList := ShBrowseForFolder(BrowseInfo);
     finally
       SetErrorMode(OldErrorMode);
       EnableTaskWindows(WindowList);
     end;
     Result :=  ItemIDList <> nil;
     if Result then
     begin
       ShGetPathFromIDList(ItemIDList, Buffer);
       ShellMalloc.Free(ItemIDList);
       Directory := Buffer;
     end;
   finally
     ShellMalloc.Free(Buffer);
   end;
 end;
end;

Вернуться в Вопросы программирования в C++Builder