Sossenbinder Sossenbinder - 2 months ago 7
C++ Question

What's wrong with my attempt at subclassing CButton?

I tried to create a subclassed control for the first time, but I feel like I did something wrong. The control is a Button, which I placed in the designer. This is its class:

class TTTField : public CButton
{
public:
BEGIN_MSG_MAP_EX(TTTField)
MSG_WM_INITDIALOG(OnInitDialog);
END_MSG_MAP()

TTTField operator=(const CWindow& btn);

private:

const BOOL OnInitDialog(const CWindow wndFocus, const LPARAM lInitParam);

};


Nothing fancy so far.

However, I can't really achieve to receive windows messages in this control. This is bad, considering the main reason for trying to subclass a control was the fact that this should be a reusable class with reusable, custom Paint behaviour. I want to overwrite certain message handlers, while keeping those I didn't explicitely ask for to the usual CButton routine.

As you can see, I implemented a message map, but the messages are just not coming in.

This is how I tried to setup the instance of this class:

TTTField fld;


is a member variable of my main dialog class. In this class I added the following DDX_MAP:

BEGIN_DDX_MAP(TTTMainDialog)
DDX_CONTROL_HANDLE(IDC_BTN, fld)
END_DDX_MAP()


with IDC_BTN being the id of the button on the designer.

In the assignment operator overload for TTTField I have the following:

TTTField TTTField::operator=(const CWindow& btn)
{
Attach(btn);
return *this;
}


I feel like this operator overload might be the source of my problems, but I just can't manage to find a website which is properly explaining the whole topic without using code which seems outdated for like 20 years.

What am I doing wrong here? I am really lost right now.

Answer

The button class should be defined as follows:

class TTTField : public CWindowImpl<TTTField, CButton>
{
protected:
    BEGIN_MSG_MAP_EX(TTTField)
        MSG_WM_LBUTTONDOWN(OnLButtonDown)
    END_MSG_MAP()

protected:
    LRESULT OnLButtonDown(UINT, CPoint)
    {
        //Edit: this override is meant for testing the subclass only
        //it's insufficient for handling button clicks
        MessageBox(L"Testing override...");
        return 0;
    }
};

Override dialog box's OnInitDialog, call SubclassWindow to subclass the button:

class TTTMainDialog: public CDialogImpl<CMainDialog>
{
public:
    enum { IDD = IDD_MYDIALOG };
    BEGIN_MSG_MAP(TTTMainDialog)
        MESSAGE_HANDLER(WM_INITDIALOG, OnInitDialog)
    END_MSG_MAP()

    TTTField fld;
    LRESULT OnInitDialog(UINT nMessage, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
    {
        fld.SubclassWindow(GetDlgItem(IDC_BTN));
        return 0;
    }
};

Edit, for initialization

class TTTField : public CWindowImpl<TTTField , CButton>
{
public:
    void Create(CWindow *wnd, int id)
    {
        SubclassWindow(wnd->GetDlgItem(id));
        //add initialization here
    }
    ...
}

Then to create the button:

//fld.SubclassWindow(GetDlgItem(IDC_BTN));
fld.Create(this, IDC_BTN); //<== use this instead