The Unofficial Newsletter
of Delphi Users - by Robert Vivrette
Opening the "Find Files..." Dialog Using Delphi.
by Eddie Shipman - eshipman@inetport.com
I received an e-mail asking how to programatically open the "Find Files..."
dialog. I scratched my head and wondered how it was done. So, the
trek began to find out how to accomplish this using Delphi.
To begin you need to know how Windows actually does it. Windows uses
the lpVerb parameter of the SHELLEXECUTEINFO structure in a ShellExecuteEx
call to accomplish this. In Delphi, the structure is called TShellExecuteInfo
and it is defined in ShellAPI.PAS like this:
TShellExecuteInfoA = record
cbSize: DWORD;
fMask: ULONG;
Wnd: HWND;
lpVerb: PAnsiChar;
lpFile: PAnsiChar;
lpParameters: PAnsiChar;
lpDirectory: PAnsiChar;
nShow: Integer;
hInstApp: HINST;
{ Optional fields }
lpIDList: Pointer;
lpClass: PAnsiChar;
hkeyClass: HKEY;
dwHotKey: DWORD;
hIcon: THandle;
hProcess: THandle;
end;
TShellExecuteInfo = TShellExecuteInfoA;
These units are required in your uses clause: ShlObj, ShellAPI, ActiveX.
In our case we only need a few of the parameters. To open the "Find
Files..." dialog on a specific Drive, you must pass the path to the drive
via the lpFile parameter. The record will be defined like this to open
the dialog on drive C:
with sei do
begin
cbSize := SizeOf(sei);
nShow := SW_SHOWNORMAL;
lpFile := PChar('C:\'); // This parameter can
also be suffixed with
// another '\' so you would have PChar('C:\\')
lpVerb := 'find';
end;
The lpVerb parameter set to 'find' instructs the call to ShellExecuteEX
to open the "Find Files..." dialog. The nShow parameter defaults to SW_SHOWNORMAL
so it is not really needed.
This is the entire call to open with a Drive selected from a DriveComboBox:
procedure TForm1.Button1Click(Sender: TObject);
var
PMalloc: IMalloc; // IMalloc is defined in ActiveX.PAS
sei : TShellExecuteInfo;
begin
try
SHGetMalloc(PMalloc);
ZeroMemory(@sei, sizeof(sei));
with sei do
begin
cbSize := SizeOf(sei);
lpFile := PChar(String(DriveComboBox1.Drive)
+ ':\');
lpVerb := 'find';
end;
ShellExecuteEx(@sei);
finally
pMalloc._Release;
pMalloc := nil;
end;
end;
Now, suppose you wanted to open with "My Computer" as the stating place?
You will have to do things a little different. Here's how:
procedure TForm1.Button1Click(Sender: TObject);
var
pidl: PITEMIDLIST;
PMalloc: IMalloc;
sei : TShellExecuteInfo;
begin
try
SHGetMalloc(PMalloc);
ZeroMemory(@sei, sizeof(sei));
SHGetSpecialFolderLocation(0,CSIDL_DRIVES,pidl);
with sei do
begin
cbSize := SizeOf(sei);
fMask := SEE_MASK_INVOKEIDLIST;
lpVerb := 'find';
lpIDList := pidl;
end;
ShellExecuteEx(@sei);
finally
pMalloc._Release;
pMalloc := nil;
end;
end;
As you can see, we are using two new parameters for the SHELLEXECUTEINFO
record. The first thing the needs to be done is to fill the pidl ItemIdList
with a call to SHGetSpecialFolderLocation. The parameter CSIDL_DRIVES tells
the function to return the info for "My Computer", which is actually just
a list of drives accessable to your computer. The parameter fMask set to
SEE_MASK_INVOKEIDLIST instructs ShellExecuteEX to use the lpIDList parameter.
This must be set correctly for the dialog to open.
So, now you can give your users access to the "Find Files..." dialog
without them having to open Explorer or moving to the Start Menu.
Here is the complete code to the project:
unit uFileOpen;
interface
uses
Windows, Messages, SysUtils, Classes, Graphics, Controls,
Forms, Dialogs,
StdCtrls, ShlObj, ShellAPI, FileCtrl, ActiveX;
type
TForm1 = class(TForm)
Button1: TButton;
DriveComboBox1: TDriveComboBox;
CheckBox1: TCheckBox;
procedure Button1Click(Sender: TObject);
procedure DriveComboBox1Change(Sender: TObject);
private
{ Private declarations }
public
{ Public declarations }
end;
var
Form1: TForm1;
implementation
{$R *.DFM}
procedure TForm1.Button1Click(Sender: TObject);
var
pidl: PITEMIDLIST;
PMalloc: IMalloc;
sei : TShellExecuteInfo;
begin
try
SHGetMalloc(PMalloc);
ZeroMemory(@sei, sizeof(sei));
if CheckBox1.Checked then
begin
SHGetSpecialFolderLocation(0,CSIDL_DRIVES,pidl);
with sei do
begin
cbSize := SizeOf(sei);
fMask := SEE_MASK_INVOKEIDLIST;
lpVerb := 'find';
lpIDList := pidl;
end;
end
else
begin
with sei do
begin
cbSize := SizeOf(sei);
lpFile := PChar(String(DriveComboBox1.Drive)
+ ':\');
lpVerb := 'find';
end;
end;
ShellExecuteEx(@sei);
finally
pMalloc._Release;
pMalloc := nil;
end;
end;
procedure TForm1.DriveComboBox1Change(Sender: TObject);
begin
if CheckBox1.Checked then CheckBox1.Checked := False;
end;
end.
Here is the DFM:
object Form1: TForm1
Left = 200
Top = 112
Width = 258
Height = 142
Caption = 'Open Find Files... Dialog'
Font.Charset = DEFAULT_CHARSET
Font.Color = clWindowText
Font.Height = -11
Font.Name = 'MS Sans Serif'
Font.Style = []
PixelsPerInch = 96
TextHeight = 13
object Button1: TButton
Left = 58
Top = 63
Width = 133
Height = 38
Caption = 'Open Find Files...'
TabOrder = 0
OnClick = Button1Click
end
object DriveComboBox1: TDriveComboBox
Left = 52
Top = 14
Width = 145
Height = 19
TabOrder = 1
OnChange = DriveComboBox1Change
end
object CheckBox1: TCheckBox
Left = 76
Top = 40
Width = 97
Height = 17
Caption = 'My Computer'
TabOrder = 2
end
end