任意改变参数的64位Thunk

首先大家要明白什么是Thunk,为什么要用Thunk,通俗的来说Thunk就是将windows中一些回调函数转变成一种面向对象的技术。
VC中函数前有callback的就是其中一种,其中最有代表的函数 SetWindowLong 这个用来子类化窗体时要求一个回调函数如下

复制代码
  1. LRESULT CALLBACK WindowProc(HWND hwnd,     
  2.             UINT uMsg,     
  3.             WPARAM wParam,     
  4.             LPARAM lParam     
  5.             );  
  6.   
  7. SetWindowsHookEx 这是HOOK函数,不同类型的HOOK使用不同的回调函数,比如鼠标HOOK就用  
  8. LRESULT CALLBACK MouseProc(          int nCode,  
  9.     WPARAM wParam,  
  10.     LPARAM lParam  
  11. );  

如果直接使用 WindowProc  MouseProc 将无法实现面向对象,因为这些函数是全局的
比如说,你有一个类subclass它的功能是子类化窗体,不同的窗体使用一个类对象,如 A,B,C窗体
你都要子类化,并对应一个子类化的类,如subclass a; subclass b; subclass c;
可是你会发现使用setwindowlong 子类化时,要的是WindowProc这个是全局的,按照
ubclass a; subclass b; subclass c; WindowProc函数共用,也就意味着你得在WindowProc特殊处理。
在这个时候Thunk就可以帮助你,使用Thunk后,WindowProc看起来就是私有的,这样你就不用特殊处理了
当然,也可以使用GetProp函数的方法来实现面向对象,因为这是窗体,正好可以使用GetProp这类函数来处理如下代码:

复制代码
  1. LRESULT CALLBACK WindowProc(HWND hwnd,     
  2.             UINT uMsg,     
  3.             WPARAM wParam,     
  4.             LPARAM lParam     
  5.             );     
  6.     
  7. 子类化窗体的回调函数还好处理些,可以将句柄与类的对应关系保存起来。或者使用::SetProp类似这种函数在窗体中设置一样标志,保存this指针,然后用     
  8. ::GetProp取出来,类似下面这样的代码     
  9.     
  10. //设置回调     
  11. void SubWindow::Test()     
  12. {     
  13.     
  14.     ::SetProp( hWnd, _T("AAA"), this);     
  15. ::SetWindowLong( hWnd, GWL_WNDPROC, WindowProc);     
  16. }     
  17.     
  18. LRESULT  SubWindow::Window_Proc(.......)     
  19. {     
  20.     
  21. }     
  22.     
  23. LRESULT CALLBACK WindowProc(HWND hwnd,     
  24.             UINT uMsg,     
  25.             WPARAM wParam,     
  26.             LPARAM lParam     
  27.             )     
  28. {     
  29.     SubWindow *pthis = ::GetProp( hwnd, _T("AAA"));     
  30.      if ( NULL != pthis )     
  31.     {     
  32.         pthis->Window_Proc(....);//这样就回到类里面去了     
  33.     }     
  34. }   

那么,其它的回调函数,要如何调呢???

那么为什么要修改任意参数的thunk呢??大家有没有发现,MouseProc第一个参数是int 在64位下是32位的,如果保存this指针,将会出错,
这个时候就得使用WPARAM wParam或LPARAM lParam来保存指针,因为这两个参数是指针变量,随着系统位数变化的.

现在来看看使用伪代码

复制代码
  1. LRESULT CALLBACK MouseProc(          int nCode,  
  2.     WPARAM wParam,  
  3.     LPARAM lParam  
  4. )  
  5. {  
  6.   subclass  *p = (subclass*)wParam;//这里假设使用第二个参数传  
  7.   
  8. return p->MouseProc(...,...,...);//这样就使现了面向对象  
  9. }  
  10.   
  11. subclass   
  12. {  
  13.   public:  
  14.    void SetHook()  
  15.   {  
  16.      SetWindowsHookEx(...,..., MouseProc);  
  17.   }  
  18. LRESULT MouseProc(int nCode,  
  19.     WPARAM wParam,  
  20.     LPARAM lParam)  
  21. {  
  22.   //这里是处理代码,到这就实现了面向对象  
  23. }  
  24. }  

 原文与源码

http://www.panshy.com/article/Sort_Desktop/other/2014-04-09/2473.php

http://www.panshy.com/download/demo_code/fun_class_code/2014-04-09/231.php

http://www.panshy.com/download/demo_code/UI/2013-08-11/70.php

www.panshy.com/article/Sort_Desktop/other/2012-05-20/1689.php

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值