【问题标题】:OnInitDialog not called in descendant of CDialogOnInitDialog 未在 CDialog 的后代中调用
【发布时间】:2015-09-23 16:45:11
【问题描述】:

我有一个派生自 CDialog (CNotificationDialog) 的类,它是在选择“添加类”选项时由 Visual Studio 自动生成的。

我还有另一个派生自 CNotificationDialog (CWebNotificationDialog) 的类。

我的代码是这样的:

CNotificationDialog* dlg = new CWebNotificationDialog();
dlg->Display();

显示对话框但未调用 CWebNotificationDialog::OnInitDialog 方法。仅调用 CNotificationDialog::OnInitDialog 方法。

在你问之前,是的,它被宣布为虚拟的。 我还尝试添加 DECLARE_DYNAMIC、BEGIN_MESSAGE_MAP 和所有其他自动生成的宏,但没有成功。

我做错了什么?

这就是 CNotificationDialog::OnInitDialog 的样子。

BOOL C1NotificationDialog::OnInitDialog()
{
   CDialog::OnInitDialog();

   HICON hIconBig = (HICON)LoadImage(AfxGetResourceHandle(), MAKEINTRESOURCE(IDR_MAINFRAME), IMAGE_ICON, 32, 32, LR_SHARED); 
   CStatic *pPictureCtrl = (CStatic*)GetDlgItem(IDS_NOTIFICATION_DLG_LOGO);
   pPictureCtrl->SetIcon(hIconBig);

   return TRUE;
}

它是这样声明的:

protected:
virtual BOOL OnInitDialog();

【问题讨论】:

  • 你做错了。你应该使用基类指针,这是一个常见的场景。我不知道你为什么对基类对象使用派生类指针,对我来说听起来很可疑。
  • 没有CDialog::Display
  • 是的,这是必要的。为 CNotificationDialog 发布 OnInitDialog。
  • 我已经更新了描述。

标签: c++ mfc cdialog


【解决方案1】:

我刚刚遇到了同样的问题,很困惑,发现就我而言,问题是这样的:

如果您在类构造函数中调用成员函数 Create() 函数,按照 MSDN 中的建议,它必须进入派生类构造函数。根据这个问题,应避免从基类构造函数中调用虚函数:

Calling virtual functions inside constructors

我发现在下面的代码中,派生类的对象在实例化时没有调用派生类OnInitDialog():

class BaseDialog : public CDialog{
public:
    BaseDialog(UINT resourceID, CWnd *pParent) : CDialog(resourceID, pParent){
        Create(resourceID, pParent);
    };
};

class DerivedDialog : public BaseDialog{
public:
   DerivedDialog(UINT resourceID, CWnd *pParent) : BaseDialog(resourceID, pParent){};

    BOOL OnInitDialog(){ /* NOT CALLED */};
};

通过从派生类构造函数调用 Create(),派生类 OnInitDialog() 被按预期调用:

class BaseDialog : public CDialog{
public:
    BaseDialog(UINT resourceID, CWnd *pParent) : CDialog(resourceID, pParent){
      //  Create(resourceID, pParent);
    };
};

class DerivedDialog : public BaseDialog{
public:
   DerivedDialog(UINT resourceID, CWnd *pParent) : BaseDialog(resourceID, pParent){
        Create(resourceID, pParent);
    };

    BOOL OnInitDialog(){ /* This was called */ };
};

【讨论】:

    【解决方案2】:

    您调用的是 CDialog 的基类,不是从 CWebNotificationDialog 派生的 OnInitDialog。试试……

    BOOL C1NotificationDialog::OnInitDialog()
    {
       CWebNotificationDialog::OnInitDialog();
    

    【讨论】:

    • 我不明白。我该怎么做?
    • 这不是它的工作原理。 CWebNotificationDialog 派生自 CNotificationDialog。 CNotificationDialog 对其后代一无所知。如果我从 C1NotificationDialog 派生另一个类怎么办?那么 C1NotificationDialog::OnInitDialog() 的代码会怎样呢?这个想法是根据 dlg 指向的内容调用正确的 OnInitDialog 。这就是多态性。
    • @conectionist 您发布的代码示例似乎与 “这就是 CNotificationDialog::OnInitDialog 的样子” 无关。因此,我的困惑。那个代码正确吗?
    • @conectionist 你能贴出类定义(来自头文件),以便准确描述类派生吗?你说...“我还有另一个派生自 CNotificationDialog (CWebNotificationDialog) 的类。” 但是,代码示例显示 CNotificationDialog 被用作指针。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2011-07-02
    • 1970-01-01
    • 1970-01-01
    • 2013-03-10
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多