Search code examples
c++inheritancemfccdialog

Creating a new base CDialogEx derived class


I have a lot of CDialogEx derived classes that do something like this in OnInitDialog:

CMeetingScheduleAssistantApp::InitialiseResizeIcon(m_bmpResize, m_lblResize, this);
CMeetingScheduleAssistantApp::RestoreWindowPosition(_T("PublisherDB"), this, true);

Then, I have the following added to each derived dialog class:

int CPublishersDatabaseDlg::OnCreate(LPCREATESTRUCT lpCreateStruct)
{
    if (CDialogEx::OnCreate(lpCreateStruct) == -1)
        return -1;

    // Save Initial window size to m_rcInit
    GetWindowRect(&m_rcInit);

    return 0;
}

void CPublishersDatabaseDlg::OnGetMinMaxInfo(MINMAXINFO* lpMMI)
{
    // Set the minimum window size to initial size.
    lpMMI->ptMinTrackSize.x = m_rcInit.Width();
    lpMMI->ptMinTrackSize.y = m_rcInit.Height();

    CDialogEx::OnGetMinMaxInfo(lpMMI);
}

void CPublishersDatabaseDlg::OnClose()
{
    CMeetingScheduleAssistantApp::SaveWindowPosition(_T("PublisherDB"), this);
    CDialogEx::OnClose();
}

The only thing that is different for each dialog is the phrase that is used for saving the window position.

I want to have a based CDialogEx class that I can inherit from that will perform the above actions. I have looked on SO and seem some questions and creating a CDialog class and inheriting from another CDialog class. But this class I want to create is more generic. Effectively to be used as a base instead of CDialogEx.

Can this be done? Am I over-complicating this?

Problems

Why I try to create a new class, derived from CDialogEx:

Setup

Result

Error

I don't know if it is because it requires a dialog ID as stated here.

Classes such as CDialog, CFormView, or CPropertyPage, which require a dialog ID.

So I can't work out the correct way to create a base CDialogEx class for use in all my other dialog classes.

Update

I created this code and it tells me that CResizingDialog is not a class or a namespace:

#include "ResizingDialog.h"
#include "resource.h"
#include "stdafx.h"

IMPLEMENT_DYNAMIC(CResizingDialog, CDialogEx)

CResizingDialog::CResizingDialog(const CString& strWindowID, UINT nIDTemplate, CWnd* pParent = nullptr)
    : m_strWindowID(strWindowID), CDialogEx(nIDTemplate, pParent)
{

}

CResizingDialog::~CResizingDialog()
{
}

void CResizingDialog::DoDataExchange(CDataExchange* pDX)
{
    CDialogEx::DoDataExchange(pDX);
}

BEGIN_MESSAGE_MAP(CResizingDialog, CDialogEx)
    ON_WM_CREATE()
    ON_WM_GETMINMAXINFO()
    ON_WM_CLOSE()
END_MESSAGE_MAP()


int CResizingDialog::OnCreate(LPCREATESTRUCT lpCreateStruct)
{
    if (CDialogEx::OnCreate(lpCreateStruct) == -1)
        return -1;

    // Save Initial window size to m_rcInit
    GetWindowRect(&m_rcInit);

    return 0;
}


void CResizingDialog::OnGetMinMaxInfo(MINMAXINFO* lpMMI)
{
    // Set the minimum window size to initial size.
    lpMMI->ptMinTrackSize.x = m_rcInit.Width();
    lpMMI->ptMinTrackSize.y = m_rcInit.Height();

    CDialogEx::OnGetMinMaxInfo(lpMMI);
}


void CResizingDialog::OnClose()
{
    SaveWindowPosition(m_strWindowID, this);

    CDialogEx::OnClose();
}

Solution

  • Based on the comments encouraging me to try to create the class manually, I have it working:

    #include "stdafx.h"
    #include "resource.h"
    #include "ResizingDialog.h"
    
    IMPLEMENT_DYNAMIC(CResizingDialog, CDialogEx)
    
    CResizingDialog::CResizingDialog(const CString& strWindowID, UINT nIDTemplate, CWnd* pParent /* nullptr */, bool bOnlyStorePosition /* false */)
        : m_strWindowID(strWindowID),
          m_bOnlyStorePosition(bOnlyStorePosition), CDialogEx(nIDTemplate, pParent)
    {
    
    }
    
    CResizingDialog::~CResizingDialog()
    {
    }
    
    void CResizingDialog::DoDataExchange(CDataExchange* pDX)
    {
        CDialogEx::DoDataExchange(pDX);
    }
    
    BEGIN_MESSAGE_MAP(CResizingDialog, CDialogEx)
        ON_WM_CREATE()
        ON_WM_GETMINMAXINFO()
        ON_WM_CLOSE()
    END_MESSAGE_MAP()
    
    int CResizingDialog::OnCreate(LPCREATESTRUCT lpCreateStruct)
    {
        if (CDialogEx::OnCreate(lpCreateStruct) == -1)
            return -1;
    
        // Save Initial window size to m_rcInit
        GetWindowRect(&m_rcInit);
    
        return 0;
    }
    
    void CResizingDialog::OnGetMinMaxInfo(MINMAXINFO* lpMMI)
    {
        // Set the minimum window size to initial size.
        lpMMI->ptMinTrackSize.x = m_rcInit.Width();
        lpMMI->ptMinTrackSize.y = m_rcInit.Height();
    
        CDialogEx::OnGetMinMaxInfo(lpMMI);
    }
    
    void CResizingDialog::OnClose()
    {
        SaveWindowPosition(m_strWindowID, this);
    
        CDialogEx::OnClose();
    }
    
    void CResizingDialog::OnOK()
    {
        SaveWindowPosition();
        CDialogEx::OnOK();
    }
    
    BOOL CResizingDialog::OnInitDialog()
    {
        CDialogEx::OnInitDialog();
    
        if(!m_bOnlyStorePosition)
            InitialiseResizeIcon(m_bmpResize, m_lblResize, this);
    
        RestoreWindowPosition(m_strWindowID, this, true);
    
        return TRUE;  // return TRUE unless you set the focus to a control
                      // EXCEPTION: OCX Property Pages should return FALSE
    }
    

    I decided to duplicate the methods that were in the app class into this new dialog class instead. Eventually they can be removed from the app class. The only thing I also had to do was #include my resource file because the image needs to know the value of the resource ID.

    This is the ResizingDialog.h header:

    #pragma once
    #include <afxwin.h>
    
    class CResizingDialog : public CDialogEx
    {
        DECLARE_DYNAMIC(CResizingDialog)
    
    public:
        CResizingDialog(const CString& phrase, UINT nIDTemplate, CWnd* pParent = nullptr, bool bOnlyStorePosition = false); // Constructor
        virtual ~CResizingDialog(); // Destructor
    
    protected:
        void OnOK() override;
        virtual void DoDataExchange(CDataExchange* pDX) override;    // DDX/DDV support
        void SaveWindowPosition(void) { SaveWindowPosition(m_strWindowID, this); }
    
    public:
        BOOL OnInitDialog() override;
        afx_msg int OnCreate(LPCREATESTRUCT lpCreateStruct);
        afx_msg void OnGetMinMaxInfo(MINMAXINFO* lpMMI);
        afx_msg void OnClose();
        DECLARE_MESSAGE_MAP()
    
    private:
        CBitmap m_bmpResize;
        CStatic m_lblResize;
        CRect m_rcInit;
        CString m_strWindowID;
        bool m_bOnlyStorePosition;
    
        void RestoreWindowPosition(CString strWindow, CWnd* pWindow, bool bOverrideState = false);
        void SaveWindowPosition(CString strWindow, CWnd* pWindow);
        void InitialiseResizeIcon(CBitmap& rBmpResize, CStatic& rLblResize, CWnd* pDialog);
    };
    

    The actual functions SaveWindowPosition, RestoreWindowPosition and InitialiseResizeIcon are not shown here as they don't directly relate to the issue.