This is a simple folder selector if anyone is still interested.
Code is attributed to its author in source. I don't see being available anymore.
Be sure to pass the owning form as AOwner to make sure this is a modal dialog.
unit FolderBrowser;
//by Johnny Mamenko, (c) 1999
//e-mail: [email protected]
//http://attend.to/johnny
interface
uses
Windows, Messages, SysUtils, Classes, controls, shlobj, DntFunc;
type
EFolderBrowserException = class(Exception);
TBrowseFlag = (bfComputersOnly, bfPrintersOnly, bfDirsOnly, bfStatusText);
TBrowseFlags = set of TBrowseFlag;
TFolderChangeEvent = procedure ( const Folder: string;
var EnabledOK : integer;
//0 - Disables the OK button
//1 - Enables the OK button
//-1 - leave as is
var StatusText : string) of object;
TFolderBrowser = class (TComponent)
private
FTitle : string;
FBrowseFlags : TBrowseFlags;
FFolder: string;
FOwnerHandle : HWND;
FOnChangeFolder: TFolderChangeEvent;
procedure SetFolder(const Value: string);
procedure SetOnChangeFolder(const Value: TFolderChangeEvent);
protected
public
constructor Create(AOwner : TComponent); override;
function Execute: boolean;
published
property BrowseFlags : TBrowseFlags read FBrowseFlags write FBrowseFlags;
property Folder : string read FFolder write SetFolder;
property Title : string read FTitle write FTitle;
property OnChangeFolder : TFolderChangeEvent read FOnChangeFolder write SetOnChangeFolder;
end;
procedure Register;
function FolderCallBack(Wnd: HWND; uMsg: UINT; lParam, lpData: LPARAM): Integer stdcall;
implementation
var
CurrentOpenedFolder : string;
CurrentEventHandler : TFolderChangeEvent;
procedure Register;
begin
RegisterComponents( 'Johnny', [ TFolderBrowser ] );
end;
function FolderCallBack(Wnd: HWND; uMsg: UINT; lParam, lpData: LPARAM): Integer stdcall;
var
a : array[0..MAX_PATH] of Char;
EnabledOK : integer;
StatusText, Folder : string;
begin
Result:=0;
if uMsg=BFFM_INITIALIZED then begin
StrPCopy(a,CurrentOpenedFolder);
SendMessage(Wnd, BFFM_SETSELECTION, 1, Integer(@a[0]));
exit;
end;//if uMsg=BFFM_INITIALIZED
if uMsg=BFFM_SELCHANGED then begin
EnabledOK:=-1;
StatusText:='';
SHGetPathFromIDList(Pointer(lParam),a);
Folder:=StrPas(a);
if Assigned(CurrentEventHandler) and (Folder<>'')
then CurrentEventHandler(Folder, EnabledOK, StatusText);
if EnabledOK<>-1 then SendMessage(Wnd, BFFM_ENABLEOK, EnabledOK, EnabledOK);
if StatusText<>''
then SendMessage(Wnd, BFFM_SETSTATUSTEXT, EnabledOK, Integer(PChar(StatusText)));
end;//if uMsg=BFFM_SELCHANGED
end;
{TFolderBrowser}
constructor TFolderBrowser.Create(AOwner : TComponent);
begin
if not(AOwner is TWinControl) then Raise EFolderBrowserException.Create('I need WinControl!!!');
inherited Create(AOwner);
FOwnerHandle:=(AOwner As TWinControl).Handle;
FTitle:='Select Folder';
FBrowseFlags:=[];
FFolder:='';
end;
function TFolderBrowser.Execute: boolean;
var bi : TBrowseInfoA;
a : array[0..MAX_PATH] of Char;
b : PChar;
idl : PItemIDList;
begin
b:=StrAlloc(Length(FTitle)+1);
try
StrPCopy(b,FTitle);
bi.hwndOwner:=FOwnerHandle;
bi.pszDisplayName:=@a[0];
bi.lpszTitle:=b;
bi.ulFlags:=BIF_BROWSEFORCOMPUTER*Byte(bfComputersOnly in BrowseFlags)+
BIF_BROWSEFORPRINTER*Byte(bfPrintersOnly in BrowseFlags)+
BIF_RETURNONLYFSDIRS*Byte(bfDirsOnly in BrowseFlags)+
BIF_STATUSTEXT*Byte(bfStatusText in BrowseFlags);
bi.lpfn:=FolderCallBack;
bi.lParam:=0;
bi.pidlRoot:=Nil;
CurrentOpenedFolder:=FFolder;
CurrentEventHandler:=FOnChangeFolder;
idl:=SHBrowseForFolder(bi);
if idl<>nil then begin
SHGetPathFromIDList(idl,a);
FFolder:=StrPas(a);
Result:=true;
end//if idl<>nil
else Result:=false;
finally
StrDispose(b);
end;//finally
end;
procedure TFolderBrowser.SetFolder(const Value: string);
begin
FFolder:=Value;
end;
procedure TFolderBrowser.SetOnChangeFolder(const Value: TFolderChangeEvent);
begin
FOnChangeFolder:=Value;
end;
initialization
CurrentOpenedFolder:='';
CurrentEventHandler:=Nil;
end.
[Screenshot of folder browser]
FileCtrl.SelectDirectory
has two overloaded implementations. One of them produces a Windows 3.1-styled dialog, while the other produces a native dialog. – OrvasTFileOpenDialog
on Vista+ and fallback using the (good!)SelectDirectory
on XP. – OrvasSelectDirectory
function: it is merely a wrapper forSHBrowseForFolder
, however it do not use all of the advantages modern shell provides (this includes the edit control - BIF_EDITBOX {v 4.71}). I suggest to use this function directly instead, or reuse someone's ready-made wrapper. – Strathspey