如何从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的主要内容,如果未能解决你的问题,请参考以下文章

如何从 c 代码中提取所有库函数的堆栈大小?

如何在 Android 主屏幕上增加图标大小?

XCTest Objective C Xcode8.1如何提取任何按钮或导航栏的标签/值/名称

如何从 SYCL 内核中提取控制流?

如何从 SYCL 内核中提取控制流?

如何确保 HTTP_REQUEST 来自正确的地方?