Aus dem Swiss Delphi Center habe ich die Routine:
Delphi-Quellcode:
function AdvSelectDirectory (const Caption : string;
const Root : WideString;
var StartDir : string;
var Directory : string;
EditBox : Boolean = False;
ShowFiles : Boolean = False;
AllowCreateDirs : Boolean = True): Boolean;
{
Callback-Funktion, die aufgerufen wird, wenn der Dialog initialisiert oder
ein neues Verzeichnis selektiert wurde
}
function SelectDirCB (Wnd: HWND;
uMsg: UINT;
lParam, lpData: lParam): Integer; stdcall;
var
PathName: array [0..MAX_PATH] of Char;
begin
case uMsg of
BFFM_INITIALIZED: SendMessage(Wnd, BFFM_SETSELECTION, Ord(True), Integer(lpData));
{
binde den folgenden Kommentar in deinen Code ein, wenn du auf das Ereignis
reagieren willst, das aufgerufen wird, wenn ein neues Verzeichnis selektiert wurde
}
BFFM_SELCHANGED: SHGetPathFromIDList(PItemIDList(lParam), @PathName);
{
das Verzeichnis "PathName" wurde selektiert
}
end;
Result := 0;
end;
var
WindowList: Pointer;
BrowseInfo: TBrowseInfo;
Buffer: PChar;
RootItemIDList, ItemIDList: PItemIDList;
ShellMalloc: IMalloc;
IDesktopFolder: IShellFolder;
Eaten, Flags: LongWord;
const
{
notwendig für einige der zusätzlichen Erweiterungen
}
BIF_USENEWUI = $0040;
BIF_NOCREATEDIRS = $0200;
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;
OleInitialize(nil);
with BrowseInfo
do begin
hwndOwner := Application.Handle;
pidlRoot := RootItemIDList;
pszDisplayName := Buffer;
lpszTitle := PChar(Caption);
{
legt fest, wie der Dialog erscheint:
}
ulFlags := $25
or BIF_RETURNONLYFSDIRS
or BIF_USENEWUI
or BIF_EDITBOX * Ord(EditBox)
or BIF_BROWSEINCLUDEFILES * Ord(ShowFiles)
or BIF_NOCREATEDIRS * Ord(not AllowCreateDirs);
lpfn := @SelectDirCB;
lParam := Integer(PChar(StartDir));
end;
WindowList := DisableTaskWindows(0);
try
ItemIDList := ShBrowseForFolder(BrowseInfo);
finally
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;
In meinem Testprogramm funktioniert es mit Delphi 7 Personal auch. Wenn ich es jedoch in mein Programm einbaue, bekomme ich bei Zeile 85
lpfn := @SelectDirCB;
die Fehlermeldung: Inkompatible Typen: 'TFNBFFCallBack' und 'Pointer'. Nehme ich das @ heraus, lautet die Fehlermeldung: Lokale Prozedur/Funktion 'BrowserCallBack' wurde Procedurenvariable zugewiesen.
In den Uses der
Unit stehen:
Windows, SysUtils, Forms, ShellAPI, Graphics, Controls, Dialogs, Classes, Registry, ShlObj,
ActiveX;
Und eine
Unit mit den Uses:
Windows, SysUtils, Forms, FileCtrl, Messages, Graphics, MMSystem, StdCtrls, ExtCtrls, Classes, Controls, Dialogs, Gauges, Grids, MPlayer, ComCtrls, Buttons;
und ein paar eigene Units.
Die Sache ist nun, wenn ich die Zeile auskommentiere, wird nicht der angegebene Startordner sondern Eigene Dateien aufgeschlagen. Hat jemand eine Idee, woran das liegen könnte oder kennt eine Alternative für diese Dialogbox?