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.

1334 lines
48 KiB

  1. /******************************************************************************
  2. *
  3. * File Name: imeui.c
  4. *
  5. * - User Interface routines.
  6. *
  7. * Author: Beomseok Oh (BeomOh)
  8. *
  9. * Copyright (C) Microsoft Corp 1993-1995. All rights reserved.
  10. *
  11. ******************************************************************************/
  12. // include files
  13. #include "precomp.h"
  14. // local definitions
  15. #define UIGWL_FLAGS 0
  16. #define UIF_WNDMOVE 0x00000001UL
  17. #define UIF_HANPRESS 0x00000002UL
  18. #define UIF_JUNPRESS 0x00000004UL
  19. #define UIF_CHIPRESS 0x00000008UL
  20. #define UIF_MOUSEIN 0x00000010UL
  21. #define UIF_SHOWSTATUS 0x00000020UL
  22. #define UIF_PRIVATEPOS 0x00000040UL
  23. extern BOOL fWndOpen[3];
  24. extern WORD wWndCmd[3];
  25. // public data
  26. #pragma data_seg(".text", "CODE")
  27. const TCHAR szUIClassName[] = TEXT("MSIME95K");
  28. const TCHAR szStateWndName[] = TEXT("IMESTATE");
  29. const TCHAR szCompWndName[] = TEXT("IMECOMP");
  30. const TCHAR szCandWndName[] = TEXT("IMECAND");
  31. const static RECT rcHan = { 4, 2, 21, 19 }, rcJun = { 24, 2, 41, 19 },
  32. rcChi = { 44, 2, 61, 19 };
  33. const static RECT rcCandCli = { 0, 0, 319, 29 },
  34. rcLArrow = { 15, 4, 27, 25 }, rcRArrow = { 292, 4, 304, 25 },
  35. rcBtn[9] = { { 30, 4, 57, 25 }, { 59, 4, 86, 25 },
  36. { 88, 4, 115, 25 }, { 117, 4, 144, 25 },
  37. { 146, 4, 173, 25 }, { 175, 4, 202, 25 },
  38. { 204, 4, 231, 25 }, { 233, 4, 260, 25 },
  39. { 262, 4, 289, 25 } };
  40. #pragma data_seg()
  41. HBITMAP hBMClient, hBMComp, hBMCand, hBMCandNum, hBMCandArr[2];
  42. HBITMAP hBMEng, hBMHan, hBMBan, hBMJun, hBMChi[2];
  43. HCURSOR hIMECursor;
  44. HFONT hFontFix = NULL;
  45. #pragma data_seg("SHAREDDATA")
  46. RECT rcScreen = { 0, 0, 0, 0 };
  47. RECT rcOldScrn = { 0, 0, 0, 0 };
  48. POINT ptDefPos[3] = { { -1, -1 }, { -1, -1 }, { -1, -1 } };
  49. POINT ptState = { -1, -1 };
  50. POINT ptComp = { -1, -1 };
  51. POINT ptCand = { -1, -1 };
  52. DWORD dwScreenRes = 0;
  53. #pragma data_seg()
  54. static POINT ptPos;
  55. static RECT rc;
  56. void UpdateUIPosition(void)
  57. {
  58. HKEY hKey;
  59. DWORD dwBuf, dwCb;
  60. SystemParametersInfo(SPI_GETWORKAREA, sizeof(rcScreen), &rcScreen, FALSE);
  61. if (!EqualRect(&rcOldScrn, &rcScreen))
  62. {
  63. ptDefPos[STATE_WINDOW].x = rcScreen.right - STATEXSIZE - GetSystemMetrics(SM_CXBORDER)
  64. - GetSystemMetrics(SM_CXVSCROLL) - GetSystemMetrics(SM_CXHSCROLL);
  65. ptDefPos[STATE_WINDOW].y = rcScreen.bottom - STATEYSIZE;
  66. ptDefPos[COMP_WINDOW].x = ptDefPos[STATE_WINDOW].x + STATEXSIZE + GAPX;
  67. ptDefPos[COMP_WINDOW].y = ptDefPos[STATE_WINDOW].y + GAPY;
  68. ptDefPos[CAND_WINDOW].x = rcScreen.right - CANDXSIZE;
  69. ptDefPos[CAND_WINDOW].y = rcScreen.bottom - CANDYSIZE;
  70. if (ptState.x == -1 && ptState.y == -1)
  71. {
  72. if (RegOpenKey(HKEY_CURRENT_USER, szIMEKey, &hKey) == ERROR_SUCCESS)
  73. {
  74. dwCb = sizeof(dwBuf);
  75. if (RegQueryValueEx(hKey, szStatePos, NULL, NULL, (LPBYTE)&dwBuf, &dwCb)
  76. == ERROR_SUCCESS)
  77. {
  78. ptState.x = HIWORD(dwBuf);
  79. ptState.y = LOWORD(dwBuf);
  80. wWndCmd[STATE_WINDOW] = wWndCmd[COMP_WINDOW] = 0x04; // MCW_SCREEN
  81. }
  82. else
  83. ptState = ptDefPos[STATE_WINDOW];
  84. dwCb = sizeof(dwBuf);
  85. if (RegQueryValueEx(hKey, szCandPos, NULL, NULL, (LPBYTE)&dwBuf, &dwCb)
  86. == ERROR_SUCCESS)
  87. {
  88. ptCand.x = HIWORD(dwBuf);
  89. ptCand.y = LOWORD(dwBuf);
  90. }
  91. else
  92. ptCand = ptDefPos[CAND_WINDOW];
  93. RegCloseKey(hKey);
  94. }
  95. else
  96. {
  97. ptState = ptDefPos[STATE_WINDOW];
  98. ptCand = ptDefPos[CAND_WINDOW];
  99. }
  100. dwScreenRes = MAKELONG(GetSystemMetrics(SM_CXSCREEN), GetSystemMetrics(SM_CYSCREEN));
  101. }
  102. else
  103. {
  104. ptState.x += rcScreen.left - rcOldScrn.left;
  105. ptState.y += rcScreen.top - rcOldScrn.top;
  106. ptComp.x += rcScreen.left - rcOldScrn.left;
  107. ptComp.y += rcScreen.top - rcOldScrn.top;
  108. ptCand.x += rcScreen.left - rcOldScrn.left;
  109. ptCand.y += rcScreen.top - rcOldScrn.top;
  110. }
  111. if (ptState.x < rcScreen.left)
  112. ptState.x = rcScreen.left;
  113. else if (ptState.x > rcScreen.right - STATEXSIZE)
  114. ptState.x = rcScreen.right - STATEXSIZE;
  115. if (ptState.y < rcScreen.top)
  116. ptState.y = rcScreen.top;
  117. else if (ptState.y > rcScreen.bottom - STATEYSIZE)
  118. ptState.y = rcScreen.bottom - STATEYSIZE;
  119. ptComp.x = (ptState.x + STATEXSIZE + GAPX + COMPSIZE > rcScreen.right)?
  120. ptState.x - GAPX - COMPSIZE: ptState.x + STATEXSIZE + GAPX;
  121. ptComp.y = ptState.y + GAPY;
  122. if (ptCand.x < rcScreen.left)
  123. ptCand.x = rcScreen.left;
  124. else if (ptCand.x > rcScreen.right - CANDXSIZE)
  125. ptCand.x = rcScreen.right - CANDXSIZE;
  126. if (ptCand.y < rcScreen.top)
  127. ptCand.y = rcScreen.top;
  128. else if (ptCand.y > rcScreen.bottom - CANDYSIZE)
  129. ptCand.y = rcScreen.bottom - CANDYSIZE;
  130. rcOldScrn = rcScreen;
  131. }
  132. }
  133. BOOL InitializeResource(HANDLE hInstance)
  134. {
  135. hBMClient = MyCreateMappedBitmap(hInst, TEXT("Client"));
  136. hBMEng = MyCreateMappedBitmap(hInst, TEXT("English"));
  137. hBMHan = MyCreateMappedBitmap(hInst, TEXT("Hangeul"));
  138. hBMBan = MyCreateMappedBitmap(hInst, TEXT("Banja"));
  139. hBMJun = MyCreateMappedBitmap(hInst, TEXT("Junja"));
  140. hBMChi[0] = MyCreateMappedBitmap(hInst, TEXT("ChineseOff"));
  141. hBMChi[1] = MyCreateMappedBitmap(hInst, TEXT("ChineseOn"));
  142. hBMComp = MyCreateMappedBitmap(hInst, TEXT("Composition"));
  143. hBMCand = MyCreateMappedBitmap(hInst, TEXT("Candidate"));
  144. hBMCandNum = MyCreateMappedBitmap(hInst, TEXT("CandNumber"));
  145. hBMCandArr[0] = MyCreateMappedBitmap(hInst, TEXT("CandArrow1"));
  146. hBMCandArr[1] = MyCreateMappedBitmap(hInst, TEXT("CandArrow2"));
  147. hIMECursor = LoadCursor(hInstance, TEXT("MyHand"));
  148. #ifdef JOHAB_IME
  149. hFontFix = CreateFont(-16,0,0,0,0,0,0,0,130,OUT_DEFAULT_PRECIS,
  150. CLIP_DEFAULT_PRECIS,DEFAULT_QUALITY,FIXED_PITCH,TEXT("����"));
  151. #else
  152. hFontFix = CreateFont(-16,0,0,0,0,0,0,0,129,OUT_DEFAULT_PRECIS,
  153. CLIP_DEFAULT_PRECIS,DEFAULT_QUALITY,FIXED_PITCH,TEXT("����"));
  154. #endif
  155. return TRUE;
  156. }
  157. BOOL RegisterUIClass(HANDLE hInstance)
  158. {
  159. BOOL fRet = TRUE;
  160. WNDCLASSEX wc;
  161. wc.cbSize = sizeof(WNDCLASSEX);
  162. wc.style = CS_VREDRAW | CS_HREDRAW | CS_IME;
  163. wc.cbClsExtra = 0;
  164. wc.hInstance = hInstance;
  165. wc.hCursor = LoadCursor(NULL, IDC_ARROW);
  166. wc.hIcon = NULL;
  167. wc.hIconSm = NULL;
  168. wc.lpszMenuName = (LPTSTR)NULL;
  169. wc.hbrBackground = NULL;
  170. wc.cbWndExtra = 8;
  171. wc.lpfnWndProc = UIWndProc;
  172. wc.lpszClassName = (LPTSTR)szUIClassName;
  173. if (!RegisterClassEx((LPWNDCLASSEX)&wc))
  174. {
  175. MyDebugOut(MDB_LOG, "RegisterClassEx() Failed for UIWindow.");
  176. fRet = FALSE;
  177. }
  178. wc.style = CS_VREDRAW | CS_HREDRAW | CS_IME;
  179. wc.cbWndExtra = 4;
  180. wc.lpfnWndProc = StateWndProc;
  181. wc.lpszClassName = (LPTSTR)szStateWndName;
  182. if (!RegisterClassEx((LPWNDCLASSEX)&wc))
  183. {
  184. MyDebugOut(MDB_LOG, "RegisterClassEx() Failed for StateWindow.");
  185. fRet = FALSE;
  186. }
  187. wc.lpfnWndProc = CompWndProc;
  188. wc.lpszClassName = (LPTSTR)szCompWndName;
  189. if (!RegisterClassEx((LPWNDCLASSEX)&wc))
  190. {
  191. MyDebugOut(MDB_LOG, "RegisterClassEx() Failed for CompWindow.");
  192. fRet = FALSE;
  193. }
  194. wc.lpfnWndProc = CandWndProc;
  195. wc.lpszClassName = (LPTSTR)szCandWndName;
  196. if (!RegisterClassEx((LPWNDCLASSEX)&wc))
  197. {
  198. MyDebugOut(MDB_LOG, "RegisterClassEx() Failed for CandWindow.");
  199. fRet = FALSE;
  200. }
  201. return fRet;
  202. }
  203. BOOL UnregisterUIClass(HANDLE hInstance)
  204. {
  205. BOOL fRet = TRUE;
  206. if (!UnregisterClass(szUIClassName, hInstance))
  207. {
  208. MyDebugOut(MDB_LOG, "UnregisterClass() Failed for UIWindow.");
  209. fRet = FALSE;
  210. }
  211. if (!UnregisterClass(szStateWndName, hInstance))
  212. {
  213. MyDebugOut(MDB_LOG, "UnregisterClass() Failed for StateWindow.");
  214. fRet = FALSE;
  215. }
  216. if (!UnregisterClass(szCompWndName, hInstance))
  217. {
  218. MyDebugOut(MDB_LOG, "UnregisterClass() Failed for CompWindow.");
  219. fRet = FALSE;
  220. }
  221. if (!UnregisterClass(szCandWndName, hInstance))
  222. {
  223. MyDebugOut(MDB_LOG, "UnregisterClass() Failed for CandWindow.");
  224. fRet = FALSE;
  225. }
  226. return fRet;
  227. }
  228. void DrawBitmap(HDC hDC, long xStart, long yStart, HBITMAP hBitmap)
  229. {
  230. HDC hMemDC;
  231. HBITMAP hBMOld;
  232. BITMAP bm;
  233. POINT pt;
  234. hMemDC = CreateCompatibleDC(hDC);
  235. hBMOld = SelectObject(hMemDC, hBitmap);
  236. GetObject(hBitmap, sizeof(BITMAP), (LPSTR)&bm);
  237. pt.x = bm.bmWidth;
  238. pt.y = bm.bmHeight;
  239. BitBlt(hDC, xStart, yStart, pt.x, pt.y, hMemDC, 0, 0, SRCCOPY);
  240. SelectObject(hMemDC, hBMOld);
  241. DeleteDC(hMemDC);
  242. return;
  243. }
  244. void ShowWindowBorder(RECT rc)
  245. {
  246. HDC hDC;
  247. HBRUSH hBrOld;
  248. int cxBorder, cyBorder;
  249. hDC = CreateDC(TEXT("DISPLAY"), NULL, NULL, NULL);
  250. hBrOld = SelectObject(hDC, GetStockObject(GRAY_BRUSH));
  251. cxBorder = GetSystemMetrics(SM_CXBORDER);
  252. cyBorder = GetSystemMetrics(SM_CYBORDER);
  253. PatBlt(hDC, rc.left, rc.top, rc.right-rc.left-cxBorder, cyBorder, PATINVERT);
  254. PatBlt(hDC, rc.right-cxBorder, rc.top, cxBorder, rc.bottom-rc.top-cyBorder, PATINVERT);
  255. PatBlt(hDC, rc.right, rc.bottom-cyBorder, -(rc.right-rc.left-cxBorder), cyBorder, PATINVERT);
  256. PatBlt(hDC, rc.left, rc.bottom, cxBorder, -(rc.bottom-rc.top-cyBorder), PATINVERT);
  257. SelectObject(hDC, hBrOld);
  258. DeleteDC(hDC);
  259. return;
  260. }
  261. void ShowHideUIWnd(HIMC hIMC, LPUIINSTANCE lpUIInst, BOOL fShow, LPARAM lParam)
  262. {
  263. LPINPUTCONTEXT lpIMC;
  264. LPCOMPOSITIONSTRING lpCompStr;
  265. DWORD fdwUIFlags;
  266. if (fShow && hIMC && (lpIMC = ImmLockIMC(hIMC)))
  267. {
  268. UpdateUIPosition();
  269. fdwUIFlags = (DWORD)GetWindowLong(lpUIInst->rghWnd[STATE_WINDOW], UIGWL_FLAGS);
  270. if (!(fdwUIFlags & UIF_PRIVATEPOS))
  271. lpIMC->ptStatusWndPos = ptState;
  272. MoveWindow(lpUIInst->rghWnd[STATE_WINDOW], lpIMC->ptStatusWndPos.x,
  273. lpIMC->ptStatusWndPos.y, STATEXSIZE, STATEYSIZE, TRUE);
  274. if (lpIMC->cfCompForm.dwStyle == CFS_DEFAULT)
  275. {
  276. MoveWindow(lpUIInst->rghWnd[COMP_WINDOW], ptComp.x, ptComp.y, COMPSIZE, COMPSIZE, TRUE);
  277. }
  278. if (fWndOpen[STATE_WINDOW] != FALSE && (fdwUIFlags & UIF_SHOWSTATUS))
  279. ShowWindow(lpUIInst->rghWnd[STATE_WINDOW], SW_SHOWNOACTIVATE);
  280. else
  281. ShowWindow(lpUIInst->rghWnd[STATE_WINDOW], SW_HIDE);
  282. lpCompStr = (LPCOMPOSITIONSTRING)ImmLockIMCC(lpIMC->hCompStr);
  283. if (lpCompStr && lpCompStr->dwCompStrLen
  284. && fWndOpen[COMP_WINDOW] && (lParam & ISC_SHOWUICOMPOSITIONWINDOW))
  285. ShowWindow(lpUIInst->rghWnd[COMP_WINDOW], SW_SHOWNOACTIVATE);
  286. else
  287. ShowWindow(lpUIInst->rghWnd[COMP_WINDOW], SW_HIDE);
  288. if (lpIMC->fdwConversion & IME_CMODE_HANJACONVERT
  289. && fWndOpen[CAND_WINDOW] && (lParam & ISC_SHOWUICANDIDATEWINDOW))
  290. ShowWindow(lpUIInst->rghWnd[CAND_WINDOW], SW_SHOWNOACTIVATE);
  291. else
  292. ShowWindow(lpUIInst->rghWnd[CAND_WINDOW], SW_HIDE);
  293. ImmUnlockIMCC(lpIMC->hCompStr);
  294. ImmUnlockIMC(hIMC);
  295. }
  296. else
  297. {
  298. ShowWindow(lpUIInst->rghWnd[STATE_WINDOW], SW_HIDE);
  299. ShowWindow(lpUIInst->rghWnd[COMP_WINDOW], SW_HIDE);
  300. ShowWindow(lpUIInst->rghWnd[CAND_WINDOW], SW_HIDE);
  301. }
  302. }
  303. LRESULT CALLBACK UIWndProc(HWND hWnd, UINT uMessage, WPARAM wParam, LPARAM lParam)
  304. {
  305. HGLOBAL hUIInst;
  306. LPUIINSTANCE lpUIInst;
  307. switch (uMessage)
  308. {
  309. case WM_CREATE:
  310. hUIInst = GlobalAlloc(GHND, sizeof(UIINSTANCE));
  311. lpUIInst = (LPUIINSTANCE)GlobalLock(hUIInst);
  312. lpUIInst->rghWnd[STATE_WINDOW] = CreateWindow(szStateWndName, TEXT("\0"),
  313. WS_DISABLED | WS_POPUP, ptState.x, ptState.y,
  314. STATEXSIZE, STATEYSIZE, hWnd, NULL, hInst, NULL);
  315. lpUIInst->rghWnd[COMP_WINDOW] = CreateWindow(szCompWndName, TEXT("\0"),
  316. WS_DISABLED | WS_POPUP, ptComp.x, ptComp.y,
  317. COMPSIZE, COMPSIZE, hWnd, NULL, hInst, NULL );
  318. lpUIInst->rghWnd[CAND_WINDOW] = CreateWindow(szCandWndName, TEXT("\0"),
  319. WS_DISABLED | WS_POPUP, ptCand.x, ptCand.y,
  320. CANDXSIZE, CANDYSIZE, hWnd, NULL, hInst, NULL );
  321. GlobalUnlock(hUIInst);
  322. SetWindowLongPtr(hWnd, IMMGWL_PRIVATE, (LONG_PTR)hUIInst);
  323. return 0;
  324. case WM_DESTROY:
  325. hUIInst = (HGLOBAL)GetWindowLongPtr(hWnd, IMMGWL_PRIVATE);
  326. lpUIInst = (LPUIINSTANCE)GlobalLock(hUIInst);
  327. DestroyWindow(lpUIInst->rghWnd[STATE_WINDOW]);
  328. DestroyWindow(lpUIInst->rghWnd[COMP_WINDOW]);
  329. DestroyWindow(lpUIInst->rghWnd[CAND_WINDOW]);
  330. GlobalUnlock(hUIInst);
  331. GlobalFree(hUIInst);
  332. SetWindowLongPtr(hWnd, IMMGWL_PRIVATE, (LONG_PTR)0);
  333. return 0;
  334. case WM_IME_SELECT:
  335. hUIInst = (HGLOBAL)GetWindowLongPtr(hWnd, IMMGWL_PRIVATE);
  336. lpUIInst = (LPUIINSTANCE)GlobalLock(hUIInst);
  337. ShowHideUIWnd(GetWindowLongPtr(hWnd, IMMGWL_IMC), lpUIInst, wParam, ISC_SHOWUIALL);
  338. GlobalUnlock(hUIInst);
  339. return 0;
  340. case WM_IME_COMPOSITION:
  341. hUIInst = (HGLOBAL)GetWindowLongPtr(hWnd, IMMGWL_PRIVATE);
  342. lpUIInst = (LPUIINSTANCE)GlobalLock(hUIInst);
  343. InvalidateRect(lpUIInst->rghWnd[COMP_WINDOW], NULL, TRUE);
  344. GlobalUnlock(hUIInst);
  345. return 0;
  346. case WM_IME_CONTROL:
  347. return (LRESULT)DoIMEControl(hWnd, wParam, lParam);
  348. case WM_IME_NOTIFY:
  349. return (LRESULT)DoIMENotify(hWnd, wParam, lParam);
  350. case WM_IME_SETCONTEXT:
  351. hUIInst = (HGLOBAL)GetWindowLongPtr(hWnd, IMMGWL_PRIVATE);
  352. lpUIInst = (LPUIINSTANCE)GlobalLock(hUIInst);
  353. ShowHideUIWnd(GetWindowLongPtr(hWnd, IMMGWL_IMC), lpUIInst, wParam, lParam);
  354. GlobalUnlock(hUIInst);
  355. return 0;
  356. case WM_IME_STARTCOMPOSITION:
  357. hUIInst = (HGLOBAL)GetWindowLongPtr(hWnd, IMMGWL_PRIVATE);
  358. lpUIInst = (LPUIINSTANCE)GlobalLock(hUIInst);
  359. ShowWindow(lpUIInst->rghWnd[COMP_WINDOW], fWndOpen[COMP_WINDOW]? SW_SHOWNOACTIVATE: SW_HIDE);
  360. GlobalUnlock(hUIInst);
  361. return 0;
  362. case WM_IME_ENDCOMPOSITION:
  363. hUIInst = (HGLOBAL)GetWindowLongPtr(hWnd, IMMGWL_PRIVATE);
  364. lpUIInst = (LPUIINSTANCE)GlobalLock(hUIInst);
  365. ShowWindow(lpUIInst->rghWnd[COMP_WINDOW], SW_HIDE);
  366. GlobalUnlock(hUIInst);
  367. return 0;
  368. case WM_SYSCOLORCHANGE:
  369. GetSysColorsAndMappedBitmap();
  370. return 0;
  371. case WM_DISPLAYCHANGE:
  372. if (dwScreenRes != (DWORD)lParam)
  373. {
  374. ptState.x += LOWORD(lParam) - LOWORD(dwScreenRes);
  375. ptState.y += HIWORD(lParam) - HIWORD(dwScreenRes);
  376. ptComp.x += LOWORD(lParam) - LOWORD(dwScreenRes);
  377. ptComp.y += HIWORD(lParam) - HIWORD(dwScreenRes);
  378. ptCand.x += LOWORD(lParam) - LOWORD(dwScreenRes);
  379. ptCand.y += HIWORD(lParam) - HIWORD(dwScreenRes);
  380. dwScreenRes = MAKELONG(GetSystemMetrics(SM_CXSCREEN), GetSystemMetrics(SM_CYSCREEN));
  381. }
  382. return 0;
  383. }
  384. return DefWindowProc(hWnd, uMessage, wParam, lParam);
  385. }
  386. LRESULT CALLBACK StateWndProc(HWND hWnd, UINT uMessage, WPARAM wParam, LPARAM lParam)
  387. {
  388. switch (uMessage)
  389. {
  390. HANDLE_DUMMYMSG(WM_IME_CHAR);
  391. HANDLE_DUMMYMSG(WM_IME_COMPOSITIONFULL);
  392. HANDLE_DUMMYMSG(WM_IME_COMPOSITION);
  393. HANDLE_DUMMYMSG(WM_IME_CONTROL);
  394. HANDLE_DUMMYMSG(WM_IME_NOTIFY);
  395. HANDLE_DUMMYMSG(WM_IME_SELECT);
  396. HANDLE_DUMMYMSG(WM_IME_SETCONTEXT);
  397. HANDLE_DUMMYMSG(WM_IME_STARTCOMPOSITION);
  398. HANDLE_DUMMYMSG(WM_IME_ENDCOMPOSITION);
  399. HANDLE_MSG(hWnd, WM_SETCURSOR, State_OnSetCursor);
  400. HANDLE_MSG(hWnd, WM_MOUSEMOVE, State_OnMouseMove);
  401. HANDLE_MSG(hWnd, WM_LBUTTONUP, State_OnLButtonUp);
  402. HANDLE_MSG(hWnd, WM_PAINT, State_OnPaint);
  403. HANDLE_MSG(hWnd, WM_COMMAND, State_OnCommand);
  404. }
  405. return DefWindowProc(hWnd, uMessage, wParam, lParam);
  406. }
  407. BOOL State_OnSetCursor(HWND hWnd, HWND hWndCursor, UINT codeHitTest, UINT msg)
  408. {
  409. HWND hWndUI;
  410. HIMC hIMC;
  411. DWORD fdwUIFlags;
  412. SetCursor(hIMECursor);
  413. switch (msg)
  414. {
  415. case WM_LBUTTONDOWN:
  416. GetCursorPos(&ptPos);
  417. ScreenToClient(hWnd, &ptPos);
  418. fdwUIFlags = (DWORD)GetWindowLong(hWnd, UIGWL_FLAGS);
  419. if (PtInRect((LPRECT)&rcHan, ptPos))
  420. {
  421. fdwUIFlags |= UIF_HANPRESS;
  422. }
  423. else if (PtInRect((LPRECT)&rcJun, ptPos))
  424. {
  425. fdwUIFlags |= UIF_JUNPRESS;
  426. }
  427. else if (PtInRect((LPRECT)&rcChi, ptPos))
  428. {
  429. fdwUIFlags |= UIF_CHIPRESS;
  430. }
  431. else
  432. {
  433. fdwUIFlags |= UIF_WNDMOVE;
  434. GetWindowRect(hWnd, &rc);
  435. ShowWindowBorder(rc);
  436. SetCapture(hWnd);
  437. }
  438. SetWindowLong(hWnd, UIGWL_FLAGS, fdwUIFlags);
  439. break;
  440. case WM_LBUTTONUP:
  441. GetCursorPos(&ptPos);
  442. ScreenToClient(hWnd, &ptPos);
  443. fdwUIFlags = (DWORD)GetWindowLong( hWnd, UIGWL_FLAGS );
  444. if ((fdwUIFlags & UIF_HANPRESS) && PtInRect((LPRECT)&rcHan, ptPos))
  445. {
  446. fdwUIFlags &= ~UIF_HANPRESS;
  447. keybd_event(VK_HANGEUL, 0, 0, 0);
  448. keybd_event(VK_HANGEUL, 0, KEYEVENTF_KEYUP, 0);
  449. }
  450. else if ((fdwUIFlags & UIF_JUNPRESS) && PtInRect((LPRECT)&rcJun, ptPos))
  451. {
  452. fdwUIFlags &= ~UIF_JUNPRESS;
  453. keybd_event(VK_JUNJA, 0, 0, 0);
  454. keybd_event(VK_JUNJA, 0, KEYEVENTF_KEYUP, 0);
  455. }
  456. else if ((fdwUIFlags & UIF_CHIPRESS) && PtInRect((LPRECT)&rcChi, ptPos))
  457. {
  458. fdwUIFlags &= ~UIF_CHIPRESS;
  459. keybd_event(VK_HANJA, 0, 0, 0);
  460. keybd_event(VK_HANJA, 0, KEYEVENTF_KEYUP, 0);
  461. }
  462. else
  463. fdwUIFlags &= ~(UIF_HANPRESS | UIF_JUNPRESS | UIF_CHIPRESS);
  464. SetWindowLong(hWnd, UIGWL_FLAGS, fdwUIFlags);
  465. break;
  466. case WM_RBUTTONDOWN:
  467. hWndUI = GetWindow(hWnd, GW_OWNER);
  468. hIMC = (HIMC)GetWindowLongPtr(hWndUI, IMMGWL_IMC);
  469. if (bState) MakeFinalMsgBuf(hIMC, 0);
  470. break;
  471. case WM_RBUTTONUP:
  472. State_OnMyMenu(hWnd);
  473. break;
  474. }
  475. return TRUE;
  476. }
  477. void State_OnMouseMove(HWND hWnd, int x, int y, UINT keyFlags)
  478. {
  479. DWORD fdwUIFlags;
  480. fdwUIFlags = (DWORD)GetWindowLong(hWnd, UIGWL_FLAGS);
  481. if (fdwUIFlags & UIF_WNDMOVE)
  482. {
  483. ShowWindowBorder(rc);
  484. rc.left += x - ptPos.x;
  485. rc.top += y - ptPos.y;
  486. rc.right += x - ptPos.x;
  487. rc.bottom += y - ptPos.y;
  488. ShowWindowBorder(rc);
  489. ptPos.x = x;
  490. ptPos.y = y;
  491. }
  492. return;
  493. UNREFERENCED_PARAMETER(keyFlags);
  494. }
  495. void State_OnLButtonUp(HWND hWnd, int x, int y, UINT keyFlags)
  496. {
  497. HKEY hKey;
  498. DWORD fdwUIFlags, dwBuf, dwCb;
  499. HGLOBAL hUIInst;
  500. LPUIINSTANCE lpUIInst;
  501. HWND hWndUI;
  502. HIMC hIMC;
  503. LPINPUTCONTEXT lpIMC;
  504. ReleaseCapture();
  505. fdwUIFlags = (DWORD)GetWindowLong(hWnd, UIGWL_FLAGS);
  506. if (fdwUIFlags & UIF_WNDMOVE)
  507. {
  508. ShowWindowBorder(rc);
  509. MoveWindow(hWnd, rc.left, rc.top, STATEXSIZE, STATEYSIZE, TRUE);
  510. ptState.x = rc.left;
  511. ptState.y = rc.top;
  512. if (RegCreateKey(HKEY_CURRENT_USER, szIMEKey, &hKey) == ERROR_SUCCESS)
  513. {
  514. dwCb = sizeof(dwBuf);
  515. dwBuf = (ptState.x << 16) | (ptState.y & 0x0FFFF); // HIWORD : X, LOWORD : Y
  516. RegSetValueEx(hKey, szStatePos, 0, REG_DWORD, (LPBYTE)&dwBuf, dwCb);
  517. RegCloseKey(hKey);
  518. }
  519. ptComp.x = (ptState.x + STATEXSIZE + GAPX + COMPSIZE > rcScreen.right)?
  520. ptState.x - GAPX - COMPSIZE: ptState.x + STATEXSIZE + GAPX;
  521. ptComp.y = ptState.y + GAPY;
  522. hWndUI = GetWindow(hWnd, GW_OWNER);
  523. hIMC = (HIMC)GetWindowLongPtr(hWndUI, IMMGWL_IMC);
  524. lpIMC = ImmLockIMC(hIMC);
  525. if (lpIMC != NULL) {
  526. lpIMC->ptStatusWndPos = ptState;
  527. if (lpIMC->cfCompForm.dwStyle == CFS_DEFAULT)
  528. {
  529. hUIInst = (HGLOBAL)GetWindowLongPtr(GetWindow(hWnd, GW_OWNER), IMMGWL_PRIVATE);
  530. lpUIInst = (LPUIINSTANCE)GlobalLock(hUIInst);
  531. MoveWindow(lpUIInst->rghWnd[COMP_WINDOW], ptComp.x, ptComp.y, COMPSIZE, COMPSIZE, TRUE);
  532. GlobalUnlock(hUIInst);
  533. lpIMC->cfCompForm.ptCurrentPos = ptComp;
  534. }
  535. ImmUnlockIMC(hIMC);
  536. }
  537. wWndCmd[STATE_WINDOW] = wWndCmd[COMP_WINDOW] = 0x04; // MCW_SCREEN
  538. fdwUIFlags &= ~UIF_WNDMOVE;
  539. }
  540. SetWindowLong(hWnd, UIGWL_FLAGS, fdwUIFlags);
  541. return;
  542. UNREFERENCED_PARAMETER(x);
  543. UNREFERENCED_PARAMETER(y);
  544. UNREFERENCED_PARAMETER(keyFlags);
  545. }
  546. typedef struct tagCOLORMAP
  547. {
  548. COLORREF bgrfrom;
  549. COLORREF bgrto;
  550. COLORREF sysColor;
  551. } COLORMAP;
  552. // these are the default colors used to map the dib colors
  553. // to the current system colors
  554. #define BGR_BUTTONTEXT (RGB(000,000,000)) // black
  555. #define BGR_BUTTONSHADOW (RGB(128,128,128)) // dark grey
  556. #define BGR_BUTTONFACE (RGB(192,192,192)) // bright grey
  557. #define BGR_BUTTONHILIGHT (RGB(255,255,255)) // white
  558. #define BGR_BACKGROUNDSEL (RGB(255,000,000)) // blue
  559. #define BGR_BACKGROUND (RGB(255,000,255)) // magenta
  560. #define FlipColor(rgb) (RGB(GetBValue(rgb), GetGValue(rgb), GetRValue(rgb)))
  561. HBITMAP MyCreateMappedBitmap(HINSTANCE hInstance, LPTSTR lpszBitmap)
  562. {
  563. HDC hdc, hdcMem = NULL;
  564. HANDLE h;
  565. LPDWORD p;
  566. LPSTR lpBits;
  567. HANDLE hRes;
  568. LPBITMAPINFOHEADER lpBitmapInfo, lpTmpBMInfo;
  569. HBITMAP hbm = NULL, hbmOld;
  570. int numcolors, i, wid, hgt;
  571. static COLORMAP ColorMap[] =
  572. {
  573. {BGR_BUTTONTEXT, BGR_BUTTONTEXT, COLOR_BTNTEXT}, // black
  574. {BGR_BUTTONSHADOW, BGR_BUTTONSHADOW, COLOR_BTNSHADOW}, // dark grey
  575. {BGR_BUTTONFACE, BGR_BUTTONFACE, COLOR_BTNFACE}, // bright grey
  576. {BGR_BUTTONHILIGHT, BGR_BUTTONHILIGHT, COLOR_BTNHIGHLIGHT},// white
  577. {BGR_BACKGROUNDSEL, BGR_BACKGROUNDSEL, COLOR_HIGHLIGHT}, // blue
  578. {BGR_BACKGROUND, BGR_BACKGROUND, COLOR_WINDOW} // magenta
  579. };
  580. #define NUM_MAPS (sizeof(ColorMap)/sizeof(COLORMAP))
  581. h = FindResource(hInstance, lpszBitmap, RT_BITMAP);
  582. if (!h)
  583. return NULL;
  584. hRes = LoadResource(hInstance, h);
  585. /* Lock the bitmap and get a pointer to the color table. */
  586. lpBitmapInfo = (LPBITMAPINFOHEADER)LockResource(hRes);
  587. if (!lpBitmapInfo)
  588. return NULL;
  589. // HACK: We need to use temp copy of BITMAPINFO because original info is destroyed
  590. // after change color. It cause next time LoadResource result has wrong info.
  591. i = sizeof(BITMAPINFOHEADER) + 16*sizeof(RGBQUAD);
  592. lpTmpBMInfo = (LPBITMAPINFOHEADER) LocalAlloc(LPTR, i);
  593. if (!lpTmpBMInfo) {
  594. UnlockResource(hRes);
  595. FreeResource(hRes);
  596. return NULL;
  597. }
  598. CopyMemory(lpTmpBMInfo, lpBitmapInfo, i);
  599. //
  600. // So what are the new colors anyway ?
  601. //
  602. for (i=0; i < NUM_MAPS; i++)
  603. ColorMap[i].bgrto = FlipColor(GetSysColor((int)ColorMap[i].sysColor));
  604. // HACK: ??? p = (LPDWORD)(((LPSTR)lpBitmapInfo) + lpBitmapInfo->biSize);
  605. p = (LPDWORD)(((LPSTR)lpTmpBMInfo) + lpTmpBMInfo->biSize);
  606. /* Replace button-face and button-shadow colors with the current values
  607. */
  608. numcolors = 16;
  609. while (numcolors-- > 0)
  610. {
  611. for (i = 0; i < NUM_MAPS; i++)
  612. {
  613. if (*p == ColorMap[i].bgrfrom)
  614. {
  615. *p = ColorMap[i].bgrto;
  616. break;
  617. }
  618. }
  619. p++;
  620. }
  621. /* First skip over the header structure */
  622. lpBits = (LPSTR)(lpBitmapInfo + 1);
  623. /* Skip the color table entries, if any */
  624. lpBits += (1 << (lpBitmapInfo->biBitCount)) * sizeof(RGBQUAD);
  625. /* Create a color bitmap compatible with the display device */
  626. i = wid = (int)lpBitmapInfo->biWidth;
  627. hgt = (int)lpBitmapInfo->biHeight;
  628. hdc = GetDC(NULL);
  629. hdcMem = CreateCompatibleDC(hdc);
  630. if (hdcMem)
  631. {
  632. hbm = CreateDiscardableBitmap(hdc, i, hgt);
  633. if (hbm)
  634. {
  635. hbmOld = SelectObject(hdcMem, hbm);
  636. // set the main image
  637. StretchDIBits(hdcMem, 0, 0, wid, hgt, 0, 0, wid, hgt, lpBits,
  638. (LPBITMAPINFO)lpTmpBMInfo, DIB_RGB_COLORS, SRCCOPY);
  639. SelectObject(hdcMem, hbmOld);
  640. }
  641. DeleteObject(hdcMem);
  642. }
  643. ReleaseDC(NULL, hdc);
  644. UnlockResource(hRes);
  645. FreeResource(hRes);
  646. // HACK: Remove hack temp BITMAPINFO.
  647. LocalFree(lpTmpBMInfo);
  648. return hbm;
  649. }
  650. void GetSysColorsAndMappedBitmap(void)
  651. {
  652. static DWORD rgbFace, rgbShadow, rgbHilight, rgbFrame;
  653. static COLORREF rgbSaveFace = 0xFFFFFFFFL,
  654. rgbSaveShadow = 0xFFFFFFFFL,
  655. rgbSaveHilight = 0xFFFFFFFFL,
  656. rgbSaveFrame = 0xFFFFFFFFL;
  657. rgbFace = GetSysColor(COLOR_BTNFACE);
  658. rgbShadow = GetSysColor(COLOR_BTNSHADOW);
  659. rgbHilight = GetSysColor(COLOR_BTNHIGHLIGHT);
  660. rgbFrame = GetSysColor(COLOR_WINDOWFRAME);
  661. if (rgbSaveFace != rgbFace || rgbSaveShadow != rgbShadow
  662. || rgbSaveHilight != rgbHilight || rgbSaveFrame != rgbFrame)
  663. {
  664. rgbSaveFace = rgbFace;
  665. rgbSaveShadow = rgbShadow;
  666. rgbSaveHilight = rgbHilight;
  667. rgbSaveFrame = rgbFrame;
  668. DeleteObject(hBMClient);
  669. DeleteObject(hBMEng);
  670. DeleteObject(hBMHan);
  671. DeleteObject(hBMBan);
  672. DeleteObject(hBMJun);
  673. DeleteObject(hBMChi[0]);
  674. DeleteObject(hBMChi[1]);
  675. DeleteObject(hBMComp);
  676. DeleteObject(hBMCand);
  677. DeleteObject(hBMCandNum);
  678. DeleteObject(hBMCandArr[0]);
  679. DeleteObject(hBMCandArr[1]);
  680. hBMClient = MyCreateMappedBitmap(hInst, TEXT("Client"));
  681. hBMEng = MyCreateMappedBitmap(hInst, TEXT("English"));
  682. hBMHan = MyCreateMappedBitmap(hInst, TEXT("Hangeul"));
  683. hBMBan = MyCreateMappedBitmap(hInst, TEXT("Banja"));
  684. hBMJun = MyCreateMappedBitmap(hInst, TEXT("Junja"));
  685. hBMChi[0] = MyCreateMappedBitmap(hInst, TEXT("ChineseOff"));
  686. hBMChi[1] = MyCreateMappedBitmap(hInst, TEXT("ChineseOn"));
  687. hBMComp = MyCreateMappedBitmap(hInst, TEXT("Composition"));
  688. hBMCand = MyCreateMappedBitmap(hInst, TEXT("Candidate"));
  689. hBMCandNum = MyCreateMappedBitmap(hInst, TEXT("CandNumber"));
  690. hBMCandArr[0] = MyCreateMappedBitmap(hInst, TEXT("CandArrow1"));
  691. hBMCandArr[1] = MyCreateMappedBitmap(hInst, TEXT("CandArrow2"));
  692. }
  693. }
  694. void State_OnPaint(HWND hWnd)
  695. {
  696. HDC hDC;
  697. HWND hWndUI;
  698. HIMC hIMC;
  699. LPINPUTCONTEXT lpIMC;
  700. PAINTSTRUCT ps;
  701. DWORD fdwUIFlags;
  702. hDC = BeginPaint(hWnd, &ps);
  703. hWndUI = GetWindow(hWnd, GW_OWNER);
  704. hIMC = (HIMC)GetWindowLongPtr(hWndUI, IMMGWL_IMC);
  705. if (hIMC && (lpIMC = ImmLockIMC(hIMC)))
  706. {
  707. fdwUIFlags = (DWORD)GetWindowLong(hWnd, UIGWL_FLAGS);
  708. DrawBitmap(hDC, 0, 0, hBMClient);
  709. DrawBitmap(hDC, rcHan.left, rcHan.top,
  710. (lpIMC->fOpen && (lpIMC->fdwConversion & IME_CMODE_HANGEUL))? hBMHan: hBMEng);
  711. DrawBitmap(hDC, rcJun.left, rcJun.top,
  712. (lpIMC->fOpen && (lpIMC->fdwConversion & IME_CMODE_FULLSHAPE))? hBMJun: hBMBan);
  713. DrawBitmap(hDC, rcChi.left, rcChi.top,
  714. (lpIMC->fdwConversion & IME_CMODE_HANJACONVERT)? hBMChi[1]: hBMChi[0]);
  715. ImmUnlockIMC(hIMC);
  716. }
  717. EndPaint(hWnd, &ps);
  718. }
  719. void State_OnCommand(HWND hWnd, int id, HWND hWndCtl, UINT codeNotify)
  720. {
  721. switch (id)
  722. {
  723. case IDM_CONFIG:
  724. State_OnMyConfig(hWnd);
  725. break;
  726. case IDM_ABOUT:
  727. State_OnMyAbout(hWnd);
  728. break;
  729. }
  730. }
  731. void State_OnMyMenu(HWND hWnd)
  732. {
  733. HMENU hMenu;
  734. POINT ptCurrent;
  735. TCHAR szBuffer[256];
  736. GetCursorPos(&ptCurrent);
  737. hMenu = CreatePopupMenu();
  738. LoadString(hInst, IDS_CONFIG, szBuffer, sizeof(szBuffer));
  739. AppendMenu(hMenu, MF_ENABLED, IDM_CONFIG, szBuffer);
  740. AppendMenu(hMenu, MF_SEPARATOR, 0, NULL);
  741. LoadString(hInst, IDS_ABOUT, szBuffer, sizeof(szBuffer));
  742. AppendMenu(hMenu, MF_ENABLED, IDM_ABOUT, szBuffer);
  743. TrackPopupMenu(hMenu, TPM_LEFTALIGN, ptCurrent.x, ptCurrent.y, 0, hWnd, NULL);
  744. DestroyMenu(hMenu);
  745. }
  746. void State_OnMyConfig(HWND hWnd)
  747. {
  748. HIMC hIMC;
  749. LPINPUTCONTEXT lpIMC;
  750. hIMC = (HIMC)GetWindowLongPtr(GetWindow(hWnd, GW_OWNER), IMMGWL_IMC);
  751. if (lpIMC = ImmLockIMC(hIMC))
  752. {
  753. ImeConfigure(0, lpIMC->hWnd, IME_CONFIG_GENERAL, NULL);
  754. ImmUnlockIMC(hIMC);
  755. }
  756. }
  757. void State_OnMyAbout(HWND hWnd)
  758. {
  759. HIMC hIMC;
  760. LPINPUTCONTEXT lpIMC;
  761. TCHAR szBuffer[256];
  762. hIMC = (HIMC)GetWindowLongPtr(GetWindow(hWnd, GW_OWNER), IMMGWL_IMC);
  763. if (lpIMC = ImmLockIMC(hIMC))
  764. {
  765. LoadString(hInst, IDS_PROGRAM, szBuffer, sizeof(szBuffer));
  766. ShellAbout(lpIMC->hWnd, szBuffer, NULL, LoadIcon(hInst, TEXT("IMEIcon")));
  767. ImmUnlockIMC(hIMC);
  768. }
  769. }
  770. LRESULT CALLBACK CompWndProc(HWND hWnd, UINT uMessage, WPARAM wParam, LPARAM lParam)
  771. {
  772. switch (uMessage)
  773. {
  774. HANDLE_DUMMYMSG(WM_IME_CHAR);
  775. HANDLE_DUMMYMSG(WM_IME_COMPOSITIONFULL);
  776. HANDLE_DUMMYMSG(WM_IME_COMPOSITION);
  777. HANDLE_DUMMYMSG(WM_IME_CONTROL);
  778. HANDLE_DUMMYMSG(WM_IME_NOTIFY);
  779. HANDLE_DUMMYMSG(WM_IME_SELECT);
  780. HANDLE_DUMMYMSG(WM_IME_SETCONTEXT);
  781. HANDLE_DUMMYMSG(WM_IME_STARTCOMPOSITION);
  782. HANDLE_DUMMYMSG(WM_IME_ENDCOMPOSITION);
  783. HANDLE_MSG(hWnd, WM_PAINT, Comp_OnPaint);
  784. }
  785. return DefWindowProc(hWnd, uMessage, wParam, lParam);
  786. }
  787. void Comp_OnPaint(HWND hWnd)
  788. {
  789. HDC hDC;
  790. HWND hWndUI;
  791. HIMC hIMC;
  792. LPINPUTCONTEXT lpIMC;
  793. LPCOMPOSITIONSTRING lpUICompStr;
  794. PAINTSTRUCT ps;
  795. HFONT hOldFont;
  796. int iSaveBkMode;
  797. hDC = BeginPaint(hWnd, &ps);
  798. hWndUI = GetWindow(hWnd, GW_OWNER);
  799. hIMC = (HIMC)GetWindowLongPtr(hWndUI, IMMGWL_IMC);
  800. lpIMC = ImmLockIMC(hIMC);
  801. if (lpIMC) {
  802. lpUICompStr = (LPCOMPOSITIONSTRING)ImmLockIMCC(lpIMC->hCompStr);
  803. if (lpUICompStr && lpUICompStr->dwCompStrLen)
  804. {
  805. DrawBitmap(hDC, 0, 0, hBMComp);
  806. iSaveBkMode = SetBkMode(hDC, TRANSPARENT);
  807. hOldFont = SelectObject(hDC, hFontFix);
  808. TextOut(hDC, 3, 3, (LPTSTR)lpUICompStr + lpUICompStr->dwCompStrOffset, 2);
  809. SelectObject(hDC, hOldFont);
  810. SetBkMode(hDC, iSaveBkMode);
  811. }
  812. ImmUnlockIMCC(lpIMC->hCompStr);
  813. ImmUnlockIMC(hIMC);
  814. }
  815. EndPaint(hWnd, &ps);
  816. }
  817. LRESULT CALLBACK CandWndProc(HWND hWnd, UINT uMessage, WPARAM wParam, LPARAM lParam)
  818. {
  819. switch (uMessage)
  820. {
  821. HANDLE_DUMMYMSG(WM_IME_CHAR);
  822. HANDLE_DUMMYMSG(WM_IME_COMPOSITIONFULL);
  823. HANDLE_DUMMYMSG(WM_IME_COMPOSITION);
  824. HANDLE_DUMMYMSG(WM_IME_CONTROL);
  825. HANDLE_DUMMYMSG(WM_IME_NOTIFY);
  826. HANDLE_DUMMYMSG(WM_IME_SELECT);
  827. HANDLE_DUMMYMSG(WM_IME_SETCONTEXT);
  828. HANDLE_DUMMYMSG(WM_IME_STARTCOMPOSITION);
  829. HANDLE_DUMMYMSG(WM_IME_ENDCOMPOSITION);
  830. HANDLE_MSG(hWnd, WM_SETCURSOR, Cand_OnSetCursor);
  831. HANDLE_MSG(hWnd, WM_PAINT, Cand_OnPaint);
  832. }
  833. return DefWindowProc(hWnd, uMessage, wParam, lParam);
  834. }
  835. BOOL Cand_OnSetCursor(HWND hWnd, HWND hWndCursor, UINT codeHitTest, UINT msg)
  836. {
  837. int iLoop;
  838. SetCursor(hIMECursor);
  839. switch (msg)
  840. {
  841. case WM_LBUTTONDOWN:
  842. GetCursorPos(&ptPos);
  843. ScreenToClient(hWnd, &ptPos);
  844. if (PtInRect((LPRECT)&rcCandCli, ptPos))
  845. {
  846. if (!PtInRect((LPRECT)&rcLArrow, ptPos)
  847. && !PtInRect((LPRECT)&rcRArrow, ptPos)
  848. && !PtInRect((LPRECT)&rcBtn[0], ptPos)
  849. && !PtInRect((LPRECT)&rcBtn[1], ptPos)
  850. && !PtInRect((LPRECT)&rcBtn[2], ptPos)
  851. && !PtInRect((LPRECT)&rcBtn[3], ptPos)
  852. && !PtInRect((LPRECT)&rcBtn[4], ptPos)
  853. && !PtInRect((LPRECT)&rcBtn[5], ptPos)
  854. && !PtInRect((LPRECT)&rcBtn[6], ptPos)
  855. && !PtInRect((LPRECT)&rcBtn[7], ptPos)
  856. && !PtInRect((LPRECT)&rcBtn[8], ptPos))
  857. MessageBeep(MB_ICONEXCLAMATION);
  858. }
  859. break;
  860. case WM_LBUTTONUP:
  861. GetCursorPos(&ptPos);
  862. ScreenToClient(hWnd, &ptPos);
  863. if (PtInRect((LPRECT)&rcLArrow, ptPos))
  864. {
  865. keybd_event(VK_LEFT, 0, 0, 0);
  866. keybd_event(VK_LEFT, 0, KEYEVENTF_KEYUP, 0);
  867. }
  868. else if (PtInRect((LPRECT)&rcRArrow, ptPos))
  869. {
  870. keybd_event(VK_RIGHT, 0, 0, 0);
  871. keybd_event(VK_RIGHT, 0, KEYEVENTF_KEYUP, 0);
  872. }
  873. else
  874. {
  875. for (iLoop = 0; iLoop < 9; iLoop++)
  876. if (PtInRect((LPRECT)&rcBtn[iLoop], ptPos))
  877. {
  878. keybd_event((BYTE)(iLoop + '1'), 0, 0, 0);
  879. keybd_event((BYTE)(iLoop + '1'), 0, KEYEVENTF_KEYUP, 0);
  880. break;
  881. }
  882. }
  883. break;
  884. }
  885. return TRUE;
  886. }
  887. void Cand_OnPaint(HWND hWnd)
  888. {
  889. HDC hDC;
  890. HWND hWndUI;
  891. HIMC hIMC;
  892. LPINPUTCONTEXT lpIMC;
  893. LPCANDIDATEINFO lpCandInfo;
  894. LPCANDIDATELIST lpCandList;
  895. LPTSTR lpCandStr;
  896. PAINTSTRUCT ps;
  897. HFONT hOldFont;
  898. DWORD iLoop, iStart;
  899. int iSaveBkMode;
  900. hDC = BeginPaint(hWnd, &ps);
  901. hWndUI = GetWindow(hWnd, GW_OWNER);
  902. hIMC = (HIMC)GetWindowLongPtr(hWndUI, IMMGWL_IMC);
  903. lpIMC = ImmLockIMC(hIMC);
  904. if (lpIMC != NULL) {
  905. lpCandInfo = (LPCANDIDATEINFO)ImmLockIMCC(lpIMC->hCandInfo);
  906. lpCandList = (LPCANDIDATELIST)((LPBYTE)lpCandInfo + sizeof(CANDIDATEINFO));
  907. if (lpCandInfo && lpCandList->dwCount)
  908. {
  909. hOldFont = SelectObject(hDC, hFontFix);
  910. DrawBitmap(hDC, 0, 0, hBMCand);
  911. iSaveBkMode = SetBkMode(hDC, TRANSPARENT);
  912. iStart = (lpCandList->dwSelection / lpCandList->dwPageSize) * lpCandList->dwPageSize;
  913. for (iLoop = 0; iLoop < 9 && iStart+iLoop < lpCandList->dwCount; iLoop++)
  914. {
  915. lpCandStr = (LPTSTR)lpCandList + lpCandList->dwOffset[iStart + iLoop];
  916. TextOut(hDC, rcBtn[iLoop].left + 10, rcBtn[iLoop].top +3, lpCandStr, 2);
  917. }
  918. SetBkMode(hDC, iSaveBkMode);
  919. for (iLoop = iLoop; iLoop < 9; iLoop++)
  920. DrawBitmap(hDC, rcBtn[iLoop].left + 3, rcBtn[iLoop].top + 6, hBMCandNum);
  921. if (iStart)
  922. DrawBitmap(hDC, 19, 8, hBMCandArr[0]);
  923. if (iStart + 9 < lpCandList->dwCount)
  924. DrawBitmap(hDC, 296, 8, hBMCandArr[1]);
  925. SelectObject(hDC, hOldFont);
  926. }
  927. ImmUnlockIMCC(lpIMC->hCandInfo);
  928. ImmUnlockIMC(hIMC);
  929. }
  930. EndPaint(hWnd, &ps);
  931. }
  932. LRESULT DoIMEControl(HWND hWnd, WPARAM wParam, LPARAM lParam)
  933. {
  934. HIMC hIMC;
  935. LPINPUTCONTEXT lpIMC;
  936. HGLOBAL hUIInst;
  937. LPUIINSTANCE lpUIInst;
  938. LPCANDIDATEFORM lpCandForm;
  939. LPLOGFONT lpLogFont;
  940. LOGFONT lfFont;
  941. LPCOMPOSITIONFORM lpCompForm;
  942. PPOINTS pPointS;
  943. RECT rcRect;
  944. LRESULT lRet = FALSE;
  945. switch (wParam)
  946. {
  947. case IMC_GETCANDIDATEPOS:
  948. hIMC = (HIMC)GetWindowLongPtr(hWnd, IMMGWL_IMC);
  949. if (hIMC && (lpIMC = ImmLockIMC(hIMC)))
  950. {
  951. lpCandForm = (LPCANDIDATEFORM)lParam;
  952. *lpCandForm = lpIMC->cfCandForm[0];
  953. hUIInst = (HGLOBAL)GetWindowLongPtr(hWnd, IMMGWL_PRIVATE);
  954. lpUIInst = (LPUIINSTANCE)GlobalLock(hUIInst);
  955. GetWindowRect(lpUIInst->rghWnd[CAND_WINDOW], (LPRECT)&rcRect);
  956. lpCandForm->ptCurrentPos.x = rcRect.left;
  957. lpCandForm->ptCurrentPos.y = rcRect.top;
  958. GlobalUnlock(hUIInst);
  959. ImmUnlockIMC(hIMC);
  960. }
  961. break;
  962. case IMC_GETCOMPOSITIONFONT:
  963. lpLogFont = (LPLOGFONT)lParam;
  964. if (GetObject(hFontFix, sizeof(lfFont), (LPVOID)&lfFont))
  965. *lpLogFont = lfFont;
  966. break;
  967. case IMC_GETCOMPOSITIONWINDOW:
  968. hIMC = (HIMC)GetWindowLongPtr(hWnd, IMMGWL_IMC);
  969. if (hIMC && (lpIMC = ImmLockIMC(hIMC)))
  970. {
  971. lpCompForm = (LPCOMPOSITIONFORM)lParam;
  972. *lpCompForm = lpIMC->cfCompForm;
  973. hUIInst = (HGLOBAL)GetWindowLongPtr(hWnd, IMMGWL_PRIVATE);
  974. lpUIInst = (LPUIINSTANCE)GlobalLock(hUIInst);
  975. GetWindowRect(lpUIInst->rghWnd[COMP_WINDOW], (LPRECT)&rcRect);
  976. lpCompForm->ptCurrentPos.x = rcRect.left;
  977. lpCompForm->ptCurrentPos.y = rcRect.top;
  978. GlobalUnlock(hUIInst);
  979. ImmUnlockIMC(hIMC);
  980. }
  981. break;
  982. case IMC_GETSTATUSWINDOWPOS:
  983. hUIInst = (HGLOBAL)GetWindowLongPtr(hWnd, IMMGWL_PRIVATE);
  984. lpUIInst = (LPUIINSTANCE)GlobalLock(hUIInst);
  985. GetWindowRect(lpUIInst->rghWnd[STATE_WINDOW], (LPRECT)&rcRect);
  986. pPointS = (PPOINTS)&lRet;
  987. pPointS->x = (short)rcRect.left;
  988. pPointS->y = (short)rcRect.top;
  989. GlobalUnlock(hUIInst);
  990. break;
  991. default:
  992. lRet = TRUE;
  993. }
  994. return lRet;
  995. }
  996. LRESULT DoIMENotify(HWND hWnd, WPARAM wParam, LPARAM lParam)
  997. {
  998. HIMC hIMC;
  999. LPINPUTCONTEXT lpIMC;
  1000. HGLOBAL hUIInst;
  1001. LPUIINSTANCE lpUIInst;
  1002. LPCANDIDATEINFO lpCandInfo;
  1003. DWORD fdwUIFlags;
  1004. POINT pt, ptTmp;
  1005. RECT rcTmp;
  1006. BOOL lRet = FALSE;
  1007. switch (wParam)
  1008. {
  1009. case IMN_OPENSTATUSWINDOW:
  1010. hUIInst = (HGLOBAL)GetWindowLongPtr(hWnd, IMMGWL_PRIVATE);
  1011. lpUIInst = (LPUIINSTANCE)GlobalLock(hUIInst);
  1012. fdwUIFlags = (DWORD)GetWindowLong(lpUIInst->rghWnd[STATE_WINDOW], UIGWL_FLAGS);
  1013. fdwUIFlags |= UIF_SHOWSTATUS;
  1014. SetWindowLong(lpUIInst->rghWnd[STATE_WINDOW], UIGWL_FLAGS, fdwUIFlags);
  1015. if (fWndOpen[STATE_WINDOW] != FALSE && GetWindowLongPtr(hWnd, IMMGWL_IMC)) {
  1016. ShowWindow(lpUIInst->rghWnd[STATE_WINDOW], SW_SHOWNOACTIVATE);
  1017. }
  1018. GlobalUnlock(hUIInst);
  1019. break;
  1020. case IMN_CLOSESTATUSWINDOW:
  1021. hUIInst = (HGLOBAL)GetWindowLongPtr(hWnd, IMMGWL_PRIVATE);
  1022. lpUIInst = (LPUIINSTANCE)GlobalLock(hUIInst);
  1023. fdwUIFlags = (DWORD)GetWindowLong(lpUIInst->rghWnd[STATE_WINDOW], UIGWL_FLAGS);
  1024. fdwUIFlags &= ~UIF_SHOWSTATUS;
  1025. SetWindowLong(lpUIInst->rghWnd[STATE_WINDOW], UIGWL_FLAGS, fdwUIFlags);
  1026. ShowWindow(lpUIInst->rghWnd[STATE_WINDOW], SW_HIDE);
  1027. GlobalUnlock(hUIInst);
  1028. break;
  1029. case IMN_CHANGECANDIDATE:
  1030. hUIInst = (HGLOBAL)GetWindowLongPtr(hWnd, IMMGWL_PRIVATE);
  1031. lpUIInst = (LPUIINSTANCE)GlobalLock(hUIInst);
  1032. InvalidateRect(lpUIInst->rghWnd[CAND_WINDOW], NULL, TRUE);
  1033. GlobalUnlock(hUIInst);
  1034. break;
  1035. case IMN_CLOSECANDIDATE:
  1036. hIMC = (HIMC)GetWindowLongPtr(hWnd, IMMGWL_IMC);
  1037. lpIMC = ImmLockIMC(hIMC);
  1038. if (lpIMC != NULL) {
  1039. hUIInst = (HGLOBAL)GetWindowLongPtr(hWnd, IMMGWL_PRIVATE);
  1040. lpUIInst = (LPUIINSTANCE)GlobalLock(hUIInst);
  1041. if (lpUIInst == NULL) {
  1042. ImmUnlockIMC(hIMC);
  1043. break;
  1044. }
  1045. lpIMC->hCandInfo = ImmReSizeIMCC(lpIMC->hCandInfo, sizeof(CANDIDATEINFO));
  1046. lpCandInfo = (LPCANDIDATEINFO)ImmLockIMCC(lpIMC->hCandInfo);
  1047. lpCandInfo->dwSize = sizeof(CANDIDATEINFO);
  1048. lpCandInfo->dwCount = 0;
  1049. ImmUnlockIMCC(lpIMC->hCandInfo);
  1050. InvalidateRect(lpUIInst->rghWnd[STATE_WINDOW], NULL, TRUE);
  1051. ShowWindow(lpUIInst->rghWnd[CAND_WINDOW], SW_HIDE);
  1052. GlobalUnlock(hUIInst);
  1053. ImmUnlockIMC(hIMC);
  1054. }
  1055. break;
  1056. case IMN_OPENCANDIDATE:
  1057. hIMC = (HIMC)GetWindowLongPtr(hWnd, IMMGWL_IMC);
  1058. lpIMC = ImmLockIMC(hIMC);
  1059. if (lpIMC != NULL) {
  1060. hUIInst = (HGLOBAL)GetWindowLongPtr(hWnd, IMMGWL_PRIVATE);
  1061. lpUIInst = (LPUIINSTANCE)GlobalLock(hUIInst);
  1062. if (lpUIInst == NULL) {
  1063. ImmUnlockIMC(hIMC);
  1064. break;
  1065. }
  1066. InvalidateRect(lpUIInst->rghWnd[STATE_WINDOW], NULL, TRUE);
  1067. ShowWindow(lpUIInst->rghWnd[CAND_WINDOW], fWndOpen[CAND_WINDOW]? SW_SHOWNOACTIVATE: SW_HIDE);
  1068. UpdateWindow(lpUIInst->rghWnd[STATE_WINDOW]);
  1069. UpdateWindow(lpUIInst->rghWnd[CAND_WINDOW]);
  1070. GlobalUnlock(hUIInst);
  1071. ImmUnlockIMC(hIMC);
  1072. }
  1073. break;
  1074. case IMN_SETCONVERSIONMODE:
  1075. case IMN_SETOPENSTATUS:
  1076. hUIInst = (HGLOBAL)GetWindowLongPtr(hWnd, IMMGWL_PRIVATE);
  1077. lpUIInst = (LPUIINSTANCE)GlobalLock(hUIInst);
  1078. if (lpUIInst != NULL) {
  1079. InvalidateRect(lpUIInst->rghWnd[STATE_WINDOW], NULL, TRUE);
  1080. GlobalUnlock(hUIInst);
  1081. }
  1082. break;
  1083. case IMN_SETCANDIDATEPOS:
  1084. hIMC = (HIMC)GetWindowLongPtr(hWnd, IMMGWL_IMC);
  1085. lpIMC = ImmLockIMC(hIMC);
  1086. if (lpIMC == NULL)
  1087. break;
  1088. hUIInst = (HGLOBAL)GetWindowLongPtr(hWnd, IMMGWL_PRIVATE);
  1089. lpUIInst = (LPUIINSTANCE)GlobalLock(hUIInst);
  1090. if (lpUIInst == NULL) {
  1091. ImmUnlockIMC(hIMC);
  1092. break;
  1093. }
  1094. if (lpIMC->cfCandForm[0].dwIndex == -1)
  1095. pt = ptCand;
  1096. else
  1097. {
  1098. switch (lpIMC->cfCandForm[0].dwStyle)
  1099. {
  1100. case CFS_CANDIDATEPOS:
  1101. pt = lpIMC->cfCandForm[0].ptCurrentPos;
  1102. ClientToScreen(lpIMC->hWnd, &pt);
  1103. if (pt.x < rcScreen.left)
  1104. pt.x = rcScreen.left;
  1105. else if (pt.x > rcScreen.right - CANDXSIZE)
  1106. pt.x = rcScreen.right - CANDXSIZE;
  1107. if (pt.y < rcScreen.top)
  1108. pt.y = rcScreen.top;
  1109. else if (pt.y > rcScreen.bottom - CANDYSIZE)
  1110. pt.y = rcScreen.bottom - CANDYSIZE;
  1111. break;
  1112. case CFS_EXCLUDE:
  1113. pt = lpIMC->cfCandForm[0].ptCurrentPos;
  1114. rcTmp.left = pt.x;
  1115. rcTmp.top = pt.y;
  1116. rcTmp.right = pt.x + CANDXSIZE;
  1117. rcTmp.bottom = pt.y + CANDYSIZE;
  1118. ClientToScreen(lpIMC->hWnd, &pt);
  1119. if (pt.x < rcScreen.left)
  1120. pt.x = rcScreen.left;
  1121. else if (pt.x > rcScreen.right - CANDXSIZE)
  1122. pt.x = rcScreen.right - CANDXSIZE;
  1123. if (pt.y < rcScreen.top)
  1124. pt.y = rcScreen.top;
  1125. else if (pt.y > rcScreen.bottom - CANDYSIZE)
  1126. pt.y = rcScreen.bottom - CANDYSIZE;
  1127. if (IntersectRect(&rcTmp, &rcTmp, &lpIMC->cfCandForm[0].rcArea))
  1128. {
  1129. ptTmp.x = lpIMC->cfCandForm[0].rcArea.right;
  1130. ptTmp.y = lpIMC->cfCandForm[0].rcArea.bottom;
  1131. ClientToScreen(lpIMC->hWnd, &ptTmp);
  1132. pt.y = (ptTmp.y < rcScreen.bottom - CANDYSIZE)? ptTmp.y:
  1133. ptTmp.y - lpIMC->cfCandForm[0].rcArea.bottom
  1134. + lpIMC->cfCandForm[0].rcArea.top - CANDYSIZE;
  1135. }
  1136. break;
  1137. default:
  1138. pt = ptCand;
  1139. }
  1140. }
  1141. MoveWindow(lpUIInst->rghWnd[CAND_WINDOW], pt.x, pt.y, CANDXSIZE, CANDYSIZE, TRUE);
  1142. GlobalUnlock(hUIInst);
  1143. ImmUnlockIMC(hIMC);
  1144. break;
  1145. case IMN_SETCOMPOSITIONWINDOW:
  1146. hIMC = (HIMC)GetWindowLongPtr(hWnd, IMMGWL_IMC);
  1147. lpIMC = ImmLockIMC(hIMC);
  1148. if (lpIMC == NULL)
  1149. break;
  1150. hUIInst = (HGLOBAL)GetWindowLongPtr(hWnd, IMMGWL_PRIVATE);
  1151. lpUIInst = (LPUIINSTANCE)GlobalLock(hUIInst);
  1152. if (lpUIInst == NULL) {
  1153. ImmUnlockIMC(hIMC);
  1154. break;
  1155. }
  1156. if (lpIMC->cfCompForm.dwStyle & CFS_RECT)
  1157. {
  1158. pt.x = lpIMC->cfCompForm.rcArea.left;
  1159. pt.y = lpIMC->cfCompForm.rcArea.top;
  1160. ClientToScreen(lpIMC->hWnd, &pt);
  1161. }
  1162. else if (lpIMC->cfCompForm.dwStyle & CFS_POINT)
  1163. {
  1164. pt = lpIMC->cfCompForm.ptCurrentPos;
  1165. ClientToScreen(lpIMC->hWnd, &pt);
  1166. }
  1167. else // For CFS_DEFAULT
  1168. pt = lpIMC->cfCompForm.ptCurrentPos = ptComp;
  1169. MoveWindow(lpUIInst->rghWnd[COMP_WINDOW], pt.x, pt.y, COMPSIZE, COMPSIZE, TRUE);
  1170. GlobalUnlock(hUIInst);
  1171. ImmUnlockIMC(hIMC);
  1172. break;
  1173. case IMN_SETSTATUSWINDOWPOS:
  1174. hIMC = (HIMC)GetWindowLongPtr(hWnd, IMMGWL_IMC);
  1175. lpIMC = ImmLockIMC(hIMC);
  1176. if (lpIMC == NULL)
  1177. break;
  1178. hUIInst = (HGLOBAL)GetWindowLongPtr(hWnd, IMMGWL_PRIVATE);
  1179. lpUIInst = (LPUIINSTANCE)GlobalLock(hUIInst);
  1180. if (lpUIInst == NULL) {
  1181. ImmUnlockIMC(hIMC);
  1182. break;
  1183. }
  1184. MoveWindow(lpUIInst->rghWnd[STATE_WINDOW], lpIMC->ptStatusWndPos.x,
  1185. lpIMC->ptStatusWndPos.y, STATEXSIZE, STATEYSIZE, TRUE);
  1186. fdwUIFlags = (DWORD)GetWindowLong(lpUIInst->rghWnd[STATE_WINDOW], UIGWL_FLAGS);
  1187. fdwUIFlags |= UIF_PRIVATEPOS;
  1188. SetWindowLong(lpUIInst->rghWnd[STATE_WINDOW], UIGWL_FLAGS, fdwUIFlags);
  1189. GlobalUnlock(hUIInst);
  1190. ImmUnlockIMC(hIMC);
  1191. break;
  1192. default:
  1193. lRet = TRUE;
  1194. }
  1195. return lRet;
  1196. UNREFERENCED_PARAMETER(lParam);
  1197. }