■ マウスやキーボードのイベントを取得する
業務用アプリケーションのプログラムとゲームプログラムの一番大きな違いはなんでしょう?
一般的に業務用アプリケーションの場合、一つの処理が始まるとその処理が終わるまでユーザーに制御が返りません。
たとえば入力値をチェックする処理ならば、ユーザーの入力が終わった時点で処理が始まり、入力値が正しければ次のコントロールへカーソルを移し、正しくないときはアラートを出してユーザーに修正を促します。
ゲームコントロールの場合、ゲームが開始されてから終了するまでの間、プログラムはずっと実行されています。
ユーザーに制御が返りませんので、プログラムはユーザーのアクションを何らかの方法で取得しなければなりません。
図で描くとこのような感じになります。
ではいったいどうすればユーザーは実行中のプログラムを外部から制御できるのでしょう?
API関数の中に、まさにうってつけの関数がありますので今回はその使い方をご紹介します。
さっそくコードを見てまいりましょう。
' モジュール宣言部に記述ここから −−−−−−−−−−−−−−−−−−−−−−−−−−
Public Declare Function GetAsyncKeyState Lib "User32.dll" ( _
ByVal vKey As Long _
) As Long
Public Const VK_LBUTTON = &H1 '[LeftClick]
Public Const VK_RBUTTON = &H2 '[RightClick]
Public Const VK_SPACE = &H20 '[Space]
Public Const VK_LEFT = &H25 '[←]
Public Const VK_UP = &H26 '[↑]
Public Const VK_RIGHT = &H27 '[→]
Public Const VK_DOWN = &H28 '[↓]
Public Declare Sub Sleep Lib "kernel32" (ByVal dwMilliseconds As Long)
' モジュール宣言部に記述ここまで −−−−−−−−−−−−−−−−−−−−−−−−−−
Public Sub test()
Do
If GetAsyncKeyState(VK_LEFT) <> 0 Then
Debug.Print "←"
ElseIf GetAsyncKeyState(VK_UP) <> 0 Then
Debug.Print "↑"
ElseIf GetAsyncKeyState(VK_RIGHT) Then
Debug.Print "→"
ElseIf GetAsyncKeyState(VK_DOWN) Then
Debug.Print "↓"
Else
Debug.Print "*"
End If
Call Sleep(500)
Loop Until GetAsyncKeyState(VK_LBUTTON)
End Sub
このプログラムは一度実行されると、マウスの左クリックイベントを取得するまでループを続けます。
イベントを取得しているのは、API関数のGetAsyncKeyStateです。
この関数の便利な所は、キーボードのイベントを取得するだけでなく、マウスのクリック状態も取得できるところです。
プログラムが実行されると、イミディエイトウィンドウに"*"が出力され続けます。
これは、どのキーも押されていない状態のとき、IF文の最後のelseが実行されているからです。
Sleep関数でインターバルを入れているのはユーザーからの制御を受け付けるのに適当なウェイトがあったほうが都合がいいからです。この値を増やしたり減らしたりして、どのように制御の受け付けが変化するかを確かめてください。
キーボードの矢印キーを上下左右にいろいろと押してみてください。
GetAsyncKeyState(VK_LEFT) <> 0 の部分でキーが押されているかどうかを判定しています。正確にはGetAsyncKeyStateの戻り値には最上位ビットと最下位ビットをセットして戻しますので、現在キーが押されているかどうかまで知ることができます。
このサンプルでは押されたかどうかだけの判定なので、矢印キーのどれかが押され0以外の値が戻ったらイミディエイトに押された矢印キーをあらわす文字列を出力しています。
※ If GetAsyncKeyState(VK_RIGHT) Then と記述した場合、False=0以外のどの値でもTrueと判定されます。つまり、If GetAsyncKeyState(VK_RIGHT) <> 0 Then と記述したことと同じになります。
動きを一通り確認したらマウスを左クリックしてください。プログラムが終了します。
(このプログラムはVBEから実行します)
GetAsyncKeyStateの戻り値ですが、少し詳しく書くと16ビットの整数値が返されます、
・呼び出した時に押されている:16ビットの最上位ビットが1(&H8000)
・前回呼び出し後に押されている:16ビットの最下位ビットが1(&H1)
・押されていない:0
のいずれかが返ります。
これをうまく使うと、どのくらいキーが押されていたかでプログラムを細かく制御することが可能です。
もうひとつサンプルを記述してみましょう。
Public Sub test2()
Dim MyKeyState As Long
Do
MyKeyState = GetAsyncKeyState(VK_SPACE)
If MyKeyState And &H8000 Then
Debug.Print "現在押されている"
ElseIf MyKeyState And &H1 Then
Debug.Print "前回押されている"
Else
Debug.Print "押されていない"
End If
Call Sleep(500)
Loop Until GetAsyncKeyState(VK_LBUTTON)
End Sub
このサンプルではスペースキーが押されている状態にあるのか、押されていたけど離したのか、細かく取得することができます。
先ほど同様、VBEから実行してください。
実行すると"押されてない"がイミディエイトに出力され続けます。
スペースを押した時点で MyKeyStateに戻り値が返りますので最上位ビットの1を調べるには&H8000との論理積を判定します。
イミディエイトには"現在押されている"が出力され続けます。
スペースキーを離した時点でMyKeyStateに最下位ビットの1が返されますので&H1との論理積を判定してやります。
イミディエイトには"前回押されている"が一度出力されます。
次のループではMyKeyStateは0を返しますので再びスペースキーが押されるまで"押されていない"を出力し続けます。
※ ビット演算についてはこちらを参照してください。 演算子について詳しく知ろう!
よくあるシューティングゲームの"タメ"などはこの方法で簡単に実現できます。
また業務用アプリへの応用ですが、長時間に及ぶバッチ処理などの場合、終了するまでユーザーからの制御を全く受け付けなくなってしまうという問題をこれで回避できます。
■ キーイベントからプログラムを実行する
さて、これとは逆にあるキーが押された時にプログラムを実行するにはどうすればよいのでしょう?
Excelには大変便利な、Application.OnKey メソッドが用意されています。
使い方はいろいろありますが、WorkbookのOpenイベントに記述すると便利です。
' ワークブックモジュールに記述ここから −−−−−−−−−−−−−−−−−−−−−−−
Private Sub Workbook_Open()
Application.OnKey "{F1}", "UserFunction1"
Application.OnKey "{F2}", "UserFunction2"
Application.OnKey "{F3}", "UserFunction3"
Application.OnKey "{F4}", "UserFunction4"
Application.OnKey "{F5}", "UserFunction5"
End Sub
' ワークブックモジュールに記述ここまで −−−−−−−−−−−−−−−−−−−−−−−
この場合、ブックの起動時にファンクションキーのF1〜F5にUserFunction1〜5という名前のユーザー関数(プロシージャ)が割り当てられます。割り当てられるキーは様々で、
↑ |
{UP} |
→ |
{RIGHT} |
↓ |
{DOWN} |
← |
{LEFT} |
BackSpace |
{BACKSPACE} |
CapsLock |
{CAPSLOCK} |
Clear |
{CLEAR} |
Ctrl + Break |
{BREAK} |
Delete |
{DELETE} |
End |
{END} |
Enter |
{ENTER} |
Esc |
{ESCAPE} |
F1 〜 F15 |
{F1} から {F15} |
Help |
{HELP} |
Home |
{HOME} |
Ins |
{INSERT} |
NumLock |
{NUMLOCK} |
PageDown |
{PGDN} |
PageUp |
{PGUP} |
Return |
{RETURN} |
ScrollLock |
{SCROLLLOCK} |
Tab |
{TAB} |
この他にも文字キーやAlt、Ctrl、Shiftと組み合わせて使用することもできます。
詳しくはExcelのヘルプ、OnKeyメソッドを参照してください。
■ 仮想キーコード表(Virtual-Key Codes)
最後に代表的な仮想キーコードも一緒に紹介しておきます。
GetAsyncKeyStateを使用するときは、下記をコピペすれば、簡単にVirtual-Keyの定数を定義することができます。
Public Const VK_LBUTTON = &H1 '[LeftClick]
Public Const VK_RBUTTON = &H2 '[RightClick]
Public Const VK_CANCEL = &H3 '[Cancel]
Public Const VK_MBUTTON = &H4 '[MiddleClick]
Public Const VK_BACK = &H8 '[BackSpace]
Public Const VK_TAB = &H9 '[TAB]
Public Const VK_CLEAR = &HC '[Clear]
Public Const VK_RETURN = &HD '[Enter]
Public Const VK_SHIFT = &H10 '[LeftShift]
Public Const VK_RSHIFT = &HA1 '[RightShift]
Public Const VK_CONTROL = &H11 '[LeftControl]
Public Const VK_RCONTROL = &HA3 '[RightControl]
Public Const VK_MENU = &H12 '[LeftMenu]
Public Const VK_RMENU = &HA5 '[RightMenu]
Public Const VK_PAUSE = &H13 '[Pause]
Public Const VK_CAPITAL = &H14 '[CapsLock]
Public Const VK_ESCAPE = &H1B '[Esc]
Public Const VK_SPACE = &H20 '[Space]
Public Const VK_PRIOR = &H21 '[PageUp]
Public Const VK_NEXT = &H22 '[PageDown]
Public Const VK_END = &H23 '[End]
Public Const VK_HOME = &H24 '[Home]
Public Const VK_LEFT = &H25 '[←]
Public Const VK_UP = &H26 '[↑]
Public Const VK_RIGHT = &H27 '[→]
Public Const VK_DOWN = &H28 '[↓]
Public Const VK_SELECT = &H29 '[Select]
Public Const VK_PRINT = &H2A '[PrintScreen]
Public Const VK_EXECUTE = &H2B '[Execute]
Public Const VK_SNAPSHOT = &H2C '[SnapShot]
Public Const VK_INSERT = &H2D '[Insert]
Public Const VK_DELETE = &H2E '[Delete]
Public Const VK_HELP = &H2F '[Help]
Public Const VK_0 = &H30 '[0]
Public Const VK_1 = &H31 '[1]
Public Const VK_2 = &H32 '[2]
Public Const VK_3 = &H33 '[3]
Public Const VK_4 = &H34 '[4]
Public Const VK_5 = &H35 '[5]
Public Const VK_6 = &H36 '[6]
Public Const VK_7 = &H37 '[7]
Public Const VK_8 = &H38 '[8]
Public Const VK_9 = &H39 '[9]
Public Const VK_A = &H41 '[A]
Public Const VK_B = &H42 '[B]
Public Const VK_C = &H43 '[C]
Public Const VK_D = &H44 '[D]
Public Const VK_E = &H45 '[E]
Public Const VK_F = &H46 '[F]
Public Const VK_G = &H47 '[G]
Public Const VK_H = &H48 '[H]
Public Const VK_I = &H49 '[I]
Public Const VK_J = &H4A '[J]
Public Const VK_K = &H4B '[K]
Public Const VK_L = &H4C '[L]
Public Const VK_M = &H4D '[M]
Public Const VK_N = &H4E '[N]
Public Const VK_O = &H4F '[O]
Public Const VK_P = &H50 '[P]
Public Const VK_Q = &H51 '[Q]
Public Const VK_R = &H52 '[R]
Public Const VK_S = &H53 '[S]
Public Const VK_T = &H54 '[T]
Public Const VK_U = &H55 '[U]
Public Const VK_V = &H56 '[V]
Public Const VK_W = &H57 '[W]
Public Const VK_X = &H58 '[X]
Public Const VK_Y = &H59 '[Y]
Public Const VK_Z = &H5A '[Z]
Public Const VK_NUMPAD0 = &H60 'テンキー[0]
Public Const VK_NUMPAD1 = &H61 'テンキー[1]
Public Const VK_NUMPAD2 = &H62 'テンキー[2]
Public Const VK_NUMPAD3 = &H63 'テンキー[3]
Public Const VK_NUMPAD4 = &H64 'テンキー[4]
Public Const VK_NUMPAD5 = &H65 'テンキー[5]
Public Const VK_NUMPAD6 = &H66 'テンキー[6]
Public Const VK_NUMPAD7 = &H67 'テンキー[7]
Public Const VK_NUMPAD8 = &H68 'テンキー[8]
Public Const VK_NUMPAD9 = &H69 'テンキー[9]
Public Const VK_MULTIPLY = &H6A 'テンキー[*]
Public Const VK_ADD = &H6B 'テンキー[+]
Public Const VK_SEPARATOR = &H6C 'テンキー[Enter]
Public Const VK_SUBTRACT = &H6D 'テンキー[-]
Public Const VK_DECIMAL = &H6E 'テンキー[.]
Public Const VK_DIVIDE = &H6F 'テンキー[/]
Public Const VK_F1 = &H70 '[F1]
Public Const VK_F2 = &H71 '[F2]
Public Const VK_F3 = &H72 '[F3]
Public Const VK_F4 = &H73 '[F4]
Public Const VK_F5 = &H74 '[F5]
Public Const VK_F6 = &H75 '[F6]
Public Const VK_F7 = &H76 '[F7]
Public Const VK_F8 = &H77 '[F8]
Public Const VK_F9 = &H78 '[F9]
Public Const VK_F10 = &H79 '[F10]
Public Const VK_F11 = &H7A '[F11]
Public Const VK_F12 = &H7B '[F12]
Public Const VK_F13 = &H7C '[F13]
Public Const VK_F14 = &H7D '[F14]
Public Const VK_F15 = &H7E '[F15]
Public Const VK_F16 = &H7F '[F16]
Public Const VK_F17 = &H80 '[F17]
Public Const VK_F18 = &H81 '[F18]
Public Const VK_F19 = &H82 '[F19]
Public Const VK_F20 = &H83 '[F20]
Public Const VK_F21 = &H84 '[F21]
Public Const VK_F22 = &H85 '[F22]
Public Const VK_F23 = &H86 '[F23]
Public Const VK_F24 = &H87 '[F24]
Public Const VK_NUMLOCK = &H90 '[Num Lock]
|
|
|