凌云窟
南山巅上火麟烈,北海潜深雪饮寒。可怜两锋未缘见,雪刀封隐孤剑鸣。
<2006年2月>
2930311234
567891011
12131415161718
19202122232425
2627281234
567891011

留言簿(0)

随笔分类

随笔档案

文章档案

相册

简历下载

搜索

最新评论

阅读排行榜

评论排行榜

 
VC知识库BLOG   首页  新随笔  联系  聚合  登录 
  随笔-22 文章-0 评论-38 Trackbacks-0
2006年2月24日

概论:

     类的非static函数本身含有一个this指针,所以这种函数不能作为一个窗口过程(callback function )。当使用static函数来做一个窗口过程函数时,static函数可以通过编译,但是它本身无法访问类的成员函数和数据,如果我们能够得到类的指针并交给static函数处理则可以实现我们的要求。

技巧:

为了确保非static窗口过程能够处理所有的消息,所以我们使用了CBT Hook(),这样我们就可以在窗口创建之前把类的指针交给static的窗口过程,他就可以调用类的成员函数。

在这个过程当中,我们还使用了Thread Local Storage TLS)。

步骤:

1:分配一个TLS空间来保存this指针。

DWORD TlsIndex=::TlsAlloc();

  2: 声明一个结构体TLSData,将this指针和HHOOK句柄保存下来,将他的指针放在在TLS中。

TLSData* pTLSCreateData = new TLSData;

pTLSCreateData->hHook=hHook; //hHook=::SetWindowsHookEx(WH_CBT,

//CWin::StaticCBTProc, 0, ::GetCurrentThreadId());

pTLSCreateData->pThis = this;

::TlsSetValue(TlsIndex  //就是上面TlsIndex=::TlsAlloc();

, pTLSCreateData);

  3:在窗口创建之前,HCBT_CREATEWND 消息会发送给staticCBTProc也就是hHook的回调函数。

TLSData* pTLSCreateData = (TLSData*)TlsGetValue(TlsIndex);

~~~~~ * w = (~~~~~~*) pTLSCreateData->pThis;//~~~~~:表示对应的那个类。

::SetWindowLong((HWND) wParam, GWL_USERDATA, (LONG)w);

//说明;这里的pTLSCreateData->hHook,

//是给函数CallNextHookEx(pTLSCreateData->hHook, msg, wParam, lParam);服务的。

  4:在注册窗口类时,已经把一个static函数注册成为他的窗口过程,所以在这个函数中,我们把指针交给他处理。

~~~~~ *w = (~~~~~~*) (LONG)::GetWindowLong(hWnd, GWL_USERDATA);

return w->WndProc(hWnd, uMsg, wParam, lParam);

  5 :即时的

       ::UnhookWindowsHookEx(hHook);

       delete pTLSCreateData;

::TlsSetValue(TlsIndex, NULL);

说明:这篇随笔是从我以前的blog转过来的,感觉还有点价值,欢迎拍砖。

发表于 2006-02-24 18:19 莫问春秋 阅读(1656) | 评论 (0)编辑 收藏