VkKeyScan returning same code without modifiers for accented and unaccented letter

匆匆过客 提交于 2019-12-23 01:57:51

问题


Background:

I am simulating keystrokes using the unmanaged function SendInput (https://msdn.microsoft.com/en-us/library/windows/desktop/ms646310(v=vs.85).aspx). There are 3 ways to call this function:

  1. Specify a keyboard scancode
  2. Specify a character unicode
  3. Specify a virtual key code

All work, but to be able to simulate shortcuts such as CTRL+P I want to use the virtual key code. I currently have a manual mapping of character to virtual key code, but this is not a good approach as it is not sensitive to the user's OS keyboard layout. For example on an English (UK) keyboard the "." character can be mapped to VirtualKeyCode.OEM_PERIOD, but if the OS keyboard layout is French then "." is VirtualKeyCode.OEM_PERIOD + SHIFT.

To make my code more robust I want to call the method VkKeyScan (https://msdn.microsoft.com/en-us/library/windows/desktop/ms646329(v=vs.85).aspx) passing in a character to get the virtual key code (plus shift/ctrl/alt). This approach, in theory, takes care of everything.

The problem:

Declaration:

[DllImport("user32.dll", CharSet = CharSet.Unicode)]
static extern short VkKeyScan(char ch);

Usage:

var vkKeyScanResult = PInvoke.VkKeyScan(character);
var vk = vkKeyScanResult & 0xff;
var shift = (vkKeyScanResult >> 8 & 1) == 1;
var ctrl = (vkKeyScanResult >> 8 & 2) == 1;
var alt = (vkKeyScanResult >> 8 & 4) == 1;

if (vk != -1)
{
  Log.InfoFormat("'{0}' => virtual key code {1}{2}{3}{4}", 
      character, vk, shift ? "+shift" : null, ctrl ? "+ctrl" : null, alt ? "+alt" : null);
}

With an OS keyboard layout of English (UK) I am seeing the following results:

  • 'e' => virtual key code 69
  • 'E' => virtual key code 69+shift
  • 'é' => virtual key code 69

N.B. 69 is 0x45 in HEX, which corresponds to the 'E' key in virtual key code lists such as this http://www.kbdedit.com/manual/low_level_vk_list.html

How can 'e' and 'é' both produce the same virtual key code? 'é' on an English (UK) keyboard is output by pressing 'e'+ctrl+alt or 'e'+altgr.

Theories:

  1. My code is wrong and I am not extracting the ctrl and alt bits correctly.
  2. VkScanKey doesn't work as I expect it to and is not capable of returning things like 'é' as 'e'+ctrl+alt (although the MSDN documentation suggests that it can).
  3. Something else.

回答1:


It looks like theory 1 - that I wasn't extracting the modifier bits correctly. This code works:

var vkKeyScan = PInvoke.VkKeyScan(character);
var vkCode = vkKeyScan & 0xff;
var shift = (vkKeyScan & 0x100) > 0;
var ctrl = (vkKeyScan & 0x200) > 0;
var alt = (vkKeyScan & 0x400) > 0;

So the problem was either something to do with the operator ordering (i.e. the & may have been taking priority over the >> (bit shift)), although I don't think so as I did try with brackets around the bit shift, OR the shift itself wasn't working as expected.

Here is the commit with working code if you're interested: https://github.com/JuliusSweetland/OptiKey/commit/0e61c52371638c61e0ef05834cd31a363181ea0d



来源:https://stackoverflow.com/questions/33523071/vkkeyscan-returning-same-code-without-modifiers-for-accented-and-unaccented-lett

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