一、子类化功能的提出:
一个控件的派生类要正常工作,首先定义类对象,这样类的构造函数会执行且生成对象,但还没HWND,这样需CreateWindow(),还要为这个对象调整位置,设置属性等,完全是在隐式状态下进行。这样有些用户会感到不爽,他们提出:如果能把一个调整好的可视化控件与这个类对象关联,这样不是很好吗?为了满足用户的需求,MFC就提供了SubclassDlgItem()和SubclassWindow这两个功能来实现。通常这样做:
1、定义类对象
2、需关联的类对象.SubclassDlgItem(要关联的控件ID,其父窗口对象)
另一种方法:
需关联的类对象.SubclassWindow(控件的HWND)
这样我们可以把可视化控件的位置和属性调整好,再和相应的派生类关联,这样省了不少事。
二、首先你应该明白,一个可视的控件,都是有HWND的。这样,在执行子类化操作时,MFC就把这个HWND与生成的类对象关联起来。此后因为类对象已经有了HWND,我们不需要再用CreateWindow()来隐式的建立HWND了。所以WM_CREATE消息不会被调用,即OnCreate()不会执行,要想执行一些初始化操作,MFC提供了一个PreSubClassWindow()虚函数,你可以重载,放入你的初始化代码。
三、VC中其实经常在子类化的。因为VC是一种可视化工具,要想实现可视化功能,就要把可视的控件与存在的类相关联,以便操作这个控件。如果不是为了可视化编辑,我们完全不需要子类化,一切在程序员的脑海里,全用代码来建立、操作和消毁对象。所以为了实现可视化,VC专门做了“建立类向导”->“建立控件变量”的功能来实现子类化功能。你也可以在此进行子类化,而不用这子类化功能函数。经过这个步骤,VC自动在类中生成两段代码:
//{{AFX_DATA(CSiceDlg)
enum { IDD = IDD_SICE_DIALOG };
CRichEditCtrl m_info;
CWargeList m_wlist;
//}}AFX_DATA
void CSiceDlg::DoDataExchange(CDataExchange* pDX)
{
CDialog::DoDataExchange(pDX);
//{{AFX_DATA_MAP(CSiceDlg)
DDX_Control(pDX, IDC_INFO, m_info);
DDX_Control(pDX, IDC_WAGERLIST, m_wlist);
//}}AFX_DATA_MAP
}
第一段是定义对象,第二段是关联到控件ID。
四、至于什么时候用SubclassDlgItem(),什么时候用SubclassWindow(),你可以这样理解:如果你知道控件ID,就用SubclassDlgItem(),如果你知道了控件的HWND,就用SubclassWindow(),作用是一样的。但你如果只知道控件的HWND,还是只能用SubclassWindow(),而不能用建立类向导->关联控件变量了。