Watl的thunk技术.
用dialog为例CAboutDlg dlg;
dlg.DoModal();
其中class CAboutDlg : public CDialogImpl<CAboutDlg>{...}
当执行到dlg.DoModal();里面的
return ::DialogBoxParam(_AtlBaseModule.GetResourceInstance(), MAKEINTRESOURCE(static_cast<T*>(this)->IDD),
hWndParent, T::StartDialogProc, dwInitParam);
时, 会调用StartDialogProc函数
该函数如下
1
template <class TBase>
2
INT_PTR CALLBACK CDialogImplBaseT< TBase >::StartDialogProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
3
{
4
CDialogImplBaseT< TBase >* pThis = (CDialogImplBaseT< TBase >*)_AtlWinModule.ExtractCreateWndData();
5
ATLASSERT(pThis != NULL);
6
if(!pThis)
7
{
8
return 0;
9
}
10
pThis->m_hWnd = hWnd;
11
// Initialize the thunk. This was allocated in CDialogImpl::DoModal or
12
// CDialogImpl::Create, so failure is unexpected here.
13
14
pThis->m_thunk.Init((WNDPROC)pThis->GetDialogProc(), pThis);
15
DLGPROC pProc = (DLGPROC)pThis->m_thunk.GetWNDPROC();
16
DLGPROC pOldProc = (DLGPROC)::SetWindowLongPtr(hWnd, DWLP_DLGPROC, (LONG_PTR)pProc);
17
#ifdef _DEBUG
18
// check if somebody has subclassed us already since we discard it
19
if(pOldProc != StartDialogProc)
20
ATLTRACE(atlTraceWindowing, 0, _T("Subclassing through a hook discarded.\n"));
21
#else
22
pOldProc; // avoid unused warning
23
#endif
24
return pProc(hWnd, uMsg, wParam, lParam);
25
}
第11行初始化thunk, 该thunk会alloc内存,然后向该内存写入 mov hWnd, pthis; jmp wndProc这里的wndProc为成员函数 template <class TBase>
2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

INT_PTR CALLBACK CDialogImplBaseT< TBase >::DialogProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
CDialogImplBaseT< TBase >* pThis = (CDialogImplBaseT< TBase >*)hWnd;
...
看到该函数第一行直接将hWnd转换为类指针了吧, 其实这个hWnd是假的, 真正保存的的确是类指针, 该替换是在thunk里面做的
具体调用顺序为:
我们设置好wndProc (其实是这个thunk)
该窗口有消息来时,调用wndproc, 这里会对hWnd做一个替换,然后真正调用成员函数DialogProc
...over....
有时间仿照这个写一个简单的, 示范一下
- 上一篇 文件压缩解压算法.
- 下一篇 Javascript画图函数库jsgraphics.