windows程序设计之窗口子类化

这几天都在家里,赶上了暑假,没啥事情可做,就做些小玩意。虽然都没什么技术含量,但自己毕竟是新手,做得不是很好,代码都得参考下别人的。委屈今天看到一个博客上面写的是关于SDK的窗口子类化,什么是窗口子类化,其实说得简单点就是有个多功能的窗口,你对它有绝对的控制权得意。举个例子好了,你自己写了一个软件,上面有个编辑框,在这里面只能输入“我是笨蛋”,(基本上没人会喜欢你的软件)客户要是想输入其他的,都输不进去。这就有一种思想,软件是我做的,我对它有绝对的控制权。

下面简单描述下原理:就拿上面那个例子来说好了,我前面的博客大概介绍了下windows是怎么处理键盘消息的。就拿‘A’键来说,你要是不处理,windows就会自己拜托DefWindowProc 自己去处理。就算你要处理了,那好,在WM_CHAR或者WM_KEYDOWN你自己处理吧,但其实这不是享有绝对的控制权。

真正要有绝对的控制权是我需要具有输入检测的能力,即每当用户输入一个字符到编辑框中时要能检测这个字符。那要怎么办呢?可以这样,把Windows的窗口过程处理函数“偷换”成自己的函数,这样你就能把所有的消息随你高兴怎么处理了,这才是真正有有绝对控制权得意,也就是所谓的窗口子类化。由于Windows是认定窗口过程函数的格式的,所以你自己定义的函数也要和Windows本事的窗口过程函数格式一样。这样一说其实也就很简单了。

窗口子类化之前

Windows< ==>Edit 控件的窗口处理函数。

子类化之后
Windows< ==>自定义的窗口处理函数==> Edit 控件的窗口处理函数。 

注意一点子类化并不局限于控件,可以子类化任何窗口

还是先看代码吧:(代码主要实现功能:在编辑框中只能输入0或者1,可用于纯二进制输入)


在 WNDCLASSEX 结构的成员 lpfnWndProc 指出了窗口函数地址。在WM_CREATE的时候创建一个编辑框。接着是

OldWndProc = (WNDPROC)SetWindowLong(hwndEdit,GWL_WNDPROC,(LONG)EditWndProc) ;
通过SetWindowLong来改变窗口的属性,第二个参赛GWL_WNDPROC 设置新的窗口处理函数地址

1.  用参数GWL_WNDPROC调用SetWindowLong函数,如果调用成功那么返回值就是与调用功能相联系的一个32位的整数。在这里我们返回的值保存在 OldWndPro中,下面的将不感兴趣的消息返回给windows还需要这个参数。下面是SetWindowLong函数MSDN上的解释。

----------------------------------------------------------------------------

Note:  This function has been superseded by the SetWindowLongPtr function. To write code that is compatible with both 32-bit and 64-bit versions of Windows, use the SetWindowLongPtr function

if you use SetWindowLong with the GWL_WNDPROC index to replace the window procedure, the window procedure must conform to the guidelines specified in the description of the WindowProc callback function

----------------------------------------------------------------------------

接着我们看看EditWndProc函数,这个是我们自己定义的函数,但是样子要和windows自己的窗口过程函数一样,不然可就识别不出的。看看这个函数,其实也和windows自己的窗口过程函数差不多,也是消息的处理,等价的,我们处理感兴趣的消息,对于不需要处理的消息我们就交还给windows自己的函数处理,我们要截获我们需要的即可,WM_CHAR中我们只处理‘0’,‘1’或者Enter然后调用

LRESULT CallWindowProc(WNDPROC lpPrevWndFunc, HWND hWnd,  UINT Msg,  WPARAM wParam,  LPARAM lParam );
lpPrevWndFunc = 窗口原来函数的地址,剩下的四个参数就是发给自定义函数的参数。
我们可以通过第四个参数创传回去。把不感兴趣的字符消息丢了(也就输不到编辑框上),感兴趣的字符消息传回windows自己函数,就这样神不知鬼不觉的“偷换”了函数。
看下我的代码注释,
KeyMsg == VK_RETURN
如果没有这个的话就会出现弹两次框的结果,这个可不是我们想要的,为什么会出现两次呢??我调试了下,第一次是直接在消息
WM_KEYDOWN中
if(LOWORD(wParam) == VK_RETURN)一次弹框,然后程序往下走竟然到了WM_CHAR里面,Enter是字符消息,,但是我们如果没有
KeyMsg == VK_RETURN的话直接会被传回windows自己的消息过程函数。Enter在消息列队里总得处理吧?对应的消息处理存在啊
case WM_KEYDOWN 所以又弹了一次框。

上面就是一个小程序,毕竟是新手,可能有错,希望指正,不甚感激!



参考资料《windows+sdk编程系列文章》

posted @ 2011-08-09 19:43  Livesss  阅读(305)  评论(0编辑  收藏  举报