我试图第一次创建一个分类控制,但我觉得我做错了什么。 该控件是一个Button,我将它放在设计器中。 这是它的课程:
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); };目前为止没有什么特别。
但是,我无法真正实现在此控件中接收窗口消息。 这很糟糕,考虑到试图对控件进行子类化的主要原因是这应该是具有可重复使用的自定义Paint行为的可重用类。 我想覆盖某些消息处理程序,同时保留那些我没有明确要求通常的CButton例程。
正如你所看到的,我实现了一个消息映射,但是这些消息不会进入。
这是我试图设置这个类的实例的方式:
TTTField fld;是我的主对话框类的成员变量。 在这个类中,我添加了以下DDX_MAP:
BEGIN_DDX_MAP(TTTMainDialog) DDX_CONTROL_HANDLE(IDC_BTN, fld) END_DDX_MAP()IDC_BTN是设计器上按钮的ID。
在TTTField的赋值运算符重载中,我有以下几点:
TTTField TTTField::operator=(const CWindow& btn) { Attach(btn); return *this; }我觉得这个操作符过载可能是我的问题的根源,但我无法设法找到一个能正确解释整个主题的网站,而无需使用似乎已过时20年的代码。
我在这里做错了什么? 我现在真的迷路了。
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.
最满意答案
按钮类应该定义如下:
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; } };重写对话框的OnInitDialog ,调用SubclassWindow来为按钮创建SubclassWindow类:
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; } };编辑,进行初始化
class TTTField : public CWindowImpl<TTTField , CButton> { public: void Create(CWindow *wnd, int id) { SubclassWindow(wnd->GetDlgItem(id)); //add initialization here } ... }然后创建按钮:
//fld.SubclassWindow(GetDlgItem(IDC_BTN)); fld.Create(this, IDC_BTN); //<== use this insteadThe 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更多推荐
发布评论