昨日の投稿で、肝心なコードが抜けていました。昨日紹介した方法でフォームを作成するとフォームのコードは、以下のようになっていると思います。
public partial class FormMain : Form
{
・・・・
}
※ FormMainは、クラス作成時に私がつけたフォームの名前
このフォームのクラスに以下のメソッドを追加する必要があります。これは、Formクラスにprotectedにて定義されているもので、これをoverrideし、ParseMessage() という昨日紹介した関数を呼び、必要な処理を実行します。ここで重要なのは、必要な処理実行後にbaseのWndProc() を呼ぶことです。これをしないと、デフォルトで行われる処理がされなくなってしまいます。逆に全てを自分のコードで処理を行い、継承元のコードに処理をさせたくない場合は、そのままこの関数呼び出しを終了します。
protected override void WndProc(ref Message m)
{
try
{
ParseMessages(ref m);
base.WndProc(ref m);
}
catch
{
}
}
前回の投稿でデバイスの追加、削除の通知を受け取る方法を紹介しましたが、さて接続されているデバイスの情報を取得するにはどのようにしたらいいのでしょうか。Win32 API / C++だと簡単なのですが、C#ではMarshaling してWin32 APIにアクセスしなくてはなりません。幾つか前のポストでWin32 APIへアクセスするためのStubクラスを紹介しているので、詳細はそちらを参照してください。(前回のポストから、いろいろと更新しているので、以前参照した方も、最新のファイルをダウンロードの上で、確認してみてください。)
さて、肝心のデバイス一覧取得方法ですが、Win32 APIのフォルダー一覧の取得方法と非常ににています。異なるのは、ハンドルを用いたOSによるステートフルな取得方法ではなく、デバイスのインデックスを指定し、順に取得していくところです。以下は、デバイス一覧を順に取得し、パラメータで指定されたデバイスが見つかれば、そのデバイスのパスを返すというものです。
/// <summary>
/// ベンダーID、プロダクトIDからデバイスを検索します。
/// </summary>
/// <param name=”nVid”></param>
/// <param name=”nPid”></param>
/// <returns></returns>
public
span> string FindDevice(int nVid, int nPid)
{
string strPath;
string strSearch;
Guid GuidHid;
IntPtr hInformationSet;
strPath= string.Empty;
// ベンダーID、プロダクトIDからデバイス・パスを作成します。
strSearch = string.Format(“vid_{0:x4}&pid_{1:x4}”, nVid, nPid);
GuidHid= HIDGuid;
// デバイスに接続されているHIDデバイスの一覧を取得します。
hInformationSet = SetupDiGetClassDevs(ref GuidHid, null, IntPtr.Zero, DIGCF_DEVICEINTERFACE | DIGCF_PRESENT);
try
{
PSP_DEVICE_INTERFACE_DATA oDeviceInterfaceData;
int nIndex;
// PSP_DEVICE_INTERFACE_DATA 構造体分のメモリーを確保します。
oDeviceInterfaceData = new PSP_DEVICE_INTERFACE_DATA();
oDeviceInterfaceData.Size =
Marshal.SizeOf(oDeviceInterfaceData);
nIndex = 0;
// 順に登録されているデバイスを確認してきます。
while (SetupDiEnumDeviceInterfaces(hInformationSet, 0, ref GuidHid, (uint)nIndex, ref oDeviceInterfaceData))
{
stringstrDevicePath;
// デバイスのパス情報を取得します。
strDevicePath = GetDevicePath(hInformationSet, ref oDeviceInterfaceData);
System.Diagnostics.Debug.WriteLine(string.Format(“{0} : {1}”, nIndex, strDevicePath));
// 取得したデバイスパスが目的としているベンダーID、プロダクトIDに該当するものか
// 確認します。
if (strDevicePath.IndexOf(strSearch) >= 0)
{
return strDevicePath;
}
nIndex++;
}
}
catch(Exception e)
{
throw HIDDeviceException.GenerateError(e.ToString());
}
finally
{
// Win32 APIを通して作成されているハンドル
SetupDiDestroyDeviceInfoList(hInformationSet);
}
return null;
}
ここでポイントとなるのは、デバイスパスのフォーマットです。デバイスパスは、ベンダーIDと製品IDから構成されており、それぞれのデバイスでユニークなものです。自分でUSBデバイスを作成し、独自のIDを指定する為には、USB.orgにて手続きしなくてはなりません。USB-IFのメンバーになるのに$4,000。ベンダーIDを取得するのに$5,000。高いですね・・・ とても個人では手が届きません。
次回このトピックで書く時は、デバイスとのデータ交換方法について紹介したいと思います。週末頃かな・・・