站内搜索

VC学习:获取游戏手柄的按键输入

  //可以查看按游戏手柄按钮时的情况.

  //USB接口的游戏手柄

  //编译环境:Windows 2000 server+VC++ 6.0+Win2K DDK

  #include 
  #include 
  #include 
  #include 
  extern "C"
  {
  #include 
  }

  void main()
  {
  GUID HidGuid;

  // 查找本系统中HID类的GUID标识
  HidD_GetHidGuid(&HidGuid);
  _tprintf("系统中HID类的GUID标识为:%08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x/n",
  HidGuid.Data1,HidGuid.Data2 ,HidGuid.Data3 ,
  HidGuid.Data4[0],HidGuid.Data4[1],HidGuid.Data4[2],
  HidGuid.Data4[3],HidGuid.Data4[4],HidGuid.Data4[5],
  HidGuid.Data4[6],HidGuid.Data4[7]);

  // 准备查找符合HID规范的USB设备
  HDEVINFO hDevInfo = SetupDiGetClassDevs(&HidGuid,
  NULL,
  NULL,
  DIGCF_PRESENT | DIGCF_DEVICEINTERFACE);
  if (hDevInfo == INVALID_HANDLE_VALUE)
  {
  _tprintf("符合HID规范的USB设备发生错误/n");

  return;
  }

  _tprintf("正在查找可用的USB设备.../n");

  DWORD MemberIndex = 0;
  SP_DEVICE_INTERFACE_DATA DeviceInterfaceData;
  BOOL bSuccess = FALSE;

  DeviceInterfaceData.cbSize = sizeof(SP_DEVICE_INTERFACE_DATA);
  do
  {
  bSuccess = SetupDiEnumDeviceInterfaces(hDevInfo,
  NULL,
  &HidGuid,
  MemberIndex,
  &DeviceInterfaceData);
  if ((!bSuccess) && (GetLastError() == ERROR_NO_MORE_ITEMS))
  {
  if(MemberIndex == 0)
  _tprintf("抱歉,未找到可用的USB设备!/n");
  else
  _tprintf("没有更多的可用的USB设备!/n");

  SetupDiDestroyDeviceInfoList(hDevInfo);
  return;
  }
  _tprintf("找到了一个USB设备:/n");
  //若找到了一个USB设备,则获取该设备的细节信息
  PSP_DEVICE_INTERFACE_DETAIL_DATA pDeviceInterfaceDetailData;
  DWORD Length = 0;
  SetupDiGetDeviceInterfaceDetail(hDevInfo,
  &DeviceInterfaceData,
  NULL,
  0,
  &Length,
  NULL);
  pDeviceInterfaceDetailData = (PSP_DEVICE_INTERFACE_DETAIL_DATA)malloc(Length);
  pDeviceInterfaceDetailData->cbSize = sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA); //MUST BE!!!

  if (!SetupDiGetDeviceInterfaceDetail(hDevInfo,
  &DeviceInterfaceData,
  pDeviceInterfaceDetailData,
  Length,
  NULL,
  NULL))
  _tprintf("查找路径设备时出错!/n");
  else
  _tprintf("设备路径:%s/n",pDeviceInterfaceDetailData->DevicePath );

  //打开设备句柄
  HANDLE hDeviceHandle = CreateFile(pDeviceInterfaceDetailData->DevicePath ,
  GENERIC_READ | GENERIC_WRITE,
  FILE_SHARE_READ | FILE_SHARE_WRITE,
  NULL,
  OPEN_EXISTING,
  0,
  NULL);
  if (hDeviceHandle == INVALID_HANDLE_VALUE)
  _tprintf("打开设备路径出错!/n");
  else

  {
  HIDD_ATTRIBUTES Attributes;
  HidD_GetAttributes(hDeviceHandle,&Attributes);
  //将有关该设备的标识显示出来
  _tprintf("供应商ID/t:0X%04X/n",Attributes.VendorID);
  _tprintf("产品ID/t:0X%04X/n",Attributes.ProductID);
  _tprintf("产品版本号:0X%04X/n",Attributes.VersionNumber);

  WCHAR mString[256];
  TCHAR Buffer[256];

  HidD_GetManufacturerString(hDeviceHandle,mString,sizeof(mString));
  if (wcstombs(Buffer,mString,256) == -1) // fail
  Buffer[0] = NULL;
  _tprintf("生产商:/t%s/n",Buffer);

  HidD_GetProductString(hDeviceHandle,mString,sizeof(mString));
  if (wcstombs(Buffer,mString,256) == -1)
  Buffer[0] = NULL;
  _tprintf("产品名称:/t%s/n",Buffer);

  // 通信:
  PHIDP_PREPARSED_DATA pHidpPreparsedData;
  HIDP_CAPS hidPCaps;
  if (!HidD_GetPreparsedData(hDeviceHandle,&pHidpPreparsedData))
  {
  _tprintf("获取 HID PREPARED DATA 失败!/n");
  return;
}
  NTSTATUS status = HidP_GetCaps(pHidpPreparsedData,&hidPCaps);
  if (status == HIDP_STATUS_SUCCESS)
  {
  _tprintf("CAP信息如下:/n");
  _tprintf(" InputReportByteLength %d/n", hidPCaps.InputReportByteLength);
  _tprintf(" OutputReportByteLength %d/n", hidPCaps.OutputReportByteLength);
  }
  DWORD nReadBytes = 0;
  BYTE *pInputReport = new BYTE[hidPCaps.InputReportByteLength];
  memset(pInputReport,0,hidPCaps.InputReportByteLength);

  do
  {
  ReadFile(hDeviceHandle,pInputReport,hidPCaps.InputReportByteLength,&nReadBytes,NULL);
  if (hidPCaps.InputReportByteLength == nReadBytes)
  {
  for(unsigned int i=0; i<(nReadBytes-1);i++)
  _tprintf("%02x-",pInputReport[i]);
  _tprintf("%02x/r",pInputReport[nReadBytes-1]);
  }
  if (pInputReport[nReadBytes-2] == 0x20) //break the loop when pressing a specific key
  {
  _tprintf("/n");
  break;
  }
  Sleep(10);
  }while(hidPCaps.InputReportByteLength == nReadBytes);

  //释放句柄资源
  CloseHandle(hDeviceHandle);
  }

  MemberIndex++;
  }while(bSuccess);

  SetupDiDestroyDeviceInfoList(hDevInfo);
  }

  • 上一篇:VC学习:拥有Office XP风格的界面
  • 下一篇:VC学习:IP地址控件小技巧