探秘窗口过程函数(WndProc)的Thunk技术

本文探讨了Windows编程中的Thunk技术,特别是如何在MFC和WTL等框架中使用它来封装窗口过程函数WndProc。文章介绍了Thunk技术的由来、实质,通过模拟程序解释了其工作原理,并针对VC 6.0和VS2010的不同进行了代码改进。最后,讨论了如何避免全局变量的使用。
摘要由CSDN通过智能技术生成

最近看了一篇讲ATL Thunk技术的好文章(下载),收获较多,在此做一个总结。

Thunk技术的由来

我们知道,经典的Windows程序设计采用纯Windows API来实现,创建一个窗口必须严格遵循“定义窗口类,注册窗口类,创建窗口,显示窗口,更新窗口,启动消息循环”的步骤。虽然经典的Windows程序设计在一定程度上已经体现出了OOP的思想 (对象 = 数据 + 代码),但是与当代的OOP (封装、继承、多态) 还有很大的差距。这种差距类似于C struct和C++ class之间的差距。

为了使Windows编程更加简洁高效,需要对纯Windows API进行封装。市场上的应用程序框架,比如MFC,WTL等,主要就做了这件事情。

按照什么思路来对纯Windows API进行封装呢?那就是对各个函数进行分组,比如许多函数的第一个参数都是HWND hwnd。何不把HWND hwnd作为类的成员变量,调用与hwnd相关的函数就不必再写hwnd参数了。这样就完成了第一步。

接下来问题来了:WndProc函数怎么处理呢?它不能是普通的类方法,因为编译器会给普通类方法悄悄添加一个this指针,从而导致参数格式与WNDPROC不相同。有办法,那就是在方法前面添加static,这样就能将类的WndProc传递给窗口类的lpfnWndProc字段了。这样就完成了第二步。

可是,真正问题才刚刚出现。WndProc现在是类的static方法,但是如果想要WndProc内部调用非static方法呢?要是能够把this指针传递进去就好了。首先想到的方法就是用全局变量。(不然就要增加函数参数,那句跟WNDPROC不同了) 使用全局变量有很大的弊端,那就是这个全局变量到底应该设多大呢?因为你很可能用相同的窗口类创建多个窗口,这时候WndProc都一样,只能以类对象实例的指针来区分。也有解决办法,大不了用动态内存。还有查找的问题呢?用Red-Black tree够快么?显然,这样思考下去就太复杂。就算花了大力气实现了这种思路,动态内存太慢了,查找也得花时间,这跟ATL的要求不吻合:速度快,尺寸小。

实际上ATL采用了另外一种技术来解决这个问题,当然就是“Thunk技术”。Thunk技术看似高深,那是因为关注它的人不多,资料不够充足而已。

Thunk技术的实质

Thunk就是“转换”的意思,从ATL的实现来看,它是一种采用小段汇编代码对WndProc参数hwnd进行偷梁换柱的方法。不要看到汇编就却步,因为它只涉及到两条指令:mov和jmp。博主对汇编也只停留在本科时所学的那点知识,而且忘得差不多,但是理解Thunk技术已经足够。

Thunk技术的模拟

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值