Skip to content

Latest commit

 

History

History
65 lines (48 loc) · 2.25 KB

2012_03_04_boss_key.md

File metadata and controls

65 lines (48 loc) · 2.25 KB

[game-dev] 如何实现老板键

按下一个快捷键,所有游戏窗口消失。再按一下,所有游戏窗口出现。

  • 基本思路,注册 system-wide hotkey。
  • 用到的API:RegisterHotKey/UnRegisterHotKey/GlobalAddAtom

对于同一个key组合,比如 Shift + D,只能有一次 RegisterHotKey(),再次注册会失败。

一个游戏多开,如何按下key组合,隐藏所有客户端呢?

  1. 每个客户端都尝试注册key组合,利用 RegisterHotKey() 会失败的特性,则只有一个游戏实例会注册成功
  2. key组合按下,EnumWindows() 遍历所有 windows
  3. 通过 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; 
}