我很想知道存储this
指针的最佳/常用方法WndProc
.我知道几种方法,但据我所知,每种方法都有其自身的缺点.我的问题是:
有哪些不同的方式来生成这种代码:
CWindow::WndProc(UINT msg, WPARAM wParam, LPARAM) { this->DoSomething(); }
我可以想到Thunks,HashMaps,Thread Local Storage和Window User Data结构.
每种方法的优点/缺点是什么?
代码示例和建议获得的分数.
这纯粹是出于好奇心.使用MFC之后,我一直想知道它是如何工作的,然后开始考虑ATL等.
编辑:我可以HWND
在窗口过程中有效使用的最早的地方是什么?它记录为WM_NCCREATE
- 但如果您实际进行实验,那不是第一个发送到窗口的消息.
编辑: ATL使用thunk访问此指针.MFC使用HWND
s 的哈希表查找.
在构造函数中,使用"this"作为lpParam参数调用CreateWindowEx.
然后,在WM_NCCREATE上,调用以下代码:
SetWindowLongPtr(hwnd, GWLP_USERDATA, (LONG_PTR) ((CREATESTRUCT*)lParam)->lpCreateParams); SetWindowPos(hwnd, 0, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE | SWP_NOZORDER);
然后,在窗口过程的顶部,您可以执行以下操作:
MyWindowClass *wndptr = (MyWindowClass*) GetWindowLongPtr(hwnd, GWL_USERDATA);
这允许你这样做:
wndptr->DoSomething();
当然,您可以使用相同的技术来调用上面的函数:
wndptr->WndProc(msg, wparam, lparam);
...然后可以按预期使用其"this"指针.
虽然使用SetWindowLongPtr和GetWindowLongPtr来访问GWL_USERDATA可能听起来不错,但我强烈建议不要使用这种方法.
这正是Zeus编辑所使用的接近,近年来它只引起了痛苦.
我认为发生的事情是第三方窗口消息被发送到Zeus,它们也设置了GWL_USERDATA值.一个应用程序特别是Microsoft工具,它提供了在任何Windows应用程序中输入亚洲字符的替代方法(即某种软件键盘实用程序).
问题是Zeus总是假设GWL_USERDATA数据是由它设置的,并尝试将数据用作this指针,然后导致崩溃.
如果我要再次使用,我现在所知道的,我将采用缓存的哈希查找方法,其中窗口句柄用作键.
你应该使用GetWindowLongPtr()
/ SetWindowLongPtr()
(或不推荐的GetWindowLong()
/ SetWindowLong()
).它们速度快,完全符合您的要求.唯一棘手的部分是确定何时调用SetWindowLongPtr()
- 您需要在发送第一个窗口消息时执行此操作,即WM_NCCREATE
.
有关示例代码和更深入的讨论,请参阅此文章.
线程本地存储是一个坏主意,因为您可能在一个线程中运行多个窗口.
哈希映射也可以工作,但计算每个窗口消息的哈希函数(并且有很多)可能会变得昂贵.
我不确定你是如何使用thunk的; 你怎么绕过thunk?
我已经使用SetProp/GetProp来存储指向窗口本身的数据的指针.我不确定它是如何叠加到你提到的其他项目.