データ出力
データ出力
HID (Human Interface Device) には、入力の生成と出力の受け取りの両方が可能なものがある。そのようなデバイスにデータ パケットを送信するには、IDirectInputDevice8::SendDeviceData メソッドを使う。
IDirectInputDevice8::SendDeviceData は、反対に IDirectInputDevice8::GetDeviceData として表示できる。SendDeviceData メソッドと同様に、GetDeviceData メソッドは、データの基本単位として DIDEVICEOBJECTDATA 構造体を使う。この場合、dwOfs メンバに含まれるのは、デバイスのデータ形式のオフセットではなく、データに関連付けられたデバイス オブジェクトのインスタンス ID である。オフセット識別子は、選択されたデータ形式での入力を提供するデバイス オブジェクトのためだけに存在するので、出力のみを受け取るオブジェクトは、オフセットを持たない。dwData メンバには、オブジェクトに適したデータが含まれる。dwTimeStamp および dwSequence メンバは使わない。これらのメンバは、ゼロに設定しなければならない。
デバイスにデータを送るには、DIDEVICEOBJECTDATA 構造体の配列を設定し、必要な数の要素をデータで埋めてから、使われる配列のアドレスと要素数を IDirectInputDevice8::SendDeviceData に渡す。異なるデバイス オブジェクトのデータは、デバイスに送られる単一パケットに結合される。
データ パケットの形式は、パケット内の未使用フィールドの処理方法と同じで、デバイスによって異なる。デバイスによっては、フィールドをオプションとして扱う。つまり、データが提供されない場合、オブジェクトの状態は前と同じである。一般的には、特にデータをフィールドに提供しない場合でも、すべてのフィールドが重要である。たとえば、単一のキーボード LED にデータを送ると、他の 2 つの LED のデータはゼロで、それらの LED はオフであると仮定される。ただし、DISDD_CONTINUE フラグを使ってこの動作を無効にすることができる。この場合、他の 2 つの LED のデータは、最後に送信した値となる。
デバイス オブジェクトの型の識別子は、HID 使用ページと使用コードを IDirectInputDevice8::GetObjectInfo に渡した後で DIDEVICEOBJECTINSTANCE 構造体 の dwType メンバから取得する。たとえば Scroll Lock LED の型識別子は、以下のコードを使って取得する。このコードで、pdev はキーボードを表す IDirectInputDevice8 インターフェイス ポインタである。
DIDEVICEOBJECTINSTANCE didoi;
DWORD NumLockID;
HRESULT hr = pdev->GetObjectInfo(&didoi,
DIMAKEUSAGEDWORD(0x07,0x53), DIPH_BYUSAGE);
NumLockID = didoi.dwType;
次の例では、コードが繰り返し実行される場合、キーボード上の LED は繰り返し点滅する。LED の状態は、データ バイトの上位ビットにより決定されるものとする。DWORD の NumLockID、CapsLockID、ScrollLockID は、すべてこの方法で取得する。
#define ARRAYSIZE 4
void FlashLEDs(void)
{
static int rgiBits[] = { 1, 2, 4, 2 };
static int iLooper = 0;
DWORD cdod = 3; // Number of items
DIDEVICEOBJECTDATA rgdod[ARRAYSIZE-1];
HRESULT hres;
// Must clear dwTimeStamp and dwSequence
ZeroMemory(rgdod, sizeof(rgdod));
rgdod[0].dwOfs = NumLockID;
rgdod[1].dwOfs = CapsLockID;
rgdod[2].dwOfs = ScrollLockID;
rgdod[0].dwData = (rgiBits[iLooper] & 1) ? 0x80 : 0;
// NumLock light on/off
rgdod[1].dwData = (rgiBits[iLooper] & 2) ? 0x80 : 0;
// CapsLock light on/off
rgdod[2].dwData = (rgiBits[iLooper] & 4) ? 0x80 : 0;
// ScrollLock light on/off
iLooper = (iLooper + 1) % ARRAYSIZE; // Loops from 0 to 3
hres = pdev->SendDeviceData(sizeof(DIDEVICEOBJECTDATA),
rgdod, &cdod, 0);
}