atl键盘钩子函数用法

前段时间因为参加个比赛要用atl做个三维控件,但是用atl写好的控件在c#里调用不能捕捉左边键盘的事件。修改了控件的很多属性,弄了很久还是解决不了,后来在网上偶遇键盘钩子的方法,然后抱着试一试的态度,竟然成功了,兴奋不已!现在没事弄,故记之。

 

1.目的:
  在用ATL写一个影像展现控件时,有一个需求,希望如windows使用习惯一样,用户可以按住Ctrl键选中多个  图片,松开Ctrl,鼠标再次点击时取消所选的图片.
  键盘钩子函数的作用是获得按键状态(按了什么键、重复多少次、Shift/Ctrl/Alt是什么状态,是Pressed 还是Released等).这里关心Ctrl是Pressed 还是Released,用一个全局bKeyBPress记录.

2.钩子函数
  控件的cpp文件里:
  extern HINSTANCE ghInstance;
  bool bKeyBPress=false;
  HHOOK   gkeyHook2=NULL;

LRESULT   CALLBACK   KeyBoardProc(int   nCode,   WPARAM   wparam,   LPARAM   lparam) 
{   
    if   (nCode>= 0)
    {    
        if(wparam==VK_CONTROL){
            if((DWORD)lparam&0x80000000){
                bKeyBPress=false;
            }
            else{
                bKeyBPress=true;
            }
        }      
    }
    return   CallNextHookEx(gkeyHook2,   nCode,   wparam,   lparam);
}

3.如何获得dll的ghInstance,如何注册钩子函数
  ghInstance实际定义在dllmain.cpp中,在DllMain中给它赋值.如下:
HINSTANCE ghInstance;
// DLL Entry Point
extern "C" BOOL WINAPI DllMain(HINSTANCE hInstance, DWORD dwReason, LPVOID lpReserved)
{
    hInstance;
    ghInstance=hInstance;
    return _AtlModule.DllMain(dwReason, lpReserved);
}

  控件的.h文件里:
  extern HHOOK gkeyHook2;
  extern LRESULT   CALLBACK   KeyBoardProc(int   nCode,   WPARAM   wparam,   LPARAM   lparam);

  在控件的OnCreate里注册:
  gkeyHook2=::SetWindowsHookEx(WH_KEYBOARD,KeyBoardProc,ghInstance,0);
  在FinalConstruct()中注销:
   ::UnhookWindowsHookEx(gkeyHook2);

4.剩下的事
  ctrl的按键状态已经在钩子函数里获得了,剩下的事就是在控件的OnLButtonDown事件里使用这个按键状态了.

5.在做这个功能时先用的方法是在控件的OnKeyDown和OnKeyUp事件里更新状态:
 LRESULT CNKIViewCtrl::OnKeyDown(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
{
    // TODO: Add your message handler code here and/or call default
    CComQIPtr<IWebBrowser2, &IID_IWebBrowser2> m_pWebBrowser2;
    HRESULT hrrs = CoCreateInstance(CLSID_WebBrowser, NULL,CLSCTX_INPROC,IID_IWebBrowser2,(void**)&m_pWebBrowser2);
    CComQIPtr<IOleInPlaceActiveObject,
        &IID_IOleInPlaceActiveObject>   pIOIPAO(m_pWebBrowser2);

    HRESULT   hr   =   S_FALSE;
    if   (pIOIPAO)
    {
        MSG   msg;
        msg.message   =   uMsg;
        msg.wParam   =   wParam;
        msg.lParam   =   lParam;        
        this->TranslateAccelerator(&msg);
      
        if   (wParam==17)
        {
            //do something
        }        
        bHandled=FALSE;
    }    
    return   hr;
}

起初的问题是控件根本没有接收KeyDown和KeyUp事件,百度后加了下面一段代码,
MESSAGE_HANDLER(WM_GETDLGCODE,   OnGetDlgCode)
LRESULT   OnGetDlgCode(UINT   uMsg,   WPARAM   wParam,   LPARAM   lParam,   BOOL&   bHandled)
{        
     return   DLGC_WANTARROWS;  
}
但也不是所有的键盘Down和up都能接收,所以最后用得键盘钩子的办法,效果终于对了.

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值