Author: Jonas Bilinkevicius
I would like to modify the behavior of the standard OpenDialog component in Delphi
6 to show my custom hints when the mouse pointer is over particular file shown on
the OpenDialog screen. By default the screen shows a hint with the file extension
and size. I tried to access the (supposedly) integrated component on the dialog
screen in a similar way I have done with the QuickReport standard preview screen
(not the Preview component from the palette) - using client.parent. I realize that
the implementation of the OpenDialog may directly reference Windows DLLs.Is there a
way I could implement custom hint messages?
Answer:
Well, it should be possible, but it will be awkward. The TOpenDialog is not a
component wrapper around a control you could easily subclass, it is a wrapper
around an API function that shows a dialog. The dialog contains a number of Windows
controls, among which is the listview that shows the files. The listviews parent
will get WM_NOTIFY messages from the listview (heaps of them, in fact), among which
is the notification asking for the tooltip text. You need to subclass the parent
the API way to get hold of this message. A place to do this is the TOpenDialogs
OnShow event. The parent handle is not the components Handle property, by the way,
you need to go one level up via Windows.GetParent to get the dialog boxes true
handle. Do a recursive EnumChildWindow on this handle to investigate the control
hierarchy on the dialog. I dimly remember that the listview and its container gets
created after OnShow, so you may have to delay the enumeration via PostMessage.
The following gets the listview's handle, the listview is recreated by the dialog
as needed so you have to retrieve the handle each time you want to access it.
1 { ... }
2 type
3 pWndSt r = ^hWndStr;
4 hWndStr = record
5 lpStr: string;
6 hWnd: HWND;
7 end;
8
9 function ClassProc(hWnd: HWND; p: pWndStr): Boolean; stdcall;
10 var
11 strBuf: array[0..20] of Char;
12 begin
13 FillChar(strBuf, SizeOf(strBuf), #0);
14 GetClassName(hWnd, @strBuf[0], 20);
15 if StrPas(strBuf) = p^.lpStr then
16 begin
17 Result := False;
18 p^.hWnd := hWnd;
19 end
20 else
21 Result := True;
22 end;
23
24 function ChildByClass(hWnd: HWND; lpzClass: string): HWND;
25 var
26 p: pWndStr;
27 begin
28 New(p);
29 p^.lpStr := lpzClass;
30 p^.hWnd := 0;
31 EnumChildWindows(hWnd, @ClassProc, Longint(p));
32 Result := p^.hWnd;
33 Dispose(p);
34 end;
35
36 function TOpenPictureDialogEx.SystemLVHWND: HWND;
37 begin
38 {Handle here is the TOpenPictureDialogEx's Handle as this is
39 a decendant of TOpenPictureDialog.}
40 result := ChildByClass(GetParent(Handle), 'SysListView32');
41 end;
|