Title: Map keys with Application OnMessage
Question: This event gives you some possibilities to do mapping to user pressed keys.
For example, map Return to Tab, decimal point mapping, numlock mapping.
Answer:
The following code, that you have to use with Application OnMessage event, has
some examples of how to do keyboard mapping. But remember that some samples, like the 'Enter like Tab' have a major flaw. The problem is that because Application OnMessage occurs before all other events, the key will be maped before the control receive the message. This means that if you have for example a TMemo, the enter will be mapped, and you will not have the chance to use the enter to add a new line.
If you search D3k for some artcicles about mapping Enter to tab, you'll find some good articles.
Anyway here is the code:
procedure SetVKeyState(vkey: Byte; down: Boolean);
// This is a routine to help doing a key change
var
keys: TKeyboardState;
begin
GetKeyboardState(keys);
if Down then
keys[vkey] := keys[vkey] or $80
else
keys[vkey] := keys[vkey] and $7F;
SetKeyboardState(keys);
end;
procedure TForm1.ApplicationEventsMessage(var Msg: tagMSG; var Handled: Boolean);
var
cCode: Integer;
begin
case Msg.Message of
WM_KEYDOWN, WM_KEYUP:
begin
// Map Return to Tab
if (Msg.wParam = VK_RETURN) {and ((Msg.lParam and $1000000) 0) } then
// If you want to map only the numpad return key, uncomment the above condition
begin
Msg.wParam := VK_TAB;
Msg.lParam := MakeLParam(Loword(msg.lparam), MapVirtualkey(VK_TAB, 0) or
(HiWord(msg.lparam) and $FE00));
end;
// Map the '+' to 'Tab' and '-' to 'Shift-Tab'
case msg.wparam of
VK_ADD, VK_SUBTRACT:
begin
if Msg.wparam = VK_SUBTRACT then
SetVKeyState(VK_SHIFT, (Msg.Message = WM_KEYDOWN));
Msg.wparam := VK_TAB;
Msg.lparam := MakeLong(LoWord(msg.lparam),
(HiWord(Msg.lparam) and $FE00) + MapVirtualKey(Msg.wparam, 0));
end;
end;
// Map NumPad when NumLock not active
if (GetKeyState(VK_NUMLOCK) = 0) and ((Msg.lparam and $1000000) = 0) then
begin
ccode := 0;
case Msg.wparam of
VK_HOME: ccode := VK_NUMPAD7;
VK_UP: ccode := VK_NUMPAD8;
VK_PRIOR: ccode := VK_NUMPAD9;
VK_LEFT: ccode := VK_NUMPAD4;
VK_CLEAR: ccode := VK_NUMPAD5;
VK_RIGHT: ccode := VK_NUMPAD6;
VK_END: ccode := VK_NUMPAD1;
VK_DOWN: ccode := VK_NUMPAD2;
VK_NEXT: ccode := VK_NUMPAD3;
VK_INSERT: ccode := VK_NUMPAD0;
VK_DELETE: ccode := VK_DECIMAL;
end;
if ccode 0 then
Msg.Wparam := ccode;
end;
// Map decimal point to Windows Decimal Separator
if (Msg.wparam = VK_DECIMAL) then
begin
Msg.wparam := VkKeyScan(DecimalSeparator);
Msg.lparam := MakeLParam(LoWord(msg.lparam), (HiWord(Msg.lparam) and $FE00) +
MapVirtualKey(Msg.wparam, 0));
end;
end;
end;
end;