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.

489 lines
14 KiB

  1. /*++
  2. Copyright (c) 2000 Microsoft Corporation
  3. Module Name:
  4. tiltcal.c
  5. Abstract: This module contains code to calibrate pen tilt of the mutoh pen
  6. tablet.
  7. Environment:
  8. User mode
  9. Author:
  10. Michael Tsang (MikeTs) 20-Apr-2000
  11. Revision History:
  12. --*/
  13. #include "pch.h"
  14. #ifdef PENPAGE
  15. #define NUM_PENTILTCAL_XPTS 2
  16. #define NUM_PENTILTCAL_YPTS 2
  17. #define NUM_PENTILTCAL_PTS (NUM_PENTILTCAL_XPTS*NUM_PENTILTCAL_YPTS)
  18. #define SCREEN_TARGET_XOFFSET 128
  19. #define SCREEN_TARGET_YOFFSET 128
  20. #define VICINITY_OFFSET 50
  21. #define INSTRUCTIONS_WIDTH 256
  22. #define INSTRUCTIONS_HEIGHT 128
  23. static TCHAR gtszCalibrate[] = TEXT("Calibrate");
  24. static TCHAR gtszCalibrateTitle[64] = {0};
  25. static TCHAR gtszInstructions[256] = {0};
  26. static RECT grectInstructions = {0};
  27. static CALIBRATE_PT gCalPts[NUM_PENTILTCAL_YPTS][NUM_PENTILTCAL_XPTS] = {0};
  28. static int giNumPenTiltCalPts = 0;
  29. static HWND ghwndParent = 0;
  30. static LONG gcxScreen = 0, gcyScreen = 0;
  31. static HPEN ghpenRed = 0, ghpenBlue = 0;
  32. /*****************************************************************************
  33. *
  34. * @doc INTERNAL
  35. *
  36. * @func BOOL | CreatePenTiltCalWindow |
  37. * Entry point of the pen tilt calibration code.
  38. *
  39. * @parm IN HWND | hwndParent | Parent Window handle.
  40. *
  41. * @rvalue SUCCESS | Returns TRUE.
  42. * @rvalue FAILURE | Returns FALSE.
  43. *
  44. *****************************************************************************/
  45. BOOL
  46. CreatePenTiltCalWindow(
  47. IN HWND hwndParent
  48. )
  49. {
  50. TRACEPROC("CreatePenTiltCalWindow", 2)
  51. BOOL rc = FALSE;
  52. HWND hwnd;
  53. TRACEENTER(("(hwndParent=%p)\n", hwndParent));
  54. giNumPenTiltCalPts = 0;
  55. RtlZeroMemory(gCalPts, sizeof(gCalPts));
  56. ghwndParent = hwndParent;
  57. LoadString(ghInstance,
  58. IDS_CALIBRATE_TITLE,
  59. gtszCalibrateTitle,
  60. sizeof(gtszCalibrateTitle)/sizeof(TCHAR));
  61. LoadString(ghInstance,
  62. IDS_CALIBRATE_INSTRUCTIONS,
  63. gtszInstructions,
  64. sizeof(gtszInstructions)/sizeof(TCHAR));
  65. gcxScreen = GetSystemMetrics(SM_CXSCREEN);
  66. gcyScreen = GetSystemMetrics(SM_CYSCREEN);
  67. grectInstructions.left = (gcxScreen - INSTRUCTIONS_WIDTH)/2;
  68. grectInstructions.top = (gcyScreen - INSTRUCTIONS_HEIGHT)/2;
  69. grectInstructions.right = grectInstructions.left + INSTRUCTIONS_WIDTH;
  70. grectInstructions.bottom = grectInstructions.top + INSTRUCTIONS_HEIGHT;
  71. RegisterPenTiltCalClass(ghInstance);
  72. hwnd = CreateWindow(gtszCalibrate, //Class Name
  73. gtszCalibrate, //Window Name
  74. WS_POPUP, //Style
  75. 0, //Window X
  76. 0, //Window Y
  77. gcxScreen, //Window Width
  78. gcyScreen, //Window Height
  79. hwndParent, //Parent Handle
  80. NULL, //Menu Handle
  81. ghInstance, //Instance Handle
  82. NULL); //Creation Data
  83. if (hwnd != NULL)
  84. {
  85. ShowWindow(hwnd, SW_SHOWNORMAL);
  86. rc = TRUE;
  87. }
  88. TRACEEXIT(("=%x\n", rc));
  89. return rc;
  90. } //CreatePenTiltCalWindow
  91. /*****************************************************************************
  92. *
  93. * @doc INTERNAL
  94. *
  95. * @func BOOL | RegisterPenTiltCalClass |
  96. * Register window class.
  97. *
  98. * @parm IN HINSTANCE | hInstance | Instance handle.
  99. *
  100. * @rvalue SUCCESS | Returns class atom
  101. * @rvalue FAILURE | Returns 0
  102. *
  103. *****************************************************************************/
  104. ATOM
  105. RegisterPenTiltCalClass(
  106. IN HINSTANCE hInstance
  107. )
  108. {
  109. TRACEPROC("RegisterPenTiltCalClass", 2)
  110. ATOM atom;
  111. WNDCLASSEX wcex;
  112. TRACEENTER(("(hInstance=%p)\n", hInstance));
  113. wcex.cbSize = sizeof(wcex);
  114. wcex.style = CS_HREDRAW | CS_VREDRAW;
  115. wcex.lpfnWndProc = PenTiltCalWndProc;
  116. wcex.cbClsExtra = 0;
  117. wcex.cbWndExtra = 0;
  118. wcex.hInstance = hInstance;
  119. wcex.hIcon = LoadIcon(hInstance, (LPCTSTR)IDI_TABLETPC);
  120. wcex.hCursor = NULL; //No cursor is shown.
  121. wcex.hbrBackground = (HBRUSH)(COLOR_WINDOW + 1);
  122. wcex.lpszMenuName = NULL;
  123. wcex.lpszClassName = gtszCalibrate;
  124. wcex.hIconSm = NULL;
  125. atom = RegisterClassEx(&wcex);
  126. TRACEEXIT(("=%x\n", atom));
  127. return atom;
  128. } //RegisterPenTiltCalClass
  129. /*****************************************************************************
  130. *
  131. * @doc EXTERNAL
  132. *
  133. * @func LRESULT | PenTiltCalWndProc |
  134. * Dialog procedure for the pen tilt calibration page.
  135. *
  136. * @parm IN HWND | hwnd | Window handle.
  137. * @parm IN UINT | uMsg | Message.
  138. * @parm IN WPARAM | wParam | Word Parameter.
  139. * @parm IN LPARAM | lParam | Long Parameter.
  140. *
  141. * @rvalue Return value depends on the message.
  142. *
  143. *****************************************************************************/
  144. LRESULT CALLBACK
  145. PenTiltCalWndProc(
  146. IN HWND hwnd,
  147. IN UINT uMsg,
  148. IN WPARAM wParam,
  149. IN LPARAM lParam
  150. )
  151. {
  152. TRACEPROC("PenTiltCalWndProc", 2)
  153. LRESULT rc = 0;
  154. HDC hDC;
  155. TRACEENTER(("(hwnd=%p,Msg=%s,wParam=%x,lParam=%x)\n",
  156. hwnd, LookupName(uMsg, WMMsgNames) , wParam, lParam));
  157. switch (uMsg)
  158. {
  159. case WM_CREATE:
  160. {
  161. ghpenRed = CreatePen(PS_SOLID, 0, RGB(255, 0, 0));
  162. ghpenBlue = CreatePen(PS_SOLID, 0, RGB(0, 0, 255));
  163. gCalPts[0][0].ScreenPt.x = SCREEN_TARGET_XOFFSET;
  164. gCalPts[0][0].ScreenPt.y = SCREEN_TARGET_YOFFSET;
  165. gCalPts[0][1].ScreenPt.x = gcxScreen - SCREEN_TARGET_XOFFSET;
  166. gCalPts[0][1].ScreenPt.y = SCREEN_TARGET_YOFFSET;
  167. gCalPts[1][0].ScreenPt.x = SCREEN_TARGET_XOFFSET;
  168. gCalPts[1][0].ScreenPt.y = gcyScreen - SCREEN_TARGET_YOFFSET;
  169. gCalPts[1][1].ScreenPt.x = gcxScreen - SCREEN_TARGET_XOFFSET;
  170. gCalPts[1][1].ScreenPt.y = gcyScreen - SCREEN_TARGET_YOFFSET;
  171. ShowCursor(FALSE);
  172. break;
  173. }
  174. case WM_LBUTTONDOWN:
  175. {
  176. PCALIBRATE_PT CalPt;
  177. WORD wButtonState;
  178. CalPt = FindVicinity(GET_X_LPARAM(lParam),
  179. GET_Y_LPARAM(lParam),
  180. VICINITY_OFFSET);
  181. if (CalPt != NULL)
  182. {
  183. CalPt->DigiPt.x = GET_X_LPARAM(lParam);
  184. CalPt->DigiPt.y = GET_Y_LPARAM(lParam);
  185. if (!(CalPt->dwFlags & CPF_CALIBRATED))
  186. {
  187. CalPt->dwFlags |= CPF_CALIBRATED;
  188. giNumPenTiltCalPts++;
  189. hDC = GetDC(hwnd);
  190. DrawTarget(hDC, CalPt);
  191. ReleaseDC(hwnd, hDC);
  192. if (giNumPenTiltCalPts == NUM_PENTILTCAL_PTS)
  193. {
  194. int rcID = DoPenTiltCal(hwnd,
  195. &PenSettings.dxPenTilt,
  196. &PenSettings.dyPenTilt);
  197. if ((rcID == IDYES) || (rcID == IDCANCEL))
  198. {
  199. SendMessage(ghwndParent,
  200. WM_PENTILTCAL_DONE,
  201. (WPARAM)rcID,
  202. (LPARAM)hwnd);
  203. }
  204. }
  205. }
  206. }
  207. break;
  208. }
  209. case WM_CHAR:
  210. switch (wParam)
  211. {
  212. case VK_ESCAPE:
  213. SendMessage(ghwndParent,
  214. WM_PENTILTCAL_DONE,
  215. (WPARAM)NULL,
  216. (LPARAM)hwnd);
  217. break;
  218. }
  219. break;
  220. case WM_PAINT:
  221. {
  222. PAINTSTRUCT ps;
  223. int i, j;
  224. hDC = BeginPaint(hwnd, &ps);
  225. for (i = 0; i < NUM_PENTILTCAL_YPTS; ++i)
  226. {
  227. for (j = 0; j < NUM_PENTILTCAL_XPTS; ++j)
  228. {
  229. DrawTarget(hDC, &gCalPts[i][j]);
  230. }
  231. }
  232. DrawText(hDC,
  233. gtszInstructions,
  234. -1,
  235. &grectInstructions,
  236. DT_WORDBREAK | DT_LEFT | DT_VCENTER);
  237. EndPaint(hwnd, &ps);
  238. break;
  239. }
  240. case WM_DESTROY:
  241. ShowCursor(TRUE);
  242. if (ghpenRed != NULL)
  243. {
  244. DeleteObject(ghpenRed);
  245. }
  246. if (ghpenBlue != NULL)
  247. {
  248. DeleteObject(ghpenBlue);
  249. }
  250. break;
  251. default:
  252. rc = DefWindowProc(hwnd, uMsg, wParam, lParam);
  253. }
  254. TRACEEXIT(("=%x\n", rc));
  255. return rc;
  256. } //PenTiltCalWndProc
  257. /*****************************************************************************
  258. *
  259. * @doc INTERNAL
  260. *
  261. * @func PCALIBRATE_PT | FindVicinity |
  262. * Find if the click is in the vicinity of the calibrate points.
  263. *
  264. * @parm IN int | x | X value.
  265. * @parm IN int | y | Y value.
  266. * @parm IN int | offset | Vicinity offset
  267. *
  268. * @rvalue SUCCESS | Returns calibrate point found in the vicinity.
  269. * @rvalue FAILURE | Returns NULL.
  270. *
  271. *****************************************************************************/
  272. PCALIBRATE_PT
  273. FindVicinity(
  274. IN int x,
  275. IN int y,
  276. IN int offset
  277. )
  278. {
  279. TRACEPROC("FindVicinity", 2)
  280. PCALIBRATE_PT CalPt = NULL;
  281. int i, j;
  282. TRACEENTER(("(x=%d,y=%d,offset=%d)\n", x, y, offset));
  283. for (i = 0; i < NUM_PENTILTCAL_YPTS; ++i)
  284. {
  285. for (j = 0; j < NUM_PENTILTCAL_XPTS; ++j)
  286. {
  287. if ((x >= gCalPts[i][j].ScreenPt.x - offset) &&
  288. (x <= gCalPts[i][j].ScreenPt.x + offset) &&
  289. (y >= gCalPts[i][j].ScreenPt.y - offset) &&
  290. (y <= gCalPts[i][j].ScreenPt.y + offset))
  291. {
  292. CalPt = & gCalPts[i][j];
  293. break;
  294. }
  295. }
  296. }
  297. TRACEEXIT(("=%p\n", CalPt));
  298. return CalPt;
  299. } //FindVicinity
  300. /*****************************************************************************
  301. *
  302. * @doc INTERNAL
  303. *
  304. * @func VOID | DrawTarget |
  305. * Draw the given target point.
  306. *
  307. * @parm IN HDC | hDC | DC handle.
  308. * @parm IN PCALIBRATE_PT | CalPt | Points to the calibration point.
  309. *
  310. * @rvalue None.
  311. *
  312. *****************************************************************************/
  313. VOID
  314. DrawTarget(
  315. IN HDC hDC,
  316. IN PCALIBRATE_PT CalPt
  317. )
  318. {
  319. TRACEPROC("DrawTarget", 2)
  320. HPEN hpenOld;
  321. TRACEENTER(("(hDC=%x,CalPt=%p)\n", hDC, CalPt));
  322. hpenOld = SelectObject(hDC,
  323. (CalPt->dwFlags & CPF_CALIBRATED)?
  324. ghpenRed: ghpenBlue);
  325. MoveToEx(hDC, CalPt->ScreenPt.x - 16, CalPt->ScreenPt.y, NULL);
  326. LineTo(hDC, CalPt->ScreenPt.x - 4, CalPt->ScreenPt.y);
  327. MoveToEx(hDC, CalPt->ScreenPt.x - 2, CalPt->ScreenPt.y, NULL);
  328. LineTo(hDC, CalPt->ScreenPt.x + 2, CalPt->ScreenPt.y);
  329. MoveToEx(hDC, CalPt->ScreenPt.x + 4, CalPt->ScreenPt.y, NULL);
  330. LineTo(hDC, CalPt->ScreenPt.x + 16, CalPt->ScreenPt.y);
  331. MoveToEx(hDC, CalPt->ScreenPt.x, CalPt->ScreenPt.y - 16, NULL);
  332. LineTo(hDC, CalPt->ScreenPt.x, CalPt->ScreenPt.y - 4);
  333. MoveToEx(hDC, CalPt->ScreenPt.x, CalPt->ScreenPt.y - 2, NULL);
  334. LineTo(hDC, CalPt->ScreenPt.x, CalPt->ScreenPt.y + 2);
  335. MoveToEx(hDC, CalPt->ScreenPt.x, CalPt->ScreenPt.y + 4, NULL);
  336. LineTo(hDC, CalPt->ScreenPt.x, CalPt->ScreenPt.y + 16);
  337. SelectObject(hDC, hpenOld);
  338. TRACEEXIT(("!\n"));
  339. return;
  340. } //DrawTarget
  341. /*****************************************************************************
  342. *
  343. * @doc INTERNAL
  344. *
  345. * @func int | DoPenTiltCal |
  346. * Confirm with the user on the calibration data and do the
  347. * calibration calculation.
  348. *
  349. * @parm IN HWND | hwnd | Window handle.
  350. * @parm OUT PLONG | pdxPenTilt | To hold the x pen tilt compensation.
  351. * @parm OUT PLONG | pdyPenTilt | To hold the y pen tilt compensation.
  352. *
  353. * @rvalue SUCCESS | Returns IDYES.
  354. * @rvalue FAILURE | Returns IDNO or IDCANCEL.
  355. *
  356. *****************************************************************************/
  357. int
  358. DoPenTiltCal(
  359. IN HWND hwnd,
  360. OUT PLONG pdxPenTilt,
  361. OUT PLONG pdyPenTilt
  362. )
  363. {
  364. TRACEPROC("DoPenTiltCal", 2)
  365. int rc;
  366. TCHAR tszMsg[128];
  367. TRACEENTER(("(hwnd=%x,pdxPenTilt=%p,pdyPenTilt)\n",
  368. hwnd, pdxPenTilt, pdyPenTilt));
  369. LoadString(ghInstance,
  370. IDS_CALIBRATE_CONFIRM,
  371. tszMsg,
  372. sizeof(tszMsg)/sizeof(TCHAR));
  373. ShowCursor(TRUE);
  374. rc = MessageBox(hwnd,
  375. tszMsg,
  376. gtszCalibrateTitle,
  377. MB_YESNOCANCEL | MB_ICONQUESTION);
  378. ShowCursor(FALSE);
  379. if (rc == IDNO)
  380. {
  381. int i, j;
  382. //
  383. // Reset the calibration.
  384. //
  385. for (i = 0; i < NUM_PENTILTCAL_YPTS; ++i)
  386. {
  387. for (j = 0; j < NUM_PENTILTCAL_XPTS; ++j)
  388. {
  389. gCalPts[i][j].dwFlags &= ~CPF_CALIBRATED;
  390. }
  391. }
  392. giNumPenTiltCalPts = 0;
  393. InvalidateRect(hwnd, NULL, TRUE);
  394. }
  395. else if (rc == IDYES)
  396. {
  397. int i, j;
  398. *pdxPenTilt = *pdyPenTilt = 0;
  399. for (i = 0; i < NUM_PENTILTCAL_YPTS; ++i)
  400. {
  401. for (j = 0; j < NUM_PENTILTCAL_XPTS; ++j)
  402. {
  403. *pdxPenTilt += gCalPts[i][j].DigiPt.x -
  404. gCalPts[i][j].ScreenPt.x;
  405. *pdyPenTilt += gCalPts[i][j].DigiPt.y -
  406. gCalPts[i][j].ScreenPt.y;
  407. }
  408. }
  409. *pdxPenTilt /= NUM_PENTILTCAL_PTS;
  410. *pdyPenTilt /= NUM_PENTILTCAL_PTS;
  411. }
  412. TRACEEXIT(("=%x\n", rc));
  413. return rc;
  414. } //DoPenTiltCal
  415. #endif