从VC6迁移到VS2010的MFC应用程序,现在OnInitDialog()没有调用CPropertyPage子类

时间:2011-08-30 05:53:31

标签: c++ visual-studio-2010 visual-c++ mfc vc6

我的任务是将产品的UI迁移到VS2010。它是一个MFC应用程序,最初用VC6编写。我执行了以下步骤:

  • 使用VS2010转换VC6 .dsp
  • 修复了由于更严格的VS2010编译器导致的编译错误
  • 删除了对VC6 mfc库和目录的所有项目引用

我的问题是,对于一个对话框对象(实际上它是一个CPropertyPage对象),OnInitDialog()在其他方法之前没有被调用。这会导致异常,因为OnInitDialog()需要设置成员变量。

对话框类(CPAGEViewDefRecordFields)是我们自己的CValidatedPropertyPage的子类,后者又是从MFC CPropertyPage类派生的。虚方法OnInitDialog()存在于所有子类中。

在VS2010版本中,当在包含属性表上调用DoModal()时,不会调用CPAGEViewDefRecordFields类的OnInitDialog()方法。在VC6版本中,它被调用,一切正常。

在VC6中,我可以看到消息WM_INITDIALOG被发送,并在AfxDlgProc()中处理,然后反过来调用对话框对象的OnInitDialog()。

在VS2010版本中,处理的第一条消息是WM_NOTIFY,而不是WM_INITDIALOG。

不幸的是我没有MFC的经验。我假设VC6版本和VS2010版本之间的MFC行为发生了变化。但是,我无法在网上找到与此相似的任何内容。

我错过了另一个迁移步骤吗?在进行迁移时,我是否应该对项目中的资源做些什么?

我已检查资源是否绑定到正确的cpp文件,因为我可以双击属性页面,IDE会将我带到CPAGEViewDefRecordFields类的正确文件。

如果你们有任何想法,我将非常感激。

谢谢! 克里斯。

class CPAGEViewDefRecordFields : public CValidatedPropertyPage
{
public:

   // Construction

   CPAGEViewDefRecordFields(CWnd*         pParent,
                           CXpViewProp*  pViewProp,
                           CFont*        pFont      = NULL,
                           UINT          nIDCaption = 0,
                           BOOL          bSumOpRequired = TRUE,
                           BOOL          bMinMaxRequired = TRUE,
                           BOOL          bAllRecords = TRUE,
                           BOOL          bShowInitSel = TRUE,
                           XLong         lLimits = 0,
                           BOOL          bSortSelTree = TRUE,
                           CXpThreshBaseLogProp* pThreshLogProp = NULL);

  ~CPAGEViewDefRecordFields();

  // Dialog Data
  //{{AFX_DATA(CPAGEViewDefRecordFields)
  enum { IDD = IDD_VIEW_DEF_RECORD_FIELDS };
  //}}AFX_DATA

  // Overrides
  // ClassWizard generate virtual function overrides
  //{{AFX_VIRTUAL(CPAGEViewDefRecordFields)
  virtual BOOL OnInitDialog();
  //}}AFX_VIRTUAL

 virtual BOOL OnSetActive();
 virtual BOOL OnKillActive();
 virtual void OnOK();

protected:

  ... 

  // Generated message map functions
  //{{AFX_MSG(CPAGEViewDefRecordFields)
  afx_msg void OnPbRemove();
  afx_msg void OnPbAdd();
  afx_msg void OnDblclkAvailableFields(NMHDR* pNMHDR, LRESULT* pResult);
  afx_msg void OnDblclkSelectedFields(NMHDR* pNMHDR, LRESULT* pResult);
  //}}AFX_MSG
  DECLARE_MESSAGE_MAP()

private:
  ...

更新:

经过一些调试后,我可以看到我认为的问题。但是,我不是MFC程序员,我不明白。

我可以看到正在为属性表调用OnInitDialog(),然后WM_INITDIALOG从属性表发送到属性页。但是,在Windows内部的某个时刻,正在发送WM_NOTIFY消息,因此这是收到的第一条消息,而不是预期的WM_INITDIALOG

我已经突出显示堆栈跟踪上的点,附加 - 有人可以解释为什么会发生这种情况吗?这是正常的行为 - 我将来应该为此做好准备吗?

我实际上找到了一种解决方法,那就是有一个初始化标志,这样在调用OnInitDialog()之前不会执行任何代码。这不是最好的解决方案,我担心更多的是黑客攻击,所以我仍然会理解对这些消息的理解。 (我不是你看到的MFC程序员!)

谢谢!

stack trace showing WM messages

2 个答案:

答案 0 :(得分:0)

在创建所有对话框控件之后且在显示对话框之前调用OnInitDialog。

答案 1 :(得分:0)

以为我最好回答这个问题。

答案来自SO用户的评论:

  

使用初始化标志的解决方法与我的做法相同。看起来树视图在创建树视图时发送通知但您的对话框尚未就绪。您可能不知道其他控件何时执行相同的操作,因此您需要初始化标志

“解决方法”是保证对话框准备就绪的唯一方法。