1. Computing
TShBrowse
Delphi component that encapsulates the ShBrowseForFolder API function call (displaying a standard Windows dialog box that enables the user to select a shell folder, network computer, printer or a file).
 Win prizes by sharing code!
Do you have some Delphi code you want to share? Are you interested in winning a prize for your work?
Delphi Programming Quickies Contest
 Join the Discussion
"Post your views, comments, questions and doubts to this article."
Discuss!
 Related Resources
• Browse for folders, files, printers and computers
• Working with Windows dialogs: various tips and articles

Article submitted by Alan Lloyd for the Delphi Programming Quickies Contest.

TSHBrowse
TShBrowse is a Delphi wrapper around a windows ShBrowseForFolder API dialog. Download full source code!

When the TShBrowse object is created, a default caption and user message are defined.
If TShBrowse options are specified then the windows BrowseInfo.ulFlags value is created by running through the Delphi set of enumerated option values and or'ing windows ShBFF values via a look-up array.

ShBrowseForFolder calls a user defined function when it responds to user action. The parameters of this callback function are (hWnd : THandle; uMsg : integer; lParam, lpData : DWord). The user code must respond by doing whatever is necessary and appropriate to the message and message data (in lParam).

Note that the lpData parameter is a value returned by windows of whatever value is specified in the BrowseInfo.lParam element when calling ShBrowseForFolder. (Note that the BrowseInfo.lParam has no relation to the callback lParam. BrowseInfo.lParam is returned as callback lpData).

The callback function is a general function not a method. If we want to use a method (to engage OO conventions) we must know what instance of what object has the callback method. This we do by passing Self (a reference to the current instance) in the BrowseInfo.lParam element. This reference is returned by the callback in lpData and is typecast to a TShBrowse object to direct the callback to the instance method.

function ShBFFCallback(hWnd : THandle; uMsg : integer; lParam, 
                       lpData : DWord) : integer; stdcall;
begin
  // calls object's method
  TShBrowse(lpData).Callback(hWnd, uMsg, lParam); 
...

Browse dialog
The callback method carries out changes appropriate to the message identifier in the uMsg parameter. The callback also returns the windows handle of the dialog box. This is stored as we need it to position the dialog box in accordance with the Left and Top properties.

To obtain the user folder selection the Execute method is called. This returns false if the user has cancelled the dialog. When the dialog is initialised it callbacks with a BFFM_INITIALIZED message. This is the time to set the position of the dialog box, the captions, and the initial folder.

Using the dialog box window handle provided by the call back hWnd parameter, the dialog window size is obtained. SystemParametersInfo allows us to get the desktop size and calculate the dialog box position which we then set.

When a user selection of a folder is made (but before clicking the OK button) the callback is called with a BFFM_SELCHANGED message. This allows us to run the FolderCheck function (if provided) to check if the selction is valid and enable th OK button.

When the OK button is clicked then the ShBrowseForFolder API returns with a pointer to an Id list (this will be nil if the Cancel button was clicked). We read the list pointed to by calling ShGetPathFromIDList and place this in the Folder property. The selected item icon index is placed in the SelIconIndex property.

The memory used by the pointer to the Id list is freed using the shell's IMalloc interface (the shell itself will free the Imalloc interface, we only use that interface to free the memory). If required the UNC form of the selected folder is available via the UNC property.

Typical usage
uses
  ShBrowseU;

procedure TForm1.BrowseBtnClick(Sender: TObject);
begin
  with TShBrowse.Create do 
  begin
    Caption := CaptionEdit.Text;
    UserMessage := UserMsgEdit.Text;
    InitFolder := 'C:\';
    FolderCheck := Check;
    if Execute then
      // do what is needed with the selected folder string
      ListBox1.Items.Add(Folder);  
    Free;
  end;
end;

function TForm1.Check
(Sender : TObject; Folder : string) : boolean;
{place the OK button logic here to return true
 when OK button should be enabled}
begin
  // or whatever test you want
  Result := Pos('Data', Folder) > 0; 
end;

Note: TShBrowse is not _actually_ a component, although one could descend it from TComponent and add a Register procedure. But one might then have to fiddle with ownership. I think I tried it and it choked somewhere. And anyway I usually create on the fly these sort of things which have no visual inheritance.

Properties and methods
constructor Create
Initiates the supporting and wrapping functionality of TshBrowse which descends from Tobject. You could descedn from Tcomponent and add a Register function to enable it to be placed on the Component Pallette

function Execute : boolean; Called to display the shell if they are greater than 0. As is usual with object classes they will initiate at with a default value of zero when the object instance is created.

propertty Caption : string
Write only. Specifies the caption appearing on the title bar of the ShBFF dialog.

property Folder : string
Read only. The folder path selected: and OK'ed by the user

property FolderCheck : TFolderCheck
Write only. Reference to the check method (defined as function(Sender : TObject; Folder : string) : boolean of object) to enable the OK button. This function is called when a user selects a folder in the dialog. It must return true or false to appropriately enable the OK button in the ShBFF dialog. Only used by TShBrowse if assigned.

property InitFolder : string
Write only. The initial directory at which the dialog opens.

property Left : integer
Write only. Opening left screen position for ShBFF dialog. Both Left and Top values must be > 0 to be used to position the dialog.

property Options : TShBrowseOptions
ShBrowseForFolder options. The Win API option values have been wrapped as a Delphi set. See the API description for the correspondingly named option description.

property SelIconIndex : integer
Read only. The ShBFF icon for the user selected item.

property Top : integer
Write only. Opening left screen position for ShBFF dialog. Both Left and Top values must be > 0 to be used to position the dialog

property UNCFolder : string
Read only. UNC form of selected folder. Returns the UNC folder or an error string. A valid UNC name will start with '\\'

property UserMessage : string
Write only. The user instruction message which appears below the title bar in the body of ShBFF dialog.

Use at will
If you have any questions or comments, please post to the Delphi Programming Forum.

©2013 About.com. All rights reserved.