Das ganze ist ja schön und gut, hat aber einen kleinen Haken: Wenn man den Dialog im Explorer-Style haben möchte, kommt in der Hook-Procedure kein WM_CTLCOLORDLG an. Windows erzeugt dann nämlich den neuen Dialog als Child eines unsichtbaren Standard-Dialogs und die DialogProcedure des Standard-Dialogs bekommt die Nachricht. Man muss also irgendwie in die DialogProc des unsichtbaren Parents der neuen DialogBox gelangen, was nur auf sehr schmutzige Art geht:
Delphi-Quellcode:
// Hier merken wir uns die Adresse der alten DialogProc des Parents unseres Dialogs
Var oldDlgProc: Pointer;
// Diese DialogProc bearbeitet WM_CTLCOLORDLG
Function DialogProc(hdlg: HWND; uiMsg: UINT; wParam: WPARAM; lParam:LPARAM): UINT; stdcall;
Begin
case uiMsg of
WM_CTLCOLORDLG:
Result := GetStockObject(WHITE_BRUSH); // zu Demozwecken
else
Result := CallWindowProc(oldDlgProc,hdlg,uiMsg,wParam,lParam);
end;
End;
// Das ist unsere eigentliche Hook-DialogProcedure
Function OpenFileNameHook(hdlg: HWND; uiMsg: UINT; wParam: WPARAM; lParam:LPARAM): UINT; stdcall;
Var ofnParent: Integer;
Begin
Result := 0;
Case uiMsg of
WM_NOTIFY: Begin
Result := 0;
If ((POFNOTIFY(lparam)^.hdr.code)=CDN_INITDONE) then Begin
// wir merken uns den Parent
ofnParent := GetParent(hdlg);
// und holen uns die Adresse der ParentDialogProc
oldDlgProc := Pointer(GetWindowLong(ofnparent,DWL_DLGPROC));
// und setzen die ParentDialogProc auf die obere Proc
SetWindowLong(ofnParent,DWL_DLGPROC,Integer(@DialogProc));
Result := 1;
End;
End;
End;
End;
procedure TForm1.Button1Click(Sender: TObject);
Var ofn: TOpenFileName;
begin
// rudimentäres Befüllen der Struktur zu Demozwecken
ZeroMemory(@ofn,sizeof(ofn));
ofn.lStructSize := sizeof(ofn);
ofn.lpstrInitialDir := 'C:\';
ofn.Flags := OFN_ENABLEHOOK or OFN_EXPLORER; // wir wollen den Explorer-Style
ofn.lpfnHook := @OpenFileNameHook;
GetOpenFileName(ofn);
end;
Zugegeben, sieht schmutzig aus, aber geht...
Gruß, teebee