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.

611 lines
19 KiB

  1. /*++
  2. Copyright (c) 2000 Microsoft Corporation
  3. Module Name:
  4. lincal.c
  5. Abstract: This module contains code to do linearity calibration of the
  6. mutoh pen tablet.
  7. Environment:
  8. User mode
  9. Author:
  10. Michael Tsang (MikeTs) 20-Jun-2000
  11. Revision History:
  12. --*/
  13. #include "pch.h"
  14. #ifdef PENPAGE
  15. #define FIRST_X 16
  16. #define FIRST_Y 16
  17. #define INTERVAL_X 32
  18. #define INTERVAL_Y 32
  19. #define VICINITY_OFFSET (INTERVAL_X/2)
  20. #define CIRCLE_RADIUS 6
  21. #define MAX_NORMALIZED_X 65536
  22. #define MAX_NORMALIZED_Y 65536
  23. #define NUM_LINEARCAL_PTS (NUM_LINEAR_XPTS*NUM_LINEAR_YPTS)
  24. static TCHAR gtszLinearCal[] = TEXT("LinearityCalibration");
  25. static TCHAR gtszLinearCalTitle[64] = {0};
  26. static HWND ghwndParent = 0;
  27. static LONG gcxScreen = 0, gcyScreen = 0;
  28. static HPEN ghpenRed = 0, ghpenBlue = 0;
  29. static CALIBRATE_PT gCalPts[NUM_LINEAR_YPTS][NUM_LINEAR_XPTS] = {0};
  30. static int giNumLinearCalPts = 0;
  31. /*****************************************************************************
  32. *
  33. * @doc INTERNAL
  34. *
  35. * @func BOOL | CreateLinearCalWindow |
  36. * Entry point of the linearity calibration code.
  37. *
  38. * @parm IN HWND | hwndParent | Parent Window handle.
  39. *
  40. * @rvalue SUCCESS | Returns TRUE.
  41. * @rvalue FAILURE | Returns FALSE.
  42. *
  43. *****************************************************************************/
  44. BOOL
  45. CreateLinearCalWindow(
  46. IN HWND hwndParent
  47. )
  48. {
  49. TRACEPROC("CreateLinearCalWindow", 2)
  50. BOOL rc = FALSE;
  51. HWND hwnd;
  52. TRACEENTER(("(hwndParent=%p)\n", hwndParent));
  53. giNumLinearCalPts = 0;
  54. RtlZeroMemory(gCalPts, sizeof(gCalPts));
  55. ghwndParent = hwndParent;
  56. LoadString(ghInstance,
  57. IDS_LINEARCAL_TITLE,
  58. gtszLinearCalTitle,
  59. sizeof(gtszLinearCalTitle)/sizeof(TCHAR));
  60. gcxScreen = GetSystemMetrics(SM_CXSCREEN);
  61. gcyScreen = GetSystemMetrics(SM_CYSCREEN);
  62. RegisterLinearCalClass(ghInstance);
  63. hwnd = CreateWindow(gtszLinearCal, //Class Name
  64. gtszLinearCal, //Window Name
  65. WS_POPUP, //Style
  66. 0, //Window X
  67. 0, //Window Y
  68. gcxScreen, //Window Width
  69. gcyScreen, //Window Height
  70. hwndParent, //Parent Handle
  71. NULL, //Menu Handle
  72. ghInstance, //Instance Handle
  73. NULL); //Creation Data
  74. if (hwnd != NULL)
  75. {
  76. ShowWindow(hwnd, SW_SHOWNORMAL);
  77. rc = TRUE;
  78. }
  79. TRACEEXIT(("=%x\n", rc));
  80. return rc;
  81. } //CreateLinearCalWindow
  82. /*****************************************************************************
  83. *
  84. * @doc INTERNAL
  85. *
  86. * @func BOOL | RegisterLinearCalClass |
  87. * Register window class.
  88. *
  89. * @parm IN HINSTANCE | hInstance | Instance handle.
  90. *
  91. * @rvalue SUCCESS | Returns class atom
  92. * @rvalue FAILURE | Returns 0
  93. *
  94. *****************************************************************************/
  95. ATOM
  96. RegisterLinearCalClass(
  97. IN HINSTANCE hInstance
  98. )
  99. {
  100. TRACEPROC("RegisterLinearCalClass", 2)
  101. ATOM atom;
  102. WNDCLASSEX wcex;
  103. TRACEENTER(("(hInstance=%p)\n", hInstance));
  104. wcex.cbSize = sizeof(wcex);
  105. wcex.style = CS_HREDRAW | CS_VREDRAW;
  106. wcex.lpfnWndProc = LinearCalWndProc;
  107. wcex.cbClsExtra = 0;
  108. wcex.cbWndExtra = 0;
  109. wcex.hInstance = hInstance;
  110. wcex.hIcon = LoadIcon(hInstance, (LPCTSTR)IDI_TABLETPC);
  111. wcex.hCursor = NULL; //No cursor is shown.
  112. wcex.hbrBackground = (HBRUSH)(COLOR_WINDOW + 1);
  113. wcex.lpszMenuName = NULL;
  114. wcex.lpszClassName = gtszLinearCal;
  115. wcex.hIconSm = NULL;
  116. atom = RegisterClassEx(&wcex);
  117. TRACEEXIT(("=%x\n", atom));
  118. return atom;
  119. } //RegisterLinearCalClass
  120. /*****************************************************************************
  121. *
  122. * @doc EXTERNAL
  123. *
  124. * @func LRESULT | LinearCalWndProc |
  125. * Dialog procedure for the pen tablet linearity calibration page.
  126. *
  127. * @parm IN HWND | hwnd | Window handle.
  128. * @parm IN UINT | uMsg | Message.
  129. * @parm IN WPARAM | wParam | Word Parameter.
  130. * @parm IN LPARAM | lParam | Long Parameter.
  131. *
  132. * @rvalue Return value depends on the message.
  133. *
  134. *****************************************************************************/
  135. LRESULT CALLBACK
  136. LinearCalWndProc(
  137. IN HWND hwnd,
  138. IN UINT uMsg,
  139. IN WPARAM wParam,
  140. IN LPARAM lParam
  141. )
  142. {
  143. TRACEPROC("LinearCalWndProc", 2)
  144. LRESULT rc = 0;
  145. HDC hDC;
  146. static BOOL fCalDone = FALSE;
  147. TRACEENTER(("(hwnd=%p,Msg=%s,wParam=%x,lParam=%x)\n",
  148. hwnd, LookupName(uMsg, WMMsgNames) , wParam, lParam));
  149. switch (uMsg)
  150. {
  151. case WM_CREATE:
  152. {
  153. int i, j;
  154. LONG x, y, xInterval, yInterval;
  155. BOOL rcRPC;
  156. RPC_TRY("TabSrvGetLinearityMap",
  157. rcRPC = TabSrvGetLinearityMap(ghBinding,
  158. &PenSettings.LinearityMap));
  159. if ((rcRPC == TRUE) &&
  160. ((PenSettings.LinearityMap.dwcbLen != sizeof(LINEAR_MAP)) ||
  161. (PenSettings.LinearityMap.wNumXPts != NUM_LINEAR_XPTS) ||
  162. (PenSettings.LinearityMap.wNumYPts != NUM_LINEAR_YPTS)))
  163. {
  164. //
  165. // The map read is not the same size as expected.
  166. //
  167. rcRPC = FALSE;
  168. }
  169. ghpenRed = CreatePen(PS_SOLID, 0, RGB(255, 0, 0));
  170. ghpenBlue = CreatePen(PS_SOLID, 0, RGB(0, 0, 255));
  171. for (i = 0; i < NUM_LINEAR_YPTS; ++i)
  172. {
  173. y = FIRST_Y + INTERVAL_Y*i;
  174. for (j = 0; j < NUM_LINEAR_XPTS; ++j)
  175. {
  176. x = FIRST_X + INTERVAL_X*j;
  177. gCalPts[i][j].ScreenPt.x = x;
  178. gCalPts[i][j].ScreenPt.y = y;
  179. if (rcRPC == TRUE)
  180. {
  181. gCalPts[i][j].dwFlags = CPF_VALID;
  182. gCalPts[i][j].DigiPt.x =
  183. PenSettings.LinearityMap.Data[i][j].wDigiPtX;
  184. gCalPts[i][j].DigiPt.y =
  185. PenSettings.LinearityMap.Data[i][j].wDigiPtY;
  186. }
  187. else
  188. {
  189. gCalPts[i][j].dwFlags = 0;
  190. gCalPts[i][j].DigiPt.x = gCalPts[i][j].DigiPt.y = 0;
  191. }
  192. }
  193. }
  194. if (rcRPC == TRUE)
  195. {
  196. giNumLinearCalPts = PenSettings.LinearityMap.wNumXPts*
  197. PenSettings.LinearityMap.wNumYPts;
  198. }
  199. else
  200. {
  201. giNumLinearCalPts = 0;
  202. }
  203. ShowCursor(FALSE);
  204. break;
  205. }
  206. case WM_LBUTTONDOWN:
  207. {
  208. PCALIBRATE_PT CalPt;
  209. WORD wButtonState;
  210. fCalDone = FALSE;
  211. CalPt = FindPoint(GET_X_LPARAM(lParam),
  212. GET_Y_LPARAM(lParam),
  213. VICINITY_OFFSET);
  214. if (CalPt != NULL)
  215. {
  216. HPEN hpenOld;
  217. RPC_TRY("TabSrvGetLastRawDigiReport",
  218. TabSrvGetLastRawDigiReport(ghBinding,
  219. &wButtonState,
  220. (WORD *)&CalPt->DigiPt.x,
  221. (WORD *)&CalPt->DigiPt.y));
  222. TRACEASSERT(wButtonState & BUTSTATE_TIP_DOWN);
  223. MessageBeep(MB_OK);
  224. hDC = GetDC(hwnd);
  225. hpenOld = SelectObject(hDC, ghpenRed);
  226. Ellipse(hDC,
  227. CalPt->ScreenPt.x - CIRCLE_RADIUS,
  228. CalPt->ScreenPt.y - CIRCLE_RADIUS,
  229. CalPt->ScreenPt.x + CIRCLE_RADIUS,
  230. CalPt->ScreenPt.y + CIRCLE_RADIUS);
  231. MoveToEx(hDC,
  232. CalPt->ScreenPt.x - CIRCLE_RADIUS,
  233. CalPt->ScreenPt.y,
  234. NULL);
  235. LineTo(hDC,
  236. CalPt->ScreenPt.x + CIRCLE_RADIUS,
  237. CalPt->ScreenPt.y);
  238. MoveToEx(hDC,
  239. CalPt->ScreenPt.x,
  240. CalPt->ScreenPt.y - CIRCLE_RADIUS,
  241. NULL);
  242. LineTo(hDC,
  243. CalPt->ScreenPt.x,
  244. CalPt->ScreenPt.y + CIRCLE_RADIUS);
  245. SelectObject(hDC, hpenOld);
  246. ReleaseDC(hwnd, hDC);
  247. CalPt->dwFlags |= CPF_CALIBRATED;
  248. if (!(CalPt->dwFlags & CPF_VALID))
  249. {
  250. CalPt->dwFlags |= CPF_VALID;
  251. giNumLinearCalPts++;
  252. }
  253. }
  254. break;
  255. }
  256. case WM_CHAR:
  257. switch (wParam)
  258. {
  259. case VK_RETURN:
  260. if (giNumLinearCalPts < NUM_LINEARCAL_PTS)
  261. {
  262. MessageBeep(MB_ICONEXCLAMATION);
  263. }
  264. else if (!fCalDone)
  265. {
  266. DoLinearCal(hwnd, &PenSettings.LinearityMap);
  267. InvalidateRect(hwnd, NULL, TRUE);
  268. fCalDone = TRUE;
  269. }
  270. else
  271. {
  272. SendMessage(ghwndParent,
  273. WM_LINEARCAL_DONE,
  274. (WPARAM)IDYES,
  275. (LPARAM)hwnd);
  276. }
  277. break;
  278. case VK_ESCAPE:
  279. SendMessage(ghwndParent,
  280. WM_LINEARCAL_DONE,
  281. (WPARAM)IDCANCEL,
  282. (LPARAM)hwnd);
  283. break;
  284. }
  285. break;
  286. case WM_PAINT:
  287. {
  288. PAINTSTRUCT ps;
  289. HPEN hpenOld;
  290. int i, j;
  291. hDC = BeginPaint(hwnd, &ps);
  292. hpenOld = SelectObject(hDC, ghpenBlue);
  293. for (i = 0; i < NUM_LINEAR_YPTS; ++i)
  294. {
  295. MoveToEx(hDC,
  296. gCalPts[i][0].ScreenPt.x,
  297. gCalPts[i][0].ScreenPt.y,
  298. NULL);
  299. LineTo(hDC,
  300. gCalPts[i][NUM_LINEAR_XPTS - 1].ScreenPt.x,
  301. gCalPts[i][NUM_LINEAR_XPTS - 1].ScreenPt.y);
  302. }
  303. for (i = 0; i < NUM_LINEAR_XPTS; ++i)
  304. {
  305. MoveToEx(hDC,
  306. gCalPts[0][i].ScreenPt.x,
  307. gCalPts[0][i].ScreenPt.y,
  308. NULL);
  309. LineTo(hDC,
  310. gCalPts[NUM_LINEAR_YPTS - 1][i].ScreenPt.x,
  311. gCalPts[NUM_LINEAR_YPTS - 1][i].ScreenPt.y);
  312. }
  313. SelectObject(hDC, ghpenRed);
  314. for (i = 0; i < NUM_LINEAR_YPTS; ++i)
  315. {
  316. for (j = 0; j < NUM_LINEAR_XPTS; ++j)
  317. {
  318. if (gCalPts[i][j].dwFlags & CPF_CALIBRATED)
  319. {
  320. Ellipse(hDC,
  321. gCalPts[i][j].ScreenPt.x - CIRCLE_RADIUS,
  322. gCalPts[i][j].ScreenPt.y - CIRCLE_RADIUS,
  323. gCalPts[i][j].ScreenPt.x + CIRCLE_RADIUS,
  324. gCalPts[i][j].ScreenPt.y + CIRCLE_RADIUS);
  325. MoveToEx(hDC,
  326. gCalPts[i][j].ScreenPt.x - CIRCLE_RADIUS,
  327. gCalPts[i][j].ScreenPt.y,
  328. NULL);
  329. LineTo(hDC,
  330. gCalPts[i][j].ScreenPt.x + CIRCLE_RADIUS,
  331. gCalPts[i][j].ScreenPt.y);
  332. MoveToEx(hDC,
  333. gCalPts[i][j].ScreenPt.x,
  334. gCalPts[i][j].ScreenPt.y - CIRCLE_RADIUS,
  335. NULL);
  336. LineTo(hDC,
  337. gCalPts[i][j].ScreenPt.x,
  338. gCalPts[i][j].ScreenPt.y + CIRCLE_RADIUS);
  339. }
  340. }
  341. }
  342. if (giNumLinearCalPts == NUM_LINEARCAL_PTS)
  343. {
  344. DisplayMap(hwnd, &PenSettings.LinearityMap);
  345. }
  346. SelectObject(hDC, hpenOld);
  347. EndPaint(hwnd, &ps);
  348. break;
  349. }
  350. case WM_DESTROY:
  351. ShowCursor(TRUE);
  352. if (ghpenRed != NULL)
  353. {
  354. DeleteObject(ghpenRed);
  355. }
  356. if (ghpenBlue != NULL)
  357. {
  358. DeleteObject(ghpenBlue);
  359. }
  360. break;
  361. default:
  362. rc = DefWindowProc(hwnd, uMsg, wParam, lParam);
  363. }
  364. TRACEEXIT(("=%x\n", rc));
  365. return rc;
  366. } //LinearCalWndProc
  367. /*****************************************************************************
  368. *
  369. * @doc INTERNAL
  370. *
  371. * @func PCALIBRATE_PT | FindPoint |
  372. * Find if the click is in the vicinity of the calibrate points.
  373. *
  374. * @parm IN int | x | X value.
  375. * @parm IN int | y | Y value.
  376. * @parm IN int | offset | Vicinity offset
  377. *
  378. * @rvalue SUCCESS | Returns calibrate point found in the vicinity.
  379. * @rvalue FAILURE | Returns NULL.
  380. *
  381. *****************************************************************************/
  382. PCALIBRATE_PT
  383. FindPoint(
  384. IN int x,
  385. IN int y,
  386. IN int offset
  387. )
  388. {
  389. TRACEPROC("FindPoint", 2)
  390. PCALIBRATE_PT CalPt = NULL;
  391. int i, j;
  392. TRACEENTER(("(x=%d,y=%d,offset=%d)\n", x, y, offset));
  393. for (i = 0; i < NUM_LINEAR_YPTS; ++i)
  394. {
  395. for (j = 0; j < NUM_LINEAR_XPTS; ++j)
  396. {
  397. if ((x >= gCalPts[i][j].ScreenPt.x - offset) &&
  398. (x <= gCalPts[i][j].ScreenPt.x + offset) &&
  399. (y >= gCalPts[i][j].ScreenPt.y - offset) &&
  400. (y <= gCalPts[i][j].ScreenPt.y + offset))
  401. {
  402. CalPt = & gCalPts[i][j];
  403. break;
  404. }
  405. }
  406. }
  407. TRACEEXIT(("=%p\n", CalPt));
  408. return CalPt;
  409. } //FindPoint
  410. /*****************************************************************************
  411. *
  412. * @doc INTERNAL
  413. *
  414. * @func VOID | DoLinearCal | Generates the linearity calibration table.
  415. *
  416. * @parm IN HWND | hwnd | Window handle.
  417. * @parm OUT PLINEAR_MAP | LinearityMap | Points to the structure to hold
  418. * the result of calculation.
  419. *
  420. * @rvalue None.
  421. *
  422. *****************************************************************************/
  423. VOID
  424. DoLinearCal(
  425. IN HWND hwnd,
  426. OUT PLINEAR_MAP LinearityMap
  427. )
  428. {
  429. TRACEPROC("DoLinearCal", 2)
  430. int i, j;
  431. TRACEENTER(("(hwnd=%x,LinearityMap=%p)\n", hwnd, LinearityMap));
  432. LinearityMap->dwcbLen = sizeof(LINEAR_MAP);
  433. LinearityMap->wNumXPts = NUM_LINEAR_XPTS;
  434. LinearityMap->wNumYPts = NUM_LINEAR_YPTS;
  435. for (i = 0; i < NUM_LINEAR_YPTS; ++i)
  436. {
  437. for (j = 0; j < NUM_LINEAR_XPTS; ++j)
  438. {
  439. LinearityMap->Data[i][j].wRefPtX =
  440. (USHORT)((gCalPts[i][j].ScreenPt.x*MAX_NORMALIZED_X)/
  441. gcxScreen);
  442. LinearityMap->Data[i][j].wRefPtY =
  443. (USHORT)((gCalPts[i][j].ScreenPt.y*MAX_NORMALIZED_Y)/
  444. gcyScreen);
  445. LinearityMap->Data[i][j].wDigiPtX =
  446. (USHORT)gCalPts[i][j].DigiPt.x;
  447. LinearityMap->Data[i][j].wDigiPtY =
  448. (USHORT)gCalPts[i][j].DigiPt.y;
  449. }
  450. }
  451. TRACEEXIT(("!\n"));
  452. return;
  453. } //DoLinearCal
  454. /*****************************************************************************
  455. *
  456. * @doc INTERNAL
  457. *
  458. * @func VOID | DisplayMap | Display the linearity map.
  459. *
  460. * @parm IN HWND | hwnd | Window handle.
  461. * @parm IN PLINEAR_MAP | LinearityMap | Points to the linearity map.
  462. *
  463. * @rvalue None.
  464. *
  465. *****************************************************************************/
  466. VOID
  467. DisplayMap(
  468. IN HWND hwnd,
  469. IN PLINEAR_MAP LinearityMap
  470. )
  471. {
  472. TRACEPROC("DisplayMap", 2)
  473. int i, j;
  474. LONG xMin, xMax, yMin, yMax, xRange, yRange;
  475. LONG xScreenMin, xScreenMax,
  476. yScreenMin, yScreenMax,
  477. xScreenRange, yScreenRange;
  478. HDC hDC;
  479. HPEN hpenOld;
  480. POINT Pts[4];
  481. TRACEENTER(("(hwnd=%x,LinearityMap=%p)\n", hwnd, LinearityMap));
  482. for (i = 0, xMin = xMax = 0; i < NUM_LINEAR_YPTS; ++i)
  483. {
  484. xMin += LinearityMap->Data[i][0].wDigiPtX;
  485. xMax += LinearityMap->Data[i][NUM_LINEAR_XPTS - 1].wDigiPtX;
  486. }
  487. xMin /= NUM_LINEAR_YPTS;
  488. xMax /= NUM_LINEAR_YPTS;
  489. xRange = xMax - xMin;
  490. xScreenMin = (LinearityMap->Data[0][0].wRefPtX*gcxScreen)/MAX_NORMALIZED_X;
  491. xScreenMax = (LinearityMap->Data[0][NUM_LINEAR_XPTS - 1].wRefPtX*gcxScreen)/
  492. MAX_NORMALIZED_X;
  493. xScreenRange = xScreenMax - xScreenMin;
  494. for (i = 0, yMin = yMax = 0; i < NUM_LINEAR_XPTS; ++i)
  495. {
  496. yMin += LinearityMap->Data[0][i].wDigiPtY;
  497. yMax += LinearityMap->Data[NUM_LINEAR_YPTS - 1][i].wDigiPtY;
  498. }
  499. yMin /= NUM_LINEAR_XPTS;
  500. yMax /= NUM_LINEAR_XPTS;
  501. yRange = yMax - yMin;
  502. yScreenMin = (LinearityMap->Data[0][0].wRefPtY*gcyScreen)/MAX_NORMALIZED_Y;
  503. yScreenMax = (LinearityMap->Data[NUM_LINEAR_YPTS - 1][0].wRefPtY*gcyScreen)/
  504. MAX_NORMALIZED_Y;
  505. yScreenRange = yScreenMax - yScreenMin;
  506. hDC = GetDC(hwnd);
  507. hpenOld = SelectObject(hDC, ghpenRed);
  508. for (i = 0; i < NUM_LINEAR_YPTS - 1; ++i)
  509. {
  510. for (j = 0; j < NUM_LINEAR_XPTS - 1; ++j)
  511. {
  512. Pts[0].x = xScreenMin +
  513. ((LinearityMap->Data[i][j].wDigiPtX - xMin)*
  514. xScreenRange)/xRange;
  515. Pts[0].y = yScreenMin +
  516. ((LinearityMap->Data[i][j].wDigiPtY - yMin)*
  517. yScreenRange)/yRange;
  518. Pts[1].x = xScreenMin +
  519. ((LinearityMap->Data[i][j+1].wDigiPtX - xMin)*
  520. xScreenRange)/xRange;
  521. Pts[1].y = yScreenMin +
  522. ((LinearityMap->Data[i][j+1].wDigiPtY - yMin)*
  523. yScreenRange)/yRange;
  524. Pts[2].x = xScreenMin +
  525. ((LinearityMap->Data[i+1][j+1].wDigiPtX - xMin)*
  526. xScreenRange)/xRange;
  527. Pts[2].y = yScreenMin +
  528. ((LinearityMap->Data[i+1][j+1].wDigiPtY - yMin)*
  529. yScreenRange)/yRange;
  530. Pts[3].x = xScreenMin +
  531. ((LinearityMap->Data[i+1][j].wDigiPtX - xMin)*
  532. xScreenRange)/xRange;
  533. Pts[3].y = yScreenMin +
  534. ((LinearityMap->Data[i+1][j].wDigiPtY - yMin)*
  535. yScreenRange)/yRange;
  536. MoveToEx(hDC, Pts[3].x, Pts[3].y, NULL);
  537. PolylineTo(hDC, Pts, 4);
  538. }
  539. }
  540. SelectObject(hDC, hpenOld);
  541. ReleaseDC(hwnd, hDC);
  542. TRACEEXIT(("!\n"));
  543. return;
  544. } //DisplayMap
  545. #endif