Discussion:
Window Hook for Open File Dialog
(too old to reply)
David Wilkinson
2005-12-29 22:59:48 UTC
Permalink
Hi all:

Using VC6, and after updating the SDK and setting _WIN32_WINNT to
0x0500, I encountered the OPENFILENAME size problem, and tried replacing
CFileDialog with the CFileDialogST that I found on CodeProject.

After slight modification, it works fine (shows the Places bar), but it
always puts the file dialog top left on the screen. So I added a Window
Hook procedure so I could center the file dialog on my application:

static UINT __stdcall OfnHookProc(HWND hdlg, UINT uiMsg, WPARAM wParam,
LPARAM lParam);

implemented as

UINT CFileDialogST::OfnHookProc(HWND hdlg, UINT uiMsg, WPARAM wParam,
LPARAM lParam)
{
if(uiMsg == WM_INITDIALOG)
{
ASSERT(::IsWindow(hdlg));
// code

}
return 0;
}

Here I expected hdlg to be the HWND of the open file dialog. But it does
not seem to be. Rather the open file dialog is the parent of hdlg. Why
is this?

The following does what I want, but I do not really understand why:

UINT CFileDialogST::OfnHookProc(HWND hdlg, UINT uiMsg, WPARAM wParam,
LPARAM lParam)
{
if(uiMsg == WM_INITDIALOG)
{
ASSERT(::IsWindow(hdlg));
CWnd* pWnd = CWnd::FromHandle(hdlg);

CWnd* pDlg = pWnd->GetParent(); // this is the dialog!!
ASSERT(::IsWindow(pDlg->GetSafeHwnd()));
CRect dlgRect;
pDlg->GetWindowRect(&dlgRect);

CWnd* pMainWnd = AfxGetMainWnd();
ASSERT(::IsWindow(pMainWnd->GetSafeHwnd()));
CRect mainRect;
pMainWnd->GetWindowRect(&mainRect);

CPoint point = mainRect.CenterPoint() - dlgRect.CenterPoint();
dlgRect += CSize(point.x, point.y);
pDlg->MoveWindow(&dlgRect);
}
return 0;
}

TIA,

David Wilkinson
Jeff Partch [MVP]
2005-12-29 23:25:45 UTC
Permalink
Post by David Wilkinson
I added a Window
Hook procedure...
static UINT __stdcall OfnHookProc(HWND hdlg, UINT uiMsg, WPARAM wParam,
LPARAM lParam);
Here I expected hdlg to be the HWND of the open file dialog. But it does
not seem to be. Rather the open file dialog is the parent of hdlg. Why
is this?
http://msdn.microsoft.com/library/default.asp?url=/library/en-us/winui/winui/windowsuserinterface/userinput/commondialogboxlibrary/commondialogboxreference/commondialogboxfunctions/ofnhookproc.asp

"hdlg -- [in] Handle to the child dialog box of the Open or Save As dialog
box. Use the GetParent function to get the handle to the Open or Save As
dialog box".

"If you provide a hook procedure for an Explorer-style common dialog box,
the system creates a dialog box that is a child of the default dialog box.
The hook procedure acts as the dialog procedure for the child dialog. This
child dialog is based on the template you specified in the OPENFILENAME
structure, or it is a default child dialog if no template is specified".
--
Jeff Partch [VC++ MVP]
David Wilkinson
2005-12-30 01:56:16 UTC
Permalink
Post by Jeff Partch [MVP]
Post by David Wilkinson
I added a Window
Hook procedure...
static UINT __stdcall OfnHookProc(HWND hdlg, UINT uiMsg, WPARAM wParam,
LPARAM lParam);
Here I expected hdlg to be the HWND of the open file dialog. But it does
not seem to be. Rather the open file dialog is the parent of hdlg. Why
is this?
http://msdn.microsoft.com/library/default.asp?url=/library/en-us/winui/winui/windowsuserinterface/userinput/commondialogboxlibrary/commondialogboxreference/commondialogboxfunctions/ofnhookproc.asp
"hdlg -- [in] Handle to the child dialog box of the Open or Save As dialog
box. Use the GetParent function to get the handle to the Open or Save As
dialog box".
Thanks Jeff!!

But this is not what it says in either the VC6 or VC7.1 documentation:

hdlg
Handle to the Open or Save As dialog box window for which the message is
intended.

Can this behavior have been changed? Or was the documentation previously
in error? (Hopefully the latter.) But what exactly is hdlg when uimsg is
WM_INITDIALOG?

David Wilkinson
Jeff Partch [MVP]
2005-12-30 03:49:34 UTC
Permalink
Post by David Wilkinson
Post by Jeff Partch [MVP]
Post by David Wilkinson
static UINT __stdcall OfnHookProc(HWND hdlg, UINT uiMsg, WPARAM wParam,
LPARAM lParam);
Here I expected hdlg to be the HWND of the open file dialog. But it does
not seem to be. Rather the open file dialog is the parent of hdlg. Why
is this?
http://msdn.microsoft.com/library/default.asp?url=/library/en-us/winui/winui/windowsuserinterface/userinput/commondialogboxlibrary/commondialogboxreference/commondialogboxfunctions/ofnhookproc.asp
Post by David Wilkinson
Post by Jeff Partch [MVP]
"hdlg -- [in] Handle to the child dialog box of the Open or Save As dialog
box. Use the GetParent function to get the handle to the Open or Save As
dialog box".
Thanks Jeff!!
I guess I don't know what documentation that is, David. It appears as I
posted in both the Oct 2001 and July 2003 editions of the MSDN Library.
Post by David Wilkinson
hdlg
Handle to the Open or Save As dialog box window for which the message is
intended.
This is how it appears in the documentation for the OFNHookProcOldStyle
callback.
Post by David Wilkinson
Can this behavior have been changed? Or was the documentation previously
in error? (Hopefully the latter.)
Changed I reckon. Since back when they implemented OFN_EXPLORER style
Open/Save dialogs. The documentation indicates that the Minimum operating
systems to support this flag are Windows 95 and Windows NT 3.1.
Post by David Wilkinson
But what exactly is hdlg when uimsg is
WM_INITDIALOG?
I think that was answered in my previous post: "the system creates a dialog
box that is a child of the default dialog box. The hook procedure acts as
the dialog procedure for the child dialog. This child dialog is based on the
template you specified in the OPENFILENAME structure, or it is a default
child dialog if no template is specified".
--
Jeff Partch [VC++ MVP]
David Wilkinson
2005-12-30 13:01:57 UTC
Permalink
Post by Jeff Partch [MVP]
Post by David Wilkinson
Post by Jeff Partch [MVP]
Post by David Wilkinson
static UINT __stdcall OfnHookProc(HWND hdlg, UINT uiMsg, WPARAM wParam,
LPARAM lParam);
Here I expected hdlg to be the HWND of the open file dialog. But it does
not seem to be. Rather the open file dialog is the parent of hdlg. Why
is this?
http://msdn.microsoft.com/library/default.asp?url=/library/en-us/winui/winui/windowsuserinterface/userinput/commondialogboxlibrary/commondialogboxreference/commondialogboxfunctions/ofnhookproc.asp
Post by David Wilkinson
Post by Jeff Partch [MVP]
"hdlg -- [in] Handle to the child dialog box of the Open or Save As
dialog
Post by David Wilkinson
Post by Jeff Partch [MVP]
box. Use the GetParent function to get the handle to the Open or Save As
dialog box".
Thanks Jeff!!
I guess I don't know what documentation that is, David. It appears as I
posted in both the Oct 2001 and July 2003 editions of the MSDN Library.
Post by David Wilkinson
hdlg
Handle to the Open or Save As dialog box window for which the message is
intended.
This is how it appears in the documentation for the OFNHookProcOldStyle
callback.
[snip]

Jeff:

I got it now. Because I did not specify OFN_EXPLORER I thought I WAS
receiving a OFNHookProcOldStyle callback, and that was the documentation
I looked at. Although the docs imply that if you specify a hook
procedure you must also specify OFN_EXPLORER, this does not seem to be
the case; my code with a hook works the same whether or not I specify
OFN_EXPLORER. But I see now that the intended usage is to specify both
OFN_ENABLEHOOK and OFN_EXPLORER, and that is how my code is now.

Thanks,

David Wilkinson
David Wilkinson
2006-01-01 11:34:55 UTC
Permalink
David Wilkinson wrote:

[snip]
Post by David Wilkinson
I got it now. Because I did not specify OFN_EXPLORER I thought I WAS
receiving a OFNHookProcOldStyle callback, and that was the documentation
I looked at. Although the docs imply that if you specify a hook
procedure you must also specify OFN_EXPLORER, this does not seem to be
the case; my code with a hook works the same whether or not I specify
OFN_EXPLORER. But I see now that the intended usage is to specify both
OFN_ENABLEHOOK and OFN_EXPLORER, and that is how my code is now.
Thanks,
David Wilkinson
Jeff:

My mistake (again!). For the record, OFN_EXPLORER was always being
defined in the CFileDialogST code (in the constructor body, not in the
default constructor arguments).

It needs a little tweaking, but I would recommend this CFileDialogST
class from CodeProject as a replacement for CFileDialog in VC6 (haven't
tried in VC7, but it should work there also). Its main features are:

1. By doing a runtime version check, it allows display of the Places bar
on OS's that support it, while displaying the old file dialog without
Places bar otherwise.

2. With a slight modification, it works also if you have updated your
Platform SDK and defined _WIN32_WINNT to a value >= 0x0500. The MFC
CFileDialog crashes in this case, because it is compiled with an
OPENFILENAME structure that is smaller than the one defined in the
Windows headers.

Interestingly, CFileDialogST is not derived form CFileDialog, or
CDialog, or even from CWnd!! It is just a wrapper that calls the Win32
functions GetOpenFileName() and GetSaveFileName() in its DoModal method.

David Wilkinson

Continue reading on narkive:
Loading...