一、注册Custom Control类
要使用Custom Control,必须把Custom Control的Class属性设置为一个窗口类,这个窗口类可以VC的类,例如:Button、Edit。
在窗体上拉个Custom Control,设置ID为IDC_EDIT,Class为Edit。在头文件增加一个CEdit类的成员变量:CEdit m_Text;
然后在OnInitDialog()中使用SubclassDlgItem把IDC_EDIT和对话框连接起来:
m_Text.SubclassDlgItem(IDC_EDIT,this); //从对话框模板创建动态子类控件,然后附加到CWnd对象
m_Text.SetWindowText("Custom Control例子"); //在其父类中可以直接操作了!
也可以把Custom Control设置为一个自定义类。
使用RegisterClass注册自定义类,然后设置Custom Control的Class属性为该类就行了,参考注册自定义类的代码:
BOOL CMyCtrl::RegisterWndClass(HINSTANCE hInstance)
{
WNDCLASS wc;
wc.lpszClassName = "CMyCtrl"; // 自定义类名
wc.hInstance = hInstance;
wc.lpfnWndProc = ::DefWindowProc;
wc.hCursor = ::LoadCursor(NULL, IDC_ARROW);
wc.hIcon = 0;
wc.lpszMenuName = NULL;
wc.hbrBackground = (HBRUSH) ::GetStockObject(LTGRAY_BRUSH);
wc.style = CS_GLOBALCLASS;
wc.cbClsExtra = 0;
wc.cbWndExtra = 0;
// 注册自定义类
return (::RegisterClass(&wc) != 0);
}
二、映射自定义消息
这里只介绍Custom Control向父窗口发送WM_NOTIFY消息,然后映射到操作函数。
在自定义操作类里增加一个Login()成员函数,当主程序调用这个成员函数后,会触发LoginEvent事件。
Login()的实现代码:
BOOL CMyCtrl::Login()
{
AfxMessageBox("主程序调用Login,将触发LoginEvent事件!");
NMHDR nm;
// 设置消息代码
nm.code = 12345;
nm.hwndFrom =m_hWnd;
nm.idFrom = GetDlgCtrlID();
// 发父窗口发送WM_NOTIFY消息
CWnd* pParent = GetParent();
pParent->SendMessage(WM_NOTIFY,nm.idFrom, (LPARAM)&nm);
return true;
}
在主窗体的头文件里声明消息响应函数:
afx_msg void LoginEvent;
在BEGIN_MESSAGE_MAP里加上:
ON_NOTIFY(12345, IDC_CUSTOM1, LoginEvent)
12345:消息代码;
IDC_CUSTOM1:控件的ID
LoginEvent:映射的函数。
然后再实现LoginEvent()的代码:
void CMainDlg::LoginEvent()
{
AfxMessageBox("触发LoginEvent事件!");
}
也可以在主窗体的OnNotify里处理WM_NOTIFY消息。
第二种自定义类的方法:
VC里的Custom Control的使用很简单,用鼠标拖动到窗体上,然后设置其“Class”属性为已注册的窗口类,比哪Edit、Button等等。因为像Edit、Button等控件可以很容易的画到窗体上,而对继承于CWnd的自定义窗口类则没有办法直接用鼠标画到窗体上,这时Custom Control就用上了,只要类是使用RegisterClass注册后就能被使用,如:
view plaincopy to clipboardprint?
WNDCLASS wc;
wc.lpszClassName = _T("MyWindow"); // matches class name in client
wc.hInstance = hInstance;
wc.lpfnWndProc = ::DefWindowProc;
wc.hCursor = ::LoadCursor(NULL, IDC_ARROW);
wc.hIcon = 0;
wc.lpszMenuName = NULL;
wc.hbrBackground = (HBRUSH) ::GetStockObject(LTGRAY_BRUSH);
wc.style = CS_GLOBALCLASS; // To be modified
wc.cbClsExtra = 0;
wc.cbWndExtra = 0;
::RegisterClass(&wc) != 0
WNDCLASS wc;
wc.lpszClassName = _T("MyWindow"); // matches class name in client
wc.hInstance = hInstance;
wc.lpfnWndProc = ::DefWindowProc;
wc.hCursor = ::LoadCursor(NULL, IDC_ARROW);
wc.hIcon = 0;
wc.lpszMenuName = NULL;
wc.hbrBackground = (HBRUSH) ::GetStockObject(LTGRAY_BRUSH);
wc.style = CS_GLOBALCLASS; // To be modified
wc.cbClsExtra = 0;
wc.cbWndExtra = 0;
::RegisterClass(&wc) != 0
这时保存在CustomControl的Class属性上输入MyWindow后,程序运行正常。
其实我们可以不用这么“麻烦”的来使用自定义类。只一个SubclassWindow就搞定了。使用方法:
1:定义我们需要类,比如从CWnd继承一个新的类MyWindow、并编写自己的代码实现。
2:在窗体上放任何一个控件(目的是使用这个控件的大小及位置),比如可以放一个Static在窗体上。为控件添加一个变量,变量类型为MyWindow,然后在代码的合适的地方(比如OnInitDialog)添加如下的代码就可以了:
view plaincopy to clipboardprint?
this->m_MyWindow.SubclassWindow(this->GetDlgItem(IDC_Static)->GetSafeHwnd()); //子类窗口句柄通过参数传递,将其与CContainedWindowT对象联系起来
this->m_MyWindow.SubclassWindow(this->GetDlgItem(IDC_Static)->GetSafeHwnd());
Notice:
Do not call SubclassWindow if you have already called Create. |