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

℡╲_俬逩灬. 提交于 2019-11-26 07:39:47

问题


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).


回答1:


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.




回答2:


You often need to set the scan code:

// Set up a generic keyboard event.
ip.type = INPUT_KEYBOARD;
ip.ki.wScan = MapVirtualKey(code, MAPVK_VK_TO_VSC); // 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));

And building an array as IInspectable suggests is also definitely the way to go.




回答3:


If you are looking to create a game bot, have you looked at the program AutoHotKey? http://www.autohotkey.com/

It offers a scripting language, that allows you to do a lot of the tasks involved in 'bot' creation and it's rather easier than trying to do it all in C++

(It certainly played Farmville for me, when all my family pressured me into creating an account)



来源:https://stackoverflow.com/questions/18647053/sendinput-not-equal-to-pressing-key-manually-on-keyboard-in-c

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!