ホーム >プログラム >Delphi 6 ローテクTips

Windows APIメモ GetAsyncKeyState

Windows APIのメモ。
GetAsyncKeyState。

function GetAsyncKeyState(vKey: Integer): SHORT; stdcall;

キーが押されているかどうかを判定するには、

function gfnbKeyState(iKey: Integer): Boolean;
begin
  //マウスの左右ボタンを入れ替えている場合に対処
  if (GetSystemMetrics(SM_SWAPBUTTON) <> 0) then
  begin
    if (iKey = VK_LBUTTON) then
    begin
      iKey := VK_RBUTTON;
    end else
    if (iKey = VK_RBUTTON) then
    begin
      iKey := VK_LBUTTON;
    end;
  end;

  Result := BOOL(Hi(GetAsyncKeyState(iKey)));
end;

とします。
入力フォーカスがないときでもタイマーを使ってこの関数を呼べばフックを使わなくてもキー入力を監視できます。
お手軽です。

上の例では最下位ビットの値は調べていませんが、きちんと最下位ビットの状態も調べて判定に加えるとよりよい判定ができるのではないかと思いました。
ということで実際にやってみた結果、マウスとキーボードで挙動が違うことが分かりました。
どちらもずっと押しっぱなしでやってみたところ Lo(li_Key) の値は、
マウスボタンの場合、押し始めの一回だけ1であとはずっと0が返ります。
キーボードのキーの場合、押し始めの一回が1であとはちょっとの間0が続き、その後ずっと1が返ります。
キーボードからの入力でキーを押しっぱなしにすると一回入力の後タイムラグがあり、その後ダダダダダと入力が続きます。
多分そのタイムラグ(ディレイタイム)なのであろうと思われます。
ということでキー入力のシミュレートをするにはこの最下位ビットを判定に加えるのが良いでしょう。

function gfnbKeyState(iKey: Integer): Boolean;
var
  li_Code: SHORT;
begin
  //マウスの左右ボタンを入れ替えている場合に対処
  if (GetSystemMetrics(SM_SWAPBUTTON) <> 0) then
  begin
    if (iKey = VK_LBUTTON) then
    begin
      iKey := VK_RBUTTON;
    end else
    if (iKey = VK_RBUTTON) then
    begin
      iKey := VK_LBUTTON;
    end;
  end;

  li_Code := GetAsyncKeyState(iKey);
  Result  := BOOL(Hi(li_Code)) and BOOL(Lo(li_Code));
end;

キー入力のシミュレートが目的ではなく、単にキーやマウスボタンが押されているかを調べたい場合は最上位ビットだけの判定の方が良いようです。
最下位ビットの判定も加えると、キーボードの場合ディレイタイムの間は取りこぼしがありますしマウスボタンの場合最初の一回だけしか押されていると判定されないので使いづらいと思われるので。