7
void WriteChar(char c)
{
    INPUT input = {0};
    input.type = INPUT_KEYBOARD;
    input.ki.wVk= VkKeyScanEx(c, GetKeyboardLayout(0) ) ;   
    SendInput(1,&input, sizeof(INPUT));
}

VkKeyScanEx 为'/'和'?'返回不同的键码(相同的键),但是如果你尝试使用这个方法写一个包含'?'的消息,它只会写'/'。我不知道发生了什么事。';' 也会发生同样的事情 和 ':'。

我部分不理解键码和扫描码。大多数字符都有一个虚拟键码,但是我找不到类似的问号。它们必须存在,但没有列出?

4

2 回答 2

9

扫描码是从键盘返回的原始键 ID。因此,101 键键盘(理论上)将有 101 个可以返回的唯一扫描码。(见脚注1

虚拟键代码是一组单独的代码,代表理想化键盘上的键。无论 TAB 键在真实键盘上的哪个位置,以及它使用什么扫描码,虚拟键码始终是 VK_TAB。 windows.h为不可打印的虚拟键定义 VK_xxx 代码,对于可打印的,虚拟键代码与 ASCII 值相同。

但虚拟键码仍然是键码。'A' 和 'a' 具有相同的虚拟键码,因此如果要发送 'A' 则必须向下发送 VK_SHIFT,然后向下发送 'a',然后向上发送 'a',然后向上发送 VK_SHIFT。

VkKeyScanEx()将字符转换为扫描键并转换状态请参阅此页面的以下引用http://msdn.microsoft.com/en-us/library/ms646332(VS.85).aspx

如果函数成功,返回值的低位字节包含虚拟键码,高位字节包含移位状态,可以是以下标志位的组合。

所以你不能只从 VkKeyScanEx() 中获取返回值,你需要检查它是否标记了 shift 键。并将 shift 键作为单独的击键发送

SHORT vk = VkKeyScanEx(c, ...);
if (vk & 0x100) // check upper byte for shift flag
{
   // send a shift key down
}
if (vk & 0x200) // check for ctrl flag
{
   // send a ctrl key down
}
input.ki.wVk = vk & 0xFF;

// send keyup for each of the keydown

您还必须为每个 keydown 发送一个 keyup。

脚注:

1这只是理论上的,实际上标准 PC 键盘会模拟您甚至无法再获得的旧 IBM 键盘,因此某些键可以根据另一个键返回 2 个不同的扫描码,而在其他情况下,两个键可以返回一样的扫码。

于 2010-01-30T07:42:02.143 回答
1

尝试这样做。如果您使用KEYEVENTF_UNICODE,则主机平台至少需要为 Windows 2000 或 XP。

INPUT input[ 2 ];

input[ 0 ].type = INPUT_KEYBOARD;
input[ 0 ].ki.wVk = 0;
input[ 0 ].ki.wScan = c;
input[ 0 ].ki.dwFlags = KEYEVENTF_UNICODE;
input[ 0 ].ki.time = 0;
input[ 0 ].ki.dwExtraInfo = GetMessageExtraInfo();

input[ 1 ].type = INPUT_KEYBOARD;
input[ 1 ].ki.wVk = 0;
input[ 1 ].ki.wScan = c;
input[ 1 ].ki.dwFlags = KEYEVENTF_UNICODE | KEYEVENTF_KEYUP;
input[ 1 ].ki.time = 0;
input[ 1 ].ki.dwExtraInfo = GetMessageExtraInfo();

SendInput( ( UINT )2, input, sizeof( *input ) );

从您没有正确填写输入结构并且未初始化一些必需的成员这一事实来看,我假设您还没有看到此文档。请参阅SendInputINPUTKEYBDINPUT

于 2010-01-30T07:25:11.340 回答