什么是子类化?
窗口子类化的目的是在不修改现有代码的前提下,扩展现有窗口、控件的功能。它的思路很简单,就是将窗口过程地址修改为一个新函数地址,新的窗口过程函数处理自己感兴趣的消息,将不感兴趣的消息丢给原窗口过程处理。
MFC框架将子类化方法应用得淋漓尽致,MFC将所有的窗口处理函数都注册成DefWndProc,那
么,是不是MFC将所有的消息都发送到DefWndProc中去了呢?答案是“不是”,而是都发送到
AfxWndProc函数中去了(您可以回想一下前面我们查看MSDN是提到的AfxWndProc)
窗口子类化的步骤如下:
(1)正常创建系统控件/窗口,得到控件/窗口的句柄。
(2)调用GetWindowLong()得到原来的系统的窗口函数OldWndProc。
(3)调用SetWindowLong()设置控件新的窗口函数为我们的NewWndProc。
(4)在NewWndProc处理感兴趣的消息
(5)不感兴趣的消息调用CallWindowProc()传递给原来的OldWndProc处理
注意:在调用旧的窗口函数时,不能直接调用OldWndProc(..),
而必须用函数CallWndProc调用,否则会出现堆栈错误。
相关函数解析
Long GetWindowLong(
HWND hWnd, //目标窗口句柄
int nlndex // 要检索的值的基于零的偏移量
);
如果函数成功,返回值是所需的32位整型值
LONG SetWindowLong(
HWND hWnd, // 目标窗口句柄
int nlndex, // 要设置的值的基于零的偏移量
LONG dwNewLong // 新的值
);
如果函数成功,返回值是指定的32位整数的原来的值。如果函数失败,返回值为0。若想获得更多错误信息,请调用GetLastError函数。
nlndex可以为以下的值
GWL_EXSTYLE | 检索扩展窗口样式。 |
GWL_HINSTANCE | 检索应用程序实例的句柄。 |
GWL_HWNDPARENT | 检索父窗口的句柄(如果有的话)。 |
GWL_ID | 检索窗口的标识符。 |
GWL_STYLE | 检索窗口样式。 |
GWL_USERDATA | 检索与窗口关联的用户数据。 |
GWL_WNDPROC | 检索窗口过程的地址或表示窗口过程地址的句柄。您必须使用CallWindowProc函数调用窗口过程。 |
DWL_DLGPROC | 检索对话框过程的地址句柄,您必须使用CallWindowProc函数来调用对话框过程。 |
DWL_MSGRESULT | 检索在对话框过程中处理的消息的返回值。 |
DWL_USER | 检索应用程序专用的额外信息,例如句柄或指针。 |
//将消息信息传递给指定的窗口过程。
LRESULT CallWindowProc(
WNDPROC lpPrevWndFunc, //窗口过程
HWND hWnd, //窗口句柄
UINT Msg, //消息
WPARAM wParam, //额外的消息特定信息
LPARAM IParam //额外的消息特定信息
);
返回类型:LRESULT
返回值指定了消息处理的结果并取决于发送的消息。
备注
使用CallWindowProc函数进行窗口子类化,应用程序必须通过调用CallWindowProc将任何未由新窗口过程处理的消息传递给前一个窗口过程
实例代码
在主窗口过程中WM_CREATE消息中,创建控件时,将窗口过程改为我们自己的
case WM_CREATE: { LPCREATESTRUCT pcs = (LPCREATESTRUCT)LParam; HWND h3 = CreateWindow(L"edit", L"这是一个文本框", WS_CHILD | WS_BORDER | WS_VISIBLE | ES_MULTILINE, 5, 100, 100, 80, hwnd, (HMENU)10003, pcs->hInstance, NULL); //将控件的窗口过程处理函数改为自定义的,从而捕获控件消息 //由于SetWindowLong会返回旧的过程,所以这里就不用GetWindowLong了 编辑框旧过程 = (WNDPROC)SetWindowLong(h3, GWL_WNDPROC, (LONG)编辑框的窗口过程); break; }
然后为编辑框写一个窗口过程
//创建一个全局变量 储存旧的过程 WNDPROC 编辑框旧过程 = NULL; //为编辑框写一个窗口过程 LRESULT CALLBACK 编辑框的窗口过程(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM LParam){ //消息所处的窗口句柄,具体消息名称 WM_xxxx消息 switch (uMsg) { //处理了我们感兴趣的消息 case WM_LBUTTONDOWN: { //MessageBox(hwnd, L"我们捕获了编辑框的左键消息", L"提示", MB_OK); SetWindowText(hwnd, L"我们捕获了编辑框的左键消息"); //return 0; 返回0代表我们自己处理了 系统默认的点击事件就没有了 所以无法置焦点 break; } } //其他的消息交给原来的处理过程函数去处理,保证控件原来的功能 return CallWindowProc(编辑框旧过程, hwnd, uMsg, wParam, LParam); }
相关推荐
wIndowsapI 高频窗口控件函数: 操作控件 创建 取句柄 取标题 取文本 置标题 置文本Win32API提供了一系列的函数来操作控件高频常用控件函数:类型说明GetDlgItem根据控件ID,取控件句柄GetDlgItemText根据控件ID,取控件文本GetDlgItemInt根据控件
wIndowsapI创建窗口 并创建 标准控件窗口的创建参考 http://qingzhouquanzi.com/269.html以下是windows 创建编辑框,文本框,标签,组合框,滚动条等头文件#include <windows.h&
wIndowsapI创建控件 或创建子窗口方法创建按钮一般是在 WM_CREATE消息的响应中创建子窗口 创建控件 创建按钮,创建单选框,复选框 等等按钮的创建:创建按钮第一个参数(类名)必须是 button 不区分大小写case WM_CREA
wIndowsapI控件:创建超级列表框超级列表框的类名是 WC_LISTVIEW样式是 LVS_ 开头的LVS_ICON图标视图LVS_SMALLICON小图标视图LVS_LIST列表视图LVS_REPORT报表视图可以向控件发送LVM_
wIndowsapI:公共控件Windows中 分为标准控件 和 公共控件标准控件包括:标签,按钮,编辑框,组合框,滚动条,公共控件包括:动画框,日期框,热键框,日历,超级列表框,进度条,超链接,测量条,树形框,分页控件,工具条,
MFC(1):c语言/c++ 纯apI 创建窗口 底层原理Visual Studio直接创建一个空项目控件的创建请参考:http://qingzhouquanzi.com/287.html新建一个 后缀为 .c 或者 .cpp文件#include <w
C++ 纯apI创建窗口与控件 包括窗口过程的写法//纯API创建窗口 底层代码 #include <windows.h> //如果出现该符号在函数中被引用需要配置:项目-》属性->配置属性->连接器=》系统 子系统 设
wIndows apI数据类型的命名规律 与常用的wIndows 数据类型WindowsAPI数据类型的命名规律基本数据来袭包括:BYTE 字节CHAR 字符WORD 单字SHORT 短整型INT 整型指针的类型命名方式一般都在对象名前面加 LP 或者 P /*字
c++ 中 char与wchar_t的区别 wIndows中apI函数后面带a和w的区别C++基本数据类型中表示字符的有两种: char、wchar_t。char叫多字节字符,一个char占1个字节,之所以叫多字节字符是因为它表示一个英文字符时是一个字节,而中文字符时是多个字节。wcha
LpsTR、LpwsTR、LpTsTR、LpCTsTR wIndowapI中的字符串数据类型LP前缀 表示指针STR 表示字符串LPWSTR W代表Unicode版本LPTSTR T代表根据项目而定LPCTSTR C表示const T表示根据项目决定LPSTR 多字节变量类型使用自