• 検索結果がありません。

キーボードAPI関数

N/A
N/A
Protected

Academic year: 2021

シェア "キーボードAPI関数"

Copied!
10
0
0

読み込み中.... (全文を見る)

全文

(1)

■ GetKeyState と GetAsyncKeyState 判定するキーが多い場合は GetKeyboardState 関数で一気に状態を取得して、其れ程多くない場合は GetKeyState 関数か GetAsyncKeyState 関数を使用して、個別にキーの状態を取得するのが一般的で 有る。 GetKeyState 関数と GetAsyncKeyState 関数の区別は、キーが押されて直ぐに反映されるのが後者で (詰まり、キーが押されて発生するハードウェア割り込みに対応する)、リアルタイム性を重視するな ら此方を使用する事に成る。GetKeyState 関数は、メッセージキューに溜められたデータを観る様なの で、何かの処理中にキーが押されてもGetKeyState 関数は反映されない。 猶、GetAsyncKeyState 関数と GetKeyState 関数の孰れが速いかを調べる為に、夫々れ 100000 回実行 した処、下記の結果を得た(勿論、環境に依り値は変わる)。 GetAsyncKeyState 関数:31ms、GetKeyState 関数:47ms 矢 張 り 、 リ ア ル タ イ ム 性 重 視 な ら 、GetAsyncKeyState 関 数 を 使 う 可 き だ ろ う 。 因 み に GetKeyboardState 関数は 281ms で有った。 ■ GetAsyncKeyState 関数呼出時にキーが押されて居るか何うか、亦、前回のGetAsyncKeyState 関数呼出以降にキーが押さ れたか何うかを判定する。 関数定義 Visual Basic 6.0

Declare Function GetAsyncKeyState Lib "user32.dll" (ByVal vKey As Long) As Long Visual Basic 2005

Declare Function GetAsyncKeyState lib "user32.dll" (ByVal vKey As Integer) As Integer Private Declare Function GetAsyncKeyState Lib "user32" Alias "GetAsyncKeyState" ( _ ByVal vKey As Keys ) As Short

<DllImport("user32")> Shared Function GetAsyncKeyState( _ <[In]( )> ByVal vKey As VirtualKeyCodes) As Short

End Function C#

using System.Runtime.InteropServices; [DllImport("user32")]

static extern short GetAsyncKeyState(Keys vKey); C/C++ SHORT GetAsyncKeyState( int vKey // 仮想キーコード );

(2)

パラメータ

vKey:最大 256 通りの仮想キーコードの孰れかを指定する。

GetAsyncKeyState 関数は、32 ビットの引数を取る。Visual Basic 2005 や Visual C# 2005 では此の引 数に、Keys 列挙体を利用する事が出来る。 戻り値 関数が成功すると、前回のGetAsyncKeyState 関数呼出以降にキーが押されたか何うか、及び、キーが 現在押されて居るか何うかを示す値が返る。下位2 バイトの最上位ビットがセットされた時、現在其の キーが押されて居る事を示し、最下位ビットがセットされた時、前回のGetAsyncKeyState 関数呼出以 降に其のキーが押された事を示す。他のスレッド(又はプロセス)のウィンドウがキーボードフォーカ スを備えて居る場合は、0 が返る。 スキャンする仮想キーコード 通常のキーボードに配置されて居るキーが対象と成る。 解説 GetAsyncKeyState 関数は、マウスボタンの状態も取得出来る。但し、此の関数は、物理的なボタンの マップ先で有る論理的なマウスボタンの状態では無く、物理的なマウスボタンの状態を取得する。例え ば、GetAsyncKeyState(VK_LBUTTON) を呼び出すと、其のボタンが論理的な左ボタンと右ボタンの 孰れに割り当てられて居るかに関り無く(後者は「左利き用」の割り当て)、常に物理的な左ボタンの 状態を返す。物理的なマウスボタンと論理的なマウスボタンの対応を調べるには、次の呼出を行う。 GetSystemMetrics(SM_SWAPBUTTON) 上記の呼出は、マウスボタンの左右が入れ替わって居る時にTRUE を返す。 vKey パラメータの値と仕て、VK_SHIFT、VK_CONTROL、VK_MENU の各仮想キーコード定数を 指定出来る。此の場合、左右を区別する事無く、Shift、Ctrl、Alt の各キーの状態を取得出来る。 ■ 使用例 GetAsyncKeyState 関数の使用は簡単で、例えば、下記のコードは、エンドユーザーが Ctrl+A キーの 組み合わせでタイプしたか何うかを調査して居る。 Visual Basic 2005

If GetAsyncKeyState(Keys.A) < 0 And GetAsyncKeyState(Keys.ControlKey) < 0 Then ' Ctrl+A キーが押された

End If C#

if ( GetAsyncKeyState(Keys.A) < 0 && GetAsyncKeyState(Keys.ControlKey) < 0 ) { // Ctrl+A キーが押された

(3)

上記コードを、Interval プロパティの値を充分に小さくした(例えば 200 ミリ秒)Timer コントロール のTick イベントで動かせば、調べ度い総てのホットキーをトラップ出来る様に成る。 併し、此の方法では、Timer コントロールのインターバル間隔が短いと、アプリケーションにより多く のオーバーヘッドを加えて了う事に成り、更に、GetAsyncKeyState のドキュメントに依れば、Windows NT、2000、XP の時に、カレントデスクトップがアクティブなデスクトップでは無い場合や、デスクト ップの設定に依り、エンドユーザーが押したキーがバックグラウンドアプリケーションに知られない様 に保護されて居て、アプリケーションがフォアグラウンド状態で無い場合には、0 を返す可能性が有る と記述されて居る。 此の様な場合、オーバーヘッドを回避する為、RegisterHotKey 関数を使用して、グローバルなホット キーを登録する方法を取ると良い。RegisterHotKey 関数の宣言は、下記の通りで有る。 Visual Basic 2005

Declare Function RegisterHotKey Lib "user32" ( _ ByVal hwnd As IntPtr, _

ByVal id As Integer, _

ByVal fsModifiers As Integer, _ ByVal vk As Keys _

) As Integer C#

[DllImport("user32")]

static extern int RegisterHotKey( IntPtr hwnd, int id,

int fsModifiers, Keys vk); hwnd は、最後の 2 個の引数に依って指定されたホットキーがエンドユーザーに依って押された時、 WM_HOTKEY メッセージを受け取るウィンドウのハンドルで有る。 引数id は、ホットキーを区別する識別子で有り、システムに登録された夫々れのグローバルキーと違っ た物でなければ成らない。アプリケーションがシャットダウンする時には、登録したグローバルホット キー情報を解除する為、UnregisterHotKey 関数を呼び出す必要が有る。 アプリケーションのメインフォームが読み込まれた場合にホットキーを登録し、サブクラスでホットキ ーをトラップし、フォームが閉じられた際にホットキーを解放するプログラムは、下記のリストの様に 成る。 クラスの夫々れのインスタンスに唯一無二の ID を作成するには、マイクロソフトのドキュメントで推 奨されて居る様に、GlobalAddAtom 関数を用いる。 幾つかのAPI を呼び、亦、フォームの WndProc メソッドをオーバーライドする事で、入力フォーカス を有して居ない時に、エンドユーザーが与えられたキーの組み合わせの通知を受けられる様にするには、 以下のコードをWindows フォームクラスに追加する。

(4)

Visual Basic 2005

' Windows API functions and constants

Private Declare Function RegisterHotKey Lib "user32" ( _ ByVal hwnd As IntPtr, _

ByVal id As Integer, _

ByVal fsModifiers As Integer, _ ByVal vk As Keys _

) As Integer

Private Declare Function UnregisterHotKey Lib "user32" ( _ ByVal hwnd As IntPtr, _

ByVal id As Integer _ ) As Integer

Private Declare Function GlobalAddAtom Lib "kernel32" Alias "GlobalAddAtomA" ( _ ByVal lpString As String _

) As Short

Private Declare Function GlobalDeleteAtom Lib "kernel32" ( _ ByVal nAtom As Short _

) As Short

Private Const MOD_ALT As Integer = &H1 Private Const MOD_CONTROL As Integer = &H2 Private Const MOD_SHIFT As Integer = &H4 Private Const MOD_WIN As Integer = &H8 Private Const WM_HOTKEY As Integer = &H312 Private hotkeyID As Short

Sub Form1_Load(ByVal sender As Object, ByVal e As System.EventArgs) _ Handles MyBase.Load

' ホットキーのために唯一無二の ID を生成する

hotkeyID = GlobalAddAtom("GlobalHotKey " & Me.GetHashCode( ).ToString( )) ' Ctrl+A キーを登録する

RegisterHotKey(Me.Handle, hotkeyID, MOD_CONTROL, Keys.A) End Sub

Sub Form1_Closing(ByVal sender As Object, _

ByVal e As System.ComponentModel.CancelEventArgs) Handles MyBase.Closing ' ホットキーの登録を解除し、アトムを削除する

UnregisterHotKey(Me.Handle, hotkeyID) GlobalDeleteAtom(hotkeyID)

End Sub

Protected Overrides Sub WndProc( ByRef m As Message) MyBase.WndProc(m) If m.Msg = WM_HOTKEY Then ' ホットキーが押されたときの処理 Debug.WriteLine("WndProc: CTRL+A") End If End Sub

(5)

C#

// Windows API functions and constants [DllImport("user32")]

static extern int RegisterHotKey(IntPtr hwnd, int id, int fsModifiers, Keys vk) ; [DllImport("user32")]

static extern int UnregisterHotKey(IntPtr hwnd, int id); [DllImport("kernel32", EntryPoint="GlobalAddAtomA")] static extern short GlobalAddAtom(string lpString); [DllImport("kernel32")]

static extern short GlobalDeleteAtom (short nAtom); private const int MOD_ALT = 0x01;

private const int MOD_CONTROL = 0x02; private const int MOD_SHIFT = 0x04; private const int MOD_WIN = 0x08; private const int WM_HOTKEY = 0x312; short hotkeyID;

void Form1_Load(object sender, EventArgs e) {

// ホットキーのために唯一無二の ID を生成する

hotkeyID = GlobalAddAtom("GlobalHotKey " + this.GetHashCode().ToString()); // Ctrl+A キーを登録する

RegisterHotKey(this.Handle, hotkeyID, MOD_CONTROL, Keys.A); }

void Form1_Closing(object sender, System.ComponentModel.CancelEventArgs e) {

// ホットキーの登録を解除し、アトムを削除する UnregisterHotKey(this.Handle, hotkeyID); GlobalDeleteAtom(hotkeyID);

}

protected override void WndProc(ref Message m) { base.WndProc(ref m); if ( m.Msg == WM_HOTKEY ) { // ホットキーが押されたときの処理 Debug.WriteLine("Ctrl+A"); } } 猶、上記のリストに示したコードには、フォームのクラス内部から呼び出された場合而巳の動作と謂う 制限が有る。

(6)

■ GetKeyState

指定された仮想キーの状態を取得する。状態とは、キーが押されて居るか、押されて居ないか、トグル に成って居るか何うか(オンとオフの2 つが有り、キーを押す度に入れ替わる)を表す。

関数定義 Visual Basic

Private Declare Function GetKeyState Lib "user32" (ByVal nVirtKey As Integer) As Short C/C++、C# SHORT GetKeyState( int nVirtKey // 仮想キーコード ); パラメータ nVirtKey:仮想キーコードを指定する。 希望の仮想キーが、文字キーか数字キー(A~Z、a~z、0~9)で有る場合、nVirtKey に其の文字の ASCII コードを指定し、他のキーの場合は、仮想キーコードを指定する。 欧州等の英語以外のキーボードレイアウトを使用して居る場合、A~Z と 0~9 の各範囲に相当する ASCII コードは、アクセント付きを含め、殆どの文字を表す為に使われて居る。例えば、独語のキーボ ードレイアウトでは、ASCII の「O」(0x4F)の値に相当する仮想キーは「o」キーを意味するが、 VK_OEM_1 は「ウムラウト(¨)付きの o」キーを意味する。 戻り値 戻り値は、指定された仮想キーの状態を表す。最上位ビットが1 の時はキーが押されて居る事を、0 の 時はキーが押されて居ない事を示す。 最下位ビットが1 の時はキーがトグル状態に有る事を示す。例えば、CapsLock キーが ON に成って居 る時は、トグル状態に成る。最下位ビットが0 の時はキーが OFF に成って居て、トグルが解除されて 居る事を示す。キーボードにトグルキーのインジケータランプが用意されて居る場合、キーがトグル状 態に成って居るとランプは点灯し、トグル解除状態ではランプは消灯する。 解説 スレッドがメッセージキューからキーメッセージを読み出す度に、此の関数が返すキーの状態は変化す る。キーの状態は、ハードウェアに依る割り込みレベルの状態を反映しない。割り込みレベルの情報を 取得するには、GetAsyncKeyState 関数を使用する。 アプリケーションは、キーボード入力メッセージに応じて GetKeyState を呼び出す。此の関数は、入 力メッセージが生成された時のキーの状態を取得する。 総ての仮想キーの状態を取得するには、GetKeyboardState 関数を使用する。

(7)

アプリケーションはnVirtKey パラメータの値と仕て、VK_SHIFT、VK_CONTROL、VK_MENU の 各仮想キーコード定数を使用する事が出来る。此の場合、左右を区別する事無く、Shift、Ctrl、Alt の 各キーの状態を取得出来る。亦、アプリケーションはnVirtKey の値と仕て次の仮想キーコード定数を 使う事に依り、此等のキーの左右を区別する事が出来る。 VK_LSHIFT VK_RSHIFT VK_LCONTROL VK_RCONTROL VK_LMENU VK_RMENU ■ GetKeyboardState 256 個の仮想キーの状態を、指定されたバッファへコピーする。 関数定義 Visual Basic

Declare Function GetKeyboardState lib "user32.dll" _ (ByRef pbKeyState As Byte) As Integer

C/C++、C# BOOL GetKeyboardState( PBYTE lpKeyState // 状態データの配列 ); パラメータ lpKeyState:総ての仮想キーの状態を保持する 256 バイトの配列へのポインタを指定する。 戻り値 関数が成功すると、0 以外の値が返る。関数が失敗すると、0 が返る。 解説 アプリケーションは此の関数を呼び出して、総ての仮想キーの現在の状態を一度に取得出来る。スレッ ドがメッセージキューからキーボードメッセージを削除すると、仮想キーの状態が変化する。キーボー ドメッセージがスレッドのメッセージキューにポストされたり、他のスレッドのメッセージキューへの キーボードメッセージのポストや削除が発生しても、状態は変化しない。 此の関数から制御が返ると、lpKeyState パラメータが指す配列の各メンバは、各仮想キーの状態デー タを保持する。最上位ビットが1 の時はキーが押されて居る事を、0 の時はキーが押されて居ない事を 示す。最下位ビットが1 の時はキーがトグル状態に有る事を、0 の時はトグルが解除されて居る事を示 す。例えば、CapsLock キーが ON に成って居る時は、トグル状態に成る。最下位ビットが 0 に成って 居る場合、キーは OFF で、トグルが解除されて居る事を意味する。キーボードにトグルキーのインジ ケータランプが用意されて居る場合、キーがトグル状態に成って居るとランプは点灯し、トグル解除状 態ではランプは消灯する。

(8)

個別のキーに関する状態情報を取得するには、GetKeyState 関数を使用する。対応するキーボードメ ッセージがメッセージキューから取得されたか何うかに関り無く、個別のキーの現在の状態を取得する には、GetAsyncKeyState 関数を使用する。 アプリケーションは lpKeyState パラメータが指す配列へのインデックスと仕て、VK_SHIFT、 VK_CONTROL、VK_MENU の各仮想キーコード定数を使用する事が出来る。此の場合、左右を区別 する事無く、Shift、Ctrl、Alt の各キーの状態を取得出来る。亦、アプリケーションはインデックスと 仕て次の仮想キーコード定数を使う事に依り、此等のキーの左右を区別出来る。 VK_LSHIFT、VK_RSHIFT、VK_LCONTROL、VK_RCONTROL、VK_LMENU、VK_RMENU ■ 使用法 Visual Basic 2005 ' API 関数の宣言

Declare Function GetKeyboardState Lib "user32" (ByRef pbKeyState As Byte) As Integer ' API 関数の呼出

Dim keys(255) as Byte

Call GetKeyboardState(keys(0)) ■ 参考

従来のN88BASIC の INP 関数に依るキースキャンが此の方式で有る。INP 関数の引数に E0H~ECH

のポート番号を指定して呼び出し、押されて居るキーを取得する。 戻り値は、1 バイトのデータで、各ビットのデータが、キーの押し下げに対応する。即ち、押し下げら れて居るキーに対応するビットが0、押し下げられて居ないキーに対応するビットが 1 に成る(従って、 何もキーが押されて居ない状態では、FFHが返される)。 アドレスパス(ポート番号)とデータパスの対応を下記に示す。猶、D0 が最下位ビット、D7 が最上位 ビットで有る。 D7 D6 D5 D4 D3 D2 D1 D0 E0 7 6 5 4 3 2 1 0 E1 Return . , = + * 9 8 E2 G F E D C B A @ E3 O N M L K J I H E4 W V U T S R Q P E5 = ^ } \ } Z Y X E6 ' & % $ # " ! 0 E7 _ ? > < + * ) (

E8 Ctrl Shift カナ Grph Del → ↑ Home

E9 Esc Space F5 F4 F3 F2 F1 Stop

EA Caps / - Copy Help ← ↓ Tab

EB RollDn RollUp

(9)

例えば、INP( &HE8) と仕た時、『→』キーが押されて居れば、戻り値は、11111011B(FBH)と成り

Shift キーが併用されて居れば、戻り値は、10111011B(BBH)と成る。

此れは、リアルタイム入力を取得する方法と仕て、良く用いられた方法で有るので、昔のゲーム等をリ メイクする場合には、参考に成ると思う。

■ キーコード定数の定義

Private Const VK_LBUTTON = &H1 'マウス左ボタン Private Const VK_RBUTTON = &H2 'マウス右ボタン Private Const VK_CANCEL = &H3 '[Cancel]

Private Const VK_MBUTTON = &H4 'マウスの中央ボタン Private Const VK_BACK = &H8 '[Back Space]

Private Const VK_TAB = &H9 '[TAB] Private Const VK_CLEAR = &HC '[Clear] Private Const VK_RETURN = &HD '[Enter] Private Const VK_SHIFT = &H10 '[Shift] Private Const VK_RSHIFT = &HA1 '[右 Shift] Private Const VK_CONTROL = &H11 '[Control] Private Const VK_RCONTROL = &HA3 '[右 Control] Private Const VK_MENU = &H12 '[Menu]

Private Const VK_RMENU = &HA5 '[右 Menu] Private Const VK_PAUSE = &H13 '[Pause] Private Const VK_CAPITAL = &H14 '[Caps Lock] Private Const VK_ESCAPE = &H1B '[Esc]

Private Const VK_SPACE = &H20 '[Space] Private Const VK_PRIOR = &H21 '[Page Up] Private Const VK_NEXT = &H22 '[Page Down] Private Const VK_END = &H23 '[End]

Private Const VK_HOME = &H24 '[Home] Private Const VK_LEFT = &H25 '[←] Private Const VK_UP = &H26 '[↑] Private Const VK_RIGHT = &H27 '[→] Private Const VK_DOWN = &H28 '[↓] Private Const VK_SELECT = &H29 '[Select] Private Const VK_PRINT = &H2A '[Print Screen] Private Const VK_EXECUTE = &H2B '[Execute] Private Const VK_SNAPSHOT = &H2C '[Snap Shot] Private Const VK_INSERT = &H2D '[Insert]

Private Const VK_DELETE = &H2E '[Delete] Private Const VK_HELP = &H2F '[Help]

Private Const VK_NUMPAD0 = &H60 'テンキーの[0] Private Const VK_NUMPAD1 = &H61 'テンキーの[1] Private Const VK_NUMPAD2 = &H62 'テンキーの[2] Private Const VK_NUMPAD3 = &H63 'テンキーの[3] Private Const VK_NUMPAD4 = &H64 'テンキーの[4] Private Const VK_NUMPAD5 = &H65 'テンキーの[5] Private Const VK_NUMPAD6 = &H66 'テンキーの[6] Private Const VK_NUMPAD7 = &H67 'テンキーの[7] Private Const VK_NUMPAD8 = &H68 'テンキーの[8] Private Const VK_NUMPAD9 = &H69 'テンキーの[9] Private Const VK_MULTIPLY = &H6A 'テンキーの[*]

(10)

Private Const VK_ADD = &H6B 'テンキーの[+]

Private Const VK_SEPARATOR = &H6C 'テンキーの[Enter] Private Const VK_SUBTRACT = &H6D 'テンキーの[-] Private Const VK_DECIMAL = &H6E 'テンキーの[.] Private Const VK_DIVIDE = &H6F 'テンキーの[/] Private Const VK_F1 = &H70 '[F1]

Private Const VK_F2 = &H71 '[F2] Private Const VK_F3 = &H72 '[F3] Private Const VK_F4 = &H73 '[F4] Private Const VK_F5 = &H74 '[F5] Private Const VK_F6 = &H75 '[F6] Private Const VK_F7 = &H76 '[F7] Private Const VK_F8 = &H77 '[F8] Private Const VK_F9 = &H78 '[F9] Private Const VK_F10 = &H79 '[F10] Private Const VK_F11 = &H7A '[F11] Private Const VK_F12 = &H7B '[F12] Private Const VK_F13 = &H7C '[F13] Private Const VK_F14 = &H7D '[F14] Private Const VK_F15 = &H7E '[F15] Private Const VK_F16 = &H7F '[F16] Private Const VK_F17 = &H80 '[F17] Private Const VK_F18 = &H81 '[F18] Private Const VK_F19 = &H82 '[F19] Private Const VK_F20 = &H83 '[F20] Private Const VK_F21 = &H84 '[F21] Private Const VK_F22 = &H85 '[F22] Private Const VK_F23 = &H86 '[F23] Private Const VK_F24 = &H87 '[F24]

参照

関連したドキュメント

Research Institute for Mathematical Sciences, Kyoto University...

東京都は他の道府県とは値が離れているように見える。相関係数はこう

これはつまり十進法ではなく、一進法を用いて自然数を表記するということである。とは いえ数が大きくなると見にくくなるので、.. 0, 1,

Bluetooth® Low Energy プロトコルスタック GUI ツールは、Microsoft Visual Studio 2012 でビルドされた C++アプリケーションです。GUI

(注)本報告書に掲載している数値は端数を四捨五入しているため、表中の数値の合計が表に示されている合計

貸借若しくは贈与に関する取引(第四項に規定するものを除く。)(以下「役務取引等」という。)が何らの

、肩 かた 深 ふかさ を掛け合わせて、ある定数で 割り、積石数を算出する近似計算法が 使われるようになりました。この定数は船

いてもらう権利﹂に関するものである︒また︑多数意見は本件の争点を歪曲した︒というのは︑第一に︑多数意見は