zoukankan      html  css  js  c++  java
  • emulate pressing a keyboard key

    emulate pressing a keyboard key

    SendInput() not equal to pressing key manually on keyboard in C++?

    I wanted to write a c++ code to emulate pressing a keyboard key "A":

    // Set up a generic keyboard event.
    ip.type = INPUT_KEYBOARD;
    ip.ki.wScan = 0; // hardware scan code for key
    ip.ki.time = 0;
    ip.ki.dwExtraInfo = 0;
    
    // Press the "..." key
    ip.ki.wVk = code; // virtual-key code for the "a" key
    ip.ki.dwFlags = 0; // 0 for key press
    SendInput(1, &ip, sizeof(INPUT));
    
    // Release the "..." key
    ip.ki.dwFlags = KEYEVENTF_KEYUP; // KEYEVENTF_KEYUP for key release
    SendInput(1, &ip, sizeof(INPUT));
    

    It works fine when I launch other program and wait to my program execute, the "A" is clicked and first program react to it. But I found that in the other application my action was somehow prevented (I can manually press "A" on keyboard, but using my program do not cause any action).

    So, what I can do to make pressing "A" from program more identical to manually pressed "A" (so the second program won't recognize that it was called from program)?

    I do not have source code of second program and do not know how it recognize that "A" wasn't pressed manually.

    I'm sure that the window I want to react to my code is foreground, receive and block my key (so it can decide that event doesn't come from user but from program).

    Answer

    You can use SendInput() to send hardware scan codes as well (as opposed to virtual scan codes, which DirectInput might ignore). It's poorly documented, but SendInput() can indeed bypass DirectInput. The reason Eric's solution didn't work is he set the hardware scan code, but ended up using a virtual scan code (by setting dwFlags to 0 and wVk to non-zero).

    Essentially, to do a key press you want to set:

    ip.ki.dwFlags = KEYEVENTF_SCANCODE;
    

    And to do a key release, set:

    ip.ki.dwFlags = KEYEVENTF_SCANCODE | KEYEVENTF_KEYUP;
    

    A full working sample is below and it prints the letter 'a'. You can find other scan codes here.

    #define WINVER 0x0500
    #include <windows.h>
    
    using namespace std;
    
    int main()
    {
    
        //Structure for the keyboard event
        INPUT ip;
    
        Sleep(5000);
    
        //Set up the INPUT structure
        ip.type = INPUT_KEYBOARD;
        ip.ki.time = 0;
        ip.ki.wVk = 0; //We're doing scan codes instead
        ip.ki.dwExtraInfo = 0;
    
        //This let's you do a hardware scan instead of a virtual keypress
        ip.ki.dwFlags = KEYEVENTF_SCANCODE;
        ip.ki.wScan = 0x1E;  //Set a unicode character to use (A)
    
        //Send the press
        SendInput(1, &ip, sizeof(INPUT));
    
        //Prepare a keyup event
        ip.ki.dwFlags = KEYEVENTF_SCANCODE | KEYEVENTF_KEYUP;
        SendInput(1, &ip, sizeof(INPUT));
    
    
    
        return 0;
    }
    

    Note: You can combine keypresses (like, shift + a for A) by passing SendInput() an array of INPUT structures.

    翻译

    我想编写一个c++代码来模拟按下键盘按键“ A”:

    // Set up a generic keyboard event.
    ip.type = INPUT_KEYBOARD;
    ip.ki.wScan = 0; // hardware scan code for key
    ip.ki.time = 0;
    ip.ki.dwExtraInfo = 0;
    
    // Press the "..." key
    ip.ki.wVk = code; // virtual-key code for the "a" key
    ip.ki.dwFlags = 0; // 0 for key press
    SendInput(1, &ip, sizeof(INPUT));
    
    // Release the "..." key
    ip.ki.dwFlags = KEYEVENTF_KEYUP; // KEYEVENTF_KEYUP for key release
    SendInput(1, &ip, sizeof(INPUT));
    


    当我启动其他程序并等待程序执行,单击“ A”并第一个程序对其做出反应时,它工作正常。但是我发现在另一个应用程序中,我的动作被某种程度上阻止了(我可以手动按下键盘上的“ A”,但是使用我的程序不会引起任何动作)。

    因此,我该怎么做才能使从程序中按“ A”与手动按“ A”更加相同(因此第二个程序将无法识别它是从程序中调用的)?

    我没有第二个程序的源代码,也不知道它如何识别“ A”不是手动按下的。

    我确定我想对我的代码作出反应的窗口是前台,接收并阻止我的密钥(这样它可以确定事件不是来自用户,而是来自程序)。
    最佳答案
    您还可以使用SendInput()发送硬件扫描代码(与虚拟扫描代码相对,DirectInput可能会忽略它们)。它的文档很少,但是SendInput()确实可以绕过DirectInput。 Eric的解决方案不起作用的原因是他设置了硬件扫描代码,但最终使用了虚拟扫描代码(通过将dwFlags设置为0并将wVk设置为非零)。

    本质上,要设置按键,您需要设置:

    ip.ki.dwFlags = KEYEVENTF_SCANCODE;
    


    并设置密钥:

    ip.ki.dwFlags = KEYEVENTF_SCANCODE | KEYEVENTF_KEYUP;
    


    下面是一个完整的工作示例,其中打印字母“ a”。您可以找到其他扫描代码here

    #define WINVER 0x0500
    #include <windows.h>
    
    using namespace std;
    
    int main()
    {
    
        //Structure for the keyboard event
        INPUT ip;
    
        Sleep(5000);
    
        //Set up the INPUT structure
        ip.type = INPUT_KEYBOARD;
        ip.ki.time = 0;
        ip.ki.wVk = 0; //We're doing scan codes instead
        ip.ki.dwExtraInfo = 0;
    
        //This let's you do a hardware scan instead of a virtual keypress
        ip.ki.dwFlags = KEYEVENTF_SCANCODE;
        ip.ki.wScan = 0x1E;  //Set a unicode character to use (A)
    
        //Send the press
        SendInput(1, &ip, sizeof(INPUT));
    
        //Prepare a keyup event
        ip.ki.dwFlags = KEYEVENTF_SCANCODE | KEYEVENTF_KEYUP;
        SendInput(1, &ip, sizeof(INPUT));
    
    
    
        return 0;
    }
    


    注意:您可以通过向SendInput()传递INPUT结构数组来组合按键(如A的shift + a)。
     

    ============ End

  • 相关阅读:
    seo课程教程笔记公布【网络转载】
    建立一个windows服务(可用于实现计划任务,事件监控..) .NET
    运行界面上,实现随意拖动控件 .NET
    定时关机的小程序 .NET
    服务 安装与删除 .NET
    模拟鼠标/键盘 .NET实现
    Google Code 创建开源项目
    一个批处理文件 启动停止服务.bat
    提升搜索引擎中网站排名的工具[持续更新中..]
    DateTime.Now.ToString()用法
  • 原文地址:https://www.cnblogs.com/lsgxeva/p/12884306.html
Copyright © 2011-2022 走看看