我不熟悉 ATL/Win32 UI 编程,我正在尝试修复关闭 ATL 对话框时发生的访问冲突。
主窗口有以下消息映射:
BEGIN_MSG_MAP(CMyWindow)
MESSAGE_HANDLER(WM_CLOSE, OnClose)
MESSAGE_HANDLER(WM_DESTROY, OnDestroy)
COMMAND_ID_HANDLER(ID_POPUP_EXIT, OnExit)
COMMAND_ID_HANDLER(ID_POPUP_LOGON, OnLogon)
COMMAND_ID_HANDLER(ID_POPUP_LOGOFF, OnLogoff)
COMMAND_ID_HANDLER(ID_POPUP_HELP, OnHelp)
COMMAND_ID_HANDLER(ID_POPUP_ABOUT, OnAbout)
COMMAND_ID_HANDLER(ID_POPUP_DATANETSETTINGS, OnConfigure)
COMMAND_ID_HANDLER(ID_POPUP_TRANSFERSTATUS, OnTransferStatus)
// etc...
OnTransferStatus 启动一个模态对话框:
LRESULT OnTransferStatus(WORD /*wNotifyCode*/, WORD wID, HWND /*hWndCtl*/, BOOL& /*bHandled*/)
{
HWND hc;
hc = FindWindow(NULL, L"MyApp Transfer Status");
if(hc)
{
::ShowWindow(hc, SW_RESTORE);
::SetForegroundWindow(hc);
}
else
{
CStatusPopup dlg;
dlg.DoModal(); // <-- Here
这CStatusPopup
只是其中之一:class CStatusPopup : public CAxDialogImpl<CStatusPopup>{...}
当我关闭 StatusPopup 窗口时,我最终出现在弹出窗口消息映射中,并且此函数运行:
LRESULT OnClose(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
{
EndDialog(IDCANCEL);
return 0;
}
EndDialog 应该干净地关闭对话窗口。但是,我似乎将 NULL hwnd 传递给对话框的 WindowProc。这发生在阻塞 DoModal 调用下的 ATL/Win32 代码深处。谁能建议我如何调试通过 NULL hwnd 的消息来自何处?
崩溃在这里:
00000000`001de6f0 00000000`7741c3c1 : 00000000`00000000 00000000`00000000 00000000`0081d1d0 00000000`00000001 : MyApp_Tray!ATL::CWindowImplBaseT<WTL::CEditT<ATL::CWindow>,ATL::CWinTraits<1442840576,0> >::WindowProc+0x81 [c:\program files (x86)\microsoft visual studio 10.0\vc\atlmfc\include\atlwin.h @ 3503]
00000000`001de790 00000000`7741a01b : 00000000`00000000 00000000`00330d20 00000000`00000000 00000000`00000000 : user32!UserCallWinProcCheckWow+0x1ad
00000000`001de850 00000000`7741a061 : 00000000`00000014 00000000`77412094 00000000`0081d1f8 0000002c`00000001 : user32!DispatchClientMessage+0xc3
00000000`001de8b0 00000000`776af5e5 : 00000000`00000000 00000000`00000000 00000000`776836a8 00000000`00000001 : user32!_fnDWORD+0x2d
00000000`001de910 00000000`7740f5ba : 00000000`7742762b 00000000`000202cc 00000000`0081d1d0 00000000`00000001 : ntdll!KiUserCallbackDispatcherContinue (TrapFrame @ 00000000`001de7d8)
00000000`001de998 00000000`7742762b : 00000000`000202cc 00000000`0081d1d0 00000000`00000001 00000000`00000001 : user32!ZwUserDestroyWindow+0xa
00000000`001de9a0 00000000`774274a5 : 00000000`000202cc 00000001`3f99b800 00000000`00000001 00000000`000202cc : user32!DialogBox2+0x2ec
00000000`001dea30 00000000`7742751a : 00000001`3fce5f00 00000000`000202cc 00000001`3f99b800 00000001`3f99b800 : user32!InternalDialogBox+0x135
00000000`001dea90 00000000`77427558 : 00000000`00000000 00000001`3f980000 00000001`3fce5f00 00000000`000202cc : user32!DialogBoxIndirectParamAorW+0x58
00000000`001dead0 00000001`3f9a3d0b : 00000000`00000004 00000000`00000070 ffffffff`ffffffff 00000000`001dec30 : user32!DialogBoxIndirectParamW+0x18
00000000`001deb10 00000001`3f99aca2 : 00000000`00008026 00000000`001dec20 00000000`001dec90 00000000`00008026 : MyApp_Tray!ATL::AtlAxDialogCreateT<wchar_t const * __ptr64,ATL::_AtlDialogBoxIndirectParamHelper,&DialogBoxIndirectParamW>+0xbb [c:\program files (x86)\microsoft visual studio 10.0\vc\atlmfc\include\atlhost.h @ 2714]
00000000`001deb60 00000001`3f995b03 : 00000000`00000000 00000000`001df270 00000000`001dec90 00000000`001df270 : MyApp_Tray!ATL::CAxDialogImpl<CStatusPopup,ATL::CWindow>::DoModal+0x82 [c:\program files (x86)\microsoft visual studio 10.0\vc\atlmfc\include\atlwin.h @ 4055]
00000000`001deb90 00000001`3f9ade73 : 00000000`00000000 00000000`001df270 00000000`001df168 000007ff`fffdd000 : MyApp_Tray!CDataNetWindow::ProcessWindowMessage+0x293 [d:\buildroot\26\datanow\datanow_features_fr1\sources\orca\datanet_tray\mainwnd.h @ 40]
00000000`001df000 00000000`7741c3c1 : 00000000`00000000 00000000`00000000 00000000`001df2e0 00000000`00000001 : MyApp_Tray!ATL::CWindowImplBaseT<WTL::CEditT<ATL::CWindow>,ATL::CWinTraits<1442840576,0> >::WindowProc+0x83 [c:\program files (x86)\microsoft visual studio 10.0\vc\atlmfc\include\atlwin.h @ 3508]
00000000`001df0a0 00000000`7741c60a : 00000000`001df2d0 00000000`00330fe0 00000000`01dae740 00000000`0083bf10 : user32!UserCallWinProcCheckWow+0x1ad
00000000`001df160 00000001`3f998236 : 00000001`3f9bada0 00000001`3f9bada0 00000000`00330fe0 00000000`00000000 : user32!DispatchMessageWorker+0x3b5
00000000`001df1e0 00000001`3f9b22b6 : 00000000`00000001 00000000`00000000 00000000`00000000 00000000`776fdffa : MyApp_Tray!wWinMain+0x886 [d:\buildroot\26\datanow\datanow_features_fr1\sources\orca\datanet_tray\tray.cpp @ 356]
00000000`001df8b0 00000000`76f9f34d : 00000000`00000000 00000000`00000000 00000000`00000000 00000000`00000000 : MyApp_Tray!__tmainCRTStartup+0x166 [f:\dd\vctools\crt_bld\self_64_amd64\crt\src\crtexe.c @ 547]
00000000`001df960 00000000`77692ca1 : 00000000`00000000 00000000`00000000 00000000`00000000 00000000`00000000 : kernel32!BaseThreadInitThunk+0xd
00000000`001df990 00000000`00000000 : 00000000`00000000 00000000`00000000 00000000`00000000 00000000`00000000 : ntdll!RtlUserThreadStart+0x1d
这是因为在此 ATL 代码中 hwnd 为 NULL 引起的:
template <class TBase, class TWinTraits>
LRESULT CALLBACK CWindowImplBaseT< TBase, TWinTraits >::WindowProc(
_In_ HWND hWnd,
_In_ UINT uMsg,
_In_ WPARAM wParam,
_In_ LPARAM lParam)
{
CWindowImplBaseT< TBase, TWinTraits >* pThis = (CWindowImplBaseT< TBase, TWinTraits >*)hWnd;
// set a ptr to this message and save the old value
_ATL_MSG msg(pThis->m_hWnd, uMsg, wParam, lParam);
const _ATL_MSG* pOldMsg = pThis->m_pCurrentMsg;
pThis->m_pCurrentMsg = &msg;
// pass to the message map to process
LRESULT lRes = 0;
BOOL bRet = pThis->ProcessWindowMessage(pThis->m_hWnd, uMsg, wParam, lParam, lRes, 0);