Platform SDK: DirectX

ステップ 4 : マウスからのバッファリング データの取得

[C++]

ここでは、Visual Basic でのアプリケーション開発について説明する。C++ については、「DirectInput C/C++ チュートリアル」を参照すること。

[Visual Basic]

ScrawlB サンプルは、frmCanvas により実装される DirectXEvent.DXCallback メソッド内部で、マウスのバッファリング データを取得する。入力イベントが発生すると必ずこのメソッドが呼び出される。

このメソッドは、DirectInput がデータの格納に使用するバッファと同じサイズのバッファを宣言する。これは、以前の DirectInputDevice.SetProperty の呼び出しにより設定されたサイズである。

Dim diDeviceData(1 To BufferSize) As DIDEVICEOBJECTDATA

また、実際に取得された項目数を受け取る変数、ループ カウンタ、およびイベントの前回のシーケンス番号を追跡する変数も必要である。

Dim NumItems As Integer
Dim i As Integer
Static OldSequence As Long

この時点でアプリケーションは、DirectInputDevice.GetDeviceData を一度呼び出すことで、利用可能なデータをすべて取得する。

On Error GoTo INPUTLOST
NumItems = objDIDev.GetDeviceData(diDeviceData, 0)
On Error GoTo 0

エラー トラップに注意してほしい。DirectInput が送信するイベントの 1 つは、取得の喪失である。たとえば、ユーザーが別のアプリケーションに切り替えた場合、ScrawlB はマウスを取得した状態にはない。イベントが送信され、このメソッドが呼び出されても、GetDeviceData は失敗する。データは、取得状態にあるデバイスからしか取得できないためである。

ここでアプリケーションは、取得した項目を反復し、DIDEVICEOBJECTDATA 型内のデータを調べ、lOfs メンバと目的のさまざまなボタンと軸を表す定数を比較する。たとえば x 軸の場合、アプリケーションは lData メンバから軸位置の変化量を取得し、ユーザー定義の感度を計算しながら、これを使ってカーソル位置を調整する。

For i = 1 To NumItems
    Select Case diDeviceData(i).lOfs
        Case DIMOFS_X
           g_cursorx = g_cursorx + diDeviceData(i).lData * _
               g_Sensitivity

また、アプリケーションはシーケンス番号を調べて、前回の番号と比較する。2 つの軸イベントが同じシーケンス番号を持つ場合、マウスは斜めに移動しており、2 つの移動を計算し終えるまでは、カーソル位置を更新したり線を描画したりするべきではない。

           If OldSequence <> diDeviceData(i).lSequence Then
             UpdateCursor  ' カーソルを移動し、直線を描画する。
             OldSequence = diDeviceData(i).lSequence
           Else
             OldSequence = 0
           End If

ボタンの場合、メソッドは、lData 内の適切なビットをチェックして、イベントの種類を決定する。ビットが設定されている場合、マウス ボタンは押されている。それ以外の場合、マウス ボタンは押されていない。GetDeviceData はデバイスの現在の状態を返すものではないので、ボタンが押し下げられているかどうかの専用記録を保持するのは、アプリケーションが行わなければならない。左ボタンの場合、ScrawlB はこの情報を Drawing ブール型変数に保持する。

         Case DIMOFS_BUTTON0
           If diDeviceData(i).lData And &H80 Then
             Drawing = True
 
             ' Line 関数の記録を保持する。
             CurrentX = g_cursorx
             CurrentY = g_cursory
 
             ' 直後にボタンアップが発生した場合は、点を描画する。
             PSet (g_cursorx, g_cursory)
           Else
             Drawing = False
           End If
.
.
.
    End Select
Next i