如何从WM_KeyUp或任何地方提取正确大小写的CharCode
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了如何从WM_KeyUp或任何地方提取正确大小写的CharCode相关的知识,希望对你有一定的参考价值。
我正在尝试处理WM_KeyUp消息,以区分大小写的方式识别按下了哪个字母数字键(如果有)。在TApplicationEvents中,我们有OnMessage处理程序,在我的项目中该处理程序分配给
procedure TForm1.DoOnAppMessage(var Msg: tagMSG; var Handled: Boolean);
var
CH : Char;
[...]
begin
Inc(MsgCount);
case Msg.Message of
WM_KeyUp : begin
CH := Chr(Msg.WParam);
// do something with CH
end;
end; case ]
就目前而言,这很好,当然我总是得到字母的大写形式。
因此,显然我需要解码Msg的LParam。到处搜寻我遇到了许多解码LParam的示例,但是我找不到任何交易我原本以为会得到呈现字母数字键的“简单”任务在正确的情况下。我的问是,请有人告诉我该怎么做。
请注意:我知道我可以通过处理WM_Char得到正确的大写字母讯息,但在现实生活中我无法使用(这是实际上在键盘挂钩中)。
答案
我基于较早的SO q&a找到了解决方案,其中涉及设置低级键盘挂钩。最初,当我尝试执行此操作时,得到的结果与q中发布的代码相同,即所有返回的字符均小写。
有趣的是,在没有大写字母和正确的大写字母-如下代码所示-是包含对GetKeyState的调用的四行之一,即KeyState[VK_SHIFT] := GetKeyState(VK_SHIFT)
。没有那个返回的字符都是小写字母(与我的q代码中的字符不同,都是大写的);
type
TOutProc = procedure(AString : String) of object;
var
OutProc : TOutProc; // requires assignment to a suitable proc in the host application
type
PKbdLlHookStruct = ^TKbdLlHookStruct;
TKbdLlHookStruct = packed record
vkCode: DWORD;
scanCode: DWORD;
flags: DWORD;
time: DWORD;
dwExtraInfo: DWORD;
end;
const
WH_KEYBOARD_LL = 13;
var
FKeyboardLayoutHandle: HKL;
hhkLowLevelKybd: HHOOK;
function LowLevelKeyBoardProc(nCode: Integer; awParam: WPARAM;
alParam: LPARAM): LRESULT; stdcall;
const
LLKHF_UP = $0080;
var
act: PKbdllHookStruct;
CH : Char;
S : String;
KeyState : TKeyboardState;
NewChar: array[0..1] of Char;
begin
// adapted from https://stackoverflow.com/q/1590983
if (nCode = HC_ACTION) then begin
case awParam of
WM_SYSKEYDOWN,
WM_KEYUP,
WM_SYSKEYUP: begin
act := PKbdLlHookStruct(alParam);
if awParam=WM_KEYUP then begin
FillChar(NewChar,2,#0);
GetKeyboardState(KeyState);
// Next four lines from https://stackoverflow.com/a/10480563
KeyState[VK_CAPITAL] := GetKeyState(VK_CAPITAL);
KeyState[VK_SHIFT] := GetKeyState(VK_SHIFT);
KeyState[VK_CONTROL] := GetKeyState(VK_CONTROL);
KeyState[VK_MENU] := GetKeyState(VK_MENU);
if ToAsciiEx(act^.vkCode, act^.scanCode, KeyState, NewChar, 0, FKeyboardLayoutHandle) = 1 then
CH := NewChar[0];
if (CH in [#8, #10, #13]) Or (CH >= ' ') then begin
S := CH;
OutProc(S);
GetClassName(GetForegroundWindow, @ClassBuffer, 100);
end;
end;
end; case
end; case
end;
Result := CallNextHookEx(hhkLowLevelKybd, nCode, awParam, alParam);
end;
以上是关于如何从WM_KeyUp或任何地方提取正确大小写的CharCode的主要内容,如果未能解决你的问题,请参考以下文章