FindWindow by class name not working?
To preface we have a strange requirement that all dialogs must be modeless for an MFC application. There is a particular dialog using region drawing and some custom controls to select dates and times for viewing past and future data per view. I need to be able to close this window when it loses focus, the main app gets 开发者_StackOverflow中文版a system command, etc.
I figured the easiest way to do this would be to register the class like so:
// for CWnd::FindWindow
WNDCLASS wndcls;
SecureZeroMemory(&wndcls, sizeof(WNDCLASS));
wndcls.lpszClassName = L"CTransactionDialog";
wndcls.style = CS_HREDRAW | CS_VREDRAW;
wndcls.lpfnWndProc = AfxWndProc;
wndcls.cbClsExtra = wndcls.cbWndExtra = 0;
wndcls.hInstance = AfxGetInstanceHandle();
wndcls.hIcon = NULL;
#ifndef _WIN32_WCE_NO_CURSOR
wndcls.hCursor = AfxGetApp()->LoadStandardCursor(IDC_ARROW);
#else
wndcls.hCursor = 0;
#endif
wndcls.hbrBackground = (HBRUSH) (COLOR_BACKGROUND + 1);
wndcls.lpszMenuName = NULL;
BOOL retVal = AfxRegisterClass(&wndcls);
if (!retVal)
AfxMessageBox(L"AfxRegisterClass(CTransactionDialog) Failed");
Then later in response to various event handlers and messages where I would want these modeless window or windows to be closed to do something simple like this:
CWnd* pFound = NULL;
while ((pFound = CWnd::FindWindow(L"CTransactionDialog", NULL)) != NULL)
pFound->DestroyWindow();
However despite the registration of the class succeeding and looking at GetRuntimeClass
of the dialog in question in debug and seeing that is matches up as expected the FindWindow
never seems to find or close these modeless dialogs as expected.
What am I doing wrong or is there a better way to go about this?
Update: This is how the dialog is created via a static method on the dialog class. The dialog resource for the id specified in create has the Popup property set which should resolve to WS_POPUP
style under the MFC covers. The dialog shouldn't and doesn't have a parent as far as I knew.
CTransactionDialog* CTransactionDialog::ShowTransactionDialog(const CRect& crCtrlToFloatAbove, UINT dialogID, Itime defaultTime, Itime initialTime)
{
CTransactionDialog* pCTDialog = new CTransactionDialog(crCtrlToFloatAbove, dialogID, defaultTime, initialTime);
pCTDialog->Create(CTransactionDialog::IDD);
pCTDialog->ShowWindow(SW_SHOW);
return pCTDialog;
}
Update: Doh! FindWindowEx
isn't finding anything either.
CWnd::FindWindowEx(AfxGetMainWnd()->GetSafeHwnd(), NULL, L"CTransactionDialog", NULL);
However I have a new plan. I'm just going to make my own window message and handle it on the main frame. I think I can get away with passing a pointer to the dialog as the lParam of the message and then casting it to a CWnd*
then calling DestroyWindow
. It will work for most cases in a very round about way. I may run into trouble with minimizing and maximizing of the main frame window for dialogs that nothing is holding a pointer too but we'll see.
FindWindow
doesn't work with child windows. To find a child window, you can use FindWindowEx
, passing the HWND of the parent window as the first parameter.
Class name denotes NOT the c++ class name - it denotes the window class name. This name was used to register the window by the OS and has nothing to do with the c++ class.
May MSDN enlight you...
CWnd::FindWindow does not search child windows.
Is it possible that the mode less window that you are creating has a parent set and that is the reason why FindWindow doesn't find it ?
Below is the simplest and cleanest solution I could come up with:
BOOL CTransactionDialog::OnNcActivate(BOOL bActive)
{
if (!bActive)
PostMessage(WM_CLOSE);
return CDialog::OnNcActivate(bActive);
}
Not 100% sure about this but I think you need to set your class name in the resource file. You are defining a windows class and creating a dialog class but you aren't linking them. Setting a class name in the WNDCLASS struct won't help unless you actually have a way of linking it to the dialog. If you use the resource file and define the dialog, and class name in there then it should work.
精彩评论