看流星社区

 找回密码
 注册账号
查看: 1839|回复: 0

Windows API 注册快捷键

[复制链接]

该用户从未签到

发表于 2016-9-21 14:27:51 | 显示全部楼层 |阅读模式

注册快捷键与hook监听键盘的区别

快捷键注册是针对某一个窗口的,注册之后当这个窗口收到快捷键,操作系统就会发送 WM_HOTKEY 消息来通知该窗口。所以快捷键注册是没办法监听全局的,比如你要定义一个快捷键 Ctrl + ` 在桌面上也能调出你的窗口,可是这个消息是发给桌面这个程序去了没办法触发你的程序。 快捷键收到消息之后消息会被转发给注册的hwnd 相当于截断了消息,如果要做全局监听的话还是推荐用 hook。

控制台注册快捷键

#include <stdio.h>
#include <Windows.h>

int main()
{
    MSG msg = {0};
    HWND hConsole = GetActiveWindow(); // 获取当前显示窗口的句柄(即控制台这个窗口的句柄)

    RegisterHotKey(
        hConsole,   // 注册快捷键的窗口句柄
        1,          // 热键标识符
        MOD_CONTROL | MOD_NOREPEAT, // Ctrl 键  No Repeat 不重复发送
        'A'         // A
    );  // Ctrl + A

    RegisterHotKey(hConsole, 2, MOD_CONTROL | MOD_NOREPEAT,'B');// Ctrl + B
    RegisterHotKey(hConsole, 3, MOD_ALT | MOD_NOREPEAT,'A');    // Alt + A
    RegisterHotKey(hConsole, 4, MOD_ALT | MOD_NOREPEAT,'B');    // Alt + B
    RegisterHotKey(hConsole, 5, MOD_NOREPEAT,'S');              // 直接按 S

    // 循环获取操作系统发来的消息
    while (GetMessage(&msg, NULL, 0, 0) != 0)
    {
        // 当收到快捷键消息时
        if (msg.message == WM_HOTKEY)
        {
            switch(msg.wParam)
            {
                case 1:
                    printf("Ctrl + A 被按下! \n\n");
                break;

                case 2:
                    printf("Ctrl + B 被按下! \n\n");
                break;

                case 3:
                    printf("Alt + A 被按下! \n\n");
                break;
                 
                case 4:
                    printf("Alt + B 被按下! \n\n");
                break;

                case 5:
                    printf("S 被按下! \n\n");
                break;
            }
        }
    }
}


hotkey_console

窗口注册快捷键

在window窗体开发中,窗口过程函数中实际上还可以通过 WM_KEYUP WM_KEYDOWN 等消息获取到用户的按键,大家可以通过如下类似的代码来查看窗口收到的消息(其实控制台下也是可以这样拿的)

case WM_KEYDOWN:
    wsprintf(text, "wParam : 0x%x  lParam : 0x%x", wParam, lParam);
    echo(text);
break;

不过这种的缺点也是很明显的,就是复合键等快捷键定义没有使用 WM_HOTKEY 方便

#include <Windows.h>

void echo(LPSTR str)
{
    MessageBox(NULL, str, TEXT("提示"), MB_OK);
}

// 5. 窗口过程处理
LRESULT CALLBACK WndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
{   
    CHAR text[50];
    switch(msg)
    {
    // 窗口创建消息
    case WM_CREATE:
        RegisterHotKey(
            hwnd,   // 注册快捷键的窗口句柄
            1,      // 热键标识符避免热键冲突
            MOD_CONTROL | MOD_NOREPEAT, // Ctrl 键  No Repeat 不重复发送
            'A'     // A
            ); // Ctrl + A
        RegisterHotKey(hwnd, 2, MOD_CONTROL | MOD_NOREPEAT,'B');// Ctrl + B
        RegisterHotKey(hwnd, 3, MOD_ALT | MOD_NOREPEAT,'A');    // Alt + A
        RegisterHotKey(hwnd, 4, MOD_ALT | MOD_NOREPEAT,'B');    // Alt + B
        RegisterHotKey(hwnd, 5, MOD_NOREPEAT,'S');              // 直接按 S
    break;

    // 快捷键消息
    case WM_HOTKEY:

        switch(wParam)
        {
            case 1:
                printf("Ctrl + A 被按下! \n\n");
            break;

            case 2:
                printf("Ctrl + B 被按下! \n\n");
            break;

            case 3:
                printf("Alt + A 被按下! \n\n");
            break;
            
            case 4:
                printf("Alt + B 被按下! \n\n");
            break;

            case 5:
                printf("S 被按下! \n\n");
            break;
        }      
    break;

    case WM_CLOSE:
        DestroyWindow(hwnd);
        break;
    case WM_DESTROY:
        PostQuitMessage(0);
        break;
    default:
        return DefWindowProc(hwnd, msg, wParam, lParam);
    }
    return 0;
}

int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,
    LPSTR lpCmdLine, int nCmdShow)
{
    WNDCLASSEX wc;
    HWND hwnd;
    MSG Msg;
    char text[30];

    const char szClassName[] = "myWindowClass";

    // 1. 设置注册窗口结构体
    wc.cbSize        = sizeof(WNDCLASSEX);              // 注册窗口结构体的大小
    wc.style         = 0;                               // 窗口的样式
    wc.lpfnWndProc   = WndProc;                         // 指向窗口处理过程的函数指针
    wc.cbClsExtra    = 0;                               // 指定紧跟在窗口类结构后的附加字节数
    wc.cbWndExtra    = 0;                               // 指定紧跟在窗口事例后的附加字节数
    wc.hInstance     = hInstance;                       // 本模块的实例句柄
    wc.hIcon         = LoadIcon(hInstance, IDI_APPLICATION);    // 图标的句柄
    wc.hCursor       = LoadCursor(NULL, IDC_ARROW);     // 光标的句柄
    wc.hbrBackground = (HBRUSH)(COLOR_WINDOW+1);        // 背景画刷的句柄
    wc.lpszMenuName  = NULL;                            // 指向菜单的指针
    wc.lpszClassName = szClassName;                     // 指向类名称的指针
    wc.hIconSm       = LoadIcon(hInstance, IDI_APPLICATION);    // 和窗口类关联的小图标

    // 2. 使用【窗口结构体】注册窗口
    if(!RegisterClassEx(&wc))
    {
        MessageBox(NULL, TEXT("窗口注册失败!"), TEXT("错误"), MB_ICONEXCLAMATION | MB_OK);
        return 0;
    }

    // 3. 创建窗口
    hwnd = CreateWindowEx(
        WS_EX_CLIENTEDGE,       // 窗口的扩展风格
        szClassName,            // 指向注册类名的指针
        TEXT("窗口标题"),       // 指向窗口名称的指针
        WS_OVERLAPPEDWINDOW,    // 窗口风格
        CW_USEDEFAULT, CW_USEDEFAULT, 350, 200, // 窗口的 x,y 坐标以及宽高
        NULL,                   // 父窗口的句柄
        NULL,                   // 菜单的句柄
        hInstance,              // 应用程序实例的句柄
        NULL                    // 指向窗口的创建数据
        );

    if(hwnd == NULL)
    {
        MessageBox(NULL, TEXT("窗口创建失败"), TEXT("错误"),MB_ICONEXCLAMATION | MB_OK);
        return 0;
    }

    // 4. 显示窗口
    ShowWindow(hwnd, nCmdShow);
    UpdateWindow(hwnd);

    // 6. 消息循环
    while(GetMessage(&Msg, NULL, 0, 0) > 0)
    {
        TranslateMessage(&Msg);
        DispatchMessage(&Msg);
    }
    return Msg.wParam;
}


hotkey_window

Ctrl + Alt 等复杂组合键

还是在控制台下编写例子,其实没有差多少

#include <stdio.h>
#include <Windows.h>

int main()
{
    MSG msg = {0};
    HWND hConsole = GetActiveWindow();

    // Ctrl + D
    RegisterHotKey(hConsole,1,MOD_CONTROL | MOD_NOREPEAT,'D');
    // Win键 + Z
    RegisterHotKey(hConsole,2,MOD_WIN | MOD_NOREPEAT,'Z');
    // Ctrl + Alt + S
    RegisterHotKey(hConsole,3,MOD_CONTROL | MOD_ALT | MOD_NOREPEAT,'S');
    // Ctrl + Alt + Shift + A
    RegisterHotKey(hConsole,4,MOD_CONTROL | MOD_ALT | MOD_SHIFT | MOD_NOREPEAT,'A');
     
    // 循环获取操作系统发来的消息
    while (GetMessage(&msg, NULL, 0, 0) != 0)
    {
        // 当收到快捷键消息时
        if (msg.message == WM_HOTKEY)
        {
            printf("收到 WM_HOTKEY 快捷键消息\n");
            printf("wParam : 0x%x  lParam : 0x%x \n", msg.wParam, msg.lParam);

            switch(msg.wParam)
            {
                case 1:
                    printf("Ctrl + D 被按下! \n\n");
                break

                case 2:
                    printf("Win + Z 被按下! \n\n");
                break

                case 3:
                    printf("Ctrl + Alt + S 被按下! \n\n");
                break

                case 4:
                    printf("Ctrl + Alt + Shift + A 被按下! \n\n");
                break
            }
        }
    }
}
点击按钮快速添加回复内容: 支持 高兴 激动 给力 加油 苦寻 生气 回帖 路过 感恩
您需要登录后才可以回帖 登录 | 注册账号

本版积分规则

小黑屋|手机版|Archiver|看流星社区 |网站地图

GMT+8, 2024-3-29 16:03

Powered by Kanliuxing X3.4

© 2010-2019 kanliuxing.com

快速回复 返回顶部 返回列表