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.

911 lines
31 KiB

  1. /*++
  2. Copyright (c) 1990-1998 Microsoft Corporation, All Rights Reserved
  3. Module Name:
  4. UI.C
  5. ++*/
  6. /**********************************************************************/
  7. #include "windows.h"
  8. #include "immdev.h"
  9. #include "fakeime.h"
  10. void PASCAL ShowUIWindows(HWND hWnd, BOOL fFlag);
  11. #ifdef DEBUG
  12. void PASCAL DumpUIExtra(LPUIEXTRA lpUIExtra);
  13. #endif
  14. #define CS_FAKEIME (CS_VREDRAW | CS_HREDRAW | CS_DBLCLKS | CS_IME)
  15. /**********************************************************************/
  16. /* */
  17. /* IMERegisterClass() */
  18. /* */
  19. /* This function is called by IMMInquire. */
  20. /* Register the classes for the child windows. */
  21. /* Create global GDI objects. */
  22. /* */
  23. /**********************************************************************/
  24. BOOL IMERegisterClass( hInstance )
  25. HANDLE hInstance;
  26. {
  27. WNDCLASSEX wc;
  28. //
  29. // register class of UI window.
  30. //
  31. wc.cbSize = sizeof(WNDCLASSEX);
  32. wc.style = CS_FAKEIME;
  33. wc.lpfnWndProc = FAKEIMEWndProc;
  34. wc.cbClsExtra = 0;
  35. wc.cbWndExtra = 8;
  36. wc.hInstance = hInstance;
  37. wc.hCursor = LoadCursor( NULL, IDC_ARROW );
  38. wc.hIcon = NULL;
  39. wc.lpszMenuName = (LPTSTR)NULL;
  40. wc.lpszClassName = (LPTSTR)szUIClassName;
  41. wc.hbrBackground = NULL;
  42. wc.hIconSm = NULL;
  43. if( !RegisterClassEx( (LPWNDCLASSEX)&wc ) )
  44. return FALSE;
  45. //
  46. // register class of composition window.
  47. //
  48. wc.cbSize = sizeof(WNDCLASSEX);
  49. wc.style = CS_FAKEIME;
  50. wc.lpfnWndProc = CompStrWndProc;
  51. wc.cbClsExtra = 0;
  52. wc.cbWndExtra = UIEXTRASIZE;
  53. wc.hInstance = hInstance;
  54. wc.hCursor = LoadCursor( NULL, IDC_ARROW );
  55. wc.hIcon = NULL;
  56. wc.lpszMenuName = (LPTSTR)NULL;
  57. wc.lpszClassName = (LPTSTR)szCompStrClassName;
  58. wc.hbrBackground = NULL;
  59. wc.hIconSm = NULL;
  60. if( !RegisterClassEx( (LPWNDCLASSEX)&wc ) )
  61. return FALSE;
  62. //
  63. // register class of candidate window.
  64. //
  65. wc.cbSize = sizeof(WNDCLASSEX);
  66. wc.style = CS_FAKEIME;
  67. wc.lpfnWndProc = CandWndProc;
  68. wc.cbClsExtra = 0;
  69. wc.cbWndExtra = UIEXTRASIZE;
  70. wc.hInstance = hInstance;
  71. wc.hCursor = LoadCursor( NULL, IDC_ARROW );
  72. wc.hIcon = NULL;
  73. wc.lpszMenuName = (LPTSTR)NULL;
  74. wc.lpszClassName = (LPTSTR)szCandClassName;
  75. wc.hbrBackground = GetStockObject(LTGRAY_BRUSH);
  76. wc.hIconSm = NULL;
  77. if( !RegisterClassEx( (LPWNDCLASSEX)&wc ) )
  78. return FALSE;
  79. //
  80. // register class of status window.
  81. //
  82. wc.cbSize = sizeof(WNDCLASSEX);
  83. wc.style = CS_FAKEIME;
  84. wc.lpfnWndProc = StatusWndProc;
  85. wc.cbClsExtra = 0;
  86. wc.cbWndExtra = UIEXTRASIZE;
  87. wc.hInstance = hInstance;
  88. wc.hCursor = LoadCursor( NULL, IDC_ARROW );
  89. wc.hIcon = NULL;
  90. wc.lpszMenuName = (LPTSTR)NULL;
  91. wc.lpszClassName = (LPTSTR)szStatusClassName;
  92. wc.hbrBackground = NULL;
  93. wc.hbrBackground = GetStockObject(LTGRAY_BRUSH);
  94. wc.hIconSm = NULL;
  95. if( !RegisterClassEx( (LPWNDCLASSEX)&wc ) )
  96. return FALSE;
  97. //
  98. // register class of guideline window.
  99. //
  100. wc.cbSize = sizeof(WNDCLASSEX);
  101. wc.style = CS_FAKEIME;
  102. wc.lpfnWndProc = GuideWndProc;
  103. wc.cbClsExtra = 0;
  104. wc.cbWndExtra = UIEXTRASIZE;
  105. wc.hInstance = hInstance;
  106. wc.hCursor = LoadCursor( NULL, IDC_ARROW );
  107. wc.hIcon = NULL;
  108. wc.lpszMenuName = (LPTSTR)NULL;
  109. wc.lpszClassName = (LPTSTR)szGuideClassName;
  110. wc.hbrBackground = NULL;
  111. //wc.hbrBackground = GetStockObject(LTGRAY_BRUSH);
  112. wc.hIconSm = NULL;
  113. if( !RegisterClassEx( (LPWNDCLASSEX)&wc ) )
  114. return FALSE;
  115. return TRUE;
  116. }
  117. /**********************************************************************/
  118. /* */
  119. /* FAKEIMEWndProc() */
  120. /* */
  121. /* IME UI window procedure */
  122. /* */
  123. /**********************************************************************/
  124. LRESULT CALLBACK FAKEIMEWndProc( hWnd, message, wParam, lParam )
  125. HWND hWnd;
  126. UINT message;
  127. WPARAM wParam;
  128. LPARAM lParam;
  129. {
  130. HIMC hUICurIMC;
  131. LPINPUTCONTEXT lpIMC;
  132. LPUIEXTRA lpUIExtra;
  133. HGLOBAL hUIExtra;
  134. LONG lRet = 0L;
  135. int i;
  136. hUICurIMC = (HIMC)GetWindowLongPtr(hWnd,IMMGWLP_IMC);
  137. //
  138. // Even if there is no current UI. these messages should not be pass to
  139. // DefWindowProc().
  140. //
  141. if (!hUICurIMC)
  142. {
  143. switch (message)
  144. {
  145. case WM_IME_STARTCOMPOSITION:
  146. case WM_IME_ENDCOMPOSITION:
  147. case WM_IME_COMPOSITION:
  148. case WM_IME_NOTIFY:
  149. case WM_IME_CONTROL:
  150. case WM_IME_COMPOSITIONFULL:
  151. case WM_IME_SELECT:
  152. case WM_IME_CHAR:
  153. #ifdef _DEBUG
  154. {
  155. TCHAR szDev[80];
  156. OutputDebugString((LPTSTR)TEXT("Why hUICurIMC is NULL????\r\n"));
  157. wsprintf((LPTSTR)szDev,TEXT("\thWnd is %x\r\n"),hWnd);
  158. OutputDebugString((LPTSTR)szDev);
  159. wsprintf((LPTSTR)szDev,TEXT("\tmessage is %x\r\n"),message);
  160. OutputDebugString((LPTSTR)szDev);
  161. wsprintf((LPTSTR)szDev,TEXT("\twParam is %x\r\n"),wParam);
  162. OutputDebugString((LPTSTR)szDev);
  163. wsprintf((LPTSTR)szDev,TEXT("\tlParam is %x\r\n"),lParam);
  164. OutputDebugString((LPTSTR)szDev);
  165. }
  166. #endif
  167. return 0L;
  168. default:
  169. break;
  170. }
  171. }
  172. switch (message)
  173. {
  174. case WM_CREATE:
  175. //
  176. // Allocate UI's extra memory block.
  177. //
  178. hUIExtra = GlobalAlloc(GHND,sizeof(UIEXTRA));
  179. lpUIExtra = (LPUIEXTRA)GlobalLock(hUIExtra);
  180. //
  181. // Initialize the extra memory block.
  182. //
  183. lpUIExtra->uiStatus.pt.x = -1;
  184. lpUIExtra->uiStatus.pt.y = -1;
  185. lpUIExtra->uiDefComp.pt.x = -1;
  186. lpUIExtra->uiDefComp.pt.y = -1;
  187. lpUIExtra->uiCand.pt.x = -1;
  188. lpUIExtra->uiCand.pt.y = -1;
  189. lpUIExtra->uiGuide.pt.x = -1;
  190. lpUIExtra->uiGuide.pt.y = -1;
  191. lpUIExtra->hFont = (HFONT)NULL;
  192. GlobalUnlock(hUIExtra);
  193. SetWindowLongPtr(hWnd,IMMGWLP_PRIVATE,(LONG_PTR)hUIExtra);
  194. break;
  195. case WM_IME_SETCONTEXT:
  196. if (wParam)
  197. {
  198. hUIExtra = (HGLOBAL)GetWindowLongPtr(hWnd,IMMGWLP_PRIVATE);
  199. lpUIExtra = (LPUIEXTRA)GlobalLock(hUIExtra);
  200. lpUIExtra->hIMC = hUICurIMC;
  201. if (hUICurIMC)
  202. {
  203. LPINPUTCONTEXT lpIMCT = NULL;
  204. //
  205. // input context was chenged.
  206. // if there are the child windows, the diplay have to be
  207. // updated.
  208. //
  209. lpIMC = ImmLockIMC(hUICurIMC);
  210. if (lpIMC)
  211. {
  212. LPCOMPOSITIONSTRING lpCompStr;
  213. LPCANDIDATEINFO lpCandInfo;
  214. lpCompStr = (LPCOMPOSITIONSTRING)ImmLockIMCC(lpIMC->hCompStr);
  215. lpCandInfo = (LPCANDIDATEINFO)ImmLockIMCC(lpIMC->hCandInfo);
  216. if (IsWindow(lpUIExtra->uiCand.hWnd))
  217. HideCandWindow(lpUIExtra);
  218. if (lParam & ISC_SHOWUICANDIDATEWINDOW)
  219. {
  220. if (lpCandInfo->dwCount)
  221. {
  222. CreateCandWindow(hWnd,lpUIExtra,lpIMC );
  223. ResizeCandWindow(lpUIExtra,lpIMC);
  224. MoveCandWindow(hWnd,lpIMC,lpUIExtra,FALSE);
  225. }
  226. }
  227. if (IsWindow(lpUIExtra->uiDefComp.hWnd))
  228. HideCompWindow(lpUIExtra);
  229. if (lParam & ISC_SHOWUICANDIDATEWINDOW)
  230. {
  231. if (lpCompStr->dwCompStrLen)
  232. {
  233. CreateCompWindow(hWnd,lpUIExtra,lpIMC );
  234. MoveCompWindow(lpUIExtra,lpIMC);
  235. }
  236. }
  237. ImmUnlockIMCC(lpIMC->hCompStr);
  238. ImmUnlockIMCC(lpIMC->hCandInfo);
  239. }
  240. else
  241. {
  242. HideCandWindow(lpUIExtra);
  243. HideCompWindow(lpUIExtra);
  244. }
  245. UpdateStatusWindow(lpUIExtra);
  246. ImmUnlockIMC(hUICurIMC);
  247. }
  248. else // it is NULL input context.
  249. {
  250. HideCandWindow(lpUIExtra);
  251. HideCompWindow(lpUIExtra);
  252. }
  253. GlobalUnlock(hUIExtra);
  254. }
  255. //else
  256. // ShowUIWindows(hWnd, FALSE);
  257. break;
  258. case WM_IME_STARTCOMPOSITION:
  259. //
  260. // Start composition! Ready to display the composition string.
  261. //
  262. hUIExtra = (HGLOBAL)GetWindowLongPtr(hWnd,IMMGWLP_PRIVATE);
  263. lpUIExtra = (LPUIEXTRA)GlobalLock(hUIExtra);
  264. lpIMC = ImmLockIMC(hUICurIMC);
  265. CreateCompWindow(hWnd,lpUIExtra,lpIMC );
  266. ImmUnlockIMC(hUICurIMC);
  267. GlobalUnlock(hUIExtra);
  268. break;
  269. case WM_IME_COMPOSITION:
  270. //
  271. // Update to display the composition string.
  272. //
  273. lpIMC = ImmLockIMC(hUICurIMC);
  274. hUIExtra = (HGLOBAL)GetWindowLongPtr(hWnd,IMMGWLP_PRIVATE);
  275. lpUIExtra = (LPUIEXTRA)GlobalLock(hUIExtra);
  276. MoveCompWindow(lpUIExtra,lpIMC);
  277. MoveCandWindow(hWnd,lpIMC,lpUIExtra, TRUE);
  278. GlobalUnlock(hUIExtra);
  279. ImmUnlockIMC(hUICurIMC);
  280. break;
  281. case WM_IME_ENDCOMPOSITION:
  282. //
  283. // Finish to display the composition string.
  284. //
  285. hUIExtra = (HGLOBAL)GetWindowLongPtr(hWnd,IMMGWLP_PRIVATE);
  286. lpUIExtra = (LPUIEXTRA)GlobalLock(hUIExtra);
  287. HideCompWindow(lpUIExtra);
  288. GlobalUnlock(hUIExtra);
  289. break;
  290. case WM_IME_COMPOSITIONFULL:
  291. break;
  292. case WM_IME_SELECT:
  293. if (wParam)
  294. {
  295. hUIExtra = (HGLOBAL)GetWindowLongPtr(hWnd,IMMGWLP_PRIVATE);
  296. lpUIExtra = (LPUIEXTRA)GlobalLock(hUIExtra);
  297. lpUIExtra->hIMC = hUICurIMC;
  298. GlobalUnlock(hUIExtra);
  299. }
  300. break;
  301. case WM_IME_CONTROL:
  302. lRet = ControlCommand(hUICurIMC, hWnd,message,wParam,lParam);
  303. break;
  304. case WM_IME_NOTIFY:
  305. lRet = NotifyCommand(hUICurIMC, hWnd,message,wParam,lParam);
  306. break;
  307. case WM_DESTROY:
  308. hUIExtra = (HGLOBAL)GetWindowLongPtr(hWnd,IMMGWLP_PRIVATE);
  309. lpUIExtra = (LPUIEXTRA)GlobalLock(hUIExtra);
  310. if (IsWindow(lpUIExtra->uiStatus.hWnd))
  311. DestroyWindow(lpUIExtra->uiStatus.hWnd);
  312. if (IsWindow(lpUIExtra->uiCand.hWnd))
  313. DestroyWindow(lpUIExtra->uiCand.hWnd);
  314. if (IsWindow(lpUIExtra->uiDefComp.hWnd))
  315. DestroyWindow(lpUIExtra->uiDefComp.hWnd);
  316. for (i = 0; i < MAXCOMPWND; i++)
  317. {
  318. if (IsWindow(lpUIExtra->uiComp[i].hWnd))
  319. DestroyWindow(lpUIExtra->uiComp[i].hWnd);
  320. }
  321. if (IsWindow(lpUIExtra->uiGuide.hWnd))
  322. DestroyWindow(lpUIExtra->uiGuide.hWnd);
  323. if (lpUIExtra->hFont)
  324. DeleteObject(lpUIExtra->hFont);
  325. GlobalUnlock(hUIExtra);
  326. GlobalFree(hUIExtra);
  327. break;
  328. case WM_UI_STATEMOVE:
  329. //
  330. // Set the position of the status window to UIExtra.
  331. // This message is sent by the status window.
  332. //
  333. hUIExtra = (HGLOBAL)GetWindowLongPtr(hWnd,IMMGWLP_PRIVATE);
  334. lpUIExtra = (LPUIEXTRA)GlobalLock(hUIExtra);
  335. lpUIExtra->uiStatus.pt.x = (long)LOWORD(lParam);
  336. lpUIExtra->uiStatus.pt.y = (long)HIWORD(lParam);
  337. GlobalUnlock(hUIExtra);
  338. break;
  339. case WM_UI_DEFCOMPMOVE:
  340. //
  341. // Set the position of the composition window to UIExtra.
  342. // This message is sent by the composition window.
  343. //
  344. hUIExtra = (HGLOBAL)GetWindowLongPtr(hWnd,IMMGWLP_PRIVATE);
  345. lpUIExtra = (LPUIEXTRA)GlobalLock(hUIExtra);
  346. if (!lpUIExtra->dwCompStyle)
  347. {
  348. lpUIExtra->uiDefComp.pt.x = (long)LOWORD(lParam);
  349. lpUIExtra->uiDefComp.pt.y = (long)HIWORD(lParam);
  350. }
  351. GlobalUnlock(hUIExtra);
  352. break;
  353. case WM_UI_CANDMOVE:
  354. //
  355. // Set the position of the candidate window to UIExtra.
  356. // This message is sent by the candidate window.
  357. //
  358. hUIExtra = (HGLOBAL)GetWindowLongPtr(hWnd,IMMGWLP_PRIVATE);
  359. lpUIExtra = (LPUIEXTRA)GlobalLock(hUIExtra);
  360. lpUIExtra->uiCand.pt.x = (long)LOWORD(lParam);
  361. lpUIExtra->uiCand.pt.y = (long)HIWORD(lParam);
  362. GlobalUnlock(hUIExtra);
  363. break;
  364. case WM_UI_GUIDEMOVE:
  365. //
  366. // Set the position of the status window to UIExtra.
  367. // This message is sent by the status window.
  368. //
  369. hUIExtra = (HGLOBAL)GetWindowLongPtr(hWnd,IMMGWLP_PRIVATE);
  370. lpUIExtra = (LPUIEXTRA)GlobalLock(hUIExtra);
  371. lpUIExtra->uiGuide.pt.x = (long)LOWORD(lParam);
  372. lpUIExtra->uiGuide.pt.y = (long)HIWORD(lParam);
  373. GlobalUnlock(hUIExtra);
  374. break;
  375. default:
  376. return DefWindowProc(hWnd,message,wParam,lParam);
  377. }
  378. return lRet;
  379. }
  380. int PASCAL GetCompFontHeight(LPUIEXTRA lpUIExtra)
  381. {
  382. HDC hIC;
  383. HFONT hOldFont = 0;
  384. SIZE sz;
  385. hIC = CreateIC(TEXT("DISPLAY"),NULL,NULL,NULL);
  386. if (lpUIExtra->hFont)
  387. hOldFont = SelectObject(hIC,lpUIExtra->hFont);
  388. GetTextExtentPoint(hIC,TEXT("A"),1,&sz);
  389. if (hOldFont)
  390. SelectObject(hIC,hOldFont);
  391. DeleteDC(hIC);
  392. return sz.cy;
  393. }
  394. /**********************************************************************/
  395. /* */
  396. /* NotifyCommand() */
  397. /* */
  398. /* Handle WM_IME_NOTIFY messages. */
  399. /* */
  400. /**********************************************************************/
  401. LONG PASCAL NotifyCommand(HIMC hUICurIMC, HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
  402. {
  403. LONG lRet = 0L;
  404. LPINPUTCONTEXT lpIMC;
  405. HGLOBAL hUIExtra;
  406. LPUIEXTRA lpUIExtra;
  407. RECT rc;
  408. LOGFONT lf;
  409. if (!(lpIMC = ImmLockIMC(hUICurIMC)))
  410. return 0L;
  411. hUIExtra = (HGLOBAL)GetWindowLongPtr(hWnd,IMMGWLP_PRIVATE);
  412. lpUIExtra = (LPUIEXTRA)GlobalLock(hUIExtra);
  413. switch (wParam)
  414. {
  415. case IMN_CLOSESTATUSWINDOW:
  416. if (IsWindow(lpUIExtra->uiStatus.hWnd))
  417. {
  418. GetWindowRect(lpUIExtra->uiStatus.hWnd,(LPRECT)&rc);
  419. lpUIExtra->uiStatus.pt.x = rc.left;
  420. lpUIExtra->uiStatus.pt.y = rc.top;
  421. ShowWindow(lpUIExtra->uiStatus.hWnd,SW_HIDE);
  422. lpUIExtra->uiStatus.bShow = FALSE;
  423. }
  424. break;
  425. case IMN_OPENSTATUSWINDOW:
  426. if (lpUIExtra->uiStatus.pt.x == -1)
  427. {
  428. GetWindowRect(lpIMC->hWnd,&rc);
  429. lpUIExtra->uiStatus.pt.x = rc.right + 1;
  430. lpUIExtra->uiStatus.pt.y = rc.top;
  431. }
  432. if (!IsWindow(lpUIExtra->uiStatus.hWnd))
  433. {
  434. lpUIExtra->uiStatus.hWnd =
  435. CreateWindowEx( WS_EX_WINDOWEDGE | WS_EX_DLGMODALFRAME,
  436. (LPTSTR)szStatusClassName,NULL,
  437. WS_DISABLED | WS_POPUP | WS_BORDER ,
  438. lpUIExtra->uiStatus.pt.x,
  439. lpUIExtra->uiStatus.pt.y,
  440. BTX * 3 + 2 * GetSystemMetrics(SM_CXBORDER)
  441. + 2 * GetSystemMetrics(SM_CXEDGE),
  442. BTX + GetSystemMetrics(SM_CYSMCAPTION)
  443. + 2 * GetSystemMetrics(SM_CYBORDER)
  444. + 2 * GetSystemMetrics(SM_CYEDGE),
  445. hWnd,NULL,hInst,NULL);
  446. }
  447. ShowWindow(lpUIExtra->uiStatus.hWnd,SW_SHOWNOACTIVATE);
  448. lpUIExtra->uiStatus.bShow = TRUE;
  449. SetWindowLongPtr(lpUIExtra->uiStatus.hWnd,FIGWL_SVRWND,(LONG_PTR)hWnd);
  450. break;
  451. case IMN_SETCONVERSIONMODE:
  452. UpdateStatusWindow(lpUIExtra);
  453. break;
  454. case IMN_SETSENTENCEMODE:
  455. break;
  456. case IMN_SETCOMPOSITIONFONT:
  457. #if defined(UNICODE)
  458. lf = lpIMC->lfFont.W;
  459. #else
  460. lf = lpIMC->lfFont.A;
  461. #endif
  462. if (lpUIExtra->hFont)
  463. DeleteObject(lpUIExtra->hFont);
  464. if (lf.lfEscapement == 2700)
  465. lpUIExtra->bVertical = TRUE;
  466. else
  467. {
  468. lf.lfEscapement = 0;
  469. lpUIExtra->bVertical = FALSE;
  470. }
  471. //
  472. // if current font can't display Japanese characters,
  473. // try to find Japanese font
  474. //
  475. if (lf.lfCharSet != NATIVE_CHARSET) {
  476. lf.lfCharSet = NATIVE_CHARSET;
  477. lf.lfFaceName[0] = TEXT('\0');
  478. }
  479. lpUIExtra->hFont = CreateFontIndirect((LPLOGFONT)&lf);
  480. SetFontCompWindow(lpUIExtra);
  481. MoveCompWindow(lpUIExtra,lpIMC);
  482. break;
  483. case IMN_SETOPENSTATUS:
  484. UpdateStatusWindow(lpUIExtra);
  485. break;
  486. case IMN_OPENCANDIDATE:
  487. CreateCandWindow(hWnd,lpUIExtra,lpIMC );
  488. break;
  489. case IMN_CHANGECANDIDATE:
  490. ResizeCandWindow(lpUIExtra,lpIMC);
  491. MoveCandWindow(hWnd,lpIMC,lpUIExtra, FALSE);
  492. break;
  493. case IMN_CLOSECANDIDATE:
  494. HideCandWindow(lpUIExtra);
  495. break;
  496. case IMN_GUIDELINE:
  497. if (ImmGetGuideLine(hUICurIMC,GGL_LEVEL,NULL,0))
  498. {
  499. if (!IsWindow(lpUIExtra->uiGuide.hWnd))
  500. {
  501. HDC hdcIC;
  502. TEXTMETRIC tm;
  503. int dx,dy;
  504. if (lpUIExtra->uiGuide.pt.x == -1)
  505. {
  506. GetWindowRect(lpIMC->hWnd,&rc);
  507. lpUIExtra->uiGuide.pt.x = rc.left;
  508. lpUIExtra->uiGuide.pt.y = rc.bottom;
  509. }
  510. hdcIC = CreateIC(TEXT("DISPLAY"),NULL,NULL,NULL);
  511. GetTextMetrics(hdcIC,&tm);
  512. dx = tm.tmAveCharWidth * MAXGLCHAR;
  513. dy = tm.tmHeight + tm.tmExternalLeading;
  514. DeleteDC(hdcIC);
  515. lpUIExtra->uiGuide.hWnd =
  516. CreateWindowEx( WS_EX_WINDOWEDGE | WS_EX_DLGMODALFRAME,
  517. (LPTSTR)szGuideClassName,NULL,
  518. WS_DISABLED | WS_POPUP | WS_BORDER,
  519. lpUIExtra->uiGuide.pt.x,
  520. lpUIExtra->uiGuide.pt.y,
  521. dx + 2 * GetSystemMetrics(SM_CXBORDER)
  522. + 2 * GetSystemMetrics(SM_CXEDGE),
  523. dy + GetSystemMetrics(SM_CYSMCAPTION)
  524. + 2 * GetSystemMetrics(SM_CYBORDER)
  525. + 2 * GetSystemMetrics(SM_CYEDGE),
  526. hWnd,NULL,hInst,NULL);
  527. }
  528. ShowWindow(lpUIExtra->uiGuide.hWnd,SW_SHOWNOACTIVATE);
  529. lpUIExtra->uiGuide.bShow = TRUE;
  530. SetWindowLongPtr(lpUIExtra->uiGuide.hWnd,FIGWL_SVRWND,(LONG_PTR)hWnd);
  531. UpdateGuideWindow(lpUIExtra);
  532. }
  533. break;
  534. case IMN_SETCANDIDATEPOS:
  535. // FAKEIME supports only one candidate list.
  536. if (lParam != 0x01)
  537. break;
  538. MoveCandWindow(hWnd,lpIMC,lpUIExtra, FALSE);
  539. break;
  540. case IMN_SETCOMPOSITIONWINDOW:
  541. MoveCompWindow(lpUIExtra,lpIMC);
  542. MoveCandWindow(hWnd,lpIMC,lpUIExtra, TRUE);
  543. break;
  544. case IMN_SETSTATUSWINDOWPOS:
  545. case IMN_PRIVATE:
  546. break;
  547. default:
  548. break;
  549. }
  550. GlobalUnlock(hUIExtra);
  551. ImmUnlockIMC(hUICurIMC);
  552. return lRet;
  553. }
  554. /**********************************************************************/
  555. /* */
  556. /* ControlCommand() */
  557. /* */
  558. /* Handle WM_IME_CONTROL messages. */
  559. /* */
  560. /**********************************************************************/
  561. #define lpcfCandForm ((LPCANDIDATEFORM)lParam)
  562. LONG PASCAL ControlCommand(HIMC hUICurIMC, HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
  563. {
  564. LONG lRet = 1L;
  565. LPINPUTCONTEXT lpIMC;
  566. HGLOBAL hUIExtra;
  567. LPUIEXTRA lpUIExtra;
  568. if (!(lpIMC = ImmLockIMC(hUICurIMC)))
  569. return 1L;
  570. hUIExtra = (HGLOBAL)GetWindowLongPtr(hWnd,IMMGWLP_PRIVATE);
  571. lpUIExtra = (LPUIEXTRA)GlobalLock(hUIExtra);
  572. switch (wParam)
  573. {
  574. case IMC_GETCANDIDATEPOS:
  575. if (IsWindow(lpUIExtra->uiCand.hWnd))
  576. {
  577. // FAKEIME has only one candidate list.
  578. *(LPCANDIDATEFORM)lParam = lpIMC->cfCandForm[0];
  579. lRet = 0;
  580. }
  581. break;
  582. case IMC_GETCOMPOSITIONWINDOW:
  583. *(LPCOMPOSITIONFORM)lParam = lpIMC->cfCompForm;
  584. lRet = 0;
  585. break;
  586. case IMC_GETSTATUSWINDOWPOS:
  587. lRet = (lpUIExtra->uiStatus.pt.x << 16) & lpUIExtra->uiStatus.pt.x;
  588. break;
  589. default:
  590. break;
  591. }
  592. GlobalUnlock(hUIExtra);
  593. ImmUnlockIMC(hUICurIMC);
  594. return lRet;
  595. }
  596. /**********************************************************************/
  597. /* */
  598. /* DrawUIBorder() */
  599. /* */
  600. /* When draging the child window, this function draws the border. */
  601. /* */
  602. /**********************************************************************/
  603. void PASCAL DrawUIBorder( LPRECT lprc )
  604. {
  605. HDC hDC;
  606. int sbx, sby;
  607. hDC = CreateDC( TEXT("DISPLAY"), NULL, NULL, NULL );
  608. SelectObject( hDC, GetStockObject( GRAY_BRUSH ) );
  609. sbx = GetSystemMetrics( SM_CXBORDER );
  610. sby = GetSystemMetrics( SM_CYBORDER );
  611. PatBlt( hDC, lprc->left,
  612. lprc->top,
  613. lprc->right - lprc->left-sbx,
  614. sby, PATINVERT );
  615. PatBlt( hDC, lprc->right - sbx,
  616. lprc->top,
  617. sbx,
  618. lprc->bottom - lprc->top-sby, PATINVERT );
  619. PatBlt( hDC, lprc->right,
  620. lprc->bottom-sby,
  621. -(lprc->right - lprc->left-sbx),
  622. sby, PATINVERT );
  623. PatBlt( hDC, lprc->left,
  624. lprc->bottom,
  625. sbx,
  626. -(lprc->bottom - lprc->top-sby), PATINVERT );
  627. DeleteDC( hDC );
  628. }
  629. /**********************************************************************/
  630. /* */
  631. /* DragUI(hWnd,message,wParam,lParam) */
  632. /* */
  633. /* Handling mouse messages for the child windows. */
  634. /* */
  635. /**********************************************************************/
  636. void PASCAL DragUI( HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
  637. {
  638. POINT pt;
  639. static POINT ptdif;
  640. static RECT drc;
  641. static RECT rc;
  642. DWORD dwT;
  643. switch (message)
  644. {
  645. case WM_SETCURSOR:
  646. if ( HIWORD(lParam) == WM_LBUTTONDOWN
  647. || HIWORD(lParam) == WM_RBUTTONDOWN )
  648. {
  649. GetCursorPos( &pt );
  650. SetCapture(hWnd);
  651. GetWindowRect(hWnd,&drc);
  652. ptdif.x = pt.x - drc.left;
  653. ptdif.y = pt.y - drc.top;
  654. rc = drc;
  655. rc.right -= rc.left;
  656. rc.bottom -= rc.top;
  657. SetWindowLong(hWnd,FIGWL_MOUSE,FIM_CAPUTURED);
  658. }
  659. break;
  660. case WM_MOUSEMOVE:
  661. dwT = GetWindowLong(hWnd,FIGWL_MOUSE);
  662. if (dwT & FIM_MOVED)
  663. {
  664. DrawUIBorder(&drc);
  665. GetCursorPos( &pt );
  666. drc.left = pt.x - ptdif.x;
  667. drc.top = pt.y - ptdif.y;
  668. drc.right = drc.left + rc.right;
  669. drc.bottom = drc.top + rc.bottom;
  670. DrawUIBorder(&drc);
  671. }
  672. else if (dwT & FIM_CAPUTURED)
  673. {
  674. DrawUIBorder(&drc);
  675. SetWindowLong(hWnd,FIGWL_MOUSE,dwT | FIM_MOVED);
  676. }
  677. break;
  678. case WM_LBUTTONUP:
  679. case WM_RBUTTONUP:
  680. dwT = GetWindowLong(hWnd,FIGWL_MOUSE);
  681. if (dwT & FIM_CAPUTURED)
  682. {
  683. ReleaseCapture();
  684. if (dwT & FIM_MOVED)
  685. {
  686. DrawUIBorder(&drc);
  687. GetCursorPos( &pt );
  688. MoveWindow(hWnd,pt.x - ptdif.x,
  689. pt.y - ptdif.y,
  690. rc.right,
  691. rc.bottom,TRUE);
  692. }
  693. }
  694. break;
  695. }
  696. }
  697. /**********************************************************************/
  698. /* */
  699. /* MyIsIMEMessage(message) */
  700. /* */
  701. /* Any UI window should not pass the IME messages to DefWindowProc. */
  702. /* */
  703. /**********************************************************************/
  704. BOOL PASCAL MyIsIMEMessage(UINT message)
  705. {
  706. switch(message)
  707. {
  708. case WM_IME_STARTCOMPOSITION:
  709. case WM_IME_ENDCOMPOSITION:
  710. case WM_IME_COMPOSITION:
  711. case WM_IME_NOTIFY:
  712. case WM_IME_SETCONTEXT:
  713. case WM_IME_CONTROL:
  714. case WM_IME_COMPOSITIONFULL:
  715. case WM_IME_SELECT:
  716. case WM_IME_CHAR:
  717. return TRUE;
  718. }
  719. return FALSE;
  720. }
  721. /**********************************************************************/
  722. /* */
  723. /* ShowUIWindows(hWnd,fFlag) */
  724. /* */
  725. /**********************************************************************/
  726. void PASCAL ShowUIWindows(HWND hWnd, BOOL fFlag)
  727. {
  728. HGLOBAL hUIExtra;
  729. LPUIEXTRA lpUIExtra;
  730. int nsw = fFlag ? SW_SHOWNOACTIVATE : SW_HIDE;
  731. if (!(hUIExtra = (HGLOBAL)GetWindowLongPtr(hWnd,IMMGWLP_PRIVATE)))
  732. return;
  733. if (!(lpUIExtra = (LPUIEXTRA)GlobalLock(hUIExtra)))
  734. return;
  735. if (IsWindow(lpUIExtra->uiStatus.hWnd))
  736. {
  737. ShowWindow(lpUIExtra->uiStatus.hWnd,nsw);
  738. lpUIExtra->uiStatus.bShow = fFlag;
  739. }
  740. if (IsWindow(lpUIExtra->uiCand.hWnd))
  741. {
  742. ShowWindow(lpUIExtra->uiCand.hWnd,nsw);
  743. lpUIExtra->uiCand.bShow = fFlag;
  744. }
  745. if (IsWindow(lpUIExtra->uiDefComp.hWnd))
  746. {
  747. ShowWindow(lpUIExtra->uiDefComp.hWnd,nsw);
  748. lpUIExtra->uiDefComp.bShow = fFlag;
  749. }
  750. if (IsWindow(lpUIExtra->uiGuide.hWnd))
  751. {
  752. ShowWindow(lpUIExtra->uiGuide.hWnd,nsw);
  753. lpUIExtra->uiGuide.bShow = fFlag;
  754. }
  755. GlobalUnlock(hUIExtra);
  756. }
  757. #ifdef DEBUG
  758. void PASCAL DumpUIExtra(LPUIEXTRA lpUIExtra)
  759. {
  760. TCHAR szDev[80];
  761. int i;
  762. wsprintf((LPTSTR)szDev,TEXT("Status hWnd %lX [%d,%d]\r\n"),
  763. lpUIExtra->uiStatus.hWnd,
  764. lpUIExtra->uiStatus.pt.x,
  765. lpUIExtra->uiStatus.pt.y);
  766. OutputDebugString((LPTSTR)szDev);
  767. wsprintf((LPTSTR)szDev,TEXT("Cand hWnd %lX [%d,%d]\r\n"),
  768. lpUIExtra->uiCand.hWnd,
  769. lpUIExtra->uiCand.pt.x,
  770. lpUIExtra->uiCand.pt.y);
  771. OutputDebugString((LPTSTR)szDev);
  772. wsprintf((LPTSTR)szDev,TEXT("CompStyle hWnd %lX]\r\n"), lpUIExtra->dwCompStyle);
  773. OutputDebugString((LPTSTR)szDev);
  774. wsprintf((LPTSTR)szDev,TEXT("DefComp hWnd %lX [%d,%d]\r\n"),
  775. lpUIExtra->uiDefComp.hWnd,
  776. lpUIExtra->uiDefComp.pt.x,
  777. lpUIExtra->uiDefComp.pt.y);
  778. OutputDebugString((LPTSTR)szDev);
  779. for (i=0;i<5;i++)
  780. {
  781. wsprintf((LPTSTR)szDev,TEXT("Comp hWnd %lX [%d,%d]-[%d,%d]\r\n"),
  782. lpUIExtra->uiComp[i].hWnd,
  783. lpUIExtra->uiComp[i].rc.left,
  784. lpUIExtra->uiComp[i].rc.top,
  785. lpUIExtra->uiComp[i].rc.right,
  786. lpUIExtra->uiComp[i].rc.bottom);
  787. OutputDebugString((LPTSTR)szDev);
  788. }
  789. }
  790. #endif