【问题标题】:CMFCPropertyPage::OnKillActive() is called before dialog box is shown在显示对话框之前调用 CMFCPropertyPage::OnKillActive()
【发布时间】:2017-12-10 21:26:57
【问题描述】:

我有一个基于CMFCPropertySheet 类的对话框。我在 CMFCPropertySheet 后代的构造函数中添加了第一页,并设置了外观 (PropSheetLook_Tree) 和一些标志:

// constructor code
m_psh.dwFlags|=PSH_NOAPPLYNOW|PSH_NOCONTEXTHELP;        
m_psh.hwndParent=hwndParent; // hwndParent - parameter passed to the constructor
m_psh.hInstance=GetModuleHandle(L"mydll");
AddPage(&m_FirstPage);  
SetLook(CMFCPropertySheet::PropSheetLook_Tree,190); 

m_FirstPageCMFCPropertyPage 的后代。

我还有其他页面,稍后在CMFCPropertySheet::InitNavigationControl()中添加

我为每个页面覆盖了CMFCPropertyPage::OnKillActive(),以检查页面上输入的数据是否正确。

问题是第一页的CMFCPropertyPage::OnKillActive()m_FirstPage)被调用了两次。第一次(意外)它在我的对话框甚至变得可见之前被调用。第二次 - 正如预期的那样 - 当用户切换页面或单击“确定”按钮时调用它。对于其他页面,OnKillActive() 仅在单击确定或切换页面时调用。

问题是在第一次m_FirstPage.OnKillActive() 调用期间,第一页上还没有数据。所以我的代码显示了一条错误消息。

OnKillActive() 在第一页被调用两次是否正常?它总是这样调用两次吗?

目前,我在我的OnKillActive() 中调用IsWindowVisible(),如果它不可见,我不会检查页面上的数据。这种方法正确吗?

(代码用Visual Studio 2008编写)

更新:

第一次意外 OnKillActive() 调用的调用堆栈

CFirstPage::OnKillActive()
CPropertyPage::OnNotify(unsigned int wParam=0, long lParam=1196668, long * pResult=0x00123fc4)
CWnd::OnWndMsg(unsigned int message=78, unsigned int wParam=0, long lParam=1196668, long * pResult=0x00123ffc)
CWnd::WindowProc(unsigned int message=78, unsigned int wParam=0, long lParam=1196668)
AfxCallWndProc(CWnd * pWnd=0x00129370, HWND__ * hWnd=0x000a0348, unsigned int nMsg=78, unsigned int wParam=0, long lParam=1196668)
AfxWndProc(HWND__ * hWnd=0x000a0348, unsigned int nMsg=78, unsigned int wParam=0, long lParam=1196668)
// many calls that look like user32.dll!7e368734() 
ATL::CTraceFileAndLineInfo::operator()(unsigned long dwCategory=272, unsigned int nLevel=590706, const wchar_t * pszFmt=0x001d4008, ...)
// many calls that look like user32.dll!7e368734() 
CComCtlWrapper::_PropertySheetW(const _PROPSHEETHEADERW_V2 * unnamed1=0x00124f30)
AfxPropertySheetW(const _PROPSHEETHEADERW_V2 * unnamed1=0x00124f30)
CPropertySheet::DoModal()
OpenSettingsDlgBox(HWND__ * hwndParent=0x00040346)
// many calls that look like user32.dll!7e368734() 

OpenSettingsDlgBox() 是一个 dll 函数。它是从另一个非 MFC 应用程序调用的

【问题讨论】:

  • 或者可以针对 NULL 测试 GetSafeHwnd()。
  • 给我们第一个意外 OnKillActive 调用的调用堆栈!
  • @xMRi 我已经添加了调用堆栈
  • 必须更多...最后导致 OnKillActive 的一切都很有趣...
  • @xMRi 我已经更新了这个问题。显示所有构造函数代码。扩展调用堆栈。并展示了我如何创建和打开对话框

标签: windows winapi mfc


【解决方案1】:

我敢打赌,这是因为在 CPropertySheet 派生类的 OnInitDialog 函数中调用了 SetActivePage,或者与 PSM_SETCURSEL 等效的 SendMessage() 调用。

您应该 (a) 删除对 SetActivePage 或 SendMessage(PSM_SETCURSEL) 的调用,并将所需的初始选项卡设置为第一个,或者 (b) 在 CPropertyPage 派生类的构造函数中设置有效的初始数据,或者(c) 在 CPropertyPage 派生类中设置一个标志来禁止验证,直到它被正确初始化。

【讨论】:

  • 我已经注释掉了我在CMFCPropertySheetCMFCPropertyPage 后代中覆盖的所有方法。除了构造函数,我现在只添加 1 页,除了OnKillActive。当我调用DoModal 时,仍然调用OnKillActive。我还注意到 CMFCPropertySheet 构造函数将 UINT iSelectPage = 0 作为默认参数。所以也许 SetActivePage 是由 MFC 设计调用的...你能告诉我,CPropertyPage 设置标志以禁止验证的最佳方法是什么,就像你在选项 (c) 中建议的那样?
猜你喜欢
  • 1970-01-01
  • 2012-06-14
  • 1970-01-01
  • 2010-12-05
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多