按下一个快捷键,所有游戏窗口消失。再按一下,所有游戏窗口出现。
- 基本思路,注册 system-wide hotkey。
- 用到的API:RegisterHotKey/UnRegisterHotKey/GlobalAddAtom
对于同一个key组合,比如 Shift + D,只能有一次 RegisterHotKey(),再次注册会失败。
一个游戏多开,如何按下key组合,隐藏所有客户端呢?
- 每个客户端都尝试注册key组合,利用 RegisterHotKey() 会失败的特性,则只有一个游戏实例会注册成功
- key组合按下,EnumWindows() 遍历所有 windows
- 通过 GetClassName() 获得 WinClassName,利用唯一的 WinClassName 来隐藏所有客户端
游戏中可能会有外置聊天窗,有可能是通过 CreateDialog() 来创建的 HWND,通过 GetClassName() 得到这样的 "#32770 (Dialog)" 的 class name。
- 不能依赖这个名字去 show/hide window,可能会和其它进程 CreateDialog() 出来的 class name 重复。
- 应该由游戏程序自己去保证 chatwnd 跟随 main window 去 show/hide。可以在 WM_SHOWWINDOW 消息中处理 chatwnd。
在做 BossKey 的过程中,更深刻地理解了 win32 消息。
- 每个线程和每个窗体,都对应一个独立的msgqueue。
- GetMessage/PeekMessage 第二个参数传 -1,就是只获取 current thread msgqueue 中的消息。
thread-1 msgqueue
thread-2 msgqueue
...
hWnd-1 msgqueue
hWnd-2 msgqueue
...
实现了个 BossKey 的库,方便以后使用。
用例
#include "BossKey.h"
#include <stdio.h>
int main()
{
BossKey::Init("MyProduct"); // 同一物理机器都在用 BossKey 的时候,用来区别
BossKey::AddWindowClsName("HOTKEY"); // 控制 ClassName == "HOTKEY" 的窗体
BossKey::RegisterHotkey("Shift + D");
BossKey::RegisterHotkey("Ctrl + Shift + F10");
MSG msg;
while(GetMessage(&msg,(HWND)-1,0,0))
{
if(BossKey::Process(&msg))
continue;
...
}
// 不要忘记调用这个,GlobalAddAtom() 的返回值是 system-wide 的,需要显式地注销
BossKey::Shutdown();
return 0;
}