-2

这个简单的捕获键可以作为独立的 VCL 项目正常工作

unit Unit1;

interface

uses
  Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
  StdCtrls, DBCtrls, DBCGrids, Db, DBTables, ExtCtrls;

type
  TForm1 = class(TForm)
    Memo1: TMemo;
    Timer1: TTimer;
    Label1: TLabel;
    procedure Timer1Timer(Sender: TObject);
  private
    { Private declarations }
    FLastMsg: TMsg;

  public
    { Public declarations }
  end;

var
  Form1: TForm1;
  capturedWord:string;
implementation

{$R *.DFM}

function GetCharFromVirtualKey(Key: Word): string;
 var
    keyboardState: TKeyboardState;
    asciiResult: Integer;
 begin
    GetKeyboardState(keyboardState) ;

    SetLength(Result, 2) ;
    asciiResult := ToAscii(key, MapVirtualKey(key, 0), keyboardState, @Result[1], 0) ;
    case asciiResult of
      0: Result := '';
      1: SetLength(Result, 1) ;
      2:;
      else
        Result := '';
    end;
 end;

procedure TForm1.Timer1Timer(Sender: TObject);
var i,j:integer;
begin

  if ((GetAsyncKeyState(13) and 1) = 1) or ((GetAsyncKeyState(32) and 1) = 1) then begin;
      capturedWord:='';
      exit;
  end;
  For i:=32 to 128 do begin;
    if ((GetAsyncKeyState(i) and 1) = 1) then begin;
      capturedWord:=capturedWord + GetCharFromVirtualKey(i);
      capturedWord:=LowerCase(capturedWord);
       label1.Caption:=      (capturedWord);

      end;
    end;
  end;

end.

但是当我将它集成到我的项目中时,它会捕获中文或无意义的键!

知道为什么吗?

在此处输入图像描述

4

1 回答 1

1

你的方法没有意义。

WM_TIMER消息是低优先级的。如果消息队列拥有更高优先级的消息,则 WM_Timer 消息将无法通过。

从 Windows 1 开始就不需要轮询来获取密钥。
它只会得到输入的片段。

不要轮询键
最好放弃计时器方法并在表单中使用 OnKeyPress。
如果要捕获所有键 OnKeyDown 是要走的路。

procedure TForm1.FormCreate(Sender: TObject);
begin
  Self.KeyPreview:= true;  (*-- all keypresses get send to the form as well.*)
end;

//Takes dead keys into account
procedure TForm1.FormKeyDown(Sender: TObject; var Key: Word; Shift: TShiftState);
//                                             ^^^^^^^^^^^^^^
//                                             virtual key code.
begin
  case Key of 
    32: if Shift = ssShift then .....
end;

//Just shows the char pressed.
procedure TForm1.FormKeyPress(Sender: TObject; var Key: Char);
begin
  case Key of .....
end;

有关详细信息,请参阅联机帮助。

此外,轮询密钥是一种糟糕的方法,无论如何它会耗尽笔记本电脑的电池,因为它会阻止系统进入睡眠状态。如果您等待关键*事件,您的系统可以进入睡眠状态,从而节省电池电量。

于 2013-10-24T20:54:50.137 回答