Leaked source code of windows server 2003
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.

1464 lines
48 KiB

  1. /**************************************************************************\
  2. * Module Name: sftkbdt1.c
  3. *
  4. * Copyright (c) 1985 - 1999, Microsoft Corporation
  5. *
  6. * Soft keyboard support for Traditional Chinese
  7. *
  8. * History:
  9. * 02-Jan-1996 wkwok - ported from Win95
  10. \**************************************************************************/
  11. #include "precomp.h"
  12. #pragma hdrstop
  13. #include "softkbd.h"
  14. CONST BYTE bSKT1VirtKey[SKT1_TOTAL_KEY_NUM] = { // Virtual Key for Letter Buttons
  15. // ` 1 2 3 4 5 6 7 8 9 0
  16. VK_OEM_3, '1', '2', '3', '4', '5', '6', '7', '8', '9', '0',
  17. // - = \\ line 1 letter above
  18. VK_OEM_MINUS, VK_OEM_EQUAL, VK_OEM_BSLASH,
  19. // q w e r t y u i o p
  20. 'Q', 'W', 'E', 'R', 'T', 'Y', 'U', 'I', 'O', 'P',
  21. // [ ] line 2 letter above
  22. VK_OEM_LBRACKET, VK_OEM_RBRACKET,
  23. // a s d f g h j k l
  24. 'A', 'S', 'D', 'F', 'G', 'H', 'J', 'K', 'L',
  25. // ; ' line 3 letter above
  26. VK_OEM_SEMICLN, VK_OEM_QUOTE,
  27. // z x c v b n m
  28. 'Z', 'X', 'C', 'V', 'B', 'N', 'M',
  29. // , . / line 4 letter above
  30. VK_OEM_COMMA, VK_OEM_PERIOD, VK_OEM_SLASH,
  31. // <- tab caps enter
  32. VK_BACK, VK_TAB, VK_CAPITAL, VK_RETURN,
  33. // shift1 shift2 ctrl1 ctrl2
  34. VK_SHIFT, VK_SHIFT, VK_CONTROL, VK_CONTROL,
  35. // alt1 alt2 esc space special key above
  36. VK_MENU, VK_MENU, VK_ESCAPE, VK_SPACE
  37. };
  38. LOGFONT lfSKT1Font;
  39. /**********************************************************************/
  40. /* GetSKT1TextMetric */
  41. /**********************************************************************/
  42. void GetSKT1TextMetric(
  43. LPTEXTMETRIC lptm)
  44. {
  45. HDC hDC;
  46. HFONT hOldFont;
  47. SIZE szDbcs;
  48. const WCHAR wcDbcs = 0x4e11;
  49. hDC = GetDC((HWND)NULL);
  50. // get the 9 pixels font
  51. RtlZeroMemory(&lfSKT1Font, sizeof lfSKT1Font);
  52. lfSKT1Font.lfHeight = -12;
  53. lfSKT1Font.lfWeight = FW_NORMAL;
  54. lfSKT1Font.lfCharSet = CHINESEBIG5_CHARSET;
  55. lfSKT1Font.lfOutPrecision = OUT_TT_ONLY_PRECIS;
  56. lfSKT1Font.lfClipPrecision = CLIP_DEFAULT_PRECIS;
  57. lfSKT1Font.lfQuality = PROOF_QUALITY;
  58. lfSKT1Font.lfPitchAndFamily = FIXED_PITCH|FF_MODERN;
  59. hOldFont = (HFONT)SelectObject(hDC, CreateFontIndirect(&lfSKT1Font));
  60. GetTextMetrics(hDC, lptm);
  61. /*
  62. * NT5: Dirty hack for "Lucida Console" which was "font linked" on NT5, and
  63. * GetTextMetrics API does not return correct text metrics.
  64. */
  65. if (GetTextExtentPoint32(hDC, &wcDbcs, 1, &szDbcs) && lptm->tmMaxCharWidth < szDbcs.cx) {
  66. TAGMSG2(DBGTAG_IMM, "GetSKT1TextMetric: tmMaxCharWidth(%d) is smaller than real width(%d).",
  67. lptm->tmMaxCharWidth, szDbcs.cx);
  68. lptm->tmMaxCharWidth = szDbcs.cx;
  69. }
  70. DeleteObject(SelectObject(hDC, hOldFont));
  71. ReleaseDC((HWND)NULL, hDC);
  72. return;
  73. }
  74. /**********************************************************************/
  75. /* InitSKT1ButtonPos */
  76. /**********************************************************************/
  77. void InitSKT1ButtonPos(
  78. LPSKT1CTXT lpSKT1Ctxt)
  79. {
  80. TEXTMETRIC tm;
  81. int nButtonWidthUnit, nButtonHeightUnit;
  82. int i, nLetterButtonStart, nLetterButtonEnd, xStartPos, yStartPos;
  83. GetSKT1TextMetric(&tm);
  84. nButtonWidthUnit = tm.tmMaxCharWidth + SKT1_LABEL_BMP_X - SKT1_XOVERLAP;
  85. #define INIT_WIDTH(name, width) \
  86. lpSKT1Ctxt->nButtonWidth[SKT1_ ## name ## _TYPE] = (width)
  87. INIT_WIDTH(LETTER, nButtonWidthUnit * SKT1_LETTER_WIDTH_TIMES / 2);
  88. INIT_WIDTH(BACKSPACE, nButtonWidthUnit * SKT1_BACKSPACE_WIDTH_TIMES / 2 + 1);
  89. INIT_WIDTH(TAB, nButtonWidthUnit * SKT1_TAB_WIDTH_TIMES / 2 + (SKT1_XIN + 1) / 2);
  90. INIT_WIDTH(CAPS, nButtonWidthUnit * SKT1_CAPS_WIDTH_TIMES / 2 + SKT1_XIN);
  91. INIT_WIDTH(ENTER, nButtonWidthUnit * SKT1_ENTER_WIDTH_TIMES / 2 + (SKT1_XIN + 1) / 2);
  92. INIT_WIDTH(SHIFT, nButtonWidthUnit * SKT1_SHIFT_WIDTH_TIMES / 2 + SKT1_XIN + (SKT1_XIN + 1) / 2);
  93. INIT_WIDTH(CTRL, nButtonWidthUnit * SKT1_CTRL_WIDTH_TIMES / 2 + (SKT1_XIN + 1) / 2);
  94. INIT_WIDTH(ALT, nButtonWidthUnit * SKT1_ALT_WIDTH_TIMES / 2 + (SKT1_XIN + 1) / 2);
  95. INIT_WIDTH(ESC, nButtonWidthUnit * SKT1_ESC_WIDTH_TIMES / 2 + SKT1_XIN / 2);
  96. INIT_WIDTH(SPACE, nButtonWidthUnit * SKT1_SPACE_WIDTH_TIMES / 2 + SKT1_XIN * 5);
  97. #undef INIT_WIDTH
  98. nButtonHeightUnit = tm.tmHeight + SKT1_LABEL_BMP_Y;
  99. lpSKT1Ctxt->nButtonHeight[0] = nButtonHeightUnit;
  100. lpSKT1Ctxt->nButtonHeight[1] = nButtonHeightUnit * 2 + SKT1_YIN; // enter
  101. // init first row attribute
  102. xStartPos = gptRaiseEdge.x + SKT1_XOUT + (SKT1_XIN + 1) / 2;
  103. yStartPos = gptRaiseEdge.y + SKT1_YOUT + (SKT1_YIN + 1) / 2;
  104. nLetterButtonStart = 0;
  105. nLetterButtonEnd = nLetterButtonStart + SKT1_ROW1_LETTER_NUM;
  106. for (i = nLetterButtonStart; i < nLetterButtonEnd; i++) {
  107. lpSKT1Ctxt->ptButtonPos[i].x = xStartPos;
  108. lpSKT1Ctxt->ptButtonPos[i].y = yStartPos;
  109. xStartPos += (lpSKT1Ctxt->nButtonWidth[SKT1_LETTER_TYPE] + SKT1_XIN);
  110. }
  111. // backspace
  112. lpSKT1Ctxt->ptButtonPos[SKT1_BACKSPACE_INDEX].x = xStartPos;
  113. lpSKT1Ctxt->ptButtonPos[SKT1_BACKSPACE_INDEX].y = yStartPos;
  114. // init second row attribute
  115. xStartPos = gptRaiseEdge.x + SKT1_XOUT + (SKT1_XIN + 1) / 2;
  116. yStartPos += (nButtonHeightUnit + SKT1_YIN);
  117. // tab
  118. lpSKT1Ctxt->ptButtonPos[SKT1_TAB_INDEX].x = xStartPos;
  119. lpSKT1Ctxt->ptButtonPos[SKT1_TAB_INDEX].y = yStartPos;
  120. xStartPos += (lpSKT1Ctxt->nButtonWidth[SKT1_TAB_TYPE] + SKT1_XIN);
  121. // letter
  122. nLetterButtonStart = nLetterButtonEnd;
  123. nLetterButtonEnd = nLetterButtonStart + SKT1_ROW2_LETTER_NUM;
  124. for (i = nLetterButtonStart; i < nLetterButtonEnd; i++) {
  125. lpSKT1Ctxt->ptButtonPos[i].x = xStartPos;
  126. lpSKT1Ctxt->ptButtonPos[i].y = yStartPos;
  127. xStartPos += (lpSKT1Ctxt->nButtonWidth[SKT1_LETTER_TYPE] + SKT1_XIN);
  128. }
  129. // enter
  130. lpSKT1Ctxt->ptButtonPos[SKT1_ENTER_INDEX].x = xStartPos;
  131. lpSKT1Ctxt->ptButtonPos[SKT1_ENTER_INDEX].y = yStartPos;
  132. // init third row
  133. xStartPos = gptRaiseEdge.x + SKT1_XOUT + (SKT1_XIN + 1) / 2;
  134. yStartPos += (nButtonHeightUnit + SKT1_YIN);
  135. // caps
  136. lpSKT1Ctxt->ptButtonPos[SKT1_CAPS_INDEX].x = xStartPos;
  137. lpSKT1Ctxt->ptButtonPos[SKT1_CAPS_INDEX].y = yStartPos;
  138. xStartPos += (lpSKT1Ctxt->nButtonWidth[SKT1_CAPS_TYPE] + SKT1_XIN);
  139. // letter
  140. nLetterButtonStart = nLetterButtonEnd;
  141. nLetterButtonEnd = nLetterButtonStart + SKT1_ROW3_LETTER_NUM;
  142. for (i = nLetterButtonStart; i < nLetterButtonEnd; i++) {
  143. lpSKT1Ctxt->ptButtonPos[i].x = xStartPos;
  144. lpSKT1Ctxt->ptButtonPos[i].y = yStartPos;
  145. xStartPos += (lpSKT1Ctxt->nButtonWidth[SKT1_LETTER_TYPE] + SKT1_XIN);
  146. }
  147. // init fourth row
  148. xStartPos = gptRaiseEdge.x + SKT1_XOUT + (SKT1_XIN + 1) / 2;
  149. yStartPos += (nButtonHeightUnit + SKT1_YIN);
  150. // shift 1
  151. lpSKT1Ctxt->ptButtonPos[SKT1_SHIFT_INDEX].x = xStartPos;
  152. lpSKT1Ctxt->ptButtonPos[SKT1_SHIFT_INDEX].y = yStartPos;
  153. xStartPos += (lpSKT1Ctxt->nButtonWidth[SKT1_SHIFT_TYPE] + SKT1_XIN);
  154. // letter
  155. nLetterButtonStart = nLetterButtonEnd;
  156. nLetterButtonEnd = nLetterButtonStart + SKT1_ROW4_LETTER_NUM;
  157. for (i = nLetterButtonStart; i < nLetterButtonEnd; i++) {
  158. lpSKT1Ctxt->ptButtonPos[i].x = xStartPos;
  159. lpSKT1Ctxt->ptButtonPos[i].y = yStartPos;
  160. xStartPos += (lpSKT1Ctxt->nButtonWidth[SKT1_LETTER_TYPE] + SKT1_XIN);
  161. }
  162. // shift 2
  163. lpSKT1Ctxt->ptButtonPos[SKT1_SHIFT_INDEX + 1].x = xStartPos;
  164. lpSKT1Ctxt->ptButtonPos[SKT1_SHIFT_INDEX + 1].y = yStartPos;
  165. // init fifth row
  166. xStartPos = gptRaiseEdge.x + SKT1_XOUT + (SKT1_XIN + 1) / 2;
  167. yStartPos += (nButtonHeightUnit + SKT1_YIN);
  168. // ctrl 1
  169. lpSKT1Ctxt->ptButtonPos[SKT1_CTRL_INDEX].x = xStartPos;
  170. lpSKT1Ctxt->ptButtonPos[SKT1_CTRL_INDEX].y = yStartPos;
  171. xStartPos += (lpSKT1Ctxt->nButtonWidth[SKT1_CTRL_TYPE] + SKT1_XIN);
  172. // esc
  173. lpSKT1Ctxt->ptButtonPos[SKT1_ESC_INDEX].x = xStartPos;
  174. lpSKT1Ctxt->ptButtonPos[SKT1_ESC_INDEX].y = yStartPos;
  175. xStartPos += (lpSKT1Ctxt->nButtonWidth[SKT1_ESC_TYPE] + SKT1_XIN);
  176. // alt 1
  177. lpSKT1Ctxt->ptButtonPos[SKT1_ALT_INDEX].x = xStartPos;
  178. lpSKT1Ctxt->ptButtonPos[SKT1_ALT_INDEX].y = yStartPos;
  179. xStartPos += (lpSKT1Ctxt->nButtonWidth[SKT1_ALT_TYPE] + SKT1_XIN);
  180. // space
  181. lpSKT1Ctxt->ptButtonPos[SKT1_SPACE_INDEX].x = xStartPos;
  182. lpSKT1Ctxt->ptButtonPos[SKT1_SPACE_INDEX].y = yStartPos;
  183. xStartPos += (lpSKT1Ctxt->nButtonWidth[SKT1_SPACE_TYPE] + SKT1_XIN);
  184. // alt 2 .. skip blank
  185. lpSKT1Ctxt->ptButtonPos[SKT1_ALT_INDEX + 1].x = xStartPos;
  186. lpSKT1Ctxt->ptButtonPos[SKT1_ALT_INDEX + 1].y = yStartPos;
  187. xStartPos += (lpSKT1Ctxt->nButtonWidth[SKT1_ALT_TYPE] + SKT1_XIN) +
  188. (lpSKT1Ctxt->nButtonWidth[SKT1_ESC_TYPE] + SKT1_XIN);
  189. // ctrl 2
  190. lpSKT1Ctxt->ptButtonPos[SKT1_CTRL_INDEX + 1].x = xStartPos;
  191. lpSKT1Ctxt->ptButtonPos[SKT1_CTRL_INDEX + 1].y = yStartPos;
  192. return;
  193. }
  194. /**********************************************************************/
  195. /* SKT1DrawConvexRect */
  196. /* draw a convex rectangle */
  197. /* (x,y) x+nWidth+1 */
  198. /* +-----1------+ */
  199. /* |+----2-----|| */
  200. /* || || */
  201. /* || 3| */
  202. /* || || */
  203. /* |V || <---- Rectangle */
  204. /* |<----------+| */
  205. /* y+nHeight+1 +------------+ */
  206. /* 1 - black */
  207. /* 2 - while */
  208. /* 3 - dark gray */
  209. /**********************************************************************/
  210. void SKT1DrawConvexRect(
  211. HDC hDC,
  212. int x,
  213. int y,
  214. int nWidth,
  215. int nHeight)
  216. {
  217. // extend the context rect size
  218. x -= (SKT1_XIN + 1) / 2;
  219. y -= (SKT1_YIN + 1) / 2;
  220. nWidth += (SKT1_XIN + 1);
  221. nHeight += (SKT1_XIN + 1);
  222. // 1
  223. SelectObject(hDC, GetStockObject(BLACK_PEN));
  224. SelectObject(hDC, GetStockObject(LTGRAY_BRUSH));
  225. Rectangle(hDC, x, y, x + nWidth, y + nHeight);
  226. PatBlt(hDC, x, y, 1, 1, PATCOPY);
  227. PatBlt(hDC, x + nWidth, y, -1, 1, PATCOPY);
  228. PatBlt(hDC, x, y + nHeight, 1, -1, PATCOPY);
  229. PatBlt(hDC, x + nWidth, y + nHeight, -1, -1, PATCOPY);
  230. x++;
  231. y++;
  232. nWidth -= 2;
  233. nHeight -= 2;
  234. // 2
  235. PatBlt(hDC, x, y + nHeight, 1, -nHeight, WHITENESS);
  236. PatBlt(hDC, x, y, nWidth , 1, WHITENESS);
  237. // 3
  238. SelectObject(hDC, GetStockObject(GRAY_BRUSH));
  239. PatBlt(hDC, x, y + nHeight, nWidth, -1, PATCOPY);
  240. PatBlt(hDC, x + nWidth, y + nHeight, -1, -nHeight, PATCOPY);
  241. return;
  242. }
  243. /**********************************************************************/
  244. /* SKT1DrawBitmap */
  245. /**********************************************************************/
  246. void SKT1DrawBitmap(
  247. HDC hDC,
  248. int x,
  249. int y,
  250. int nWidth,
  251. int nHeight,
  252. LPCWSTR lpszBitmap)
  253. {
  254. HDC hMemDC;
  255. HBITMAP hBitmap, hOldBmp;
  256. hBitmap = (HBITMAP)LoadBitmap(ghInst, lpszBitmap);
  257. hMemDC = CreateCompatibleDC(hDC);
  258. hOldBmp = (HBITMAP)SelectObject(hMemDC, hBitmap);
  259. BitBlt(hDC, x, y, nWidth, nHeight, hMemDC, 0 , 0, SRCCOPY);
  260. SelectObject(hMemDC, hOldBmp);
  261. DeleteObject(hBitmap);
  262. DeleteDC(hMemDC);
  263. return;
  264. }
  265. /**********************************************************************/
  266. /* SKT1DrawLabel */
  267. /**********************************************************************/
  268. void SKT1DrawLabel(
  269. HDC hDC,
  270. LPSKT1CTXT lpSKT1Ctxt,
  271. LPCWSTR lpszLabel)
  272. {
  273. HDC hMemDC;
  274. HBITMAP hBitmap, hOldBmp;
  275. int i;
  276. hBitmap = LoadBitmap(ghInst, lpszLabel);
  277. hMemDC = CreateCompatibleDC(hDC);
  278. hOldBmp = (HBITMAP)SelectObject(hMemDC, hBitmap);
  279. for (i = 0; i < SKT1_LETTER_KEY_NUM; i++) {
  280. BitBlt(hDC,
  281. lpSKT1Ctxt->ptButtonPos[i].x, lpSKT1Ctxt->ptButtonPos[i].y,
  282. SKT1_LABEL_BMP_X, SKT1_LABEL_BMP_Y,
  283. hMemDC, i * SKT1_LABEL_BMP_X, 0, SRCCOPY);
  284. }
  285. SelectObject(hMemDC, hOldBmp);
  286. DeleteDC(hMemDC);
  287. DeleteObject(hBitmap);
  288. return;
  289. }
  290. /**********************************************************************/
  291. /* InitSKT1Bitmap */
  292. /**********************************************************************/
  293. void InitSKT1Bitmap(
  294. HWND hSKWnd,
  295. LPSKT1CTXT lpSKT1Ctxt)
  296. {
  297. HDC hDC, hMemDC;
  298. RECT rcClient;
  299. int i;
  300. hDC = GetDC(hSKWnd);
  301. hMemDC = CreateCompatibleDC(hDC);
  302. GetClientRect(hSKWnd, &rcClient);
  303. lpSKT1Ctxt->hSKBitmap = CreateCompatibleBitmap(hDC,
  304. rcClient.right - rcClient.left,
  305. rcClient.bottom - rcClient.top);
  306. ReleaseDC(hSKWnd, hDC);
  307. SelectObject(hMemDC, lpSKT1Ctxt->hSKBitmap);
  308. // draw SK rectangle
  309. SelectObject(hMemDC, GetStockObject(NULL_PEN));
  310. SelectObject(hMemDC, GetStockObject(LTGRAY_BRUSH));
  311. Rectangle(hMemDC, rcClient.left, rcClient.top,
  312. rcClient.right + 1, rcClient.bottom + 1);
  313. DrawEdge(hMemDC, &rcClient, BDR_RAISED, BF_RECT);
  314. // draw the button from the last line
  315. // ctrl 1 -> line 5 special key
  316. SKT1DrawConvexRect(hMemDC,
  317. lpSKT1Ctxt->ptButtonPos[SKT1_CTRL_INDEX].x,
  318. lpSKT1Ctxt->ptButtonPos[SKT1_CTRL_INDEX].y,
  319. lpSKT1Ctxt->nButtonWidth[SKT1_CTRL_TYPE],
  320. lpSKT1Ctxt->nButtonHeight[0]);
  321. SKT1DrawBitmap(hMemDC,
  322. lpSKT1Ctxt->ptButtonPos[SKT1_CTRL_INDEX].x +
  323. lpSKT1Ctxt->nButtonWidth[SKT1_CTRL_TYPE] / 2 - SKT1_CTRL_BMP_X / 2,
  324. lpSKT1Ctxt->ptButtonPos[SKT1_CTRL_INDEX].y +
  325. lpSKT1Ctxt->nButtonHeight[0] / 2 - SKT1_CTRL_BMP_Y / 2,
  326. SKT1_CTRL_BMP_X,
  327. SKT1_CTRL_BMP_Y,
  328. MAKEINTRESOURCEW(CTRL_T1));
  329. // ctrl 2
  330. SKT1DrawConvexRect(hMemDC,
  331. lpSKT1Ctxt->ptButtonPos[SKT1_CTRL_INDEX + 1].x,
  332. lpSKT1Ctxt->ptButtonPos[SKT1_CTRL_INDEX + 1].y,
  333. lpSKT1Ctxt->nButtonWidth[SKT1_CTRL_TYPE],
  334. lpSKT1Ctxt->nButtonHeight[0]);
  335. SKT1DrawBitmap(hMemDC,
  336. lpSKT1Ctxt->ptButtonPos[SKT1_CTRL_INDEX + 1].x +
  337. lpSKT1Ctxt->nButtonWidth[SKT1_CTRL_TYPE] / 2 - SKT1_CTRL_BMP_X / 2,
  338. lpSKT1Ctxt->ptButtonPos[SKT1_CTRL_INDEX + 1].y +
  339. lpSKT1Ctxt->nButtonHeight[0] / 2 - SKT1_CTRL_BMP_Y / 2,
  340. SKT1_CTRL_BMP_X, SKT1_CTRL_BMP_Y,
  341. MAKEINTRESOURCEW(CTRL_T1));
  342. // esc
  343. SKT1DrawConvexRect(hMemDC,
  344. lpSKT1Ctxt->ptButtonPos[SKT1_ESC_INDEX].x,
  345. lpSKT1Ctxt->ptButtonPos[SKT1_ESC_INDEX].y,
  346. lpSKT1Ctxt->nButtonWidth[SKT1_ESC_TYPE],
  347. lpSKT1Ctxt->nButtonHeight[0]);
  348. SKT1DrawBitmap(hMemDC,
  349. lpSKT1Ctxt->ptButtonPos[SKT1_ESC_INDEX].x +
  350. lpSKT1Ctxt->nButtonWidth[SKT1_ESC_TYPE] / 2 - SKT1_ESC_BMP_X / 2,
  351. lpSKT1Ctxt->ptButtonPos[SKT1_ESC_INDEX].y +
  352. lpSKT1Ctxt->nButtonHeight[0] / 2 - SKT1_ESC_BMP_Y / 2,
  353. SKT1_ESC_BMP_X, SKT1_ESC_BMP_Y,
  354. MAKEINTRESOURCEW(ESC_T1));
  355. // alt 1
  356. SKT1DrawConvexRect(hMemDC,
  357. lpSKT1Ctxt->ptButtonPos[SKT1_ALT_INDEX].x,
  358. lpSKT1Ctxt->ptButtonPos[SKT1_ALT_INDEX].y,
  359. lpSKT1Ctxt->nButtonWidth[SKT1_ALT_TYPE],
  360. lpSKT1Ctxt->nButtonHeight[0]);
  361. SKT1DrawBitmap(hMemDC,
  362. lpSKT1Ctxt->ptButtonPos[SKT1_ALT_INDEX].x +
  363. lpSKT1Ctxt->nButtonWidth[SKT1_ALT_TYPE] / 2 - SKT1_ALT_BMP_X / 2,
  364. lpSKT1Ctxt->ptButtonPos[SKT1_ALT_INDEX].y +
  365. lpSKT1Ctxt->nButtonHeight[0] / 2 - SKT1_ALT_BMP_Y / 2,
  366. SKT1_ALT_BMP_X, SKT1_ALT_BMP_Y,
  367. MAKEINTRESOURCEW(ALT_T1));
  368. // alt 2
  369. SKT1DrawConvexRect(hMemDC,
  370. lpSKT1Ctxt->ptButtonPos[SKT1_ALT_INDEX + 1].x,
  371. lpSKT1Ctxt->ptButtonPos[SKT1_ALT_INDEX + 1].y,
  372. lpSKT1Ctxt->nButtonWidth[SKT1_ALT_TYPE],
  373. lpSKT1Ctxt->nButtonHeight[0]);
  374. SKT1DrawBitmap(hMemDC,
  375. lpSKT1Ctxt->ptButtonPos[SKT1_ALT_INDEX + 1].x +
  376. lpSKT1Ctxt->nButtonWidth[SKT1_ALT_TYPE] / 2 - SKT1_ALT_BMP_X / 2,
  377. lpSKT1Ctxt->ptButtonPos[SKT1_ALT_INDEX + 1].y +
  378. lpSKT1Ctxt->nButtonHeight[0] / 2 - SKT1_ALT_BMP_Y / 2,
  379. SKT1_ALT_BMP_X, SKT1_ALT_BMP_Y,
  380. MAKEINTRESOURCEW(ALT_T1));
  381. // space
  382. SKT1DrawConvexRect(hMemDC,
  383. lpSKT1Ctxt->ptButtonPos[SKT1_SPACE_INDEX].x,
  384. lpSKT1Ctxt->ptButtonPos[SKT1_SPACE_INDEX].y,
  385. lpSKT1Ctxt->nButtonWidth[SKT1_SPACE_TYPE],
  386. lpSKT1Ctxt->nButtonHeight[0]);
  387. // line 4
  388. // shift 1
  389. SKT1DrawConvexRect(hMemDC,
  390. lpSKT1Ctxt->ptButtonPos[SKT1_SHIFT_INDEX].x,
  391. lpSKT1Ctxt->ptButtonPos[SKT1_SHIFT_INDEX].y,
  392. lpSKT1Ctxt->nButtonWidth[SKT1_SHIFT_TYPE],
  393. lpSKT1Ctxt->nButtonHeight[0]);
  394. SKT1DrawBitmap(hMemDC,
  395. lpSKT1Ctxt->ptButtonPos[SKT1_SHIFT_INDEX].x +
  396. lpSKT1Ctxt->nButtonWidth[SKT1_SHIFT_TYPE] / 2 - SKT1_SHIFT_BMP_X / 2,
  397. lpSKT1Ctxt->ptButtonPos[SKT1_SHIFT_INDEX].y +
  398. lpSKT1Ctxt->nButtonHeight[0] / 2 - SKT1_SHIFT_BMP_Y / 2,
  399. SKT1_SHIFT_BMP_X, SKT1_SHIFT_BMP_Y,
  400. MAKEINTRESOURCEW(SHIFT_T1));
  401. // shift 2
  402. SKT1DrawConvexRect(hMemDC,
  403. lpSKT1Ctxt->ptButtonPos[SKT1_SHIFT_INDEX + 1].x,
  404. lpSKT1Ctxt->ptButtonPos[SKT1_SHIFT_INDEX + 1].y,
  405. lpSKT1Ctxt->nButtonWidth[SKT1_SHIFT_TYPE],
  406. lpSKT1Ctxt->nButtonHeight[0]);
  407. SKT1DrawBitmap(hMemDC,
  408. lpSKT1Ctxt->ptButtonPos[SKT1_SHIFT_INDEX + 1].x +
  409. lpSKT1Ctxt->nButtonWidth[SKT1_SHIFT_TYPE] / 2 - SKT1_SHIFT_BMP_X / 2,
  410. lpSKT1Ctxt->ptButtonPos[SKT1_SHIFT_INDEX + 1].y +
  411. lpSKT1Ctxt->nButtonHeight[0] / 2 - SKT1_SHIFT_BMP_Y / 2,
  412. SKT1_SHIFT_BMP_X, SKT1_SHIFT_BMP_Y,
  413. MAKEINTRESOURCEW(SHIFT_T1));
  414. // line 3
  415. // caps
  416. SKT1DrawConvexRect(hMemDC,
  417. lpSKT1Ctxt->ptButtonPos[SKT1_CAPS_INDEX].x,
  418. lpSKT1Ctxt->ptButtonPos[SKT1_CAPS_INDEX].y,
  419. lpSKT1Ctxt->nButtonWidth[SKT1_CAPS_TYPE],
  420. lpSKT1Ctxt->nButtonHeight[0]);
  421. SKT1DrawBitmap(hMemDC,
  422. lpSKT1Ctxt->ptButtonPos[SKT1_CAPS_INDEX].x +
  423. lpSKT1Ctxt->nButtonWidth[SKT1_CAPS_TYPE] / 2 - SKT1_CAPS_BMP_X / 2,
  424. lpSKT1Ctxt->ptButtonPos[SKT1_CAPS_INDEX].y +
  425. lpSKT1Ctxt->nButtonHeight[0] / 2 - SKT1_CAPS_BMP_Y / 2,
  426. SKT1_CAPS_BMP_X, SKT1_CAPS_BMP_Y,
  427. MAKEINTRESOURCEW(CAPS_T1));
  428. // line 2
  429. // tab
  430. SKT1DrawConvexRect(hMemDC,
  431. lpSKT1Ctxt->ptButtonPos[SKT1_TAB_INDEX].x,
  432. lpSKT1Ctxt->ptButtonPos[SKT1_TAB_INDEX].y,
  433. lpSKT1Ctxt->nButtonWidth[SKT1_TAB_TYPE],
  434. lpSKT1Ctxt->nButtonHeight[0]);
  435. SKT1DrawBitmap(hMemDC,
  436. lpSKT1Ctxt->ptButtonPos[SKT1_TAB_INDEX].x +
  437. lpSKT1Ctxt->nButtonWidth[SKT1_TAB_TYPE] / 2 - SKT1_TAB_BMP_X / 2,
  438. lpSKT1Ctxt->ptButtonPos[SKT1_TAB_INDEX].y +
  439. lpSKT1Ctxt->nButtonHeight[0] / 2 - SKT1_TAB_BMP_Y / 2,
  440. SKT1_TAB_BMP_X, SKT1_TAB_BMP_Y,
  441. MAKEINTRESOURCEW(TAB_T1));
  442. // enter
  443. SKT1DrawConvexRect(hMemDC,
  444. lpSKT1Ctxt->ptButtonPos[SKT1_ENTER_INDEX].x,
  445. lpSKT1Ctxt->ptButtonPos[SKT1_ENTER_INDEX].y,
  446. lpSKT1Ctxt->nButtonWidth[SKT1_ENTER_TYPE],
  447. lpSKT1Ctxt->nButtonHeight[1]);
  448. SKT1DrawBitmap(hMemDC,
  449. lpSKT1Ctxt->ptButtonPos[SKT1_ENTER_INDEX].x +
  450. lpSKT1Ctxt->nButtonWidth[SKT1_ENTER_TYPE] / 2 - SKT1_ENTER_BMP_X / 2,
  451. lpSKT1Ctxt->ptButtonPos[SKT1_ENTER_INDEX].y +
  452. lpSKT1Ctxt->nButtonHeight[1] / 2 - SKT1_ENTER_BMP_Y / 2,
  453. SKT1_ENTER_BMP_X, SKT1_ENTER_BMP_Y,
  454. MAKEINTRESOURCEW(ENTER_T1));
  455. // line 1
  456. // backspace
  457. SKT1DrawConvexRect(hMemDC,
  458. lpSKT1Ctxt->ptButtonPos[SKT1_BACKSPACE_INDEX].x,
  459. lpSKT1Ctxt->ptButtonPos[SKT1_BACKSPACE_INDEX].y,
  460. lpSKT1Ctxt->nButtonWidth[SKT1_BACKSPACE_TYPE],
  461. lpSKT1Ctxt->nButtonHeight[0]);
  462. SKT1DrawBitmap(hMemDC,
  463. lpSKT1Ctxt->ptButtonPos[SKT1_BACKSPACE_INDEX].x +
  464. lpSKT1Ctxt->nButtonWidth[SKT1_BACKSPACE_TYPE] / 2 - SKT1_BACKSPACE_BMP_X / 2,
  465. lpSKT1Ctxt->ptButtonPos[SKT1_BACKSPACE_INDEX].y +
  466. lpSKT1Ctxt->nButtonHeight[0] / 2 - SKT1_BACKSPACE_BMP_Y / 2,
  467. SKT1_BACKSPACE_BMP_X, SKT1_BACKSPACE_BMP_Y,
  468. MAKEINTRESOURCEW(BACK_T1));
  469. // draw letter buttons
  470. for (i = SKT1_LETTER_KEY_NUM - 1; i >= 0 ; i--) {
  471. SKT1DrawConvexRect(hMemDC,
  472. lpSKT1Ctxt->ptButtonPos[i].x,
  473. lpSKT1Ctxt->ptButtonPos[i].y,
  474. lpSKT1Ctxt->nButtonWidth[SKT1_LETTER_TYPE],
  475. lpSKT1Ctxt->nButtonHeight[0]);
  476. }
  477. // draw latter label
  478. SKT1DrawLabel(hMemDC, lpSKT1Ctxt, MAKEINTRESOURCEW(LABEL_T1));
  479. DeleteDC(hMemDC);
  480. return;
  481. }
  482. /**********************************************************************/
  483. /* CreateT1Window */
  484. /**********************************************************************/
  485. LRESULT CreateT1Window(
  486. HWND hSKWnd)
  487. {
  488. HGLOBAL hSKT1Ctxt;
  489. LPSKT1CTXT lpSKT1Ctxt;
  490. hSKT1Ctxt = GlobalAlloc(GHND, sizeof(SKT1CTXT));
  491. if (!hSKT1Ctxt) {
  492. return (-1);
  493. }
  494. lpSKT1Ctxt = (LPSKT1CTXT)GlobalLock(hSKT1Ctxt);
  495. if (!lpSKT1Ctxt) {
  496. GlobalFree(hSKT1Ctxt);
  497. return (-1);
  498. }
  499. SetWindowLongPtr(hSKWnd, SKT1_CONTEXT, (LONG_PTR)hSKT1Ctxt);
  500. lpSKT1Ctxt->uKeyIndex = SKT1_TOTAL_INDEX;
  501. lpSKT1Ctxt->ptSkOffset.x = SKT1_NOT_DRAG;
  502. lpSKT1Ctxt->ptSkOffset.y = SKT1_NOT_DRAG;
  503. lpSKT1Ctxt->lfCharSet = CHINESEBIG5_CHARSET;
  504. InitSKT1ButtonPos(lpSKT1Ctxt);
  505. InitSKT1Bitmap(hSKWnd, lpSKT1Ctxt);
  506. GlobalUnlock(hSKT1Ctxt);
  507. return (0L);
  508. }
  509. /**********************************************************************/
  510. /* SKT1DrawDragBorder() */
  511. /**********************************************************************/
  512. void SKT1DrawDragBorder(
  513. HWND hWnd, // window of IME is dragged
  514. LPPOINT lpptCursor, // the cursor position
  515. LPPOINT lpptOffset) // the offset form cursor to window org
  516. {
  517. HDC hDC;
  518. int cxBorder, cyBorder;
  519. int x, y;
  520. RECT rcWnd;
  521. cxBorder = GetSystemMetrics(SM_CXBORDER); // width of border
  522. cyBorder = GetSystemMetrics(SM_CYBORDER); // height of border
  523. x = lpptCursor->x - lpptOffset->x;
  524. y = lpptCursor->y - lpptOffset->y;
  525. // check for the max boundary of the display
  526. GetWindowRect(hWnd, &rcWnd);
  527. // draw the moving track
  528. hDC = CreateDC(L"DISPLAY", NULL, NULL, NULL);
  529. SelectObject(hDC, GetStockObject(GRAY_BRUSH));
  530. // ->
  531. PatBlt(hDC, x, y, rcWnd.right - rcWnd.left - cxBorder, cyBorder,
  532. PATINVERT);
  533. // v
  534. PatBlt(hDC, x, y + cyBorder, cxBorder, rcWnd.bottom - rcWnd.top -
  535. cyBorder, PATINVERT);
  536. // _>
  537. PatBlt(hDC, x + cxBorder, y + rcWnd.bottom - rcWnd.top,
  538. rcWnd.right - rcWnd.left - cxBorder, -cyBorder, PATINVERT);
  539. // v
  540. PatBlt(hDC, x + rcWnd.right - rcWnd.left, y,
  541. - cxBorder, rcWnd.bottom - rcWnd.top - cyBorder, PATINVERT);
  542. DeleteDC(hDC);
  543. return;
  544. }
  545. /**********************************************************************/
  546. /* DestroyT1Window */
  547. /**********************************************************************/
  548. void DestroyT1Window(
  549. HWND hSKWnd)
  550. {
  551. HGLOBAL hSKT1Ctxt;
  552. LPSKT1CTXT lpSKT1Ctxt;
  553. HWND hUIWnd;
  554. hSKT1Ctxt = (HGLOBAL)GetWindowLongPtr(hSKWnd, SKT1_CONTEXT);
  555. if (!hSKT1Ctxt) {
  556. return;
  557. }
  558. lpSKT1Ctxt = (LPSKT1CTXT)GlobalLock(hSKT1Ctxt);
  559. if (!lpSKT1Ctxt) {
  560. return;
  561. }
  562. if (lpSKT1Ctxt->ptSkOffset.x != SKT1_NOT_DRAG &&
  563. lpSKT1Ctxt->ptSkOffset.y != SKT1_NOT_DRAG) {
  564. SKT1DrawDragBorder(hSKWnd, &lpSKT1Ctxt->ptSkCursor,
  565. &lpSKT1Ctxt->ptSkOffset);
  566. }
  567. DeleteObject(lpSKT1Ctxt->hSKBitmap);
  568. GlobalUnlock(hSKT1Ctxt);
  569. GlobalFree(hSKT1Ctxt);
  570. hUIWnd = GetWindow(hSKWnd, GW_OWNER);
  571. if (!hUIWnd) {
  572. return;
  573. }
  574. SendMessage(hUIWnd, WM_IME_NOTIFY, IMN_SOFTKBDDESTROYED, 0);
  575. return;
  576. }
  577. /**********************************************************************/
  578. /* SKT1InvertButton */
  579. /**********************************************************************/
  580. void SKT1InvertButton(
  581. HWND hSKWnd,
  582. HDC hPaintDC,
  583. LPSKT1CTXT lpSKT1Ctxt,
  584. UINT uKeyIndex)
  585. {
  586. HDC hDC;
  587. int nWidth, nHeight;
  588. if (uKeyIndex >= SKT1_TOTAL_INDEX) {
  589. return;
  590. }
  591. nWidth = 0;
  592. if (hPaintDC) {
  593. hDC = hPaintDC;
  594. } else {
  595. hDC = GetDC(hSKWnd);
  596. }
  597. if (uKeyIndex < SKT1_LETTER_KEY_NUM) {
  598. nWidth = lpSKT1Ctxt->nButtonWidth[SKT1_LETTER_TYPE];
  599. } else {
  600. switch (uKeyIndex) {
  601. case SKT1_BACKSPACE_INDEX:
  602. nWidth = lpSKT1Ctxt->nButtonWidth[SKT1_BACKSPACE_TYPE];
  603. break;
  604. case SKT1_TAB_INDEX:
  605. nWidth = lpSKT1Ctxt->nButtonWidth[SKT1_TAB_TYPE];
  606. break;
  607. case SKT1_CAPS_INDEX:
  608. nWidth = 0;
  609. MessageBeep((UINT) -1);
  610. break;
  611. case SKT1_ENTER_INDEX:
  612. nWidth = lpSKT1Ctxt->nButtonWidth[SKT1_ENTER_TYPE];
  613. break;
  614. case SKT1_SHIFT_INDEX:
  615. case SKT1_SHIFT_INDEX + 1:
  616. case SKT1_CTRL_INDEX:
  617. case SKT1_CTRL_INDEX + 1:
  618. case SKT1_ALT_INDEX:
  619. case SKT1_ALT_INDEX + 1:
  620. nWidth = 0;
  621. MessageBeep((UINT) -1);
  622. break;
  623. case SKT1_ESC_INDEX:
  624. nWidth = lpSKT1Ctxt->nButtonWidth[SKT1_ESC_TYPE];
  625. break;
  626. case SKT1_SPACE_INDEX:
  627. nWidth = lpSKT1Ctxt->nButtonWidth[SKT1_SPACE_TYPE];
  628. break;
  629. default:
  630. break;
  631. }
  632. }
  633. if (uKeyIndex == SKT1_ENTER_INDEX) {
  634. nHeight = lpSKT1Ctxt->nButtonHeight[1];
  635. } else {
  636. nHeight = lpSKT1Ctxt->nButtonHeight[0];
  637. }
  638. if (nWidth) {
  639. // do not reverse border
  640. PatBlt(hDC, lpSKT1Ctxt->ptButtonPos[uKeyIndex].x - 1,
  641. lpSKT1Ctxt->ptButtonPos[uKeyIndex].y - 1,
  642. nWidth + 2, nHeight + 2, DSTINVERT);
  643. }
  644. if (!hPaintDC) {
  645. ReleaseDC(hSKWnd, hDC);
  646. }
  647. return;
  648. }
  649. /**********************************************************************/
  650. /* UpdateSKT1Window */
  651. /**********************************************************************/
  652. void UpdateSKT1Window(
  653. HDC hDC,
  654. HWND hSKWnd)
  655. {
  656. HGLOBAL hSKT1Ctxt;
  657. LPSKT1CTXT lpSKT1Ctxt;
  658. HDC hMemDC;
  659. RECT rcClient;
  660. hSKT1Ctxt = (HGLOBAL)GetWindowLongPtr(hSKWnd, SKT1_CONTEXT);
  661. if (!hSKT1Ctxt) {
  662. return;
  663. }
  664. lpSKT1Ctxt = (LPSKT1CTXT)GlobalLock(hSKT1Ctxt);
  665. if (!lpSKT1Ctxt) {
  666. return;
  667. }
  668. hMemDC = CreateCompatibleDC(hDC);
  669. SelectObject(hMemDC, lpSKT1Ctxt->hSKBitmap);
  670. GetClientRect(hSKWnd, &rcClient);
  671. BitBlt(hDC, 0, 0, rcClient.right - rcClient.left,
  672. rcClient.bottom - rcClient.top,
  673. hMemDC, 0, 0, SRCCOPY);
  674. DeleteDC(hMemDC);
  675. if (lpSKT1Ctxt->uKeyIndex < SKT1_TOTAL_INDEX) {
  676. SKT1InvertButton(hSKWnd, hDC, lpSKT1Ctxt, lpSKT1Ctxt->uKeyIndex);
  677. }
  678. GlobalUnlock(hSKT1Ctxt);
  679. return;
  680. }
  681. /**********************************************************************/
  682. /* SKT1MousePosition() */
  683. /**********************************************************************/
  684. UINT SKT1MousePosition(
  685. LPSKT1CTXT lpSKT1Ctxt,
  686. LPPOINT lpptCursor)
  687. {
  688. int i;
  689. // check letter button
  690. for (i = 0; i < SKT1_LETTER_KEY_NUM; i++) {
  691. if (ImmPtInRect(lpSKT1Ctxt->ptButtonPos[i].x,
  692. lpSKT1Ctxt->ptButtonPos[i].y,
  693. lpSKT1Ctxt->nButtonWidth[SKT1_LETTER_TYPE],
  694. lpSKT1Ctxt->nButtonHeight[0],
  695. lpptCursor)) {
  696. return i;
  697. }
  698. }
  699. // backSapce
  700. if (ImmPtInRect(lpSKT1Ctxt->ptButtonPos[SKT1_BACKSPACE_INDEX].x,
  701. lpSKT1Ctxt->ptButtonPos[SKT1_BACKSPACE_INDEX].y,
  702. lpSKT1Ctxt->nButtonWidth[SKT1_BACKSPACE_TYPE],
  703. lpSKT1Ctxt->nButtonHeight[0],
  704. lpptCursor)) {
  705. return SKT1_BACKSPACE_INDEX;
  706. }
  707. // tab
  708. if (ImmPtInRect(lpSKT1Ctxt->ptButtonPos[SKT1_TAB_INDEX].x,
  709. lpSKT1Ctxt->ptButtonPos[SKT1_TAB_INDEX].y,
  710. lpSKT1Ctxt->nButtonWidth[SKT1_TAB_TYPE],
  711. lpSKT1Ctxt->nButtonHeight[0],
  712. lpptCursor)) {
  713. return SKT1_TAB_INDEX;
  714. }
  715. // caps
  716. if (ImmPtInRect(lpSKT1Ctxt->ptButtonPos[SKT1_CAPS_INDEX].x,
  717. lpSKT1Ctxt->ptButtonPos[SKT1_CAPS_INDEX].y,
  718. lpSKT1Ctxt->nButtonWidth[SKT1_CAPS_TYPE],
  719. lpSKT1Ctxt->nButtonHeight[0],
  720. lpptCursor)) {
  721. return SKT1_CAPS_INDEX;
  722. }
  723. // enter
  724. if (ImmPtInRect(lpSKT1Ctxt->ptButtonPos[SKT1_ENTER_INDEX].x,
  725. lpSKT1Ctxt->ptButtonPos[SKT1_ENTER_INDEX].y,
  726. lpSKT1Ctxt->nButtonWidth[SKT1_ENTER_TYPE],
  727. lpSKT1Ctxt->nButtonHeight[1],
  728. lpptCursor)) {
  729. return SKT1_ENTER_INDEX;
  730. }
  731. // shift 1
  732. if (ImmPtInRect(lpSKT1Ctxt->ptButtonPos[SKT1_SHIFT_INDEX].x,
  733. lpSKT1Ctxt->ptButtonPos[SKT1_SHIFT_INDEX].y,
  734. lpSKT1Ctxt->nButtonWidth[SKT1_SHIFT_TYPE],
  735. lpSKT1Ctxt->nButtonHeight[0],
  736. lpptCursor)) {
  737. return SKT1_SHIFT_INDEX;
  738. }
  739. // shift 2
  740. if (ImmPtInRect(lpSKT1Ctxt->ptButtonPos[SKT1_SHIFT_INDEX + 1].x,
  741. lpSKT1Ctxt->ptButtonPos[SKT1_SHIFT_INDEX + 1].y,
  742. lpSKT1Ctxt->nButtonWidth[SKT1_SHIFT_TYPE],
  743. lpSKT1Ctxt->nButtonHeight[0],
  744. lpptCursor)) {
  745. return SKT1_SHIFT_INDEX;
  746. }
  747. // ctrl 1
  748. if (ImmPtInRect(lpSKT1Ctxt->ptButtonPos[SKT1_CTRL_INDEX].x,
  749. lpSKT1Ctxt->ptButtonPos[SKT1_CTRL_INDEX].y,
  750. lpSKT1Ctxt->nButtonWidth[SKT1_CTRL_TYPE],
  751. lpSKT1Ctxt->nButtonHeight[0],
  752. lpptCursor)) {
  753. return SKT1_CTRL_INDEX;
  754. }
  755. // ctrl 2
  756. if (ImmPtInRect(lpSKT1Ctxt->ptButtonPos[SKT1_CTRL_INDEX + 1].x,
  757. lpSKT1Ctxt->ptButtonPos[SKT1_CTRL_INDEX + 1].y,
  758. lpSKT1Ctxt->nButtonWidth[SKT1_CTRL_TYPE],
  759. lpSKT1Ctxt->nButtonHeight[0],
  760. lpptCursor)) {
  761. return SKT1_CTRL_INDEX;
  762. }
  763. // alt 1
  764. if (ImmPtInRect(lpSKT1Ctxt->ptButtonPos[SKT1_ALT_INDEX].x,
  765. lpSKT1Ctxt->ptButtonPos[SKT1_ALT_INDEX].y,
  766. lpSKT1Ctxt->nButtonWidth[SKT1_ALT_TYPE],
  767. lpSKT1Ctxt->nButtonHeight[0],
  768. lpptCursor)) {
  769. return SKT1_ALT_INDEX;
  770. }
  771. // alt 2
  772. if (ImmPtInRect(lpSKT1Ctxt->ptButtonPos[SKT1_ALT_INDEX + 1].x,
  773. lpSKT1Ctxt->ptButtonPos[SKT1_ALT_INDEX + 1].y,
  774. lpSKT1Ctxt->nButtonWidth[SKT1_ALT_TYPE],
  775. lpSKT1Ctxt->nButtonHeight[0],
  776. lpptCursor)) {
  777. return SKT1_ALT_INDEX;
  778. }
  779. // esc
  780. if (ImmPtInRect(lpSKT1Ctxt->ptButtonPos[SKT1_ESC_INDEX].x,
  781. lpSKT1Ctxt->ptButtonPos[SKT1_ESC_INDEX].y,
  782. lpSKT1Ctxt->nButtonWidth[SKT1_ESC_TYPE],
  783. lpSKT1Ctxt->nButtonHeight[0],
  784. lpptCursor)) {
  785. return SKT1_ESC_INDEX;
  786. }
  787. // space
  788. if (ImmPtInRect(lpSKT1Ctxt->ptButtonPos[SKT1_SPACE_INDEX].x,
  789. lpSKT1Ctxt->ptButtonPos[SKT1_SPACE_INDEX].y,
  790. lpSKT1Ctxt->nButtonWidth[SKT1_SPACE_TYPE],
  791. lpSKT1Ctxt->nButtonHeight[0],
  792. lpptCursor)) {
  793. return SKT1_SPACE_INDEX;
  794. }
  795. return SKT1_TOTAL_INDEX; // This means out of range
  796. }
  797. /**********************************************************************/
  798. /* SKT1IsValidButton */
  799. /**********************************************************************/
  800. BOOL SKT1IsValidButton(
  801. UINT uKeyIndex,
  802. LPSKT1CTXT lpSKT1Ctxt)
  803. {
  804. BOOL fRet;
  805. if (uKeyIndex < SKT1_LETTER_KEY_NUM) {
  806. if (lpSKT1Ctxt->wCodeTable[uKeyIndex]) {
  807. return TRUE;
  808. } else {
  809. return FALSE;
  810. }
  811. }
  812. // special key
  813. switch (uKeyIndex) {
  814. case SKT1_BACKSPACE_INDEX:
  815. case SKT1_TAB_INDEX:
  816. case SKT1_ENTER_INDEX:
  817. case SKT1_ESC_INDEX:
  818. case SKT1_SPACE_INDEX:
  819. fRet = TRUE;
  820. break;
  821. default:
  822. fRet = FALSE;
  823. break;
  824. }
  825. return fRet;
  826. }
  827. /**********************************************************************/
  828. /* SKT1SetCursor */
  829. /**********************************************************************/
  830. BOOL SKT1SetCursor(
  831. HWND hSKWnd,
  832. LPARAM lParam)
  833. {
  834. HGLOBAL hSKT1Ctxt;
  835. LPSKT1CTXT lpSKT1Ctxt;
  836. UINT uKeyIndex;
  837. RECT rcWnd;
  838. RECT rcWork;
  839. SIZE szWork;
  840. extern void GetAllMonitorSize(LPRECT lprc);
  841. hSKT1Ctxt = (HGLOBAL)GetWindowLongPtr(hSKWnd, SKT1_CONTEXT);
  842. if (!hSKT1Ctxt) {
  843. return (FALSE);
  844. }
  845. lpSKT1Ctxt = (LPSKT1CTXT)GlobalLock(hSKT1Ctxt);
  846. if (!lpSKT1Ctxt) {
  847. return (FALSE);
  848. }
  849. if (lpSKT1Ctxt->ptSkOffset.x != SKT1_NOT_DRAG &&
  850. lpSKT1Ctxt->ptSkOffset.y != SKT1_NOT_DRAG) {
  851. // in drag operation
  852. SetCursor(LoadCursor(NULL, IDC_SIZEALL));
  853. goto UnlockSKT1Ctxt;
  854. }
  855. GetCursorPos(&lpSKT1Ctxt->ptSkCursor);
  856. ScreenToClient(hSKWnd, &lpSKT1Ctxt->ptSkCursor);
  857. uKeyIndex = SKT1MousePosition(lpSKT1Ctxt, &lpSKT1Ctxt->ptSkCursor);
  858. if (uKeyIndex < SKT1_TOTAL_INDEX) {
  859. SetCursor(LoadCursor(NULL, IDC_HAND));
  860. } else {
  861. SetCursor(LoadCursor(NULL, IDC_SIZEALL));
  862. }
  863. if (HIWORD(lParam) != WM_LBUTTONDOWN) {
  864. goto UnlockSKT1Ctxt;
  865. }
  866. SetCapture(hSKWnd);
  867. if (lpSKT1Ctxt->uKeyIndex < SKT1_TOTAL_INDEX) {
  868. UINT uVirtKey;
  869. uVirtKey = bSKT1VirtKey[lpSKT1Ctxt->uKeyIndex];
  870. keybd_event((BYTE)uVirtKey, (BYTE)guScanCode[uVirtKey],
  871. (DWORD)KEYEVENTF_KEYUP, 0);
  872. SKT1InvertButton(hSKWnd, NULL, lpSKT1Ctxt, lpSKT1Ctxt->uKeyIndex);
  873. lpSKT1Ctxt->uKeyIndex = SKT1_TOTAL_INDEX;
  874. }
  875. if (uKeyIndex < SKT1_TOTAL_INDEX) {
  876. UINT uVirtKey;
  877. if (SKT1IsValidButton(uKeyIndex, lpSKT1Ctxt)) {
  878. uVirtKey = bSKT1VirtKey[uKeyIndex];
  879. keybd_event((BYTE)uVirtKey, (BYTE)guScanCode[uVirtKey],
  880. 0, 0);
  881. lpSKT1Ctxt->uKeyIndex = uKeyIndex;
  882. SKT1InvertButton(hSKWnd, NULL, lpSKT1Ctxt, lpSKT1Ctxt->uKeyIndex);
  883. } else {
  884. MessageBeep((UINT)-1);
  885. }
  886. goto UnlockSKT1Ctxt;
  887. }
  888. GetAllMonitorSize(&rcWork);
  889. szWork.cx = rcWork.right - rcWork.left;
  890. szWork.cy = rcWork.bottom - rcWork.top;
  891. GetCursorPos(&lpSKT1Ctxt->ptSkCursor);
  892. GetWindowRect(hSKWnd, &rcWnd);
  893. lpSKT1Ctxt->ptSkOffset.x = lpSKT1Ctxt->ptSkCursor.x - rcWnd.left;
  894. lpSKT1Ctxt->ptSkOffset.y = lpSKT1Ctxt->ptSkCursor.y - rcWnd.top;
  895. SKT1DrawDragBorder(hSKWnd, &lpSKT1Ctxt->ptSkCursor,
  896. &lpSKT1Ctxt->ptSkOffset);
  897. UnlockSKT1Ctxt:
  898. GlobalUnlock(hSKT1Ctxt);
  899. return (TRUE);
  900. }
  901. /**********************************************************************/
  902. /* SKT1MouseMove */
  903. /**********************************************************************/
  904. BOOL SKT1MouseMove(
  905. HWND hSKWnd)
  906. {
  907. HGLOBAL hSKT1Ctxt;
  908. LPSKT1CTXT lpSKT1Ctxt;
  909. hSKT1Ctxt = (HGLOBAL)GetWindowLongPtr(hSKWnd, SKT1_CONTEXT);
  910. if (!hSKT1Ctxt) {
  911. return FALSE;
  912. }
  913. lpSKT1Ctxt = (LPSKT1CTXT)GlobalLock(hSKT1Ctxt);
  914. if (!lpSKT1Ctxt) {
  915. return FALSE;
  916. }
  917. if (lpSKT1Ctxt->ptSkOffset.x == SKT1_NOT_DRAG ||
  918. lpSKT1Ctxt->ptSkOffset.y == SKT1_NOT_DRAG) {
  919. GlobalUnlock(hSKT1Ctxt);
  920. return FALSE;
  921. }
  922. SKT1DrawDragBorder(hSKWnd, &lpSKT1Ctxt->ptSkCursor,
  923. &lpSKT1Ctxt->ptSkOffset);
  924. GetCursorPos(&lpSKT1Ctxt->ptSkCursor);
  925. SKT1DrawDragBorder(hSKWnd, &lpSKT1Ctxt->ptSkCursor,
  926. &lpSKT1Ctxt->ptSkOffset);
  927. GlobalUnlock(hSKT1Ctxt);
  928. return TRUE;
  929. }
  930. /**********************************************************************/
  931. /* SKT1ButtonUp */
  932. /**********************************************************************/
  933. BOOL SKT1ButtonUp(
  934. HWND hSKWnd)
  935. {
  936. HGLOBAL hSKT1Ctxt;
  937. LPSKT1CTXT lpSKT1Ctxt;
  938. BOOL fRet;
  939. POINT pt;
  940. HWND hUIWnd;
  941. HIMC hIMC;
  942. LPINPUTCONTEXT lpIMC;
  943. fRet = FALSE;
  944. if (IsWndEqual(GetCapture(), hSKWnd)) {
  945. ReleaseCapture();
  946. }
  947. hSKT1Ctxt = (HGLOBAL)GetWindowLongPtr(hSKWnd, SKT1_CONTEXT);
  948. if (!hSKT1Ctxt) {
  949. return (fRet);
  950. }
  951. lpSKT1Ctxt = (LPSKT1CTXT)GlobalLock(hSKT1Ctxt);
  952. if (!lpSKT1Ctxt) {
  953. return (fRet);
  954. }
  955. if (lpSKT1Ctxt->uKeyIndex < SKT1_TOTAL_INDEX) {
  956. UINT uVirtKey;
  957. uVirtKey = bSKT1VirtKey[lpSKT1Ctxt->uKeyIndex];
  958. keybd_event((BYTE)uVirtKey, (BYTE)guScanCode[uVirtKey],
  959. (DWORD)KEYEVENTF_KEYUP, 0);
  960. SKT1InvertButton(hSKWnd, NULL, lpSKT1Ctxt, lpSKT1Ctxt->uKeyIndex);
  961. lpSKT1Ctxt->uKeyIndex = SKT1_TOTAL_INDEX;
  962. fRet = TRUE;
  963. goto UnlockSKT1Context;
  964. }
  965. if (lpSKT1Ctxt->ptSkOffset.x == SKT1_NOT_DRAG ||
  966. lpSKT1Ctxt->ptSkOffset.y == SKT1_NOT_DRAG) {
  967. goto UnlockSKT1Context;
  968. }
  969. SKT1DrawDragBorder(hSKWnd, &lpSKT1Ctxt->ptSkCursor,
  970. &lpSKT1Ctxt->ptSkOffset);
  971. pt.x = lpSKT1Ctxt->ptSkCursor.x - lpSKT1Ctxt->ptSkOffset.x,
  972. pt.y = lpSKT1Ctxt->ptSkCursor.y - lpSKT1Ctxt->ptSkOffset.y,
  973. SetWindowPos(hSKWnd, (HWND)NULL, pt.x, pt.y,
  974. 0, 0, SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOZORDER);
  975. lpSKT1Ctxt->ptSkOffset.x = SKT1_NOT_DRAG;
  976. lpSKT1Ctxt->ptSkOffset.y = SKT1_NOT_DRAG;
  977. lpSKT1Ctxt->uKeyIndex = SKT1_TOTAL_INDEX;
  978. fRet = TRUE;
  979. hUIWnd = GetWindow(hSKWnd, GW_OWNER);
  980. hIMC = (HIMC)GetWindowLongPtr(hUIWnd, IMMGWLP_IMC);
  981. if (!hIMC) {
  982. goto UnlockSKT1Context;
  983. }
  984. lpIMC = (LPINPUTCONTEXT)ImmLockIMC(hIMC);
  985. if (!lpIMC) {
  986. goto UnlockSKT1Context;
  987. }
  988. lpIMC->ptSoftKbdPos.x = pt.x;
  989. lpIMC->ptSoftKbdPos.y = pt.y;
  990. lpIMC->fdwInit |= INIT_SOFTKBDPOS;
  991. ImmUnlockIMC(hIMC);
  992. UnlockSKT1Context:
  993. GlobalUnlock(hSKT1Ctxt);
  994. return (fRet);
  995. }
  996. /**********************************************************************/
  997. /* SetSKT1Data */
  998. /**********************************************************************/
  999. LRESULT SetSKT1Data(
  1000. HWND hSKWnd,
  1001. LPSOFTKBDDATA lpSoftKbdData)
  1002. {
  1003. HGLOBAL hSKT1Ctxt;
  1004. LPSKT1CTXT lpSKT1Ctxt;
  1005. HDC hDC, hMemDC;
  1006. HGDIOBJ hOldFont;
  1007. int i;
  1008. hSKT1Ctxt = (HGLOBAL)GetWindowLongPtr(hSKWnd, SKT1_CONTEXT);
  1009. if (!hSKT1Ctxt) {
  1010. return (1);
  1011. }
  1012. lpSKT1Ctxt = (LPSKT1CTXT)GlobalLock(hSKT1Ctxt);
  1013. if (!lpSKT1Ctxt) {
  1014. return (1);
  1015. }
  1016. hDC = GetDC(hSKWnd);
  1017. hMemDC = CreateCompatibleDC(hDC);
  1018. ReleaseDC(hSKWnd, hDC);
  1019. SelectObject(hMemDC, lpSKT1Ctxt->hSKBitmap);
  1020. SetBkColor(hMemDC, RGB(0xC0, 0xC0, 0xC0));
  1021. if (lpSKT1Ctxt->lfCharSet != DEFAULT_CHARSET) {
  1022. LOGFONT lfFont;
  1023. CopyMemory(&lfFont, &lfSKT1Font, sizeof (LOGFONT));
  1024. lfFont.lfCharSet = (BYTE)lpSKT1Ctxt->lfCharSet;
  1025. hOldFont = (HFONT)SelectObject(hMemDC, CreateFontIndirect(&lfFont));
  1026. }
  1027. else {
  1028. hOldFont = (HFONT)SelectObject(hMemDC, CreateFontIndirect(&lfSKT1Font));
  1029. }
  1030. for (i = 0; i < SKT1_LETTER_KEY_NUM; i++) {
  1031. int cbCount;
  1032. RECT rcOpaque;
  1033. lpSKT1Ctxt->wCodeTable[i] = lpSoftKbdData->wCode[0][bSKT1VirtKey[i]];
  1034. cbCount = (lpSKT1Ctxt->wCodeTable[i] == 0) ? 0 : 1;
  1035. rcOpaque.left = lpSKT1Ctxt->ptButtonPos[i].x + SKT1_LABEL_BMP_X -
  1036. SKT1_XOVERLAP;
  1037. rcOpaque.top = lpSKT1Ctxt->ptButtonPos[i].y + SKT1_LABEL_BMP_Y;
  1038. rcOpaque.right = rcOpaque.left +
  1039. lpSKT1Ctxt->nButtonWidth[SKT1_LETTER_TYPE] - SKT1_LABEL_BMP_X +
  1040. SKT1_XOVERLAP;
  1041. rcOpaque.bottom = rcOpaque.top + lpSKT1Ctxt->nButtonHeight[0] -
  1042. SKT1_LABEL_BMP_Y;
  1043. ExtTextOut(hMemDC, rcOpaque.left, rcOpaque.top,
  1044. ETO_OPAQUE, &rcOpaque,
  1045. (LPWSTR)&lpSKT1Ctxt->wCodeTable[i], cbCount, NULL);
  1046. }
  1047. DeleteObject(SelectObject(hMemDC, hOldFont));
  1048. DeleteDC(hMemDC);
  1049. GlobalUnlock(hSKT1Ctxt);
  1050. return (0);
  1051. }
  1052. /**********************************************************************/
  1053. /* SKWndProcT1 */
  1054. /**********************************************************************/
  1055. LRESULT CALLBACK SKWndProcT1(
  1056. HWND hSKWnd,
  1057. UINT uMsg,
  1058. WPARAM wParam,
  1059. LPARAM lParam)
  1060. {
  1061. switch (uMsg) {
  1062. case WM_CREATE:
  1063. return CreateT1Window(hSKWnd);
  1064. case WM_DESTROY:
  1065. DestroyT1Window(hSKWnd);
  1066. break;
  1067. case WM_PAINT:
  1068. {
  1069. HDC hDC;
  1070. PAINTSTRUCT ps;
  1071. hDC = BeginPaint(hSKWnd, &ps);
  1072. UpdateSKT1Window(hDC, hSKWnd);
  1073. EndPaint(hSKWnd, &ps);
  1074. }
  1075. break;
  1076. case WM_SETCURSOR:
  1077. if (!SKT1SetCursor(hSKWnd, lParam)) {
  1078. return DefWindowProc(hSKWnd, uMsg, wParam, lParam);
  1079. }
  1080. break;
  1081. case WM_MOUSEMOVE:
  1082. if (!SKT1MouseMove(hSKWnd)) {
  1083. return DefWindowProc(hSKWnd, uMsg, wParam, lParam);
  1084. }
  1085. break;
  1086. case WM_LBUTTONUP:
  1087. if (!SKT1ButtonUp(hSKWnd)) {
  1088. return DefWindowProc(hSKWnd, uMsg, wParam, lParam);
  1089. }
  1090. break;
  1091. case WM_MOUSEACTIVATE:
  1092. return (MA_NOACTIVATE);
  1093. case WM_SHOWWINDOW:
  1094. if (lParam != 0) {
  1095. } else if ((BOOL)wParam == TRUE) {
  1096. } else {
  1097. // we want to hide the soft keyboard on mouse button down
  1098. SKT1ButtonUp(hSKWnd);
  1099. }
  1100. return DefWindowProc(hSKWnd, uMsg, wParam, lParam);
  1101. case WM_IME_CONTROL:
  1102. switch (wParam) {
  1103. case IMC_GETSOFTKBDFONT:
  1104. {
  1105. HGLOBAL hSKT1Ctxt;
  1106. LPSKT1CTXT lpSKT1Ctxt;
  1107. BYTE lfCharSet;
  1108. hSKT1Ctxt = (HGLOBAL)GetWindowLongPtr(hSKWnd, SKT1_CONTEXT);
  1109. if (!hSKT1Ctxt) {
  1110. return (1);
  1111. }
  1112. lpSKT1Ctxt = (LPSKT1CTXT)GlobalLock(hSKT1Ctxt);
  1113. if (!lpSKT1Ctxt) {
  1114. return (1);
  1115. }
  1116. lfCharSet = (BYTE)lpSKT1Ctxt->lfCharSet;
  1117. GlobalUnlock(hSKT1Ctxt);
  1118. *(LPLOGFONT)lParam = lfSKT1Font;
  1119. if (lfCharSet != DEFAULT_CHARSET) {
  1120. ((LPLOGFONT)lParam)->lfCharSet = lfCharSet;
  1121. }
  1122. return (0);
  1123. }
  1124. break;
  1125. case IMC_SETSOFTKBDFONT:
  1126. {
  1127. // in differet version of Windows
  1128. if (lfSKT1Font.lfCharSet != ((LPLOGFONT)lParam)->lfCharSet) {
  1129. HGLOBAL hSKT1Ctxt;
  1130. LPSKT1CTXT lpSKT1Ctxt;
  1131. hSKT1Ctxt = (HGLOBAL)GetWindowLongPtr(hSKWnd,
  1132. SKT1_CONTEXT);
  1133. if (!hSKT1Ctxt) {
  1134. return 1;
  1135. }
  1136. lpSKT1Ctxt = (LPSKT1CTXT)GlobalLock(hSKT1Ctxt);
  1137. if (!lpSKT1Ctxt) {
  1138. return 1;
  1139. }
  1140. lpSKT1Ctxt->lfCharSet = ((LPLOGFONT)lParam)->lfCharSet;
  1141. GlobalUnlock(hSKT1Ctxt);
  1142. }
  1143. }
  1144. break;
  1145. case IMC_GETSOFTKBDPOS:
  1146. {
  1147. RECT rcWnd;
  1148. GetWindowRect(hSKWnd, &rcWnd);
  1149. return MAKELRESULT(rcWnd.left, rcWnd.top);
  1150. }
  1151. break;
  1152. case IMC_SETSOFTKBDPOS:
  1153. {
  1154. POINT ptSoftKbdPos;
  1155. HWND hUIWnd;
  1156. HIMC hIMC;
  1157. LPINPUTCONTEXT lpIMC;
  1158. ptSoftKbdPos.x = ((LPPOINTS)lParam)->x;
  1159. ptSoftKbdPos.y = ((LPPOINTS)lParam)->y;
  1160. SetWindowPos(hSKWnd, NULL,
  1161. ptSoftKbdPos.x, ptSoftKbdPos.y,
  1162. 0, 0, SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOZORDER);
  1163. // Here we want to get - the owner or parent window
  1164. hUIWnd = GetParent(hSKWnd);
  1165. if (!hUIWnd) {
  1166. return (1);
  1167. }
  1168. hIMC = (HIMC) GetWindowLongPtr(hUIWnd, IMMGWLP_IMC);
  1169. if (!hIMC) {
  1170. return (1);
  1171. }
  1172. lpIMC = (LPINPUTCONTEXT)ImmLockIMC(hIMC);
  1173. if (!lpIMC) {
  1174. return (1);
  1175. }
  1176. lpIMC->ptSoftKbdPos = ptSoftKbdPos;
  1177. ImmUnlockIMC(hIMC);
  1178. return (0);
  1179. }
  1180. break;
  1181. case IMC_SETSOFTKBDDATA:
  1182. {
  1183. LRESULT lRet;
  1184. lRet = SetSKT1Data(hSKWnd, (LPSOFTKBDDATA)lParam);
  1185. if (!lRet) {
  1186. InvalidateRect(hSKWnd, NULL, FALSE);
  1187. PostMessage(hSKWnd, WM_PAINT, 0, 0);
  1188. }
  1189. return (lRet);
  1190. }
  1191. break;
  1192. case IMC_GETSOFTKBDSUBTYPE:
  1193. case IMC_SETSOFTKBDSUBTYPE:
  1194. {
  1195. HGLOBAL hSKT1Ctxt;
  1196. LPSKT1CTXT lpSKT1Ctxt;
  1197. LRESULT lRet;
  1198. lRet = -1;
  1199. hSKT1Ctxt = (HGLOBAL)GetWindowLongPtr(hSKWnd, SKT1_CONTEXT);
  1200. if (!hSKT1Ctxt) {
  1201. return (lRet);
  1202. }
  1203. lpSKT1Ctxt = (LPSKT1CTXT)GlobalLock(hSKT1Ctxt);
  1204. if (!lpSKT1Ctxt) {
  1205. return (lRet);
  1206. }
  1207. if (wParam == IMC_GETSOFTKBDSUBTYPE) {
  1208. lRet = lpSKT1Ctxt->uSubType;
  1209. } else if (wParam == IMC_SETSOFTKBDSUBTYPE) {
  1210. lRet = lpSKT1Ctxt->uSubType;
  1211. lpSKT1Ctxt->uSubType = (UINT)lParam;
  1212. } else {
  1213. lRet = -1;
  1214. }
  1215. GlobalUnlock(hSKT1Ctxt);
  1216. return (lRet);
  1217. }
  1218. break;
  1219. default:
  1220. break;
  1221. }
  1222. break;
  1223. default:
  1224. return DefWindowProc(hSKWnd, uMsg, wParam, lParam);
  1225. }
  1226. return (0L);
  1227. }