C++ 注册全局热键而不禁用其密钥

C++ 注册全局热键而不禁用其密钥,c++,winapi,hotkeys,C++,Winapi,Hotkeys,我想制作一个可以捕捉键盘事件的程序,即使它在任何时刻都不处于活动状态。钩子太复杂了,我要做的所有事情(制作DLL,读取它,等等),所以我决定继续使用热键 但现在我有一个问题。注册热键将禁用键盘上的键,因此我只能将键发送到程序,而无法在任何其他程序(如记事本)上键入 这是我的代码: #include <iostream> #include <windows.h> using namespace std; int main(int argc, char* argv[]) {

我想制作一个可以捕捉键盘事件的程序,即使它在任何时刻都不处于活动状态。钩子太复杂了,我要做的所有事情(制作DLL,读取它,等等),所以我决定继续使用热键

但现在我有一个问题。注册热键将禁用键盘上的键,因此我只能将键发送到程序,而无法在任何其他程序(如记事本)上键入

这是我的代码:

#include <iostream>
#include <windows.h>
using namespace std;

int main(int argc, char* argv[]) {
    RegisterHotKey(NULL, 1, NULL, 0x41); //Register A
    MSG msg = {0};

    while (GetMessageA(&msg, NULL, 0, 0) != 0) {
        if (msg.message == WM_HOTKEY) {
            cout << "A"; //Print A if I pressed it
        }
    }

    UnregisterHotKey(NULL, 1);
    return 0;
}

// and now I can't type A's
#包括
#包括
使用名称空间std;
int main(int argc,char*argv[]){
RegisterHotKey(NULL,1,NULL,0x41);//寄存器A
MSG={0};
while(GetMessageA(&msg,NULL,0,0)!=0){
if(msg.message==WM_热键){

cout我会让您的程序模拟一个与您实际执行的按键相同的按键。这意味着:

  • 你按“A”
  • 该程序捕获“A”
  • 该程序模拟按键
  • 这很简单。唯一的问题是您的程序也会捕获模拟按键。要避免它,您可以执行以下操作:

  • 你按“A”
  • 该程序捕获“A”
  • 程序将注销热键
  • 该程序模拟按键
  • (程序没有(!)捕捉到“A”。)
  • 程序再次注册热键
  • 这就是整个循环

    现在,要模拟按键,您需要添加一些额外的代码。请看以下内容:

    #include <iostream>
    #include <windows.h>
    using namespace std;
    
    int main(int argc, char* argv[]) {
        RegisterHotKey(NULL, 1, 0, 0x41);            //Register A; Third argument should also be "0" instead of "NULL", so it is not seen as pointer argument
        MSG msg = {0};
        INPUT ip;
        ip.type = INPUT_KEYBOARD;
        ip.ki.wScan = 0;
        ip.ki.time = 0;
        ip.ki.dwExtraInfo = 0;
        ip.ki.wVk = 0x41;                            //The key to be pressed is A.
    
        while (GetMessage(&msg, NULL, 0, 0) != 0) {
            if (msg.message == WM_HOTKEY) {
                UnregisterHotKey(NULL, 1);           //Prevents the loop from caring about the following
                ip.ki.dwFlags = 0;                   //Prepares key down
                SendInput(1, &ip, sizeof(INPUT));    //Key down
                ip.ki.dwFlags = KEYEVENTF_KEYUP;     //Prepares key up
                SendInput(1, &ip, sizeof(INPUT));    //Key up
                cout << "A";                         //Print A if I pressed it
                RegisterHotKey(NULL, 1, 0, 0x41);    //you know...
            }
        }
    
        UnregisterHotKey(NULL, 1);
        return 0;
    }
    
    #包括
    #包括
    使用名称空间std;
    int main(int argc,char*argv[]){
    RegisterHotKey(NULL,1,0,0x41);//寄存器A;第三个参数也应该是“0”而不是“NULL”,因此它不被视为指针参数
    MSG={0};
    输入ip;
    ip.type=输入\键盘;
    ip.ki.wScan=0;
    ip.ki.time=0;
    ip.ki.dwExtraInfo=0;
    ip.ki.wVk=0x41;//要按下的键是A。
    while(GetMessage(&msg,NULL,0,0)!=0){
    if(msg.message==WM_热键){
    UnregisterHotKey(NULL,1);//防止循环关心以下内容
    ip.ki.dwFlags=0;//准备向下键
    SendInput(1,&ip,sizeof(INPUT));//向下键
    ip.ki.dwFlags=KEYEVENTF\u KEYUP;//准备密钥更新
    SendInput(1,&ip,sizeof(INPUT));//向上键
    
    如果缺点无关紧要,您可以使用非dll挂钩(带
    WH\u-KEYBOARD\u-LL
    )。所有这些都是一对钩子/解除钩子的调用和一个回调。用它做点什么,传递它。你也可以返回到循环
    GetAsyncKeyState
    。好吧,这就是钩子和热键之间的区别。钩子告诉你当按下它时,热键会覆盖默认处理。多亏了上面的评论,我做到了。谢谢!缺点使用nInputs参数等于1对
    SendInput
    的连续调用是一个bug。
    keybd_event
    SendInput
    之间的唯一区别是后者能够将整批输入以原子方式注入到输入队列中,这样它就不会与其他来源的输入交叉。