Ui.pas
上传用户:wen198501
上传日期:2013-04-01
资源大小:335k
文件大小:34k
源码类别:

输入法编程

开发平台:

Delphi

  1.  {******************************************************}
  2.  {                                                      }
  3.  {    Copyright (c) 1990-1999 Microsoft Corporation     }
  4.  {                                                      }
  5.  {    Module Name:  Ui.c ->>  Ui.pas                    }
  6.  {                                                      }
  7.  {    Translator:  Liu_mazi@126.com, 2005-11-17         }
  8.  {                                                      }
  9.  {******************************************************}
  10. unit Ui;
  11. {$I Define.Inc}
  12. interface
  13. uses Windows;
  14. function UIWndProc(hUIWnd: hWnd; uMsg: uInt; wParam: WParam; lParam: LParam): LResult; stdcall; // UI窗口回调
  15. procedure DrawConvexRect(_hDC: hDC; x1, y1, x2, y2: Integer); // 绘制凸出边框
  16. procedure DrawConvexRectP(_hDC: hDC; x1, y1, x2, y2: Integer); // 绘制凸出边框
  17. procedure DrawConcaveRect(_hDC: hDC; x1, y1, x2, y2: Integer); // 绘制凹陷边框
  18. implementation
  19. uses Messages, ImmDev, ImeDefs, Init, Data, DDIS, Notify, Statusui, Compui, Candui, LogText;
  20.   // IMN_PRIVATE_CMENUDESTROYED处理
  21. procedure CMenuDestroyed(hUIWnd: hWnd);
  22. var
  23.   hUIPrivate: hGlobal;
  24.   lpUIPrivate: PUIPriv;
  25. begin
  26.   hUIPrivate := GetWindowLong(hUIWnd, IMMGWLP_PRIVATE);
  27.   if (hUIPrivate = 0) then Exit;
  28.   lpUIPrivate := GlobalLock(hUIPrivate);
  29.   if (lpUIPrivate = nil) then Exit;
  30.   lpUIPrivate.hCMenuWnd := 0;
  31.   GlobalUnlock(hUIPrivate);
  32. end;
  33.   // IMN_PRIVATE_SOFTKEYMENUDESTROYED处理
  34. procedure SoftkeyMenuDestroyed(hUIWnd: hWnd);
  35. var
  36.   hUIPrivate: hGlobal;
  37.   lpUIPrivate: PUIPriv;
  38. begin
  39.   hUIPrivate := GetWindowLong(hUIWnd, IMMGWLP_PRIVATE);
  40.   if (hUIPrivate = 0) then Exit;
  41.   lpUIPrivate := GlobalLock(hUIPrivate);
  42.   if (lpUIPrivate = nil) then Exit;
  43.   lpUIPrivate.hSoftkeyMenuWnd := 0;
  44.   GlobalUnlock(hUIPrivate);
  45. end;
  46.   // WM_CREATE消息处理
  47. procedure CreateUIWindow(hUIWnd: hWnd);
  48. var
  49.   hUIPrivate: hGlobal;
  50. begin
  51. {$IfDef Debug}
  52.   ImeLog('CreateUIWindow ..');
  53. {$EndIf}
  54.   // create storage for UI setting
  55.   hUIPrivate := GlobalAlloc(GHND, SizeOf(TUIPriv));
  56.   if (hUIPrivate = 0) then Exit;
  57.   SetWindowLong(hUIWnd, IMMGWLP_PRIVATE, hUIPrivate);
  58.   // set the default position for UI window, it is hide now, **
  59.   SetWindowPos(hUIWnd, 0, 0, 0, 0, 0, SWP_NOACTIVATE or SWP_NOZORDER);
  60.   ShowWindow(hUIWnd, SW_SHOWNOACTIVATE);
  61. end;
  62.   // WM_DESTROY消息处理
  63. procedure DestroyUIWindow(hUIWnd: hWnd);
  64. var
  65.   hUIPrivate: hGlobal;
  66.   lpUIPrivate: PUIPriv;
  67. begin
  68. {$IfDef Debug}
  69.   ImeLog('DestroyUIWindow ..');
  70. {$EndIf}
  71.   hUIPrivate := GetWindowLong(hUIWnd, IMMGWLP_PRIVATE);
  72.   if (hUIPrivate = 0) then Exit;
  73.   lpUIPrivate := GlobalLock(hUIPrivate);
  74.   if (lpUIPrivate = nil) then Exit;
  75.   // destroy ContextMenuWnd
  76.   if IsWindow(lpUIPrivate.hCMenuWnd) then
  77.   begin
  78.     SetWindowLong(lpUIPrivate.hCMenuWnd, CMENU_HUIWND, 0);
  79.     SendMessage(lpUIPrivate.hCMenuWnd, WM_USER_DESTROY, 0, 0); // **, 恐怕用Post来不及..
  80.   end;
  81.   // destroy SoftkeyMenuWnd
  82.   if IsWindow(lpUIPrivate.hSoftkeyMenuWnd) then
  83.   begin
  84.     SetWindowLong(lpUIPrivate.hSoftkeyMenuWnd, SOFTKEYMENU_HUIWND, 0);
  85.     SendMessage(lpUIPrivate.hSoftkeyMenuWnd, WM_USER_DESTROY, 0, 0); // **, 恐怕用Post来不及..
  86.   end;
  87.   // composition window need to be destroyed
  88.   if IsWindow(lpUIPrivate.hCompWnd) then DestroyWindow(lpUIPrivate.hCompWnd);
  89.   // candidate window need to be destroyed
  90.   if IsWindow(lpUIPrivate.hCandWnd) then DestroyWindow(lpUIPrivate.hCandWnd);
  91.   // status window need to be destroyed
  92.   if IsWindow(lpUIPrivate.hStatusWnd) then DestroyWindow(lpUIPrivate.hStatusWnd);
  93.   // soft keyboard window need to be destroyed
  94.   if IsWindow(lpUIPrivate.hSoftKbdWnd) then ImmDestroySoftKeyboard(lpUIPrivate.hSoftKbdWnd);
  95.   GlobalUnlock(hUIPrivate);
  96.   // free storage for UI settings
  97.   GlobalFree(hUIPrivate);
  98. end;
  99.   // 显示隐藏软键盘
  100. procedure ShowSoftKbd(hUIWnd: hWnd; nShowSoftKbdCmd: Integer; lpImcP: PPrivContext);
  101. var
  102.   hUIPrivate: hGlobal;
  103.   lpUIPrivate: PUIPriv;
  104.   J: uInt;
  105. begin
  106.   hUIPrivate := GetWindowLong(hUIWnd, IMMGWLP_PRIVATE);
  107.   if (hUIPrivate = 0) then Exit;         // can not darw status window
  108.   lpUIPrivate := GlobalLock(hUIPrivate);
  109.   if (lpUIPrivate = nil) then Exit;      // can not draw status window
  110.   for J := IDM_SKL1 to IDM_SKL13 do CheckMenuItem(sImeL.hSKMenu, J, MF_UNCHECKED); // **
  111.   if IsWindow(lpUIPrivate.hSoftKbdWnd) and (lpUIPrivate.nShowSoftKbdCmd <> nShowSoftKbdCmd) then
  112.   begin
  113.     ImmShowSoftKeyboard(lpUIPrivate.hSoftKbdWnd, nShowSoftKbdCmd);
  114.     lpUIPrivate.nShowSoftKbdCmd := nShowSoftKbdCmd;
  115.   end;
  116.   GlobalUnlock(hUIPrivate);
  117. end;
  118.   // 计算软键盘位置
  119. procedure CheckSoftKbdPosition(lpUIPrivate: PUIPriv; lpIMC: PInputContext);
  120. var
  121.   fPortionBits: uInt; // = 0;
  122.   fPortionTest: uInt;
  123.   xPortion, yPortion, nPortion: Integer;
  124.   rcWnd: TRect;
  125. begin
  126.   // portion of dispaly
  127.   // 0  1
  128.   // 2  3
  129.   fPortionBits := 0;
  130.   if IsWindow(lpUIPrivate.hCompWnd) then
  131.   begin
  132.     GetWindowRect(lpUIPrivate.hCompWnd, rcWnd);
  133.     if (rcWnd.Left > sImeG.rcWorkArea.Right div 2) then xPortion := 1 else xPortion := 0;
  134.     if (rcWnd.Top > sImeG.rcWorkArea.Bottom div 2) then yPortion := 1 else yPortion := 0;
  135.     fPortionBits := fPortionBits or ($0001 shl (yPortion * 2 + xPortion));
  136.   end;
  137.   if IsWindow(lpUIPrivate.hStatusWnd) then
  138.   begin
  139.     GetWindowRect(lpUIPrivate.hStatusWnd, rcWnd);
  140.     if (rcWnd.Left > sImeG.rcWorkArea.Right div 2) then xPortion := 1 else xPortion := 0;
  141.     if (rcWnd.Top > sImeG.rcWorkArea.Bottom div 2) then yPortion := 1 else yPortion := 0;
  142.     fPortionBits := fPortionBits or ($0001 shl (yPortion * 2 + xPortion));
  143.   end;
  144.   GetWindowRect(lpUIPrivate.hSoftKbdWnd, rcWnd);
  145.   // start from portion 3
  146.   nPortion := 3;
  147.   fPortionTest := $0008;
  148.   while (fPortionTest <> 0) do
  149.   begin
  150.     if (fPortionTest and fPortionBits <> 0) then
  151.     begin
  152.       Dec(nPortion);
  153.       fPortionTest := fPortionTest shr 1;
  154.     end else
  155.     begin
  156.       if (nPortion mod 2 <> 0) then // 左半部分
  157.         lpIMC.ptSoftKbdPos.x := sImeG.rcWorkArea.Right - (rcWnd.Right - rcWnd.Left) - UI_MARGIN
  158.       else
  159.         lpIMC.ptSoftKbdPos.x := sImeG.rcWorkArea.Left;
  160.       if (nPortion div 2 <> 0) then // 下半部分
  161.         lpIMC.ptSoftKbdPos.y := sImeG.rcWorkArea.Bottom - (rcWnd.Bottom - rcWnd.Top) - UI_MARGIN
  162.       else
  163.         lpIMC.ptSoftKbdPos.y := sImeG.rcWorkArea.Top;
  164.       lpIMC.fdwInit := lpIMC.fdwInit or INIT_SOFTKBDPOS;
  165.       Break;
  166.     end;
  167.   end;
  168. end;
  169.   // 设置软键盘数据
  170. procedure SetSoftKbdData(hSoftKbdWnd: hWnd; lpIMC: PInputContext);
  171. var
  172.   J, K: Integer;
  173.   lpSoftKbdData: PSoftKbdData;
  174.   lpImcP: PPrivContext;
  175.   hsSoftKbdData: hGlobal;
  176.   bVirtKey: Byte;
  177.   cHiByte, cLoByte: Word;
  178. begin
  179.   lpImcP := ImmLockIMCC(lpIMC.hPrivate);
  180.   if (lpImcP = nil) then Exit;
  181.   hsSoftKbdData := GlobalAlloc(GHND, SizeOf(TSoftKbdData) * 2); // **
  182.   if (hsSoftKbdData = 0) then
  183.   begin
  184.     ImmUnlockIMCC(lpIMC.hPrivate);
  185.     Exit;
  186.   end;
  187.   lpSoftKbdData := GlobalLock(hsSoftKbdData);
  188.   if (lpSoftKbdData = nil) then         // can not draw soft keyboard window
  189.   begin
  190.     ImmUnlockIMCC(lpIMC.hPrivate);
  191.     Exit;
  192.   end;
  193.   lpSoftKbdData.uCount := 2;
  194.   K := 1;
  195.   for J := 0 to 47 do
  196.   begin
  197.     bVirtKey := VirtKey48Map[J];
  198.     if (bVirtKey = 0) then Continue;
  199.     cHiByte := Ord(SKLayout[sImeL.dwSKWant][J * 2]) and $00FF;
  200.     cLoByte := Ord(SKLayout[sImeL.dwSKWant][J * 2 + 1]) and $00FF;
  201.     lpSoftKbdData.wCode[0][bVirtKey] := (cHiByte shl 8) or cLoByte;
  202.     cHiByte := Ord(SKLayoutS[sImeL.dwSKWant][J * 2]) and $00FF;
  203.     cLoByte := Ord(SKLayoutS[sImeL.dwSKWant][J * 2 + 1]) and $00FF;
  204.     lpSoftKbdData.wCode[K][bVirtKey] := (cHiByte shl 8) or cLoByte;
  205.   end;
  206.   SendMessage(hSoftKbdWnd, WM_IME_CONTROL, IMC_SETSOFTKBDDATA, Integer(lpSoftKbdData));
  207.   GlobalUnlock(hsSoftKbdData);
  208.   // free storage for UI settings
  209.   GlobalFree(hsSoftKbdData);
  210.   ImmUnlockIMCC(lpIMC.hPrivate);
  211. end;
  212.   // "更新"软键盘
  213. procedure UpdateSoftKbd(hUIWnd: hWnd);
  214. var
  215.   _hIMC: hIMC;
  216.   lpIMC: PInputContext;
  217.   lpImcP: PPrivContext;
  218.   hUIPrivate: hGlobal;
  219.   lpUIPrivate: PUIPriv;
  220. begin
  221.   _hIMC := GetWindowLong(hUIWnd, IMMGWLP_IMC);
  222.   if (_hIMC = 0) then Exit;
  223.   lpIMC := ImmLockIMC(_hIMC);
  224.   if (lpIMC = nil) then Exit;
  225.   hUIPrivate := GetWindowLong(hUIWnd, IMMGWLP_PRIVATE);
  226.   if (hUIPrivate = 0) then       // can not darw soft keyboard window
  227.   begin
  228.     ImmUnlockIMC(_hIMC);
  229.     Exit;
  230.   end;
  231.   lpUIPrivate := GlobalLock(hUIPrivate);
  232.   if (lpUIPrivate = nil) then    // can not draw soft keyboard window
  233.   begin
  234.     ImmUnlockIMC(_hIMC);
  235.     Exit;
  236.   end;
  237.   lpImcP := ImmLockIMCC(lpIMC.hPrivate);
  238.   if (lpImcP = nil) then
  239.   begin
  240.     GlobalUnlock(hUIPrivate);
  241.     ImmUnlockIMC(_hIMC);
  242.     Exit;
  243.   end;
  244.   if (lpIMC.fdwConversion and IME_CMODE_SOFTKBD) = 0 then
  245.   begin
  246.     if IsWindow(lpUIPrivate.hSoftKbdWnd) then
  247.     begin
  248.       ImmDestroySoftKeyboard(lpUIPrivate.hSoftKbdWnd);
  249.       lpUIPrivate.hSoftKbdWnd := 0;
  250.     end;
  251.     lpUIPrivate.nShowSoftKbdCmd := SW_HIDE;
  252.   end else
  253.     if (lpIMC.fOpen = False) then
  254.     begin
  255.       if (lpUIPrivate.nShowSoftKbdCmd <> SW_HIDE) then ShowSoftKbd(hUIWnd, SW_HIDE, nil);
  256.     end else
  257.     begin
  258.       if (IsWindow(lpUIPrivate.hSoftKbdWnd) = False) then
  259.         lpUIPrivate.hSoftKbdWnd := ImmCreateSoftKeyboard(SOFTKEYBOARD_TYPE_C1, hUIWnd, 0, 0);
  260.       if (lpIMC.fdwInit and INIT_SOFTKBDPOS) = 0 then CheckSoftKbdPosition(lpUIPrivate, lpIMC);
  261.       SetSoftKbdData(lpUIPrivate.hSoftKbdWnd, lpIMC);
  262.       lpUIPrivate.fdwSetContext := lpUIPrivate.fdwSetContext or ISC_SHOW_SOFTKBD;
  263.       if (lpUIPrivate.nShowSoftKbdCmd = SW_HIDE) then
  264.       begin
  265.         SetWindowPos(lpUIPrivate.hSoftKbdWnd, 0,
  266.           lpIMC.ptSoftKbdPos.x, lpIMC.ptSoftKbdPos.y, 0, 0, SWP_NOACTIVATE or SWP_NOSIZE or SWP_NOZORDER);
  267.         // only show, if the application want to show it
  268.         if (lpUIPrivate.fdwSetContext and ISC_SHOW_SOFTKBD) <> 0 then ShowSoftKbd(hUIWnd, SW_SHOWNOACTIVATE, lpImcP);
  269.       end;
  270.     end;
  271.   ImmUnlockIMCC(lpIMC.hPrivate);
  272.   GlobalUnlock(hUIPrivate);
  273.   ImmUnlockIMC(_hIMC);
  274. end;
  275.   // IMN_SOFTKBDDESTROYED处理
  276. procedure SoftKbdDestroyed(hUIWnd: hWnd);
  277. var
  278.   hUIPrivate: HGlobal;
  279.   lpUIPrivate: PUIPriv;
  280. begin
  281.   hUIPrivate := GetWindowLong(hUIWnd, IMMGWLP_PRIVATE);
  282.   if (hUIPrivate = 0) then Exit;
  283.   lpUIPrivate := GlobalLock(hUIPrivate);
  284.   if (lpUIPrivate = nil) then Exit;
  285.   lpUIPrivate.hSoftKbdWnd := 0;
  286.   GlobalUnlock(hUIPrivate);
  287. end;
  288.   // 打开关闭Status窗口
  289. procedure StatusWndMsg(hUIWnd: hWnd; fOn: Bool);
  290. var
  291.   hUIPrivate: hGlobal;
  292.   _hIMC: hIMC;
  293.   hStatusWnd: hWnd;
  294.   lpUIPrivate: PUIPriv;
  295.   fdwSetContext: DWord;
  296. begin
  297.   hUIPrivate := GetWindowLong(hUIWnd, IMMGWLP_PRIVATE);
  298.   if (hUIPrivate = 0) then Exit;
  299.   lpUIPrivate := GlobalLock(hUIPrivate);
  300.   if (lpUIPrivate = nil) then Exit;
  301.   _hIMC := GetWindowLong(hUIWnd, IMMGWLP_IMC);
  302.   if (_hIMC = 0) then
  303.   begin
  304.     GlobalUnlock(hUIPrivate);
  305.     Exit;
  306.   end;
  307.   if (fOn = True) then
  308.   begin
  309.     lpUIPrivate.fdwSetContext := lpUIPrivate.fdwSetContext or ISC_OPEN_STATUS_WINDOW;
  310.     if (IsWindow(lpUIPrivate.hStatusWnd) = False) then OpenStatus(hUIWnd); // 重建
  311.   end else
  312.   begin
  313.     lpUIPrivate.fdwSetContext := lpUIPrivate.fdwSetContext and (not ISC_OPEN_STATUS_WINDOW);
  314.   end;
  315.   hStatusWnd := lpUIPrivate.hStatusWnd;
  316.   GlobalUnlock(hUIPrivate);
  317.   if (IsWindow(hStatusWnd) = False) then Exit;
  318.   if (fOn = False) then
  319.   begin
  320.     fdwSetContext := lpUIPrivate.fdwSetContext and (ISC_SHOWUICOMPOSITIONWINDOW or ISC_HIDE_COMP_WINDOW);
  321.     if (fdwSetContext = ISC_HIDE_COMP_WINDOW) then ShowComp(hUIWnd, SW_HIDE);
  322.     fdwSetContext := lpUIPrivate.fdwSetContext and (ISC_SHOWUICANDIDATEWINDOW or ISC_HIDE_CAND_WINDOW);
  323.     if (fdwSetContext = ISC_HIDE_CAND_WINDOW) then ShowCand(hUIWnd, SW_HIDE);
  324.     fdwSetContext := lpUIPrivate.fdwSetContext and (ISC_SHOW_SOFTKBD or ISC_HIDE_SOFTKBD);
  325.     if (fdwSetContext = ISC_HIDE_SOFTKBD) then
  326.     begin
  327.       lpUIPrivate.fdwSetContext := lpUIPrivate.fdwSetContext and (not ISC_HIDE_SOFTKBD);
  328.       ShowSoftKbd(hUIWnd, SW_HIDE, nil);
  329.     end;
  330.     ShowStatus(hUIWnd, SW_HIDE);
  331.   end else
  332.     if (_hIMC <> 0) then ShowStatus(hUIWnd, SW_SHOWNOACTIVATE) else ShowStatus(hUIWnd, SW_HIDE);
  333. end;
  334.   // 显示隐藏Ime界面
  335. procedure ShowUI(hUIWnd: hWnd; nShowCmd: Integer);
  336. label
  337.   ShowUIUnlockIMCC;
  338. var
  339.   _hIMC: hIMC;
  340.   lpIMC: PInputContext;
  341.   lpImcP: PPrivContext;
  342.   hUIPrivate: hGlobal;
  343.   lpUIPrivate: PUIPriv;
  344. begin
  345.   lpIMC := nil;
  346.   lpImcP := nil;
  347.   if (nShowCmd <> SW_HIDE) then
  348.   begin
  349.     _hIMC := GetWindowLong(hUIWnd, IMMGWLP_IMC);
  350.     if (_hIMC = 0) then
  351.     begin
  352.       nShowCmd := SW_HIDE;
  353.     end else
  354.     begin
  355.       lpIMC := ImmLockIMC(_hIMC);
  356.       if (lpIMC = nil) then
  357.       begin
  358.         nShowCmd := SW_HIDE;
  359.       end else
  360.       begin
  361.         lpImcP := ImmLockIMCC(lpIMC.hPrivate);
  362.         if (lpImcP = nil) then
  363.         begin
  364.           ImmUnlockIMC(_hIMC);
  365.           nShowCmd := SW_HIDE;
  366.         end;
  367.       end;
  368.     end;
  369.   end else
  370.     _hIMC := 0; // ++
  371.   if (nShowCmd = SW_HIDE) then
  372.   begin
  373.     ShowStatus(hUIWnd, nShowCmd);
  374.     ShowComp(hUIWnd, nShowCmd);
  375.     ShowCand(hUIWnd, nShowCmd);
  376.     ShowSoftKbd(hUIWnd, nShowCmd, nil);
  377.     Exit;
  378.   end;
  379.   hUIPrivate := GetWindowLong(hUIWnd, IMMGWLP_PRIVATE);
  380.   if (hUIPrivate = 0) then goto ShowUIUnlockIMCC;  // can not darw status window
  381.   lpUIPrivate := GlobalLock(hUIPrivate);
  382.   if (lpUIPrivate = nil) then goto ShowUIUnlockIMCC;  // can not draw status window
  383.   lpUIPrivate.fdwSetContext := lpUIPrivate.fdwSetContext or ISC_SHOWUICOMPOSITIONWINDOW;
  384.   // Composition窗口
  385.   if (lpUIPrivate.fdwSetContext and ISC_SHOWUICOMPOSITIONWINDOW <> 0) and
  386.      (lpImcP.fdwImeMsg and MSG_ALREADY_START <> 0) then
  387.   begin
  388.     if IsWindow(lpUIPrivate.hCompWnd) then
  389.     begin
  390.       if (lpUIPrivate.nShowCompCmd <> SW_HIDE) then
  391.         RedrawWindow(lpUIPrivate.hCompWnd, nil, 0, RDW_FRAME or RDW_INVALIDATE or RDW_ERASE);
  392.       if (sImeG.IC_Trace <> 0) then // modify 95.7.17
  393.         SendMessage(lpUIPrivate.hCompWnd, WM_IME_NOTIFY, IMN_SETCOMPOSITIONWINDOW, 0);
  394.       if (lpUIPrivate.nShowCompCmd = SW_HIDE) then ShowComp(hUIWnd, nShowCmd);
  395.     end else
  396.       StartComp(hUIWnd);
  397.   end else
  398.   begin
  399.     if (lpUIPrivate.nShowCompCmd <> SW_HIDE) then
  400.       if (lpUIPrivate.fdwSetContext and ISC_OPEN_STATUS_WINDOW) <> 0 then
  401.         lpUIPrivate.fdwSetContext := lpUIPrivate.fdwSetContext or ISC_HIDE_COMP_WINDOW
  402.       else
  403.         ShowComp(hUIWnd, SW_HIDE);
  404.   end;
  405.   // Candidate窗口
  406.   if (lpUIPrivate.fdwSetContext and ISC_SHOWUICANDIDATEWINDOW <> 0) and
  407.      (lpImcP.fdwImeMsg and MSG_ALREADY_OPEN <> 0) then
  408.   begin
  409.     if IsWindow(lpUIPrivate.hCandWnd) then
  410.     begin
  411.       if (lpUIPrivate.nShowCandCmd <> SW_HIDE) then
  412.         RedrawWindow(lpUIPrivate.hCandWnd, nil, 0, RDW_FRAME or RDW_INVALIDATE or RDW_ERASE);
  413.       if (sImeG.IC_Trace <> 0) then
  414.         SendMessage(lpUIPrivate.hCandWnd, WM_IME_NOTIFY, IMN_SETCANDIDATEPOS, 1);
  415.       if (lpUIPrivate.nShowCandCmd = SW_HIDE) then ShowCand(hUIWnd, nShowCmd);
  416.     end else
  417.       OpenCand(hUIWnd);
  418.   end else
  419.   begin
  420.     if (lpUIPrivate.nShowCandCmd <> SW_HIDE) then
  421.       if (lpUIPrivate.fdwSetContext and ISC_OPEN_STATUS_WINDOW) <> 0 then
  422.         lpUIPrivate.fdwSetContext := lpUIPrivate.fdwSetContext or ISC_HIDE_CAND_WINDOW
  423.       else
  424.         ShowCand(hUIWnd, SW_HIDE);
  425.   end;
  426.   // Status窗口
  427.   if (lpUIPrivate.fdwSetContext and ISC_OPEN_STATUS_WINDOW) <> 0 then
  428.   begin
  429.     if (IsWindow(lpUIPrivate.hStatusWnd) = False) then OpenStatus(hUIWnd);
  430.     if (lpUIPrivate.nShowStatusCmd <> SW_HIDE) then
  431.       RedrawWindow(lpUIPrivate.hStatusWnd, nil, 0, RDW_FRAME or RDW_INVALIDATE or RDW_ERASE);
  432.     SendMessage(lpUIPrivate.hStatusWnd, WM_IME_NOTIFY, IMN_SETSTATUSWINDOWPOS, 0);
  433.     ShowStatus(hUIWnd, nShowCmd);
  434.   end else
  435.     if IsWindow(lpUIPrivate.hStatusWnd) then DestroyWindow(lpUIPrivate.hStatusWnd);
  436.   // 处于关闭状态
  437.   if (lpIMC.fOpen = False) then
  438.   begin
  439.     if (lpUIPrivate.nShowCompCmd <> SW_HIDE) then ShowSoftKbd(hUIWnd, SW_HIDE, nil);
  440.   end else
  441.     if (lpUIPrivate.fdwSetContext and ISC_SHOW_SOFTKBD <> 0) and
  442.        (lpIMC.fdwConversion and IME_CMODE_SOFTKBD <> 0) then
  443.     begin
  444.       if (IsWindow(lpUIPrivate.hSoftKbdWnd) = False) then
  445.       begin
  446.         UpdateSoftKbd(hUIWnd);
  447.       end else
  448.         if (lpUIPrivate.nShowSoftKbdCmd = SW_HIDE) then
  449.         begin
  450.           ShowSoftKbd(hUIWnd, nShowCmd, lpImcP);
  451.         end else
  452.           if (lpUIPrivate.hIMC <> _hIMC) then // **
  453.             UpdateSoftKbd(hUIWnd)
  454.           else
  455.             RedrawWindow(lpUIPrivate.hSoftKbdWnd, nil, 0, RDW_FRAME or RDW_INVALIDATE);
  456.     end else
  457.     begin
  458.       if (lpUIPrivate.nShowSoftKbdCmd <> SW_HIDE) then
  459.         if (lpUIPrivate.fdwSetContext and ISC_OPEN_STATUS_WINDOW) <> 0 then
  460.           lpUIPrivate.fdwSetContext := lpUIPrivate.fdwSetContext or ISC_HIDE_SOFTKBD
  461.         else
  462.           ShowSoftKbd(hUIWnd, SW_HIDE, nil);
  463.     end;
  464.   // we switch to this hIMC
  465.   lpUIPrivate.hIMC := _hIMC;
  466.   GlobalUnlock(hUIPrivate);    
  467. ShowUIUnlockIMCC:
  468.   ImmUnlockIMCC(lpIMC.hPrivate);
  469.   ImmUnlockIMC(_hIMC); 
  470. end;
  471.   // IMN_GUIDELINE处理
  472. procedure ShowGuideLine(hUIWnd: hWnd);
  473. var
  474.   _hIMC: hIMC;
  475.   lpIMC: PInputContext;
  476.   lpGuideLine: PGuideLine;
  477. begin
  478.   _hIMC := GetWindowLong(hUIWnd, IMMGWLP_IMC);
  479.   if (_hIMC = 0) then Exit;
  480.   lpIMC := ImmLockIMC(_hIMC);
  481.   if (lpIMC = nil) then Exit;
  482.   lpGuideLine := ImmLockIMCC(lpIMC.hGuideLine);
  483.   if (lpGuideLine <> nil) then
  484.     if (lpGuideLine.dwLevel = GL_LEVEL_ERROR) then
  485.     begin
  486.       MessageBeep($FFFFFFFF);
  487.       MessageBeep($FFFFFFFF);
  488.     end else
  489.       if (lpGuideLine.dwLevel = GL_LEVEL_WARNING) then MessageBeep($FFFFFFFF);
  490.   ImmUnlockIMCC(lpIMC.hGuideLine);
  491.   ImmUnlockIMC(_hIMC);
  492. end;
  493.   // IMN_PRIVATE_UPDATE_STATUS处理
  494. function UpdateStatusWindow(hUIWnd: hWnd): Bool;
  495. var
  496.   hStatusWnd: hWnd;
  497. begin
  498.   Result := False;
  499.   hStatusWnd := GetStatusWnd(hUIWnd);
  500.   if (IsWindow(hStatusWnd) = False) then Exit;
  501.   InvalidateRect(hStatusWnd, @sImeG.rcStatusText, True);
  502.   UpdateWindow(hStatusWnd);
  503.   Result := True;
  504. end;
  505.   // WM_IME_NOTIFY消息处理
  506. procedure NotifyUI(hUIWnd: hWnd; wParam: WParam; lParam: LParam);
  507. var
  508.   hStatusWnd, hCandWnd, hCompWnd: hWnd;
  509.   _hDC: hDC;
  510.   rcRect: TRect;
  511. begin
  512.   case (wParam) of
  513.     IMN_OPENSTATUSWINDOW:     // 打开Status窗口
  514.       StatusWndMsg(hUIWnd, True);
  515.     IMN_CLOSESTATUSWINDOW:    // 关闭Status窗口
  516.       StatusWndMsg(hUIWnd, False);
  517.     IMN_OPENCANDIDATE:        // 打开Candidate窗口
  518.       if (lParam and $00000001) <> 0 then OpenCand(hUIWnd);
  519.     IMN_CHANGECANDIDATE:      // 更新Candidate窗口
  520.       if (lParam and $00000001) <> 0 then
  521.       begin
  522.         hCandWnd := GetCandWnd(hUIWnd);
  523.         if (IsWindow(hCandWnd) = False) then Exit;
  524.         _hDC := GetDC(hCandWnd);
  525.         PaintCandWindow(hCandWnd, _hDC);
  526.         ReleaseDC(hCandWnd, _hDC);
  527.       end;
  528.     IMN_CLOSECANDIDATE:       // 关闭Candidate窗口
  529.       if (lParam and $00000001) <> 0 then CloseCand(hUIWnd);
  530.     IMN_SETSENTENCEMODE:
  531.       ;
  532.     IMN_SETOPENSTATUS,        // 设置输入法状态
  533.     IMN_SETCONVERSIONMODE:    // 改变输入法状态
  534.     begin
  535.       hStatusWnd := GetStatusWnd(hUIWnd);
  536.       if (IsWindow(hStatusWnd) = False) then Exit;
  537.       rcRect := sImeG.rcStatusText;
  538.       // off by 1
  539.       Inc(rcRect.Right);
  540.       Inc(rcRect.Bottom);
  541.       RedrawWindow(hStatusWnd, @rcRect, 0, RDW_INVALIDATE);
  542.     end;
  543.     IMN_SETCOMPOSITIONFONT:
  544.       // we are not going to change font, but an IME can do this if it want
  545.       ;
  546.     IMN_SETCOMPOSITIONWINDOW: // 设置Composition窗口
  547.     begin
  548.       hCompWnd := GetCompWnd(hUIWnd);
  549.       if IsWindow(hCompWnd) then PostMessage(hCompWnd, WM_IME_NOTIFY, wParam, lParam);
  550.     end;
  551.     IMN_SETCANDIDATEPOS:      // 设置Candidate窗口
  552.     begin
  553.       hCandWnd := GetCandWnd(hUIWnd);
  554.       if IsWindow(hCandWnd) then PostMessage(hCandWnd, WM_IME_NOTIFY, wParam, lParam);
  555.     end;
  556.     IMN_SETSTATUSWINDOWPOS:   // 设置Status窗口
  557.     begin
  558.       hStatusWnd := GetStatusWnd(hUIWnd);
  559.       if IsWindow(hStatusWnd) then  PostMessage(hStatusWnd, WM_IME_NOTIFY, wParam, lParam);
  560.     end;
  561.     IMN_GUIDELINE:            // 错误信息处理
  562.       ShowGuideLine(hUIWnd);
  563.     IMN_PRIVATE:              // 自定义Ime通知
  564.     begin
  565.       case (lParam) of
  566.         IMN_PRIVATE_UPDATE_SOFTKBD: UpdateSoftKbd(hUIWnd);
  567.         IMN_PRIVATE_UPDATE_STATUS: UpdateStatusWindow(hUIWnd);
  568.         IMN_PRIVATE_DESTROYCANDWIN: SendMessage(GetCandWnd(hUIWnd), WM_DESTROY, 0, 0);
  569.         IMN_PRIVATE_CMENUDESTROYED: CMenuDestroyed(hUIWnd);
  570.         IMN_PRIVATE_SOFTKEYMENUDESTROYED: SoftkeyMenuDestroyed(hUIWnd);
  571.       end;
  572.     end;
  573.     IMN_SOFTKBDDESTROYED:     // 软键盘被销毁
  574.       SoftKbdDestroyed(hUIWnd);
  575.   end;
  576. end;
  577.   // WM_PAINT处理
  578. function UIPaint(hUIWnd: hWnd): LResult;
  579. var
  580.   ps: TPaintStruct;
  581.   sMsg: TMsg;
  582.   hUIPrivate: hGlobal;
  583.   lpUIPrivate: PUIPriv;
  584. begin
  585.   Result := 0;
  586.   // for safety
  587.   BeginPaint(hUIWnd, ps);
  588.   EndPaint(hUIWnd, ps);
  589.   // some application will not remove the WM_PAINT messages
  590.   PeekMessage(sMsg, hUIWnd, WM_PAINT, WM_PAINT, PM_REMOVE or PM_NOYIELD);
  591.   hUIPrivate := GetWindowLong(hUIWnd, IMMGWLP_PRIVATE);
  592.   if (hUIPrivate = 0) then Exit;
  593.   lpUIPrivate := GlobalLock(hUIPrivate);
  594.   if (lpUIPrivate = nil) then Exit;
  595.   if (lpUIPrivate.fdwSetContext and ISC_SETCONTEXT_UI) <> 0 then
  596.     ShowUI(hUIWnd, SW_SHOWNOACTIVATE)
  597.   else
  598.     ShowUI(hUIWnd, SW_HIDE);
  599.   GlobalUnlock(hUIPrivate);
  600. end;
  601.   // 激活休眠输入法
  602. procedure SetContext(hUIWnd: hWnd; fOn: Bool; lShowUI: LParam);
  603. label
  604.   SetShowStatus;
  605. var
  606.   _hIMC: hIMC;
  607.   lpIMC: PInputContext;
  608.   lpImcP: PPrivContext;
  609.   hUIPrivate: hGlobal;
  610.   lpUIPrivate: PUIPriv;
  611.   fdwSetContext, fdwConversion: DWord;
  612.   _hKey, hKeyCurrVersion, hKeyGB: hKey;
  613.   Buf: array[0..MAX_PATH] of Char;
  614.   bcData, ValueType, ValueSize, retCode: DWord;
  615.   ui_Mode: Integer;
  616.   lpbKeyState: TKeyboardState;
  617.   ptSTFixPos, ptNew, ptSTWPos: TPoint;
  618. begin
  619.   _hIMC := GetWindowLong(hUIWnd, IMMGWLP_IMC);
  620.   if (_hIMC = 0) then Exit;
  621.   lpIMC := ImmLockIMC(_hIMC);
  622.   if (lpIMC = nil)  then Exit;
  623.   hUIPrivate := GetWindowLong(hUIWnd, IMMGWLP_PRIVATE);
  624.   if (hUIPrivate = 0) then
  625.   begin
  626.     ImmUnlockIMC(_hIMC);
  627.     Exit;
  628.   end;
  629.   lpUIPrivate := GlobalLock(hUIPrivate);
  630.   if (lpUIPrivate = nil) then
  631.   begin
  632.     ImmUnlockIMC(_hIMC);
  633.     Exit;
  634.   end;
  635.   if (fOn = True) then
  636.   begin
  637.     lpUIPrivate.fdwSetContext := lpUIPrivate.fdwSetContext and not(ISC_SHOWUIALL or ISC_HIDE_SOFTKBD);
  638.     lpUIPrivate.fdwSetContext := lpUIPrivate.fdwSetContext or (lShowUI and ISC_SHOWUIALL) or ISC_SHOW_SOFTKBD;
  639.     bcData := 256;
  640.     if (RegOpenKeyEx(HKEY_CURRENT_USER, 'Control PanelInput Method', 0, KEY_ENUMERATE_SUB_KEYS or KEY_EXECUTE or KEY_QUERY_VALUE, _hKey) <> ERROR_SUCCESS) then
  641.     begin
  642.       goto SetShowStatus;
  643.     end;
  644.     if (RegQueryValueEx(_hKey, 'show status', nil, nil, @Buf, @bcData) <> ERROR_SUCCESS) then
  645.     begin
  646.       lpUIPrivate.fdwSetContext := lpUIPrivate.fdwSetContext or ISC_OPEN_STATUS_WINDOW;
  647.       goto SetShowStatus;
  648.     end;
  649.     if (Buf[0] = '1') then
  650.       lpUIPrivate.fdwSetContext := lpUIPrivate.fdwSetContext or ISC_OPEN_STATUS_WINDOW
  651.     else
  652.       lpUIPrivate.fdwSetContext := lpUIPrivate.fdwSetContext and (not ISC_OPEN_STATUS_WINDOW);
  653. SetShowStatus:
  654.     RegCloseKey(_hKey);
  655.     fdwSetContext := lpUIPrivate.fdwSetContext and (ISC_SHOWUICOMPOSITIONWINDOW or ISC_HIDE_COMP_WINDOW);
  656.     if (fdwSetContext = ISC_HIDE_COMP_WINDOW) then
  657.     begin
  658.       ShowComp(hUIWnd, SW_HIDE);
  659.     end else
  660.       if ((fdwSetContext and ISC_HIDE_COMP_WINDOW) <> 0) then
  661.       begin
  662.         lpUIPrivate.fdwSetContext := lpUIPrivate.fdwSetContext and (not ISC_HIDE_COMP_WINDOW);
  663.       end else
  664.       begin
  665.       end;
  666.     fdwSetContext := lpUIPrivate.fdwSetContext and (ISC_SHOWUICANDIDATEWINDOW or ISC_HIDE_CAND_WINDOW);
  667.     if (fdwSetContext = ISC_HIDE_CAND_WINDOW) then
  668.     begin
  669.       ShowCand(hUIWnd, SW_HIDE);
  670.     end else
  671.       if ((fdwSetContext and ISC_HIDE_CAND_WINDOW) = 0) then
  672.       begin
  673.         lpUIPrivate.fdwSetContext := lpUIPrivate.fdwSetContext and (not ISC_HIDE_CAND_WINDOW);
  674.       end else
  675.       begin
  676.       end;
  677.     if (lpIMC.cfCandForm[0].dwIndex <> 0) then lpIMC.cfCandForm[0].dwStyle := CFS_DEFAULT;
  678.     lpImcP := ImmLockIMCC(lpIMC.hPrivate);
  679.     if (lpImcP = nil) then
  680.     begin
  681.       GlobalUnlock(hUIPrivate);
  682.       ImmUnlockIMC(_hIMC);
  683.       Exit;
  684.     end;
  685.     // init ime properties & reset context
  686.     retCode := OpenReg_PathSetup(@hKeyCurrVersion);
  687.     if (retCode <> ERROR_SUCCESS) then
  688.     begin
  689.       wvsprintf(Buf, 'Error: RegOpenKeyEx = %d', @retCode);
  690.       MessageBox(lpIMC.hWnd, Buf, szWarnTitle, MB_OK or MB_ICONINFORMATION);
  691.       Exit;
  692.     end;
  693.     // query 光标跟随 value
  694.     retCode := OpenReg_User(hKeyCurrVersion, szImeRegName, @hKeyGB);
  695.     ValueSize := SizeOf(DWord);
  696.     RegQueryValueEx(hKeyGB, szTrace, nil, @ValueType, @sImeG.IC_Trace, @ValueSize);
  697.     RegCloseKey(hKeyGB);
  698.     RegCloseKey(hKeyCurrVersion);
  699.     if (sImeG.IC_Trace <> SaTC_Trace) then // **
  700.     begin
  701.       lpImcP.iImeState := CST_INIT;
  702.       CompCancel(_hIMC, lpIMC);
  703.       // init fields of hPrivate
  704.       lpImcP.fdwImeMsg := 0;
  705.       lpImcP.dwCompChar := 0;
  706.       lpImcP.fdwGcsFlag := 0;
  707.       lpImcP.uSYHFlg := $00000000;
  708.       lpImcP.uDYHFlg := $00000000;
  709.       // change compwnd size
  710.       // init fields of hIMC
  711.       lpIMC.fOpen := True;
  712.       SendMessage(GetCandWnd(hUIWnd), WM_DESTROY, 0, 0);
  713.       // set cand window data
  714.       if (sImeG.IC_Trace <> 0) then
  715.       begin
  716.         ui_Mode := BOX_UI;
  717.       end else
  718.       begin
  719.         ui_Mode := LIN_UI;
  720.         ptSTFixPos.x := 0;
  721.         ptSTFixPos.y := sImeG.rcWorkArea.Bottom - sImeG.yStatusHi;
  722.         ImmSetStatusWindowPos(_hIMC, @ptSTFixPos);
  723.       end;
  724.       InitCandUIData(GetSystemMetrics(SM_CXBORDER), GetSystemMetrics(SM_CYBORDER), ui_Mode);
  725.     end;
  726.     SaTC_Trace := sImeG.IC_Trace;
  727.     // init Caps
  728.     GetKeyboardState(lpbKeyState);
  729.     if (lpbKeyState[VK_CAPITAL] and $01) <> 0 then
  730.     begin
  731.       // 10.11 add
  732.       uCaps := 1;
  733.       // change to alphanumeric mode
  734.       fdwConversion := lpIMC.fdwConversion and not(IME_CMODE_CHARCODE or IME_CMODE_NATIVE or IME_CMODE_EUDC);
  735.     end else
  736.     begin
  737.       // change to native mode
  738.       if (uCaps = 1) then
  739.         fdwConversion := (lpIMC.fdwConversion or IME_CMODE_NATIVE) and not(IME_CMODE_CHARCODE or IME_CMODE_EUDC)
  740.       else
  741.         fdwConversion := lpIMC.fdwConversion;
  742.       uCaps := 0;
  743.     end;
  744.     ImmSetConversionStatus(_hIMC, fdwConversion, lpIMC.fdwSentence);
  745.     if (lpIMC.cfCompForm.dwStyle and CFS_FORCE_POSITION <> 0) and (sImeG.IC_Trace <> 0) then
  746.     begin
  747.       ImmGetStatusWindowPos(_hIMC, @ptSTWPos);
  748.       ptNew.x := ptSTWPos.x + sImeG.xStatusWi + ui_Margin;
  749.       if (ptSTWPos.x + sImeG.xStatusWi + sImeG.xCandWi + sImeL.xCompWi + 2 * ui_Margin) >= sImeG.rcWorkArea.Right then
  750.       begin
  751.        ptNew.x := ptSTWPos.x - sImeL.xCompWi - ui_Margin;
  752.       end;
  753.       Inc(ptNew.x, sImeL.cxCompBorder);
  754.       ptNew.y := ptSTWPos.y + sImeL.cyCompBorder;
  755.       lpIMC.cfCompForm.ptCurrentPos := ptNew;
  756.       ScreenToClient(lpIMC.hWnd, lpIMC.cfCompForm.ptCurrentPos);
  757.       lpIMC.cfCompForm.dwStyle := CFS_DEFAULT;
  758.     end;
  759.   end else
  760.     lpUIPrivate.fdwSetContext := lpUIPrivate.fdwSetContext and (not ISC_SETCONTEXT_UI);
  761.   GlobalUnlock(hUIPrivate);
  762.   UIPaint(hUIWnd);
  763.   ImmUnlockIMC(_hIMC);
  764. end;
  765.   // IMC_GETCOMPOSITIONWINDOW处理
  766. function GetCompWindow(hUIWnd: hWnd; lpCompForm: PCompositionForm): LResult;
  767. var
  768.   hCompWnd: hWnd;
  769.   rcCompWnd: TRect;
  770. begin
  771.   Result := 1;
  772.   hCompWnd := GetCompWnd(hUIWnd);
  773.   if IsWindow(hCompWnd) = False then Exit;
  774.   if (GetWindowRect(hCompWnd, rcCompWnd) = False) then Exit;
  775.   lpCompForm.dwStyle := CFS_POINT or CFS_RECT;
  776.   lpCompForm.ptCurrentPos := PPoint(@rcCompWnd)^;
  777.   lpCompForm.rcArea := rcCompWnd;
  778.   Result := 0;
  779. end;
  780.   // UI窗口回调
  781. function UIWndProc(hUIWnd: hWnd; uMsg: uInt; wParam: WParam; lParam: LParam): LResult; stdcall;
  782. var
  783.   hCompWnd, hStatusWnd: hWnd;
  784.   rcRect, rcStatusWnd: TRect;
  785.   _hIMC: hIMC;
  786.   lpIMC: PInputContext;
  787.   lpImcP: PPrivContext;
  788.   ptPos: TPoint;
  789. begin
  790. {$IfDef Debug}
  791.   ImeLog('UIWndProc, uMsg:' + Int2Hex(uMsg) + ', wParam:' + Int2Hex(wParam) + ', lParam:' + Int2Hex(lParam));
  792. {$EndIf}
  793.   Result := 0;
  794.   case (uMsg) of
  795.     WM_CREATE:
  796.       CreateUIWindow(hUIWnd);
  797.     WM_DESTROY:
  798.       DestroyUIWindow(hUIWnd);
  799.     WM_IME_STARTCOMPOSITION: // you can create a window as the composition window here
  800.       StartComp(hUIWnd);
  801.     WM_IME_COMPOSITION:      // 编码(Composition)状态改变
  802.     begin
  803.       if (sImeG.IC_Trace = 0) then
  804.       begin
  805.       end else
  806.         if (lParam and GCS_RESULTSTR) <> 0 then
  807.         begin
  808.           MoveDefaultCompPosition(hUIWnd);
  809.         end else
  810.         begin
  811.         end;
  812.       hCompWnd := GetCompWnd(hUIWnd);
  813.       if IsWindow(hCompWnd) then
  814.       begin
  815.         rcRect := sImeL.rcCompText;
  816.         // off by 1
  817.         Inc(rcRect.Right, 1);
  818.         Inc(rcRect.Bottom, 1);
  819.         RedrawWindow(hCompWnd, @rcRect, 0, RDW_INVALIDATE);
  820.       end;
  821.     end;
  822.     WM_IME_ENDCOMPOSITION:  // you can destroy the composition window here
  823.       EndComp(hUIWnd);
  824.     WM_IME_NOTIFY:          // Ime通知消息组
  825.       NotifyUI(hUIWnd, wParam, lParam);
  826.     WM_IME_SETCONTEXT:      // 激活/休眠输入法
  827.     begin
  828.       SetContext(hUIWnd, Bool(wParam), lParam);
  829.       if (wParam <> 0) and (GetWindowLong(hUIWnd, IMMGWLP_IMC) <> 0) then
  830.         SetWindowPos(hUIWnd, 0, 0, 0, 0, 0, SWP_NOSIZE or SWP_NOACTIVATE or SWP_NOMOVE);
  831.     end;
  832.     WM_IME_CONTROL:         // Ime控制消息组
  833.       case (wParam) of
  834.         IMC_GETCANDIDATEPOS:      // not implemented yet
  835.         begin
  836.           Result := 1;
  837.         end;
  838.         IMC_GETCOMPOSITIONFONT:   // not implemented yet
  839.         begin
  840.           Result := 1;
  841.         end;
  842.         IMC_GETCOMPOSITIONWINDOW: // 取Composition窗口位置
  843.         begin
  844.           Result := GetCompWindow(hUIWnd, PCompositionForm(lParam));
  845.         end;
  846.         IMC_GETSTATUSWINDOWPOS:   // 取Status窗口位置
  847.         begin
  848.           hStatusWnd := GetStatusWnd(hUIWnd);
  849.           if IsWindow(hStatusWnd) = False then Exit;
  850.           if (GetWindowRect(hStatusWnd, rcStatusWnd) = False) then Exit;
  851.           Result := MakeLResult(rcStatusWnd.Left, rcStatusWnd.Top);
  852.         end;
  853.         IMC_SETSTATUSWINDOWPOS:   // 设Status窗口位置
  854.         begin
  855.           Result := 1;
  856.           ptPos.x := PSmallPoint(@lParam).x;
  857.           ptPos.y := PSmallPoint(@lParam).y;
  858.           _hIMC := GetWindowLong(hUIWnd, IMMGWLP_IMC);
  859.           if (_hIMC = 0) then Exit;
  860.           if (ImmSetStatusWindowPos(_hIMC, @ptPos) = False) then  Exit;
  861.           // set comp window position when TraceCuer
  862.           lpIMC := ImmLockIMC(_hIMC);
  863.           if (lpIMC = nil) then Exit;
  864.           lpImcP := ImmLockIMCC(lpIMC.hPrivate);
  865.           if (lpImcP = nil) then Exit;
  866.           if (sImeG.IC_Trace = 0) then
  867.           begin
  868.             lpIMC.cfCompForm.dwStyle := CFS_RECT;
  869.             lpIMC.cfCompForm.ptCurrentPos.x := ptPos.x + sImeG.xStatusWi + ui_Margin;
  870.             lpIMC.cfCompForm.ptCurrentPos.y := ptPos.y;
  871.             CopyRect(lpIMC.cfCompForm.rcArea, sImeG.rcWorkArea);
  872.             ScreenToClient(lpIMC.hWnd, lpIMC.cfCompForm.ptCurrentPos);
  873.             // set composition window to the new poosition
  874.             PostMessage(GetCompWnd(hUIWnd), WM_IME_NOTIFY, IMN_SETCOMPOSITIONWINDOW, 0);
  875.           end;
  876.           ImmUnlockIMCC(lpIMC.hPrivate);
  877.           ImmUnlockIMC(_hIMC);
  878.           Result := 0;
  879.         end;
  880.         else begin
  881.           Result := 1;
  882.         end;
  883.       end;
  884.     WM_IME_COMPOSITIONFULL:
  885.       ;
  886.     WM_IME_SELECT:                // 选中新的输入法
  887.       SetContext(hUIWnd, Bool(wParam), 0);
  888.     WM_MOUSEACTIVATE:
  889.       Result := MA_NOACTIVATE;
  890.     WM_PAINT:
  891.       Result := UIPaint(hUIWnd);
  892.     else
  893.       Result := DefWindowProc(hUIWnd, uMsg, wParam, lParam);
  894.   end;
  895. end;
  896.   // 绘制凸出边框
  897. procedure DrawConvexRect(_hDC: hDC; x1, y1, x2, y2: Integer);
  898. var
  899.   _hPen, hOldPen: hPen;
  900. begin
  901.   SelectObject(_hDC, GetStockObject(LTGRAY_BRUSH));
  902.   SelectObject(_hDC, GetStockObject(WHITE_PEN));
  903.   MoveToEx(_hDC, x1, y1, nil);
  904.   LineTo(_hDC, x2, y1);
  905.   MoveToEx(_hDC, x1, y1, nil);
  906.   LineTo(_hDC, x1, y2);
  907.   _hPen := CreatePen(PS_SOLID, 1, RGB(128, 128, 128));
  908.   hOldPen := SelectObject(_hDC, _hPen);
  909.   MoveToEx(_hDC, x2 - 1, y2 - 1, nil);
  910.   LineTo(_hDC, x2 - 1, y1);
  911.   MoveToEx(_hDC, x2 - 1, y2 - 1, nil);
  912.   LineTo(_hDC, x1, y2 - 1);
  913.   SelectObject(_hDC, hOldPen);
  914.   DeleteObject(_hPen);
  915. end;
  916.   // 绘制凸出边框
  917. procedure DrawConvexRectP(_hDC: hDC; x1, y1, x2, y2: Integer);
  918. var
  919.   _hPen, hOldPen: hPen;
  920. begin
  921.   SelectObject(_hDC, GetStockObject(LTGRAY_BRUSH));
  922.   SelectObject(_hDC, GetStockObject(WHITE_PEN));
  923.   MoveToEx(_hDC, x1, y1, nil);
  924.   LineTo(_hDC, x2 - 1, y1);
  925.   MoveToEx(_hDC, x1, y1, nil);
  926.   LineTo(_hDC, x1, y2 - 1);
  927.   _hPen := CreatePen(PS_SOLID, 1, RGB(0, 0, 0));
  928.   hOldPen := SelectObject(_hDC, _hPen);
  929.   MoveToEx(_hDC, x2 - 1, y2 - 1, nil);
  930.   LineTo(_hDC, x2 - 1, y1);
  931.   MoveToEx(_hDC, x2 - 1, y2 - 1, nil);
  932.   LineTo(_hDC, x1, y2 - 1);
  933.   SelectObject(_hDC, hOldPen);
  934.   DeleteObject(_hPen);
  935. end;
  936.   // 绘制凹陷边框
  937. procedure DrawConcaveRect(_hDC: hDC; x1, y1, x2, y2: Integer);
  938. var
  939.   hLtPen, OldPen: hPen;
  940. begin
  941.   hLtPen := CreatePen(PS_SOLID, 1, $00808080);
  942.   OldPen := SelectObject(_hDC, hLtPen);
  943.   MoveToEx(_hDC, x1, y1, nil);
  944.   LineTo(_hDC, x2, y1);
  945.   MoveToEx(_hDC, x1, y1, nil);
  946.   LineTo(_hDC, x1, y2);
  947.   SelectObject(_hDC, GetStockObject(WHITE_PEN));
  948.   MoveToEx(_hDC, x2, y2, nil);
  949.   LineTo(_hDC, x2, y1 - 1);
  950.   MoveToEx(_hDC, x2, y2, nil);
  951.   LineTo(_hDC, x1 - 1, y2);
  952.   SelectObject(_hDC, OldPen);
  953.   DeleteObject(hLtPen);
  954. end;
  955. end.