I am trying to obtain keyboard scan codes from virtual key codes in a Windows Forms
application using the MapVirtualKey
Windows function. The declaration of the P/Invoke stuff is:
private const uint MAPVK_VK_TO_VSC = 0;
[DllImport("user32.dll",
CallingConvention = CallingConvention.StdCall,
CharSet = CharSet.Unicode,
EntryPoint = "MapVirtualKey",
SetLastError = true,
ThrowOnUnmappableChar = false)]
private static extern uint MapVirtualKey(
uint uCode,
uint uMapType);
I have overridden the OnPreviewKeyDown
method of my application main window class (derived from System.Windows.Forms.Form
); in here I take the value of the KeyCode
property of the given PreviewKeyDownEventArgs
object and pass it to the MapVirtualKey
method (I assume that the value is actually a virtual key code).
protected override void OnPreviewKeyDown(PreviewKeyDownEventArgs e)
{
uint uCode = (uint)e.KeyCode;
uint scanCode = MapVirtualKey(uCode, MAPVK_VK_TO_VSC);
this.HandleScanCode(scanCode);
base.OnPreviewKeyDown(e);
}
The problem is that I receive wrong scan codes for the arrow keys (I recieve scan codes for the num-pad arrow keys instead). For instance, if the up-arrow key is pressed, I expect the scan code to be 200 instead of 72.
It seems, that this problem belongs to enhanced keyboards only. The MapVirtualKey
method is agnostic to left- and right-hand key codes. This means, the key codes 38 Up
and 104 NumPad8
result in the same scan code because the Up
key is an enhanced key.
I decided to intercept the WM_KEYDOWN
message directly because the lParam
argument of that message contains both the wanted scan code and a bit indicating whether the key is an enhanced key, or not. This solved my problem...
protected override void WndProc(ref Message m)
{
base.WndProc(ref m);
switch (m.Msg)
{
case WM_KEYDOWN:
{
int lParam = m.LParam.ToInt32();
int scanCode = (lParam >> 16) & 0x000000ff; // extract bit 16-23
int ext = (lParam >> 24) & 0x00000001; // extract bit 24
if (ext == 1)
scanCode += 128;
this.HandleScanCode(scanCode);
break;
}
}
}
If a key is an enhanced key the wanted scan code can be calculated by adding 128.