BUG: CFileDialog with Multiple File Types Causes Help Window to Appear on WinCE 2.11 (245002)
The information in this article applies to:
- The Microsoft Foundation Classes (MFC), when used with:
- Microsoft Windows CE Toolkit for Visual C++ 6.0
This article was previously published under Q245002 SYMPTOMS
On an H/PC Pro device running the Microsoft Windows CE 2.11 operating system, if you have an MFC application that calls CFileDialg::DoModal and uses multiple file types, when you change the file type in the Open file name dialog box and click OK to open the file, the application's Help window is displayed, instead of opening the file. The Help window only appears if the application handles the ID_HELP command; otherwise, nothing happens.
CAUSE
The CFileDialog class specifies a hook function, and sets the OFN_ENABLEHOOK flag in the OPENFILENAME structure. The CFileDialog class then passes this structure to the ::GetOpenFilenames function. The CFileDialog class expects to receive a WM_INITDIALOG message from the dialog box that is created from calling ::GetOpenFilenames. However, the CFileDialog class does not receive this message, and some necessary variables are not initialized correctly.
These variables are custom Windows messages that are sent to the hook procedure when certain events occur. The two variables that cause this bug (although they are only part of the problem) are _afxMsgFILEOK and _afxMsgHELP. Both of these variables are initially set to 0 (zero) and should be initialized in the WM_INITDIALOG handler.
The problem occurs only when you change the file type in the Open file name dialog box, because the only message sent to the hook procedure is a WM_NOTIFY message with the CDN_TYPECHANGE code. When this message is handled by the CFileDialog procedure, the dialog box window is subclassed so that MFC's hook procedure receives all other messages going to the dialog box. When the OK button is clicked, the hook procedure is sent a _afxMsgFILEOK message. However, because the _afxMsgFILEOK and _afxMsgHELP variables were not initialized correctly, the value of _afxMsgFILEOK is 0 (zero), which is the same as a _afxMsgHELP message. Therefore, when the following code in the CFileDialog hook procedure is called, the Help window is displayed:
if (message == _afxMsgHELP ||
(message == WM_COMMAND && LOWORD(wParam) == pshHelp))
{
// Translate the message into the AFX standard help command.
SendMessage(hWnd, WM_COMMAND, ID_HELP, 0);
return 1;
}
RESOLUTION
Windows CE does not support the lpfnHook and OFN_ENABLEHOOK flags of the OPENFILENAME structure. Therefore, you must create a new class that derives from CFileDialog and overrides DoModal. The following code demonstrates how to override DoModal in the derived class.
In the new class, add a declaration for DoModal as follows:
virtual int DoModal();
Include Afxpriv.h and implement DoModal as follows in the class .cpp file:
int CMyFileDialog::DoModal()
{
ASSERT_VALID(this);
m_ofn.Flags &= ~OFN_ENABLEHOOK;
m_ofn.lpfnHook = NULL;
// Zero out the file buffer for constant parsing later.
ASSERT(AfxIsValidAddress(m_ofn.lpstrFile, m_ofn.nMaxFile));
memset(m_ofn.lpstrFile, 0, m_ofn.nMaxFile);
// WINBUG: This is a special case for the file Open/Save dialog box,
// which sometimes pumps while it is coming up but before it has
// disabled the main window.
HWND hWndFocus = ::GetFocus();
BOOL bEnableParent = FALSE;
m_ofn.hwndOwner = PreModal();
AfxUnhookWindowCreate();
if (m_ofn.hwndOwner != NULL && ::IsWindowEnabled(m_ofn.hwndOwner))
{
bEnableParent = TRUE;
::EnableWindow(m_ofn.hwndOwner, FALSE);
}
_AFX_THREAD_STATE* pThreadState = AfxGetThreadState();
ASSERT(pThreadState->m_pAlternateWndInit == NULL);
#if !defined(_WIN32_WCE)
if (m_ofn.Flags & OFN_EXPLORER)
pThreadState->m_pAlternateWndInit = this;
else
AfxHookWindowCreate(this);
#endif // _WIN32_WCE
int nResult;
if (m_bOpenFileDialog)
nResult = ::GetOpenFileName(&m_ofn);
else
nResult = ::GetSaveFileName(&m_ofn);
#if defined(_WIN32_WCE_PSPC)
// WinCE: By default (no choice in "Location" is selected), m_ofn.lpstrFile has
// double slashes in front of it. Get rid of one if necessary.
if (!m_bOpenFileDialog && (*m_ofn.lpstrFile == _T('\\')) && (*(m_ofn.lpstrFile+1) == _T('\\')))
memmove((void*)m_ofn.lpstrFile, (void*)(m_ofn.lpstrFile + 1), _tcslen(m_ofn.lpstrFile)*sizeof(TCHAR));
#endif // _WIN32_WCE_PSPC
if (nResult)
ASSERT(pThreadState->m_pAlternateWndInit == NULL);
pThreadState->m_pAlternateWndInit = NULL;
// WINBUG: Second part of special case for File Open/Save dialog box.
if (bEnableParent)
::EnableWindow(m_ofn.hwndOwner, TRUE);
if (::IsWindow(hWndFocus))
::SetFocus(hWndFocus);
PostModal();
return nResult ? nResult : IDCANCEL;
}
STATUSMicrosoft has confirmed that this is a bug in the Microsoft products that are listed at the beginning of this article.
Modification Type: | Major | Last Reviewed: | 10/24/2003 |
---|
Keywords: | kbBug kbCmnDlg KB245002 |
---|
|