简体   繁体   English

winuser.h 键盘输入字符到十六进制转换

[英]winuser.h keyboard input char to hex convertion

I've been searching and testing this for a while now and haven't found an answer to the problem i have.我已经搜索和测试了一段时间,但还没有找到我遇到的问题的答案。

What i'm trying to do is make my own kind of library for mouse and keyboard simulated keypress.我想做的是为鼠标和键盘模拟按键创建自己的库。 I'm trying to do this for a fun little project where i can automate some tasks that are impossible to integrate with any other way.我正在尝试为一个有趣的小项目执行此操作,我可以在其中自动化一些无法与任何其他方式集成的任务。 Simulating a user this way would be handy.以这种方式模拟用户会很方便。

My problem lies with keyboard key presses.我的问题在于键盘按键。 to be more precise here's an example code for pressing the letter 'a' on the keyboard:更准确地说,这是在键盘上按下字母“a”的示例代码:

    INPUT inputs[2] = {};
    inputs[0].type = INPUT_KEYBOARD;
    inputs[0].ki.wVk = 0x41;

    inputs[1].type = INPUT_KEYBOARD;
    inputs[1].ki.wVk = 0x41;
    inputs[1].ki.dwFlags = KEYEVENTF_KEYUP;
    SendInput(ARRAYSIZE(inputs), inputs, sizeof(INPUT));

This works fine.这工作正常。 So i tried to make it into a variable:所以我试图把它变成一个变量:

void keyboardKeyPress(char key)
{
    INPUT inputs[2] = {};
    inputs[0].type = INPUT_KEYBOARD;
    inputs[0].ki.wVk = key;

    inputs[1].type = INPUT_KEYBOARD;
    inputs[1].ki.wVk = key;
    inputs[1].ki.dwFlags = KEYEVENTF_KEYUP;
    SendInput(ARRAYSIZE(inputs), inputs, sizeof(INPUT));
}

This also works fine.这也很好用。 BUT as soon as i iterate through a string using this function, it outputs something weird.但是一旦我使用这个 function 遍历一个字符串,它就会输出一些奇怪的东西。 i tested this with the string "hello" and it outputs "85/".我用字符串“hello”测试了它,它输出“85/”。 Here's the code i'm using:这是我正在使用的代码:

#include <iostream>
#include <cmath>
#include <windows.h>
#include <winuser.h>

using namespace std;

void keyboardKeyPress(char key)
{
    INPUT inputs[2] = {};
    inputs[0].type = INPUT_KEYBOARD;
    inputs[0].ki.wVk = key;

    inputs[1].type = INPUT_KEYBOARD;
    inputs[1].ki.wVk = key;
    inputs[1].ki.dwFlags = KEYEVENTF_KEYUP;
    SendInput(ARRAYSIZE(inputs), inputs, sizeof(INPUT));
}

void keyboardType(const string str)
{
    for(int i = 0; i < str.length(); i++)
    {
        keyboardKeyPress(str[i]);
    }

}

int main()
{
    keyboardKeyPress(65);
    keyboardKeyPress(66);
    keyboardKeyPress(' ');
    keyboardType("hello");
    return 0;
}

It outputs "ab 85/".它输出“ab 85/”。 I tried to do many things.我尝试做很多事情。 i realised you can use hex codes instead of chars because the.ki.wVk actually wants unsigned short's.我意识到你可以使用十六进制代码而不是字符,因为.ki.wVk 实际上想要无符号短。 it works when you plug the values in statically but as soon as you try to get the hex values from an eg unsigned short array, it goes back to displaying "85/".它在您静态插入值时起作用,但是一旦您尝试从例如无符号短数组中获取十六进制值,它就会返回显示“85 /”。 The array:数组:


WORD ascii[] = {
    0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
    0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F,
    0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
    0x18, 0x19, 0x1A, 0x1B, 0x1C, 0x1D, 0x1E, 0x1F,
    0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27,
    0x28, 0x29, 0x2A, 0x2B, 0x2C, 0x2D, 0x2E, 0x2F,
    0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37,
    0x38, 0x39, 0x3A, 0x3B, 0x3C, 0x3D, 0x3E, 0x3F,
    0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47,
    0x48, 0x49, 0x4A, 0x4B, 0x4C, 0x4D, 0x4E, 0x4F,
    0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57,
    0x58, 0x59, 0x5A, 0x5B, 0x5C, 0x5D, 0x5E, 0x5F,
    0x60, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67,
    0x68, 0x69, 0x6A, 0x6B, 0x6C, 0x6D, 0x6E, 0x6F,
    0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77,
    0x78, 0x79, 0x7A, 0x7B, 0x7C, 0x7D, 0x7E, 0x7F
};

The array index is basically the ascii integer number and the value stored is the unsigned short (or WORD from winuser).数组索引基本上是 ascii integer 数字,存储的值是 unsigned short(或来自 winuser 的 WORD)。 And here's the changed function:这是更改后的 function:

void keyboardKeyPress(char key)
{
    INPUT inputs[2] = {};
    inputs[0].type = INPUT_KEYBOARD;
    inputs[0].ki.wVk = ascii[int(key)];

    inputs[1].type = INPUT_KEYBOARD;
    inputs[1].ki.wVk = ascii[int(key)];
    inputs[1].ki.dwFlags = KEYEVENTF_KEYUP;
    SendInput(ARRAYSIZE(inputs), inputs, sizeof(INPUT));
}

Your functions don't work as expected because ASCII codes are not Virtual Key codes , though there is some overlap but not the way you think.您的功能无法按预期工作,因为ASCII 代码不是Virtual Key 代码,尽管有一些重叠但不是您想的那样。

The A and B keys on the keyboard are represented by virtual key codes VK_A (65/0x41) and VK_B (66/0x42), respectively.键盘上的AB键分别由虚拟键代码VK_A (65/0x41) 和VK_B (66/0x42) 表示。 They also happen to be the same values as the ASCII codes for the 'A' and 'B' characters, not the 'a' (97/0x61) and 'b' (98/0x62) characters.它们也恰好与'A''B'字符的 ASCII 码相同,而不是'a' (97/0x61)和'b' (98/0x62)字符。

When typing on a keyboard, uppercase and lowercase letters are differentiated by whether the Shift key (virtual key code VK_SHIFT , 16/0x10) is held down or not.在键盘上打字时,大小写字母通过Shift键(虚拟键码VK_SHIFT ,16/0x10)是否被按住来区分。

Since you are not simulating the Shift key being held down, that is why keyboardKeyPress(65) and keyboardKeyPress(66) are outputting a and b .由于您没有模拟按住 Shift键,这就是为什么keyboardKeyPress(65)keyboardKeyPress(66)输出ab

However, the ASCII code for the 'h' character (104/0x68) is the same value as the virtual key code VK_NUMPAD8 .但是, 'h'字符 (104/0x68) 的 ASCII 码与虚拟键码VK_NUMPAD8的值相同。 The H key on the keyboard is represented by virtual key code VK_H (72/0x48) instead.键盘上的H键由虚拟键代码VK_H (72/0x48) 表示。

The 'e' character is ASCII code 101/0x65, aka virtual key code VK_NUMPAD5 , not VK_E (69/0x45). 'e'字符是 ASCII 码 101/0x65,也就是虚拟键码VK_NUMPAD5 ,而不是VK_E (69/0x45)。

The 'l' character is ASCII code 108/0x6C, aka virtual key code VK_SEPARATOR (which does not represent any ASCII character), not VK_L (76/0x4C). 'l'字符是 ASCII 码 108/0x6C,也就是虚拟键码VK_SEPARATOR (不代表任何 ASCII 字符),而不是VK_L (76/0x4C)。

The 'o' character is ASCII code 111/0x6F, aka virtual key code VK_DIVIDE , not VK_O (79/0x4F). 'o'字符是 ASCII 码 111/0x6F,也就是虚拟键码VK_DIVIDE ,而不是VK_O (79/0x4F)。

That is why keyboardType("hello") is outputting 85/ .这就是为什么keyboardType("hello")输出85/的原因。

Also, your ascii[] array is useless, because it is simply mapping the character codes back to their original values as-is, not to the proper virtual key codes.此外,您的ascii[]数组是无用的,因为它只是将字符代码原样映射回其原始值,而不是正确的虚拟键代码。

So, to fix your code, you would have to get rid of the ascii[] array, and instead add additional logic to "hold down" the VK_SHIFT virtual key for an uppercase letter if it is not currently down, and "release" it for a lowercase letter if it is currently down.因此,要修复您的代码,您将不得不摆脱ascii[]数组,而是添加额外的逻辑来“按住” VK_SHIFT虚拟键的大写字母,如果它当前没有关闭,然后“释放”它如果当前已关闭,则为小写字母。 And then things get more complex if you need to deal with languages that have non-ASCII characters, etc.如果您需要处理具有非 ASCII 字符等的语言,事情就会变得更加复杂。

That said, simulating textual characters is much easier if you use the KEYEVENTF_UNICODE flag.也就是说,如果您使用KEYEVENTF_UNICODE标志,模拟文本字符会容易得多。 Use virtual key codes only for non-textual keys.仅对非文本键使用虚拟键代码。 And you should send the entire string as one atomic unit instead of sending each character individually (injecting multiple events atomically into the event queue is one of the key features of SendInput() over keybd_event() ).您应该将整个字符串作为一个原子单元发送,而不是单独发送每个字符(将多个事件原子地注入事件队列是SendInput() over keybd_event()的关键特性之一)。 See my previous answer for an example of using SendInput() with strings.有关将SendInput()与字符串一起使用的示例,请参见我之前的答案

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM