如何从 WM_KeyUp 或任何地方提取正确大小写的 CharCode
How to extract correctly cased CharCode from WM_KeyUp or whereever
我正在尝试处理 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 的例子,但是 none 我可以找到交易
我本以为 "simple" 任务是渲染字母数字键
在正确的情况下。我的问题是,有人可以告诉我该怎么做吗?
请注意:我知道我可以通过处理 WM_Char
消息,但我不能在我试图处理的现实生活中使用它(这是
实际上在键盘挂钩内)。
我找到了一个基于早期 SO q&a 的解决方案,其中涉及设置低级键盘挂钩。最初当我尝试这个时,我得到了与我的 q 中发布的代码相同的结果,即所有返回的字符都是小写的。
有趣的是,在没有大写和
正确的大小写 - 下面的代码所做的 - 是包含对 GetKeyState 的调用的 4 行之一,即 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 = [=10=]80;
var
act: PKbdllHookStruct;
CH : Char;
S : String;
KeyState : TKeyboardState;
NewChar: array[0..1] of Char;
begin
// adapted from
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
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 消息,以区分大小写的方式识别按下了哪个字母数字键(如果有)。在 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 的例子,但是 none 我可以找到交易 我本以为 "simple" 任务是渲染字母数字键 在正确的情况下。我的问题是,有人可以告诉我该怎么做吗?
请注意:我知道我可以通过处理 WM_Char 消息,但我不能在我试图处理的现实生活中使用它(这是 实际上在键盘挂钩内)。
我找到了一个基于早期 SO q&a 的解决方案,其中涉及设置低级键盘挂钩。最初当我尝试这个时,我得到了与我的 q 中发布的代码相同的结果,即所有返回的字符都是小写的。
有趣的是,在没有大写和
正确的大小写 - 下面的代码所做的 - 是包含对 GetKeyState 的调用的 4 行之一,即 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 = [=10=]80;
var
act: PKbdllHookStruct;
CH : Char;
S : String;
KeyState : TKeyboardState;
NewChar: array[0..1] of Char;
begin
// adapted from
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
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;