Source code of Windows XP (NT5)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

441 lines
12 KiB

  1. /*****************************************************************************
  2. *
  3. * diqacq.c
  4. *
  5. * "Data" (acquire) property sheet page.
  6. *
  7. *****************************************************************************/
  8. #include "diquick.h"
  9. /*****************************************************************************
  10. *
  11. * Acq_AddDeviceData
  12. *
  13. *****************************************************************************/
  14. void INTERNAL
  15. Acq_AddDeviceData(PDEVDLGINFO pddi, LPTSTR ptsz)
  16. {
  17. if (pddi->celtData >= pddi->celtDataMax) {
  18. ListBox_DeleteString(pddi->hwndData, 0);
  19. } else {
  20. pddi->celtData++;
  21. }
  22. ListBox_AddString(pddi->hwndData, ptsz);
  23. }
  24. /*****************************************************************************
  25. *
  26. * Acq_OnDataAvailable
  27. *
  28. *****************************************************************************/
  29. void INTERNAL
  30. Acq_OnDataAvailable(HWND hdlg)
  31. {
  32. PDEVDLGINFO pddi = GetDialogPtr(hdlg);
  33. HRESULT hres;
  34. TCHAR tszBuf[1024];
  35. DWORD dw;
  36. DIDEVICEOBJECTDATA rgdod[10];
  37. ResetEvent(pddi->hevt);
  38. hres = pddi->pvtbl->UpdateStatus(pddi, tszBuf);
  39. if (SUCCEEDED(hres)) {
  40. TCHAR tszPrev[256];
  41. GetWindowText(pddi->hwndState, tszPrev, cA(tszPrev));
  42. /* Don't set text if same as before; avoids flicker */
  43. if (lstrcmp(tszBuf, tszPrev)) {
  44. SetWindowText(pddi->hwndState, tszBuf);
  45. UpdateWindow(pddi->hwndState);
  46. }
  47. } else {
  48. if (hres == DIERR_INPUTLOST) {
  49. SetWindowText(pddi->hwndState, TEXT("Input lost"));
  50. } else if (hres == DIERR_NOTACQUIRED) {
  51. SetWindowText(pddi->hwndState, TEXT("Not acquired"));
  52. } else {
  53. wsprintf(tszBuf, TEXT("Error %08x"), hres);
  54. SetWindowText(pddi->hwndState, tszBuf);
  55. }
  56. }
  57. dw = cA(rgdod);
  58. hres = IDirectInputDevice8_GetDeviceData(pddi->pdid, cbX(rgdod[0]), rgdod,
  59. &dw, 0);
  60. if (SUCCEEDED(hres)) {
  61. DWORD idod;
  62. for (idod = 0; idod < dw; idod++) {
  63. DIDEVICEOBJECTINSTANCE doi;
  64. if (SUCCEEDED(GetObjectInfo(pddi, &doi, rgdod[idod].dwOfs,
  65. DIPH_BYOFFSET))) {
  66. } else {
  67. lstrcpy(doi.tszName, TEXT("?"));
  68. }
  69. wsprintf(tszBuf, TEXT("%04x %04x %5d %02x [%s]"),
  70. rgdod[idod].dwSequence & 0xFFFF,
  71. rgdod[idod].dwTimeStamp & 0xFFFF,
  72. rgdod[idod].dwData,
  73. rgdod[idod].dwOfs,
  74. doi.tszName);
  75. Acq_AddDeviceData(pddi, tszBuf);
  76. }
  77. if (hres == S_FALSE) {
  78. Acq_AddDeviceData(pddi, TEXT("<data lost>"));
  79. }
  80. }
  81. }
  82. #define TEST_SENDDEVICEDATA
  83. #ifdef TEST_SENDDEVICEDATA
  84. #include <hidusage.h>
  85. DWORD INTERNAL
  86. Acq_GetUsageId(IDirectInputDevice8 *pdid8, DWORD dwUsage)
  87. {
  88. HRESULT hres;
  89. DIDEVICEOBJECTINSTANCE inst;
  90. inst.dwSize = cbX(inst);
  91. hres = IDirectInputDevice8_GetObjectInfo(pdid8, &inst, dwUsage, DIPH_BYUSAGE);
  92. if (SUCCEEDED(hres)) {
  93. return inst.dwType;
  94. } else {
  95. return 0;
  96. }
  97. }
  98. #endif
  99. /*****************************************************************************
  100. *
  101. * Acq_CheckDataAvailable
  102. *
  103. * Timer callback procedure
  104. *
  105. *****************************************************************************/
  106. void CALLBACK
  107. Acq_CheckDataAvailable(HWND hdlg, UINT wm, UINT_PTR id, DWORD tm)
  108. {
  109. PDEVDLGINFO pddi = GetDialogPtr(hdlg);
  110. /*
  111. * If we can QI for IDirectInputDevice8::Poll, then call it.
  112. */
  113. IDirectInputDevice8 *pdid8;
  114. HRESULT hres;
  115. hres = IDirectInputDevice8_QueryInterface(pddi->pdid,
  116. &IID_IDirectInputDevice8,
  117. (PV)&pdid8);
  118. if (SUCCEEDED(hres)) {
  119. IDirectInputDevice8_Poll(pdid8);
  120. #ifdef TEST_SENDDEVICEDATA
  121. {
  122. // static int rgiBlah[] = { 1, 3, 2, 6, 4, 6, 2, 3 };
  123. static int rgiBlah[] = { 1, 2, 4, 2 };
  124. static int iBlah;
  125. DWORD cdod = 3;
  126. static DIDEVICEOBJECTDATA rgdod[3];
  127. HRESULT hres;
  128. iBlah = (iBlah + 1) % cA(rgiBlah);
  129. // ZeroMemory(rgdod, sizeof(rgdod));
  130. if (rgdod[2].dwOfs == 0) {
  131. rgdod[0].dwOfs = Acq_GetUsageId(pdid8,
  132. DIMAKEUSAGEDWORD(HID_USAGE_PAGE_LED, HID_USAGE_LED_NUM_LOCK));
  133. rgdod[1].dwOfs = Acq_GetUsageId(pdid8,
  134. DIMAKEUSAGEDWORD(HID_USAGE_PAGE_LED, HID_USAGE_LED_CAPS_LOCK));
  135. rgdod[2].dwOfs = Acq_GetUsageId(pdid8,
  136. DIMAKEUSAGEDWORD(HID_USAGE_PAGE_LED, HID_USAGE_LED_SCROLL_LOCK));
  137. }
  138. // rgdod[0].dwOfs = 0x80006e84;
  139. // rgdod[1].dwOfs = 0x80006f84;
  140. // rgdod[2].dwOfs = 0x80007084;
  141. rgdod[0].dwData = (rgiBlah[iBlah] & 1) != 0;
  142. rgdod[1].dwData = (rgiBlah[iBlah] & 2) != 0;
  143. rgdod[2].dwData = (rgiBlah[iBlah] & 4) != 0;
  144. hres = IDirectInputDevice8_SendDeviceData(pdid8,
  145. sizeof(DIDEVICEOBJECTDATA), rgdod, &cdod, 0);
  146. }
  147. #endif
  148. IDirectInputDevice8_Release(pdid8);
  149. }
  150. Acq_OnDataAvailable(hdlg);
  151. }
  152. /*****************************************************************************
  153. *
  154. * Acq_Listbox_Subclass
  155. *
  156. * Subclass procedure for the list box control, so that we eat
  157. * every single key. Except that we allow syskeys to go through
  158. * so that keyboard accelerators work.
  159. *
  160. *****************************************************************************/
  161. LRESULT CALLBACK
  162. Acq_Listbox_Subclass(HWND hwnd, UINT wm, WPARAM wp, LPARAM lp)
  163. {
  164. PDEVDLGINFO pddi = GetDialogPtr(GetParent(hwnd));
  165. if (pddi->fAcquired) {
  166. switch (wm) {
  167. case WM_GETDLGCODE:
  168. return DLGC_WANTALLKEYS;
  169. case WM_KEYDOWN:
  170. return 0;
  171. }
  172. }
  173. return CallWindowProc(pddi->wpListbox, hwnd, wm, wp, lp);
  174. }
  175. /*****************************************************************************
  176. *
  177. * Acq_OnInitDialog
  178. *
  179. * Init random goo.
  180. *
  181. *****************************************************************************/
  182. BOOL INTERNAL
  183. Acq_OnInitDialog(HWND hdlg, LPARAM lp)
  184. {
  185. PDEVDLGINFO pddi = (PV)(((LPPROPSHEETPAGE)lp)->lParam);
  186. RECT rc;
  187. SetDialogPtr(hdlg, pddi);
  188. pddi->hevt = CreateEvent(0, 1, 0, 0);
  189. pddi->hwndState = GetDlgItem(hdlg, IDC_ACQ_STATE);
  190. pddi->hwndData = GetDlgItem(hdlg, IDC_ACQ_DATA);
  191. pddi->celtData = 0;
  192. GetClientRect(pddi->hwndData, &rc);
  193. pddi->celtDataMax = (rc.bottom - rc.top) /
  194. ListBox_GetItemHeight(pddi->hwndData, 0);
  195. pddi->wpListbox = SubclassWindow(pddi->hwndData, Acq_Listbox_Subclass);
  196. SetFocus(pddi->hwndData);
  197. return 0;
  198. }
  199. /*****************************************************************************
  200. *
  201. * Acq_OnSetActive
  202. *
  203. * Don't put up message boxes, because we aren't visible yet.
  204. *
  205. *****************************************************************************/
  206. BOOL INTERNAL
  207. Acq_OnSetActive(HWND hdlg)
  208. {
  209. PDEVDLGINFO pddi = GetDialogPtr(hdlg);
  210. HRESULT hres;
  211. UINT ids = 0;
  212. hres = IDirectInputDevice8_SetEventNotification(pddi->pdid,
  213. pddi->fPoll ? 0 : pddi->hevt);
  214. if (SUCCEEDED(hres)) {
  215. hres = IDirectInputDevice8_Acquire(pddi->pdid);
  216. if (SUCCEEDED(hres)) {
  217. pddi->fAcquired = 1;
  218. SetFocus(pddi->hwndData);
  219. if (pddi->fPoll) {
  220. SetTimer(hdlg, IDT_DATA, msData, Acq_CheckDataAvailable);
  221. }
  222. } else {
  223. ids = IDS_ERR_ACQUIRE;
  224. }
  225. } else {
  226. ids = IDS_ERR_SETEVENTNOT;
  227. }
  228. if (ids) {
  229. TCHAR tsz[256];
  230. LoadString(g_hinst, ids, tsz, cA(tsz));
  231. SetDlgItemText(hdlg, IDC_ACQ_STATE, tsz);
  232. } else {
  233. Acq_OnDataAvailable(hdlg);
  234. }
  235. return 0;
  236. }
  237. /*****************************************************************************
  238. *
  239. * Acq_OnKillActive
  240. *
  241. *****************************************************************************/
  242. BOOL INTERNAL
  243. Acq_OnKillActive(HWND hdlg)
  244. {
  245. PDEVDLGINFO pddi = GetDialogPtr(hdlg);
  246. if (pddi) {
  247. if (pddi->fAcquired) {
  248. pddi->fAcquired = 0;
  249. IDirectInputDevice8_Unacquire(pddi->pdid);
  250. }
  251. if (pddi->fPoll) {
  252. KillTimer(hdlg, IDT_DATA);
  253. } else {
  254. IDirectInputDevice8_SetEventNotification(pddi->pdid, 0);
  255. }
  256. }
  257. return 0;
  258. }
  259. /*****************************************************************************
  260. *
  261. * Acq_OnDestroy
  262. *
  263. * Clean up.
  264. *
  265. *****************************************************************************/
  266. BOOL INTERNAL
  267. Acq_OnDestroy(HWND hdlg)
  268. {
  269. PDEVDLGINFO pddi = GetDialogPtr(hdlg);
  270. Acq_OnKillActive(hdlg);
  271. if (pddi && pddi->hevt) {
  272. CloseHandle(pddi->hevt);
  273. }
  274. return 1;
  275. }
  276. /*****************************************************************************
  277. *
  278. * Acq_OnSelfEnterIdle
  279. *
  280. * This dialog box is idle. Do a custom message loop if needed.
  281. *
  282. *****************************************************************************/
  283. BOOL INTERNAL
  284. Acq_OnSelfEnterIdle(HWND hdlg)
  285. {
  286. PDEVDLGINFO pddi = GetDialogPtr(hdlg);
  287. if (pddi->fAcquired && !pddi->fPoll) {
  288. for (;;) {
  289. DWORD dwRc;
  290. MSG msg;
  291. dwRc = MsgWaitForMultipleObjects(1, &pddi->hevt,
  292. 0, INFINITE, QS_ALLINPUT);
  293. switch (dwRc) {
  294. case WAIT_OBJECT_0: /* Data available */
  295. Acq_OnDataAvailable(hdlg);
  296. break;
  297. /* Sometimes we get woken spuriously */
  298. case WAIT_OBJECT_0 + 1:
  299. if (PeekMessage(&msg, 0, 0, 0, PM_NOREMOVE)) {
  300. goto stop;
  301. }
  302. break;
  303. default:
  304. /* Return and let the dialog box loop handle the message */
  305. goto stop;
  306. }
  307. }
  308. stop:;
  309. }
  310. return 1;
  311. }
  312. /*****************************************************************************
  313. *
  314. * Acq_OnNotify
  315. *
  316. *****************************************************************************/
  317. BOOL INLINE
  318. Acq_OnNotify(HWND hdlg, NMHDR *pnm)
  319. {
  320. switch (pnm->code) {
  321. case PSN_SETACTIVE: return Acq_OnSetActive(hdlg);
  322. case PSN_KILLACTIVE: return Acq_OnKillActive(hdlg);
  323. }
  324. return 0;
  325. }
  326. /*****************************************************************************
  327. *
  328. * Acq_OnUnacquire
  329. *
  330. *****************************************************************************/
  331. BOOL INTERNAL
  332. Acq_OnUnacquire(PDEVDLGINFO pddi, HWND hdlg)
  333. {
  334. HRESULT hres;
  335. hres = IDirectInputDevice8_Unacquire(pddi->pdid);
  336. return 1;
  337. }
  338. /*****************************************************************************
  339. *
  340. * Acq_OnCommand
  341. *
  342. *****************************************************************************/
  343. BOOL INTERNAL
  344. Acq_OnCommand(HWND hdlg, int id, UINT cmd)
  345. {
  346. PDEVDLGINFO pddi = GetDialogPtr(hdlg);
  347. if (cmd == BN_CLICKED) {
  348. switch (id) {
  349. case IDC_ACQ_UNACQ:
  350. return Acq_OnUnacquire(pddi, hdlg);
  351. break;
  352. }
  353. }
  354. return 0;
  355. }
  356. /*****************************************************************************
  357. *
  358. * Acq_DlgProc
  359. *
  360. *****************************************************************************/
  361. INT_PTR CALLBACK
  362. Acq_DlgProc(HWND hdlg, UINT wm, WPARAM wp, LPARAM lp)
  363. {
  364. switch (wm) {
  365. case WM_INITDIALOG: return Acq_OnInitDialog(hdlg, lp);
  366. case WM_DESTROY: return Acq_OnDestroy(hdlg);
  367. case WM_SELFENTERIDLE: return Acq_OnSelfEnterIdle(hdlg);
  368. case WM_NOTIFY: return Acq_OnNotify(hdlg, (NMHDR *)lp);
  369. case WM_COMMAND:
  370. return Acq_OnCommand(hdlg,
  371. (int)GET_WM_COMMAND_ID(wp, lp),
  372. (UINT)GET_WM_COMMAND_CMD(wp, lp));
  373. }
  374. return 0;
  375. }