2013-03-05 50 views
1

我在MFC中有一个简单的测试应用程序,但它不起作用。消息处理程序根本不会被调用。该窗口接收消息,但不调用在消息映射中注册的处理程序。正在生成无效的mfc消息映射

这是一个标准的mfc单个对话框应用程序,它有一个巨大的按钮块,并在推送库时对库进行各种调用。但它不叫处理程序。

我跟踪了它,消息映射似乎已损坏。有标准的声明,如:

BEGIN_MESSAGE_MAP(CommLib_test_x86Dlg, CDialog) 
    ON_WM_SYSCOMMAND() 
    ON_WM_PAINT() 
    ON_WM_QUERYDRAGICON() 
    ON_BN_CLICKED(IDCANCEL, &CommLib_test_x86Dlg::OnBnClickedCancel) 
    ON_BN_CLICKED(IDOK, &CommLib_test_x86Dlg::OnBnClickedOk) 
    ON_BN_CLICKED(IDC_BUTTON1, &CommLib_test_x86Dlg::OnBnClickedButton1) 
    ON_BN_CLICKED(IDC_BUTTON2, &CommLib_test_x86Dlg::OnBnClickedButton2) 
    ON_BN_CLICKED(IDC_BUTTON3, &CommLib_test_x86Dlg::OnBnClickedButton3) 
    ON_BN_CLICKED(IDC_BUTTON4, &CommLib_test_x86Dlg::OnBnClickedButton4) 
    ON_BN_CLICKED(IDC_BUTTON5, &CommLib_test_x86Dlg::OnBnClickedButton5) 
    // many more buttons, but I commented the rest out for test 
END_MESSAGE_MAP() 

如果我把一个断点第一ON_WM_ *(即进入GetThisMessageMap静态方法),并期待在消息映射的内容,第一项是正确的,但其余大部分是0 数组大小并不对应实际定义。作为

[0] {nMessage=274 nCode=0 nID=0 ...} 
[1] {nMessage=0 nCode=0 nID=0 ...} 
[2] {nMessage=0 nCode=19 nID=4206192 ...} 
[3] {nMessage=55 nCode=0 nID=0 ...} 
[4] {nMessage=0 nCode=0 nID=0 ...} 
[5] {nMessage=0 nCode=0 nID=0 ...} 
[6] {nMessage=0 nCode=0 nID=0 ...} 
[7] {nMessage=0 nCode=0 nID=0 ...} 
[8] {nMessage=0 nCode=0 nID=0 ...} 
[9] {nMessage=0 nCode=0 nID=0 ...} 
[10] {nMessage=0 nCode=0 nID=0 ...} 
[11] {nMessage=0 nCode=0 nID=0 ...} 
[12] {nMessage=0 nCode=0 nID=0 ...} 
[13] {nMessage=0 nCode=0 nID=0 ...} 
[14] {nMessage=0 nCode=0 nID=0 ...} 
[15] {nMessage=0 nCode=0 nID=0 ...} 

代码编译罚款,没有警告或任何调试器报告的价值。

重要的是要指出,该应用程序是巨大的项目集合的一部分,并且这些项目共享编译器选项。我们实际上生成了visual studio项目,但是在我们使用.vsprops文件之前。我没有使用该项目一段时间,可以想象,编译器标志已经改变了。

回答

2

好吧,我找到了。编译器标志确实改变了。可怕的/vmg标志被添加(我们在其他一些库中使用它,并在重构期间传播到不正确的项目)。此标志与MFC不兼容,因为它会更改消息映射项目的定义。长篇小说:为了节省一些空间,微软决定,指向成员的指针将根据类是使用单个,多个还是虚拟继承而有所不同。尽管理论上看起来很好,但在实践中它有以下问题:

  • 指向不完整类型成员的指针(在C++中是合法的)。

我怀疑这也导致当问题:需要被转换为指针,用更简单的指针基类的成员

  • 指针更复杂的指针类的成员。

该文档没有提到这种情况,但它很明显。这正是MFC所做的。

规范(ISO/IEC 14882-2011)仅要求static_cast指向基本成员,如果基本不是虚拟继承的,但在Microsoft编译器中,即使基类只具有线性继承,它也不起作用,但该子类具有多重继承,并且该基类不是第一类。那么,大家都知道编译器已经不合格了。