将 MFC 应用程序从 VC6 迁移到 VS2010,现在不为 CPropertyPage 子类调用 OnInitDialog()
我的任务是将我们产品的 UI 迁移到 VS2010。它是一个MFC应用程序,最初是用VC6编写的。我已执行以下步骤:
- 使用 VS2010 转换 VC6 .dsp 修复了
- 由于更严格的 VS2010 编译器导致的编译错误
- 删除了对 VC6 mfc 库和目录的所有项目引用
我的问题是,对于对话框对象(实际上是 CPropertyPage 对象),OnInitDialog () 不会在其他方法之前被调用。这会导致异常,因为 OnInitDialog() 需要设置成员变量。
对话框类 (CPAGEViewDefRecordFields) 是我们自己的 CValidatedPropertyPage 的子类,而 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 程序员!)
谢谢!
I have been tasked with migrating our product's UI to VS2010. It is an MFC app, originally written in VC6. I have performed the following steps:
- Converted the VC6 .dsp using VS2010
- fixed up compile errors due to stricter VS2010 compiler
- Removed all project references to VC6 mfc libs and directories
My problem is that for a dialog object (actually it's a CPropertyPage object), OnInitDialog() is not being called before other methods are. This causes an exception as OnInitDialog() needs to setup member variables.
The dialog class (CPAGEViewDefRecordFields) is subclassed from our own CValidatedPropertyPage, which in turn is derived from the MFC CPropertyPage class. The virtual method OnInitDialog() is present in all subclasses.
In the VS2010 version, when DoModal() is called on the containing property sheet, the OnInitDialog() method of the CPAGEViewDefRecordFields class is not being called. In the VC6 version, it is being called and all works ok.
In VC6, I can see that the message WM_INITDIALOG is sent, and handled in AfxDlgProc(), which in turn then calls OnInitDialog() of the dialog object.
In the VS2010 version, the first message that is processed is WM_NOTIFY, not WM_INITDIALOG.
Unfortunately I have no prior experience in MFC. What I am assuming that something has changed in the behaviour of MFC between the VC6 version and the VS2010 version. However I've not been able to find anything on the net which is similar to this.
Is there another migration step I have missed? Should I have to do something to the resources in the project when doing the migration?
I have checked that the resource is tied to the correct cpp file, as I can double click on the property page, and the IDE takes me to the correct file for the CPAGEViewDefRecordFields class.
If any of you have any ideas, I'd be very grateful.
Thanks!
Chris.
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:
...
UPDATE:
After some debugging, I can see what I think is the problem. However, not being an MFC programmer, I don't understand it.
I can see that OnInitDialog() is being called for the property sheet, and that a WM_INITDIALOG is then sent from the property sheet to the property pages. however, at some point in the windows internals, a WM_NOTIFY message is being sent, so this is the first message that is received, not the expected WM_INITDIALOG
I've highlighted the points on the stack trace, attached - can anyone explain why this is occuring? Is this normal behaviour - should I be catering for this in the future?
I've actually found a workaround, and that's to have an initialised flag, so that no code is executed until OnInitDialog() has been called. This is not the best solution, and I fear is more of a hack, so i would still appreciated any understanding of these messages. (I'm not an MFC programmer by trade you see!)
thanks!
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
OnInitDialog 在所有对话框控件创建之后、对话框显示之前调用。
OnInitDialog is called after all the dialog controls are created and just before the dialog box is displayed.
我想我最好回答这个问题。
答案来自一位SO用户的评论:
“解决方法”是保证对话框准备就绪的唯一方法。
Thought I'd better answer this.
The answer came from a SO user's comment:
The "workaround" is the only way to guarantee that the dialog is ready.