RegisterHotKey不认CHotKeyCtrl的帐

    程序的所谓热键,简单点来说就它的快捷键,特别适合去激活后台运行或已隐藏了窗口程序,为达同种目的,程序也可以弄个dll安装全局钩子,可当你理解了热键之后便会发现这种钩子方法可谓笨又烦。。。

      对于热键,及将几个特殊键组合在一起,由系统封装之后向程序发送WM_HOTKEY消息,接下来就是程序员的事了。为了让自己的程序能收到特定的热键消息,首先要向系统注册自定义热键,直接调用API RegisterHotKey( HWND hWnd,int id, UINT fsModifiers, UINT vk );其中fsModifiers以是MOD_ALT、CONTROL、KEYUP、SHIFT、WIN(ENTER)的组合,然后与vk一起组成热键,hwnd当然指明是谁要注册,而id一看就知道是热键的身份证了。接下来就可相应WM_HOTKEY消息了,如

void xxxx::OnHotKey(UINT nHotKeyId, UINT nKey1, UINT nKey2)
{
 // TODO: 在此添加消息处理程序代码和/或调用默认值
   if(!IsWindowVisible())
 {
  OnShellnotifyBegin();
 }
 CDialog::OnHotKey(nHotKeyId, nKey1, nKey2);
}

这种方法最简明了当了,可程序往往要求我们要与用户打交道,就是要能让用户手动设置热键,当我想到这个问题时我立马想到了在对话框上放两个个combo box,然后在一个得下拉列表中列出前面参数fsModifiers的可能组合项在,另一个放VK,乖乖,幸亏没试过......微软早就为我们想好,就是控件CHotKeyCtrl,这个控件很简单,就是给出个与CEdit很类似的输入框让用户直接往里输热键,当然它也是通用控件,有这一般的创建准则,这里直接在对话框拖一个,然后给它关联个CHotKeyCtrl的对象,如m_hotKey,然后就是对它的初始化,msdn推荐在对话框的初始化函数搞定,不错的建议:

m_hotKey.SetHotKey(m_wVirtualKeyCode,m_wModifiers);

它的参数是对话框的成员变量

WORD m_wVirtualKeyCode,m_wModifiers;//存放热键

 

在对话框的构造函数或初始化函数中

m_wVirtualKeyCode=VK_F2;
m_wModifiers=HOTKEYF_ALT;//默认alt+F2

之所以不用常量直接对它初始化,是因为我要用户能动态改变热键,每次修改的值都是放在这两个变量的

然后再对话框的ONOK函数中对热键进行存储和注册,这些都是要手动的,不要天真的以为

UpdateData(TRUE);就能搞定了,笑了。。

m_hotKey.GetHotKey(m_wVirtualKeyCode,m_wModifiers);//存储热键

接下来就是要注册热键了,这一点MSDN给出了两个方法,一个是通过发送WM_SETHOTKEY给需要热键的窗口(一般是对话框的父窗口),在OK中如此实现

WORD wKeyAndShift = m_HotKeyCtrl.GetHotKey( );
pMainWnd->SendMessage( WM_SETHOTKEY, wKeyAndShift );

然后pMainWnd响应WM_SYSCOMMAND消息
另一个就是上面提到的api注册,这个更简单明了,直接在上面的存储热键后

RegisterHotKey(AfxGetMainWnd()->m_hWnd,1,m_wModifiers,m_wVirtualKeyCode);
到此,在理论上来说,这个动态设置热键的工作已经完成了,可当你真的去设置一个之后,你会发现按那个热键,程序根本一点反应都没有,这种境况下是最郁闷的了,在仔细研读msdn后你发现其实你的做法是相当精确地,通过调试你很可能会发现上面的函数是返回非零的,热键已注册成功。。。。微软又要被我怀疑了~~

于是我猜测,是不是这个RegisterHotKey中的参数与CHotKey的GetHotKey()返回的不一致呢,于是我调出了这几个MODIFIERS的定义

#define HOTKEYF_SHIFT           0x01
#define HOTKEYF_CONTROL         0x02
#define HOTKEYF_ALT             0x04
#ifdef _MAC
#define HOTKEYF_EXT             0x80
#else
#define HOTKEYF_EXT             0x08

 

//上面的是CHotKeyCtrl对几个热键的定义,下面的是Api函数中引用的定义

 

#define MOD_ALT         0x0001
#define MOD_CONTROL     0x0002
#define MOD_SHIFT       0x0004
#define MOD_WIN         0x0008

仔细看下,是不是发觉他们很不一致呢,alt与shift的定义刚好相反!这就是问题所在了,难怪当我通过控件设置热键为Alt+F2时起作用的偏偏是Shift+F2了,微软太不厚道了。。。

解决方法:

//热键控件与registerhotkey不同!转化下
 if ((m_wModifiers & HOTKEYF_ALT) && !(m_wModifiers & HOTKEYF_SHIFT) )//Shift->ALt

 {
  m_wModifiers&=~HOTKEYF_ALT;
  m_wModifiers|=MOD_ALT;
  RegisterHotKey(AfxGetMainWnd()->m_hWnd,1,m_wModifiers,m_wVirtualKeyCode);
        //在恢复到CHotKeyCtrl,以便下次显示
  m_wModifiers|=HOTKEYF_ALT;
  m_wModifiers&=~MOD_ALT;
 }
 else if (!(m_wModifiers & HOTKEYF_ALT) && (m_wModifiers & HOTKEYF_SHIFT))//Alt->Shift
 {
  m_wModifiers&=~HOTKEYF_SHIFT;
  m_wModifiers|=MOD_SHIFT;
  RegisterHotKey(AfxGetMainWnd()->m_hWnd,1,m_wModifiers,m_wVirtualKeyCode);
       
  m_wModifiers|=HOTKEYF_SHIFT;
  m_wModifiers&=~MOD_SHIFT;  
 }
 else
        RegisterHotKey(AfxGetMainWnd()->m_hWnd,1,m_wModifiers,m_wVirtualKeyCode);

 

问题解决了!。。。有时微软真是让人又爱又恨。。。。

 

 

你可能感兴趣的:(工作,api,ext,存储,dll,微软)