ATL中的Thunk机制学习

ATL和MFC的C++类和HWND的映射机制 最近看深入解析ATL这本书的时候看到ATL中的窗口类实现的时候,很是惊异于ATL的Thunk的运用技术,,ATL运用Thunk技术把C++的成员函数置换成Windows窗口的消息处理函数。那么更古老的MFC框架又是怎么实现CWnd类到HWND窗口类之间的映射的呢? 下面的文章将ATL和MFC的窗口封装机制做个对比. 如果让我完成C++类到HWND窗口的映射,我会写如下的代码BOOL  阅读详情

ATL利用一系列的类来管理窗口。为了使代码尽量紧凑而高效,ATL使用了一种有趣的技术来实现与窗口消息相关联的HWND和负责处理消息的对象的this指针之间的映射。具体过程如下:

 

在窗口注册时声明的窗口过程为此窗口对应的窗口类的静态成员函数StartWindowProc,当第一条消息到达此函数时,其处理如下:

 

template <class TBase, class TWinTraits>

LRESULT CALLBACK CWindowImplBaseT< TBase, TWinTraits >::StartWindowProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)

{

         CWindowImplBaseT< TBase, TWinTraits >* pThis =

(CWindowImplBaseT< TBase, TWinTraits >*)_Module.ExtractCreateWndData();

         ATLASSERT(pThis != NULL);

         pThis->m_hWnd = hWnd;

         pThis->m_thunk.Init(pThis->GetWindowProc(), pThis);

         WNDPROC pProc = (WNDPROC)&(pThis->m_thunk.thunk);

         WNDPROC pOldProc = (WNDPROC)::SetWindowLong(hWnd, GWL_WNDPROC, (LONG)pProc);

#ifdef _DEBUG

         // check if somebody has subclassed us already since we discard it

         if(pOldProc != StartWindowProc)

                   ATLTRACE2(atlTraceWindowing, 0, _T("Subclassing through a hook discarded./n"));

#else

         pOldProc;  // avoid unused warning

#endif

         return pProc(hWnd, uMsg, wParam, lParam);

}

 

它先由全局变量_Module中取得此窗口对应的窗口类的this指针,然后通过m_thunk运用汇编指令改造此窗口类的窗口过程成员函数。m_thunk是CWndProcThunk的实例,每个窗口类各有一个。它的定义如下:

 

class CWndProcThunk

{

public:

         union

         {

                   _AtlCreateWndData cd;

                   _WndProcThunk thunk;

         };

         void Init(WNDPROC proc, void* pThis)

         {

#if defined (_M_IX86)

                   thunk.m_mov = 0x042444C7;  //C7 44 24 0C

                   thunk.m_this = (DWORD)pThis;

                   thunk.m_jmp = 0xe9;

                   thunk.m_relproc = (int)proc - ((int)this+sizeof(_WndProcThunk));

#elif defined (_M_ALPHA)

                   thunk.ldah_at = (0x279f0000 | HIWORD(proc)) + (LOWORD(proc)>>15);

                   thunk.ldah_a0 = (0x261f0000 | HIWORD(pThis)) + (LOWORD(pThis)>>15);

                   thunk.lda_at = 0x239c0000 | LOWORD(proc);

                   thunk.lda_a0 = 0x22100000 | LOWORD(pThis);

                   thunk.jmp = 0x6bfc0000;

#endif

                   // write block from data cache and

                   //  flush from instruction cache

                   FlushInstructionCache(GetCurrentProcess(), &thunk, sizeof(thunk));

         }

};

 

其Init()函数完成对WndProcThunk结构的初始化工作。WndProcThunk结构针对X86体系的定义如下:

 

struct _WndProcThunk

{

         DWORD   m_mov;          // mov dword ptr [esp+0x4], pThis (esp+0x4 is hWnd)

         DWORD   m_this;         //

         BYTE    m_jmp;          // jmp WndProc

         DWORD   m_relproc;      // relative jmp

};

 

结构成员中保存的是一组汇编指令。在X86体系下,在Init()函数中这组汇编指令被初始化为下面的指令:

 

mov dword ptr [esp+0x4], pThis

jmp (int)proc - ((int)this+sizeof(_WndProcThunk))

 

它完成的功能是,用窗口类的指针pThis代替窗口句柄hWnd(esp+0x4中放的就是hWnd),然后跳转到传入的proc函数处((int)proc - ((int)this+sizeof(_WndProcThunk))是proc与thunk之间的距离)。

 

在调用完m_thunk.Init()函数之后,实际上就得到了经过改造的窗口过程(m_thunk.thunk),此窗口过程是窗口类的一个成员函数,它的第一个参数定义虽然是HWND,但实际上是它的类的this指针。最后使用SetWindowLong()用这个新的窗口过程替换掉原有的窗口过程(也就是StartWindowProc),以后的所有消息都会被路由给新的窗口过程。

ATL中的Thunk机制学习 ATL中的Thunk机制学习 http://blog.youkuaiyun.com/sam1111/article/details/9790 阅读详情

相关推荐

【记录】游戏体验报告怎么写(自我成长篇)

2019年3月更新: 这个倒是不用推翻,我个人虽然写的东西还是有一些偏差的,但是“表哥”说的倒是没毛病的,这篇主要是为了记录用,具体的干货也有,都在图片里,请自行提取 =====18年初原答案 作为一个游戏策划新人,游戏分析可能抓不到点子上,试着总结记录一下游戏体验报告分析的成长(因为水平不同,视野可能也不一样,也许之后几年回头看这些东西都是小儿科或者是错误的,所以只写出当下的想...

eat_human的博客 6万+

ATL中的Thunk机制学习 (转)

ATL中的Thunk机制学习 (转)[@more@]ATL利用一系列的类来管理窗口。为了使代码尽量紧凑而高效,ATL使用了一种有趣的技术来实现与窗口消息相关联的HWND和负责处理消息的对象的this指针之间的映射。具体过程如下:...

csd3176的博客 153

边表法

边表法是用来绘制填充一个面的,边表法的关键是边表和连接边表的扫描线。 对于边的描述利用边表数据结构,包含边与扫描线的交点x坐标,边的最大y坐标,这样可以知道边加入到哪些扫描线上,便还有一个指针来记录扫描线上其它边。 //边数据结构 #pragma once #ifndef __CAETZ__ #define __CAETZ__ #include "pch.h" #include "CPoin...

weixin_42376458的博客 2101

ATL Thunk技术简单解析

Thunk的基本原理是分配一段内存,然后将窗口过程设置为这段内存。这段内存的作用是将窗口过程的第一个参数(窗口句柄)替换成类的This指针,并jump到类的WinProc函数中。这样就完成了窗口过程到类的成员函数的一个转换。 ATL采用一种称为thunk的机制,简单来说,公共的窗口过程依然是类的一个静态函数,但只负责窗口的第一个消息WM_NCCREATE,其目的是在堆上开辟一小块数据区,

jdzfjfhnui的专栏 1379

别再死磕SPWM了!手把手教你用STM32实现SVPWM驱动PMSM电机(附代码)

本文详细介绍了如何使用STM32实现SVPWM驱动PMSM电机,对比传统SPWM方案,SVPWM在电压利用率、电流THD、转矩脉动和稳态温升等方面均有显著提升。通过克拉克变换优化、扇区快速判断和矢量作用时间补偿等核心算法,结合STM32硬件加速技巧,实现高效电机控制。附代码示例,助力开发者快速掌握SVPWM技术。

weixin_28733777的博客 274

电脑蓝牙与ESP32蓝牙连接,让电脑发现ESP32

让PC发现ESP32蓝牙

injre! injre~ 5446

ATL之thunk技术

<br /><br /><br />学习下 ATL 的 thunk<br />由于 C++ 成员函数的调用机制问题,对C语言回调函数的 C++ 封装是件比较棘手的事。为了保持C++对象的独立性,理想情况是将回调函数设置到成员函数,而一般的回调函数格式通常是普通的C函数,尤其是 Windows API 中的。好在有些回调函数中留出了一个额外参数,这样便可以由这个通道将 this 指针传入。比如线程函数的定义为:<br />typedef DWORD (WINAPI *PTHREAD_START_ROUTINE

xsh_123321的专栏 4790

用Multisim和AD2复刻经典:手把手教你搭建μA741三角波-方波发生器(附完整避坑指南)

本文详细介绍了如何使用Multisim和AD2搭建基于μA741运算放大器的三角波-方波发生器,包括电路原理、Multisim仿真流程、AD2硬件搭建及调试技巧。通过对比理论计算、仿真和实测数据,深入分析器件非理想特性的影响,并提供16个典型问题的解决方案,帮助读者掌握波形发生器的设计原理和工程调试经验。

weixin_28744423的博客 284

ATL Thunk机制学习

      ATL模板类库使用Thunk技术来实现与窗口消息相关联的HWND和负责处理消息的对象的this指针之间的映射。    ATL中窗口类注册时,窗口过程函数缺省值都是StartWindowProc,当创建窗口产生第一条消息时将调用此函数。StartWindowProc是CWindowImplBase的一个静态成员函数,它的工作是建立CWindowImpl派生对象的HWND与对象

热爱工作,快乐生活 4743

MobileFusion:基于结构重参数化的移动端红外可见光图像融合方法

MobileFusion提出了一种轻量化的红外与可见光图像融合框架,通过结构重参数化技术实现移动端实时部署。该方法包含可重参数多分支卷积(RepMBConv)、轻量化上下文感知注意力(LCAA)和重参数前馈网络(RepFFN)三大模块,在训练时保留多分支结构增强特征学习,推理时合并为单路算子提升效率。实验表明,MobileFusion在MSRS、FMB等数据集上实现了融合质量与推理速度的平衡,参数量仅4000,在边缘设备上也能高效运行,为资源受限场景提供了实用解决方案。代码已开源。

毕竟是Shy哥 137

基于TF-IDF+KMeans聚类算法构建中文文本分类模型(附案例实战)

TF-IDF(Term Frequency-Inverse Document Frequency, 词频-逆文件频率)是一种用于资讯检索与资讯探勘的常用加权技术。TF-IDF是一种统计方法,用以评估一字词对于一个文件集或一个语料库中的其中一份文件的重要程度。字词的重要性随着它在文件中出现的次数成正比增加,但同时会随着它在语料库中出现的频率成反比下降。简单来说就是:一个词语在一篇文章中出现次数越多, 同时在所有文档中出现次数越少, 越能够代表该文章。这也就是TF-IDF的含义。

m0_64336780的博客 1万+

w/atl的thunk技术

用dialog为例CAboutDlg dlg;dlg.DoModal();其中class CAboutDlg : public CDialogImpl&lt;CAboutDlg&gt;{...}当执行到dlg.DoModal();里面的return ::DialogBoxParam(_AtlBaseModule.GetResourceInstance(), MAKEINTRESOURCE(stat...

weixin_34064653的博客 151

36、T5L 迪文屏C51开发之绘制动态曲线

T5L 迪文屏C51开发之绘制动态曲线1、介绍2、例程功能简介3、GUI界面设计3、C51程序设计 1、介绍   本文将利用DGUS Tool软件中的【动态曲线控件】来绘制曲线效果,在T5L迪文屏中总共支持8个通道的曲线,而曲线数据是需要缓冲区的,如果 8 通道曲线同时使用,0x1000-0x4FFF 将作为曲线缓冲区地址,此时该部分变量地址不能被其他控键使用,其他控键地址使用范围为0x5000-0xFFFF,当某曲线通道不被使用时,那么其所对应的缓冲区地址可以做其他用途,曲线通道具体的地址分布如下图所示:

嵌入式羊圈 3131

(转载)ATL_NO_VTABLE详解

<br />我们可以注意到在用ATL编写COM组件时,在类前面都有一个宏ATL_NO_VTABLE,那么这个宏到底有什     <br />   么作用呢?这个宏的定义如下:     <br />   #define    __declspec(novtable)    ATL_NO_VTABLE;     <br />    <br />   下面这段是MSDN中对这个宏的描述:     <br />   This    form    of    _declspec    can    be    ap

kanguolaikanguolaik的专栏 1365

win10 跳过U8环境检测的IE WebControls.rar

win10 安装u8的时候 提示IE WebControls 不通过,这个工具可以欺骗u8的检查。 跳过U8环境检测的IE WebControls。提示导入失败后,重新检测通过。

SIMATIC S7-1200, S7-1500 PID 控制[手册]

SIMATIC S7-1200, S7-1500 PID 控制[手册]

ATL Thunk机制深入分析

如果你有SDK的编程经验,就一定应该知道在创建窗口时需要指定窗口类,窗口类中的一种重要的参数就是窗口过程。任何窗口接收到的消息,都是由该窗口过程来处理。 在面向对象编程中,如果还需要开发人员来使用原始的窗口过程这种面向过程的开发方式,面向对象就显得不那么纯粹了。所以,在界面编程的框架中,框架往往会隐藏窗口过程,开发人员看到的都是一个个的类。 如果要处理某一个消息,则需要在窗口对应的类...

dhpvukzt509573的博客 357

计算机控制技术及应用

《计算机控制技术及应用》通过总结作者的科研成果和吸收国内外的先进理论、方法和技术,以计算机控制系统的网络化、开放化、智能化和集成化发展趋势为主线索,主要介绍计算机控制系统的基本概念和计算机控制系统的典型形式,计算机控制系统的数学描述与基本分析方法,以及数字PID控制器、最少拍控制系统、达林算法、状态变量设计法等设计方法及其各种改进算法。重点突出计算机控制系统输入输出通道接口的设计方法和典型控制系统的设计案例与实现方法等。

ATL thunk机制

起初在DECLARE_WND_CLASS宏中可以知道,窗口类的窗口过程是CWindowImplBaseT的静态成员函数StartWindowProc,在StartWindowProc第一次被调用的时候,它把CWindowImplBaseT的非静态成员函数通过thunk机制设置为窗口过程。 template LRESULT CALLBACK CWindowImplBaseT::Start

w的专栏 1906

老版QQ原生表情gif动态

这是老版的QQ表情,不过全是动态的的,Windows照片查看器是不会动的,可以右击用浏览器打开查看,再说一遍是老版的,只是分享给宁愿用老版也要动态的人。

atl thunk源码

atlstdthunk.h // This is a part of the Active Template Library. // Copyright (C) Microsoft Corporation // All rights reserved. // // This source code is only intended as a supplement to the // A...

晓晓梦 334

[wtl学习]-[第三天]-THUNK技术学习

还是前言:本文只是本人学习过程的思考和记录。有错误的地方诚请指教。        今天继续看ATL Internals: Working with ATL 8, Second Edition By Christopher Tavares, Kirk Fertitta, Brent Rector, Chris Sells这本书第十章,学习了CWindowImpl的一些设计思想,边看书边翻看源码

HainuCrazy的专栏 1311

ATL thunk机制

2009-05-06 23:04 344人阅读 评论(0) 收藏 举报 起初在DECLARE_WND_CLASS宏中可以知道,窗口类的窗口过程是CWindowImplBaseT的静态成员函数StartWindowProc, 在StartWindowProc第一次被调用的时候,它把CWindowImplBaseT的非静态成员函数通过thunk机制设置为窗口过程。   tem

wxl1986622的专栏 873

MFC、ATL窗口消息封装机制对比分析

http://www.brucesky.com/articles/242 新产品在不紧不慢的进行中,这应该是有史以来开发比较“自由”的一个项目。在折腾完一个功能服务器的demo之后,开始折腾起PC客户端。Leader说客户端界面需用ATL来实现。这时候可以满足一下客户端界面开发的兴趣,于是开始学习ATL界面开发,有人说做界面是个累人加无趣的体力活,但对于做界面的新手来说自得其乐,君子懂得

珍爱生命 远离C++ 2545

ATL与MFC消息分发机制的对比

上面说完了ATL的消息分发方式,下面继续MFC的实现机制。二、MFC消息分发的实现方式:     首先来看注册窗口时:     还是以对话框为例子,调用DoModal 后,进入:view plaincopy to clipboardprint?INT_PTR CDialog::DoModal()       {           //···进行资源的准备           // disable parent (before creating dialog)           HWND hWndPare

fjclc2008的专栏 1894

理解ATL中的一些汇编代码

我们知道ATL(活动模板库)是一套很小巧高效的COM开发库,它本身的核心文件其实没几个,COM相关的(主要是atlbase.h, atlcom.h),另外还有一个窗口相关的(atlwin.h), 所以拿来学习应该是很方便的。但是因为ATL的代码充满了模板和宏,内部还夹杂着汇编,所以如果没有比较丰富的C++模板和系统底层的知识,一般人会看得一头雾水。 下面我们主要分析一下ATL中的一些汇编代码

Chinamming的专栏 1510
上一篇: C++模板代码的组织方式 ——包含模式(Inclusion Model)
下一篇: 在.NET中读写INI文件 ——兼谈正则表达式的应用
sam1111
博客等级 码龄26年 18粉丝 28原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

抵扣说明:

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

余额充值