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

输入法编程

开发平台:

Delphi

  1.  {******************************************************}
  2.  {                                                      }
  3.  {    Copyright (c) 1990-1999 Microsoft Corporation     }
  4.  {                                                      }
  5.  {    Module Name:  Candui.c ->>  Candui.pas            }
  6.  {                                                      }
  7.  {    Translator:  Liu_mazi@126.com, 2005-11-17         }
  8.  {                                                      }
  9.  {******************************************************}
  10. unit Candui;
  11. {$I Define.Inc}
  12. interface
  13. uses Windows, ImmDev;
  14. function GetCandWnd(hUIWnd: hWnd): hWnd;  // 返回Candidate窗口句柄
  15. function CandWndProc(hCandWnd: hWnd; uMsg: uInt; wParam: WParam; lParam: LParam): LResult; stdcall;  // Candidate窗口回调
  16. procedure ShowCand(hUIWnd: hWnd; nShowCandCmd: Integer);  // 显示隐藏Candidate窗口
  17. procedure OpenCand(hUIWnd: hWnd);  // "打开"Candidate窗口
  18. procedure PaintCandWindow(hCandWnd: hWnd; _hDC: hDC);  // 绘制Candidate窗口
  19. procedure CloseCand(hUIWnd: hWnd);  // 隐藏Candidate窗口
  20. procedure CalcCandPos(_hIMC: hIMC; hUIWnd: hWnd; lpptWnd: PPoint); // 计算Candidate窗口位置
  21. implementation
  22. uses Messages, ImeDefs, Data, Notify, Ui, Uisubs, Compui, Chcand, LogText;
  23.   // 返回Candidate窗口句柄
  24. function GetCandWnd(hUIWnd: hWnd): hWnd;
  25. var
  26.   hUIPrivate: hGlobal;
  27.   lpUIPrivate: PUIPriv;
  28. begin
  29.   Result := 0;
  30.   hUIPrivate := GetWindowLong(hUIWnd, IMMGWLP_PRIVATE);
  31.   if (hUIPrivate = 0) then Exit;    // can not darw candidate window
  32.   lpUIPrivate := GlobalLock(hUIPrivate);
  33.   if (lpUIPrivate = nil) then Exit; // can not draw candidate window
  34.   Result := lpUIPrivate.hCandWnd;
  35.   GlobalUnlock(hUIPrivate);
  36. end;
  37.   // 计算Candidate窗口位置
  38. procedure CalcCandPos(_hIMC: hIMC; hUIWnd: hWnd; lpptWnd: PPoint);
  39. var
  40.   ptNew, ptSTWPos: TPoint;
  41.   hCompWnd: hWnd;
  42. begin
  43.   if (sImeG.IC_Trace = 0) then // 光标跟随 = False
  44.   begin
  45.     ImmGetStatusWindowPos(_hIMC, @ptSTWPos);
  46.     hCompWnd := GetCompWnd(hUIWnd);
  47.     if IsWindow(hCompWnd) then
  48.     begin
  49.       ptNew.x := ptSTWPos.x + sImeG.xStatusWi + sImeL.xCompWi + 2 * UI_MARGIN;
  50.       if (ptNew.x + sImeG.xCandWi > sImeG.rcWorkArea.Right) then
  51.       begin
  52.         if (ptSTWPos.x >= (sImeG.xCandWi + sImeL.xCompWi + 2 * UI_MARGIN)) then
  53.           ptNew.x := ptSTWPos.x - sImeL.xCompWi - sImeG.xCandWi - 2 * UI_MARGIN
  54.         else
  55.           ptNew.x := ptSTWPos.x + sImeG.xStatusWi + UI_MARGIN;
  56.       end;
  57.       ptNew.y := ptSTWPos.y + sImeL.cyCompBorder - sImeG.cyCandBorder;
  58.       if (ptNew.y + sImeG.yCandHi > sImeG.rcWorkArea.Bottom) then ptNew.y := sImeG.rcWorkArea.Bottom - sImeG.yCandHi;
  59.     end else
  60.     begin
  61.       ptNew.x := ptSTWPos.x + sImeG.xStatusWi + UI_MARGIN;
  62.       if (ptNew.x + sImeG.xCandWi >= sImeG.rcWorkArea.Right) and
  63.          (ptSTWPos.x >= sImeG.xCandWi + UI_MARGIN) then
  64.       begin
  65.         ptNew.x := ptSTWPos.x - sImeG.xCandWi - UI_MARGIN;
  66.       end;
  67.       ptNew.y := ptSTWPos.y + sImeL.cyCompBorder - sImeG.cyCandBorder;
  68.       if (ptNew.y + sImeG.yCandHi > sImeG.rcWorkArea.Bottom) then ptNew.y := sImeG.rcWorkArea.Bottom - sImeG.yCandHi;
  69.     end;
  70.   end else                     // 光标跟随 = True
  71.   begin
  72.     ptNew.x := lpptWnd.x + sImeL.xCompWi + UI_MARGIN;
  73.     if (ptNew.x + sImeG.xCandWi > sImeG.rcWorkArea.Right) then ptNew.x := lpptWnd.x - sImeG.xCandWi - UI_MARGIN;
  74.     ptNew.y := lpptWnd.y + sImeL.cyCompBorder - sImeG.cyCandBorder;
  75.     if (ptNew.y + sImeG.yCandHi > sImeG.rcWorkArea.Bottom) then ptNew.y := sImeG.rcWorkArea.Bottom - sImeG.yCandHi;
  76.   end;
  77.   lpptWnd^ := ptNew;
  78. end;
  79.   // 微调Candidate窗口位置
  80. procedure AdjustCandPos(_hIMC: hIMC; lpptWnd: PPoint);
  81. var
  82.   lpIMC: PInputContext;
  83.   ptFontHi: Integer;
  84.   uEsc: uInt;
  85. begin
  86.   lpIMC := ImmLockIMC(_hIMC);
  87.   if (lpIMC = nil) then Exit;
  88.   if (lpIMC.lfFont.A.lfHeight > 0) then
  89.   begin
  90.     ptFontHi := lpIMC.lfFont.A.lfHeight;
  91.   end else
  92.     if (lpIMC.lfFont.A.lfWidth = 0) then
  93.       ptFontHi := sImeL.yCompHi
  94.     else
  95.       ptFontHi := -lpIMC.lfFont.A.lfHeight;
  96.   if (ptFontHi > sImeL.yCompHi * 8) then ptFontHi := sImeL.yCompHi * 8;
  97.   if (ptFontHi < sImeG.yChiCharHi) then ptFontHi := sImeG.yChiCharHi;
  98.   // -450 to 450 index 0
  99.   // 450 to 1350 index 1
  100.   // 1350 to 2250 index 2
  101.   // 2250 to 3150 index 3
  102.   uEsc := (lpIMC.lfFont.A.lfEscapement + 450) div 900 mod 4;
  103.   // find the location after IME do an adjustment
  104.   ptFontHi := ptFontHi * ptInputEsc[uEsc].y;
  105.   if (lpptWnd.y + ptFontHi + sImeG.yCandHi <= sImeG.rcWorkArea.Bottom) then
  106.     Inc(lpptWnd.y, ptFontHi)
  107.   else
  108.     Dec(lpptWnd.y, ptFontHi + sImeG.yCandHi);
  109.   ImmUnlockIMC(_hIMC);
  110. end;
  111.   // 修正Candidate窗口位置
  112. procedure AdjustCandBoundry(lpptCandWnd: PPoint);
  113. begin
  114.   if (lpptCandWnd.x < sImeG.rcWorkArea.Left) then
  115.   begin
  116.     lpptCandWnd.x := sImeG.rcWorkArea.Left;
  117.   end else
  118.     if (lpptCandWnd.x + sImeG.xCandWi > sImeG.rcWorkArea.Right) then
  119.     begin
  120.       lpptCandWnd.x := sImeG.rcWorkArea.Right - sImeG.xCandWi;
  121.     end;
  122.   if (lpptCandWnd.y < sImeG.rcWorkArea.Top) then
  123.   begin
  124.     lpptCandWnd.y := sImeG.rcWorkArea.Top;
  125.   end else
  126.     if (lpptCandWnd.y + sImeG.yCandHi > sImeG.rcWorkArea.Bottom) then
  127.     begin
  128.       lpptCandWnd.y := sImeG.rcWorkArea.Bottom - sImeG.yCandHi;
  129.     end;
  130. end;
  131.   // 设置Candidate窗口位置
  132. function SetCandPosition(hCandWnd: hWnd): LResult;
  133. var
  134.   hUIWnd: hWnd;
  135.   _hIMC: hIMC;
  136.   lpIMC: PInputContext;
  137.   ptNew: TPoint;
  138. begin
  139.   Result := 1;
  140.   hUIWnd := GetWindow(hCandWnd, GW_OWNER);
  141.   if (IsWindow(hUIWnd) = False) then Exit;
  142.   _hIMC := GetWindowLong(hUIWnd, IMMGWLP_IMC);
  143.   if (_hIMC = 0) then Exit;
  144.   lpIMC := ImmLockIMC(_hIMC);
  145.   if (lpIMC = nil) then Exit;
  146.   ptNew := lpIMC.cfCandForm[0].ptCurrentPos;
  147.   ClientToScreen(lpIMC.hWnd, ptNew);
  148.   if ((lpIMC.cfCandForm[0].dwStyle and CFS_FORCE_POSITION) <> 0) then
  149.   begin
  150.   end else
  151.     if (lpIMC.cfCandForm[0].dwStyle = CFS_CANDIDATEPOS) then
  152.     begin
  153.       AdjustCandBoundry(@ptNew);
  154.     end else
  155.       if (lpIMC.cfCandForm[0].dwStyle = CFS_EXCLUDE) then
  156.       begin
  157.         if (sImeG.IC_Trace = 0) then CalcCandPos(_hIMC, hUIWnd, @ptNew);
  158.         AdjustCandBoundry(@ptNew);
  159.       end;
  160.   SetWindowPos(hCandWnd, 0, ptNew.x, ptNew.y, 0, 0, SWP_NOACTIVATE or SWP_NOSIZE or SWP_NOZORDER);
  161.   ImmUnlockIMC(_hIMC);
  162.   Result := 0;
  163. end;
  164.   // 显示隐藏Candidate窗口
  165. procedure ShowCand(hUIWnd: hWnd; nShowCandCmd: Integer);
  166. label
  167.   ShowCand;
  168. var
  169.   hUIPrivate: hGlobal;
  170.   lpUIPrivate: PUIPriv;
  171.   _hIMC: hIMC;
  172.   ptSTWPos: TPoint;  
  173.   Comp_CandWndLen: Integer;
  174. begin
  175.   hUIPrivate := GetWindowLong(hUIWnd, IMMGWLP_PRIVATE);
  176.   if (hUIPrivate = 0) then Exit;          // can not darw candidate window
  177.   lpUIPrivate := GlobalLock(hUIPrivate);
  178.   if (lpUIPrivate = nil) then Exit;       // can not draw candidate window
  179.   if (lpUIPrivate.nShowCandCmd = nShowCandCmd) then Exit; // **
  180.   if (nShowCandCmd = SW_HIDE) then
  181.     lpUIPrivate.fdwSetContext := lpUIPrivate.fdwSetContext and (not ISC_HIDE_CAND_WINDOW);
  182.   if IsWindow(lpUIPrivate.hCandWnd) then
  183.     if (lpUIPrivate.nShowCandCmd = nShowCandCmd) then // 无变化
  184.     begin
  185.     end else
  186.     begin
  187.       if (nShowCandCmd = SW_HIDE) then
  188.       begin
  189.         uOpenCand := 0;
  190.       end else
  191.       begin
  192.         uOpenCand := 1;
  193.         // reset status window for LINE_UI(FIX_UI)
  194.         _hIMC := GetWindowLong(hUIWnd, IMMGWLP_IMC);
  195.         if (_hIMC = 0) then goto ShowCand;
  196.         ImmGetStatusWindowPos(_hIMC, @ptSTWPos);
  197.         Comp_CandWndLen := 0;
  198.         if (uOpenCand <> 0) then
  199.         begin
  200.           Inc(Comp_CandWndLen, sImeG.xCandWi + UI_MARGIN);
  201.           if (uStartComp <> 0) then Inc(Comp_CandWndLen, sImeL.xCompWi + UI_MARGIN);
  202.           if (ptSTWPos.x + sImeG.xStatusWi + Comp_CandWndLen > sImeG.rcWorkArea.Right) then
  203.             PostMessage(GetCompWnd(hUIWnd), WM_IME_NOTIFY, IMN_SETCOMPOSITIONWINDOW, 0);
  204.         end;
  205.       end;
  206. ShowCand:
  207.       ShowWindow(lpUIPrivate.hCandWnd, nShowCandCmd);
  208.       lpUIPrivate.nShowCandCmd := nShowCandCmd;
  209.     end;
  210.   GlobalUnlock(hUIPrivate);
  211. end;
  212.   // "打开"Candidate窗口
  213. procedure OpenCand(hUIWnd: hWnd);
  214. label
  215.   OpenCandUnlockUIPriv;
  216. var
  217.   hUIPrivate: hGlobal;
  218.   lpUIPrivate: PUIPriv;
  219.   _hIMC: hIMC;
  220.   lpIMC: PInputContext;
  221.   ptWnd, ptCaret: TPoint;
  222. begin
  223.   hUIPrivate := GetWindowLong(hUIWnd, IMMGWLP_PRIVATE);
  224.   if (hUIPrivate = 0) then Exit;          // can not darw candidate window
  225.   lpUIPrivate := GlobalLock(hUIPrivate);
  226.   if (lpUIPrivate = nil) then Exit;       // can not draw candidate window
  227.   lpUIPrivate.fdwSetContext := lpUIPrivate.fdwSetContext or ISC_SHOWUICANDIDATEWINDOW;
  228.   _hIMC := GetWindowLong(hUIWnd, IMMGWLP_IMC);
  229.   if (_hIMC = 0) then goto OpenCandUnlockUIPriv;
  230.   lpIMC := ImmLockIMC(_hIMC);
  231.   if (lpIMC = nil) then goto OpenCandUnlockUIPriv;
  232.   if (lpIMC.cfCandForm[0].dwIndex = 0) then
  233.   begin
  234.     ptWnd := lpIMC.cfCandForm[0].ptCurrentPos;
  235.     ClientToScreen(lpIMC.hWnd, ptWnd);
  236.     if (lpIMC.cfCandForm[0].dwStyle and CFS_FORCE_POSITION) <> 0 then
  237.     begin
  238.     end else
  239.     begin
  240.       if (lpIMC.cfCandForm[0].dwStyle = CFS_EXCLUDE) then
  241.       begin
  242.         AdjustCandBoundry(@ptWnd);
  243.         if (sImeG.IC_Trace = 0) or (GetCaretPos(ptCaret) = False) then // **
  244.         begin
  245.           if IsWindow(GetCompWnd(hUIWnd)) then
  246.           begin
  247.             ptWnd.x := 0;
  248.             ptWnd.y := 0;
  249.             ClientToScreen(lpIMC.hWnd, ptWnd);
  250.             Dec(ptWnd.x, sImeL.cxCompBorder + 1);
  251.             Dec(ptWnd.y, sImeL.cyCompBorder + 1);
  252.           end else
  253.           begin
  254.             ptWnd.x := sImeL.cxCompBorder + 1;
  255.             ptWnd.y := sImeL.cyCompBorder + 1;
  256.           end;
  257.           CalcCandPos(_hIMC, hUIWnd, @ptWnd);
  258.           lpIMC.cfCandForm[0].dwStyle := lpIMC.cfCandForm[0].dwStyle or CFS_CANDIDATEPOS;
  259.           lpIMC.cfCandForm[0].ptCurrentPos := ptWnd;
  260.           ScreenToClient(lpIMC.hWnd, lpIMC.cfCandForm[0].ptCurrentPos);
  261.         end else
  262.         begin
  263.           AdjustCandPos(_hIMC, @ptWnd);
  264.         end;
  265.       end else
  266.         if (lpIMC.cfCandForm[0].dwStyle = CFS_CANDIDATEPOS) then
  267.         begin
  268.           AdjustCandBoundry(@ptWnd);
  269.         end else
  270.         begin
  271.           if (lpUIPrivate.nShowCompCmd <> SW_HIDE) then
  272.           begin
  273.             ptWnd.x := 0;
  274.             ptWnd.y := 0;
  275.             ClientToScreen(lpUIPrivate.hCompWnd, ptWnd);
  276.           end else
  277.           begin
  278.             ptWnd := lpIMC.cfCompForm.ptCurrentPos;
  279.             ClientToScreen(lpIMC.hWnd, ptWnd);
  280.           end;
  281.           Dec(ptWnd.x, sImeL.cxCompBorder + 1);
  282.           Dec(ptWnd.y, sImeL.cyCompBorder + 1);
  283.           CalcCandPos(_hIMC, hUIWnd, @ptWnd);
  284.           lpIMC.cfCandForm[0].dwStyle := lpIMC.cfCandForm[0].dwStyle or CFS_CANDIDATEPOS;
  285.           lpIMC.cfCandForm[0].ptCurrentPos := ptWnd;
  286.           ScreenToClient(lpIMC.hWnd, lpIMC.cfCandForm[0].ptCurrentPos);
  287.         end;
  288.     end;
  289.   end else
  290.   begin
  291.     // make cand windows trace comp window !
  292.     if (lpUIPrivate.nShowCompCmd <> SW_HIDE) then
  293.     begin
  294.       ptWnd.x := 0;
  295.       ptWnd.y := 0;
  296.       ClientToScreen(lpUIPrivate.hCompWnd, ptWnd);
  297.     end else
  298.     begin
  299.       ptWnd := lpIMC.cfCompForm.ptCurrentPos;
  300.       ClientToScreen(lpIMC.hWnd, ptWnd);
  301.     end;
  302.     Dec(ptWnd.x, sImeL.cxCompBorder + 1);
  303.     Dec(ptWnd.y, sImeL.cyCompBorder + 1);
  304.     CalcCandPos(_hIMC, hUIWnd, @ptWnd);
  305.     lpIMC.cfCandForm[0].dwStyle := lpIMC.cfCandForm[0].dwStyle or CFS_CANDIDATEPOS;
  306.     lpIMC.cfCandForm[0].ptCurrentPos := ptWnd;
  307.     ScreenToClient(lpIMC.hWnd, lpIMC.cfCandForm[0].ptCurrentPos);
  308.   end;
  309.   ImmUnlockIMC(_hIMC);
  310.   if IsWindow(lpUIPrivate.hCandWnd) then
  311.   begin
  312.     SetWindowPos(lpUIPrivate.hCandWnd, 0, ptWnd.x, ptWnd.y, 0, 0, SWP_NOACTIVATE or SWP_NOSIZE or SWP_NOZORDER);
  313.   end else
  314.   begin
  315.     lpUIPrivate.hCandWnd := CreateWindowEx(WS_EX_WINDOWEDGE or WS_EX_DLGMODALFRAME,
  316.       szCandClassName, nil, WS_POPUP or WS_DISABLED, ptWnd.x, ptWnd.y,
  317.       sImeG.xCandWi, sImeG.yCandHi, hUIWnd, 0, HInstance, nil);
  318.     SetWindowLong(lpUIPrivate.hCandWnd, UI_MOVE_OFFSET, WINDOW_NOT_DRAG);
  319.     SetWindowLong(lpUIPrivate.hCandWnd, UI_MOVE_XY, 0);
  320.   end;
  321.   ShowCand(hUIWnd, SW_SHOWNOACTIVATE);
  322. OpenCandUnlockUIPriv:
  323.   GlobalUnlock(hUIPrivate);
  324. end;
  325.   // 隐藏Candidate窗口
  326. procedure CloseCand(hUIWnd: hWnd);
  327. begin
  328.   uOpenCand := 0;
  329.   ShowCand(hUIWnd, SW_HIDE);
  330. end;
  331.   // WM_DESTROY消息处理
  332. procedure DestroyCandWindow(hCandWnd: hWnd);
  333. var
  334.   hUIPrivate: hGlobal;
  335.   lpUIPrivate: PUIPriv;
  336. begin
  337.   if (GetWindowLong(hCandWnd, UI_MOVE_OFFSET) <> WINDOW_NOT_DRAG) then  // undo the drag border
  338.     DrawDragBorder(hCandWnd, GetWindowLong(hCandWnd, UI_MOVE_XY), GetWindowLong(hCandWnd, UI_MOVE_OFFSET));
  339.   hUIPrivate := GetWindowLong(GetWindow(hCandWnd, GW_OWNER), IMMGWLP_PRIVATE);
  340.   if (hUIPrivate = 0) then Exit;    // can not darw candidate window
  341.   lpUIPrivate := GlobalLock(hUIPrivate);
  342.   if (lpUIPrivate = nil) then Exit; // can not draw candidate window
  343.   lpUIPrivate.nShowCandCmd := SW_HIDE;
  344.   lpUIPrivate.hCandWnd := 0;
  345.   GlobalUnlock(hUIPrivate);
  346. end;
  347.   // 鼠标点击选择汉字
  348. procedure MouseSelectCandStr(hCandWnd: hWnd; lpCursor: PPoint);
  349. var
  350.   _hIMC: hIMC;
  351.   lpIMC: PInputContext;
  352.   lpCandInfo: PCandiDateInfo;
  353.   lpCandList: PCandiDateList;
  354.   dwValue: DWord;
  355. begin
  356.   _hIMC := GetWindowLong(GetWindow(hCandWnd, GW_OWNER), IMMGWLP_IMC);
  357.   if (_hIMC = 0) then Exit;
  358.   lpIMC := ImmLockIMC(_hIMC);
  359.   if (lpIMC = nil) then Exit;
  360.   if (lpIMC.hCandInfo = 0) then
  361.   begin
  362.     ImmUnlockIMC(_hIMC);
  363.     Exit;
  364.   end;
  365.   lpCandInfo := ImmLockIMCC(lpIMC.hCandInfo);
  366.   if (lpCandInfo = nil) then
  367.   begin
  368.     ImmUnlockIMC(_hIMC);
  369.     Exit;
  370.   end;
  371.   dwValue := (lpCursor.y - sImeG.rcCandText.Top) div sImeG.yChiCharHi; // **
  372.   lpCandList := PCandidateList(DWord(lpCandInfo) + lpCandInfo.dwOffset[0]);
  373.   dwValue := dwValue + lpCandList.dwSelection div lpCandList.dwPageSize * lpCandList.dwPageSize;
  374.   if (dwValue >= lpCandList.dwCount) then MessageBeep($FFFFFFFF)  // invalid choice
  375.   else NotifyIME(_hIMC, NI_SELECTCANDIDATESTR, 0, dwValue);
  376.   ImmUnlockIMCC(lpIMC.hCandInfo);
  377.   ImmUnlockIMC(_hIMC);
  378. end;
  379.   // Candidate窗口翻页
  380. procedure CandPageDownUP(hCandWnd: hWnd; uCandDownUp: uInt);
  381. var
  382.   _hIMC: hIMC;
  383.   lpIMC: PInputContext;
  384.   lpImcP: PPrivContext;
  385.   lpCandInfo: PCandiDateInfo;
  386.  // lpCandList: PCandiDateList;
  387.   _hDC: hDC;
  388.   hCandHpBmp, hCandUpBmp, hCandDpBmp, hCandEpBmp, hOldBmp: hBitmap;
  389.   hMemDC: hDC;
  390. begin
  391.   // change candlist
  392.   _hIMC := GetWindowLong(GetWindow(hCandWnd, GW_OWNER), IMMGWLP_IMC);
  393.   if (_hIMC = 0) then Exit;
  394.   // get lpIMC
  395.   lpIMC := ImmLockIMC(_hIMC);
  396.   if (lpIMC = nil) then Exit;
  397.   // get lpImcP
  398.   lpImcP := ImmLockIMCC(lpIMC.hPrivate);
  399.   if (lpImcP = nil) then Exit;
  400.   // get lpCandInfo
  401.   lpCandInfo := ImmLockIMCC(lpIMC.hCandInfo);
  402.   if (lpCandInfo = nil) then Exit;
  403.   // get lpCandList and init dwCount & dwSelection, 未用到, --
  404.   // lpCandList := PCandiDateList(DWord(lpCandInfo) + lpCandInfo.dwOffset[0]);
  405.   case (uCandDownUp) of
  406.     uCandHome:
  407.     begin
  408.       ChooseCand($24, lpIMC, lpCandInfo, lpImcP);
  409.       NotifyIME(_hIMC, NI_CHANGECANDIDATELIST, 0, 0);
  410.     end;
  411.     uCandUp:
  412.     begin
  413.       ChooseCand(Ord('-'), lpIMC, lpCandInfo, lpImcP);
  414.       NotifyIME(_hIMC, NI_CHANGECANDIDATELIST, 0, 0);
  415.     end;
  416.     uCandDown:
  417.     begin
  418.       ChooseCand(Ord('='), lpIMC, lpCandInfo, lpImcP);
  419.       NotifyIME(_hIMC, NI_CHANGECANDIDATELIST, 0, 0);
  420.     end;
  421.     uCandEnd:
  422.     begin
  423.       ChooseCand($0023, lpIMC, lpCandInfo, lpImcP);
  424.       NotifyIME(_hIMC, NI_CHANGECANDIDATELIST, 0, 0);
  425.     end;
  426.   end;
  427.   ImmUnlockIMCC(lpIMC.hPrivate);
  428.   ImmUnlockIMCC(lpIMC.hCandInfo);
  429.   ImmUnlockIMC(_hIMC);
  430.   // draw button down
  431.   _hDC := GetDC(hCandWnd);
  432.   hCandHpBmp := LoadBitmap(HInstance, 'CandHp');
  433.   hCandUpBmp := LoadBitmap(HInstance, 'CandUp');
  434.   hCandDpBmp := LoadBitmap(HInstance, 'CandDp');
  435.   hCandEpBmp := LoadBitmap(HInstance, 'CandEp');
  436.   hMemDC := CreateCompatibleDC(_hDC);
  437.   case (uCandDownUp) of
  438.     uCandHome:
  439.     begin
  440.       hOldBmp := SelectObject(hMemDC, hCandHpBmp);
  441.       BitBlt(_hDC, sImeG.rcCandBTH.Left, sImeG.rcCandBTH.Top,
  442.         sImeG.rcCandBTH.Right - sImeG.rcCandBTH.Left, STATUS_DIM_Y, hMemDC, 0, 0, SRCCOPY);
  443.     end;
  444.     uCandUp:
  445.     begin
  446.       hOldBmp := SelectObject(hMemDC, hCandUpBmp);
  447.       BitBlt(_hDC, sImeG.rcCandBTU.Left, sImeG.rcCandBTU.Top,
  448.         sImeG.rcCandBTU.Right - sImeG.rcCandBTU.Left, STATUS_DIM_Y, hMemDC, 0, 0, SRCCOPY);
  449.     end;
  450.     uCandDown:
  451.     begin
  452.       hOldBmp := SelectObject(hMemDC, hCandDpBmp);
  453.       BitBlt(_hDC, sImeG.rcCandBTD.Left, sImeG.rcCandBTD.Top,
  454.         sImeG.rcCandBTD.Right - sImeG.rcCandBTD.Left, STATUS_DIM_Y, hMemDC, 0, 0, SRCCOPY);
  455.     end;
  456.     uCandEnd:
  457.     begin
  458.       hOldBmp := SelectObject(hMemDC, hCandEpBmp);
  459.       BitBlt(_hDC, sImeG.rcCandBTE.Left, sImeG.rcCandBTE.Top,
  460.         sImeG.rcCandBTE.Right - sImeG.rcCandBTE.Left, STATUS_DIM_Y, hMemDC, 0, 0, SRCCOPY);
  461.     end;
  462.     else hOldBmp := 0;
  463.   end;
  464.   SelectObject(hMemDC, hOldBmp);
  465.   DeleteDC(hMemDC);
  466.   DeleteObject(hCandEpBmp);
  467.   DeleteObject(hCandDpBmp);
  468.   DeleteObject(hCandUpBmp);
  469.   DeleteObject(hCandHpBmp);
  470.   ReleaseDC(hCandWnd, _hDC);
  471. end;
  472.   // WM_SETCURSOR消息处理
  473. procedure CandSetCursor(hCandWnd: hWnd; lParam: LParam);
  474. var
  475.   ptCursor: TPoint;
  476.   rcWnd: TRect;
  477.   _hDC, hMemDC: hDC;
  478.   hCandHBmp, hCandUBmp, hCandDBmp, hCandEBmp, hOldBmp: hBitmap;
  479. begin
  480.   if (GetWindowLong(hCandWnd, UI_MOVE_OFFSET) <> WINDOW_NOT_DRAG) then
  481.   begin
  482.     SetCursor(LoadCursor(0, IDC_SIZEALL));
  483.     Exit;
  484.   end;
  485.   if (HiWord(lParam) = WM_LBUTTONDOWN) then
  486.   begin
  487.     SystemParametersInfo(SPI_GETWORKAREA, 0, @sImeG.rcWorkArea, 0);
  488.     GetCursorPos(ptCursor);
  489.     ScreenToClient(hCandWnd, ptCursor);
  490.     if PtInRect(sImeG.rcCandText, ptCursor) // 文字
  491.        and (sImeG.IC_Trace <> 0) then
  492.     begin
  493.       SetCursor(LoadCursor(HInstance, szHandCursor));
  494.       MouseSelectCandStr(hCandWnd, @ptCursor);
  495.     end else
  496.       if PtInRect(sImeG.rcCandBTH, ptCursor) then // 首页
  497.       begin
  498.         CandPageDownUP(hCandWnd, uCandHome);
  499.       end else
  500.         if PtInRect(sImeG.rcCandBTU, ptCursor) then // 上翻
  501.         begin
  502.           CandPageDownUP(hCandWnd, uCandUp);
  503.         end else
  504.           if PtInRect(sImeG.rcCandBTD, ptCursor) then // 下翻
  505.           begin
  506.             CandPageDownUP(hCandWnd, uCandDown);
  507.           end else
  508.             if (PtInRect(sImeG.rcCandBTE, ptCursor)) then // 末页
  509.             begin
  510.               CandPageDownUP(hCandWnd, uCandEnd);
  511.             end else
  512.             begin
  513.               SetCursor(LoadCursor(0, IDC_SIZEALL));
  514.               SetCapture(hCandWnd);
  515.               GetCursorPos(ptCursor);
  516.               SetWindowLong(hCandWnd, UI_MOVE_XY, MakeLong(ptCursor.x, ptCursor.y));
  517.               GetWindowRect(hCandWnd, rcWnd);
  518.               SetWindowLong(hCandWnd, UI_MOVE_OFFSET, MakeLong(ptCursor.x - rcWnd.Left, ptCursor.y - rcWnd.Top));
  519.               
  520.               DrawDragBorder(hCandWnd, MakeLong(ptCursor.x, ptCursor.y), GetWindowLong(hCandWnd, UI_MOVE_OFFSET));
  521.             end;
  522.   end else
  523.     if (HiWord(lParam) = WM_LBUTTONUP) then
  524.     begin
  525.       _hDC := GetDC(hCandWnd);
  526.       hCandHBmp := LoadBitmap(HInstance, 'CandH');
  527.       hCandUBmp := LoadBitmap(HInstance, 'CandU');
  528.       hCandDBmp := LoadBitmap(HInstance, 'CandD');
  529.       hCandEBmp := LoadBitmap(HInstance, 'CandE');
  530.       hMemDC := CreateCompatibleDC(_hDC);
  531.       hOldBmp := SelectObject(hMemDC, hCandHBmp);
  532.       BitBlt(_hDC, sImeG.rcCandBTH.Left, sImeG.rcCandBTH.Top,
  533.         sImeG.rcCandBTH.Right - sImeG.rcCandBTH.Left, STATUS_DIM_Y, hMemDC, 0, 0, SRCCOPY);
  534.       SelectObject(hMemDC, hCandUBmp);
  535.       BitBlt(_hDC, sImeG.rcCandBTU.Left, sImeG.rcCandBTU.Top,
  536.         sImeG.rcCandBTU.Right - sImeG.rcCandBTU.Left, STATUS_DIM_Y, hMemDC, 0, 0, SRCCOPY);
  537.       SelectObject(hMemDC, hCandDBmp);
  538.       BitBlt(_hDC, sImeG.rcCandBTD.Left, sImeG.rcCandBTD.Top,
  539.         sImeG.rcCandBTD.Right - sImeG.rcCandBTD.Left, STATUS_DIM_Y, hMemDC, 0, 0, SRCCOPY);
  540.       SelectObject(hMemDC, hCandEBmp);
  541.       BitBlt(_hDC, sImeG.rcCandBTE.Left, sImeG.rcCandBTE.Top,
  542.         sImeG.rcCandBTE.Right - sImeG.rcCandBTE.Left, STATUS_DIM_Y, hMemDC, 0, 0, SRCCOPY);
  543.       SelectObject(hMemDC, hOldBmp);
  544.       DeleteObject(hCandEBmp);
  545.       DeleteObject(hCandDBmp);
  546.       DeleteObject(hCandUBmp);
  547.       DeleteObject(hCandEBmp);
  548.       DeleteDC(hMemDC);
  549.       ReleaseDC(hCandWnd, _hDC);
  550.     end else
  551.     begin
  552.       SystemParametersInfo(SPI_GETWORKAREA, 0, @sImeG.rcWorkArea, 0);
  553.       GetCursorPos(ptCursor);
  554.       ScreenToClient(hCandWnd, ptCursor);
  555.       if PtInRect(sImeG.rcCandText, ptCursor) then
  556.       begin
  557.         SetCursor(LoadCursor(HInstance, szHandCursor));
  558.       end else
  559.         if PtInRect(sImeG.rcCandBTH, ptCursor) or
  560.            PtInRect(sImeG.rcCandBTU, ptCursor) or
  561.            PtInRect(sImeG.rcCandBTD, ptCursor) or
  562.            PtInRect(sImeG.rcCandBTE, ptCursor) then
  563.         begin
  564.           SetCursor(LoadCursor(HInstance, szHandCursor));
  565.         end else
  566.           SetCursor(LoadCursor(0, IDC_SIZEALL));
  567.     end;
  568. end;
  569.   // WM_LBUTTONUP消息处理
  570. function CandButtonUp(hCandWnd: hWnd): Bool;
  571. var
  572.   lTmpCursor, lTmpOffset: DWord;
  573.   pt: TPoint;
  574.   hUIWnd: hWnd;
  575.   _hIMC: hIMC;
  576.   lpIMC: PInputContext;
  577. begin
  578.   Result := False;
  579.   // Candidate 窗口未处于"拖拽"状态
  580.   if (GetWindowLong(hCandWnd, UI_MOVE_OFFSET) = WINDOW_NOT_DRAG) then Exit;
  581.   lTmpCursor := GetWindowLong(hCandWnd, UI_MOVE_XY);
  582.   lTmpOffset := GetWindowLong(hCandWnd, UI_MOVE_OFFSET);
  583.   // calculate the org by the offset
  584.   pt.x := PSmallPoint(@lTmpCursor).x - PSmallPoint(@lTmpOffset).x;
  585.   pt.y := PSmallPoint(@lTmpCursor).y - PSmallPoint(@lTmpOffset).y;
  586.   DrawDragBorder(hCandWnd, lTmpCursor, lTmpOffset);
  587.   SetWindowLong(hCandWnd, UI_MOVE_OFFSET, WINDOW_NOT_DRAG);
  588.   ReleaseCapture();
  589.   hUIWnd := GetWindow(hCandWnd, GW_OWNER);
  590.   if IsWindow(hUIWnd) = False then Exit;
  591.   _hIMC := GetWindowLong(hUIWnd, IMMGWLP_IMC);
  592.   if (_hIMC = 0) then Exit;
  593.   lpIMC := ImmLockIMC(_hIMC);
  594.   if (lpIMC = nil) then Exit;
  595.   AdjustCandBoundry(@pt);
  596.   ScreenToClient(lpIMC.hWnd, pt);
  597.   lpIMC.cfCandForm[0].dwStyle := lpIMC.cfCandForm[0].dwStyle or CFS_CANDIDATEPOS;
  598.   lpIMC.cfCandForm[0].ptCurrentPos := pt;
  599.   ImmUnlockIMC(_hIMC);
  600.   
  601.   PostMessage(hCandWnd, WM_IME_NOTIFY, IMN_SETCANDIDATEPOS, $0001);
  602.   Result := True;
  603. end;
  604.   // 绘制Candidate窗口
  605. procedure PaintCandWindow(hCandWnd: hWnd; _hDC: hDC);
  606. label
  607.   UpCandW2UnlockIMC, UpCandW2UnlockCandInfo;
  608. var
  609.   _hIMC: hIMC;
  610.   lpIMC: PInputContext;
  611.   lpCandInfo: PCandiDateInfo;
  612.   lpCandList: PCandiDateList;
  613.   lpImcP: PPrivContext;
  614.   hOldFont: hGdiObj;
  615.   dwStart, dwEnd: DWord;
  616.   szStrBuf: array[0..2 * MAXSTRLEN + 1] of Char;
  617.   szMyStrBuf: array[0..12] of Char;
  618.   iLen, I, J, K, X, StrLen: Integer;
  619.   hCandIconBmp, hCandInfBmp: hBitmap;
  620.   hOldBmp, hCandHBmp, hCandUBmp, hCandDBmp, hCandEBmp: hBitmap;
  621.   hMemDC: hDC;
  622.   lfFont: TLogFont;
  623.   rcWnd: TRect;
  624.   wCode, wGB: Word;
  625.   AbSeq: array[0..4] of Char;
  626.   GbSeq: array[0..4] of Char;
  627.   GBARInfo: TRect;
  628.   AnsiStr: array[0..MAXCODE] of Char;
  629.   StrSize: TSize;
  630.   ArgList: array[0..1] of DWord;
  631. begin
  632.   _hIMC := GetWindowLong(GetWindow(hCandWnd, GW_OWNER), IMMGWLP_IMC);
  633.   if (_hIMC = 0) then Exit;
  634.   lpIMC := ImmLockIMC(_hIMC);
  635.   if (lpIMC = nil) then Exit;
  636.   if (lpIMC.hCandInfo = 0) then goto UpCandW2UnlockIMC;
  637.   lpCandInfo := ImmLockIMCC(lpIMC.hCandInfo);
  638.   if (lpCandInfo = nil) then goto UpCandW2UnlockIMC;
  639.   if (lpIMC.hPrivate = 0) then goto UpCandW2UnlockCandInfo;
  640.   lpImcP := ImmLockIMCC(lpIMC.hPrivate);
  641.   if (lpImcP = nil) then goto UpCandW2UnlockCandInfo;
  642.   // set font
  643.   if (sImeG.fDiffSysCharSet) then
  644.   begin
  645.     hOldFont := GetCurrentObject(_hDC, OBJ_FONT);
  646.     ZeroMemory(@lfFont, SizeOf(TLogFont));
  647.     lfFont.lfHeight := -MulDiv(12, GetDeviceCaps(_hDC, LOGPIXELSY), 72);
  648.     lfFont.lfCharSet := NATIVE_CHARSET;
  649.     lStrCpy(lfFont.lfFaceName, '宋体');
  650.     SelectObject(_hDC, CreateFontIndirect(lfFont));
  651.   end else
  652.     hOldFont := 0;
  653.   lpCandList := PCandiDateList(DWord(lpCandInfo) + lpCandInfo.dwOffset[0]);
  654.   dwStart := lpCandList.dwSelection;
  655.   dwEnd := dwStart + lpCandList.dwPageSize;
  656.   if (dwEnd > lpCandList.dwCount) then dwEnd := lpCandList.dwCount;
  657.   // 凹陷边框
  658.   if (sImeG.IC_Trace <> 0) then
  659.   begin
  660.     GetClientRect(hCandWnd, rcWnd);
  661.     DrawConcaveRect(_hDC, rcWnd.Left, rcWnd.Top + UI_CANDINF, rcWnd.Right - 1, rcWnd.Bottom - 1);
  662.   end else
  663.   begin
  664.     GetClientRect(hCandWnd, rcWnd);
  665.     DrawConcaveRect(_hDC, sImeG.rcCandText.Left - 1, rcWnd.Top, sImeG.rcCandText.Right + 1, rcWnd.Bottom - 1);
  666.   end;
  667.   // 黑字灰底
  668.   SetTextColor(_hDC, RGB($00, $00, $00));
  669.   SetBkColor(_hDC, RGB($C0, $C0, $C0));
  670.   if (sImeG.IC_Trace <> 0) then
  671.   begin
  672.     ExtTextOut(_hDC, sImeG.rcCandText.Left, sImeG.rcCandText.Top, ETO_OPAQUE, @sImeG.rcCandText, nil, 0, nil);
  673.     szStrBuf[0] := '1'; // **
  674.     szStrBuf[1] := ':';
  675.     I := 0;
  676.     while (dwStart < dwEnd) do
  677.     begin
  678.       // I 行文字
  679.       szStrBuf[0] := szDigit[I + CAND_START];
  680.       iLen := lStrLen(PChar(DWord(lpCandList) + lpCandList.dwOffset[dwStart]));
  681.       if (iLen > 10 * 2) then
  682.       begin
  683.         iLen := 10 * 2;
  684.         CopyMemory(@szStrBuf[2], Pointer(DWord(lpCandList) + lpCandList.dwOffset[dwStart]), iLen - 2);
  685.         szStrBuf[iLen] := '.';
  686.         szStrBuf[iLen + 1] := '.';
  687.         szStrBuf[iLen + 2] := #0;
  688.       end else
  689.       begin
  690.         CopyMemory(@szStrBuf[2], Pointer(DWord(lpCandList) + lpCandList.dwOffset[dwStart]), iLen);
  691.       end;
  692.       ExtTextOut(_hDC, sImeG.rcCandText.Left,
  693.         sImeG.rcCandText.Top + I * sImeG.yChiCharHi, 0, nil, szStrBuf, iLen + 2, nil);
  694.       // QW/GB info
  695.       wCode := PUnaWord(DWord(lpCandList) + lpCandList.dwOffset[dwStart])^;
  696.       wCode := HiByte(wCode) or (LoByte(wCode) shl 8);
  697.       ArgList[0] := wCode;
  698.       wvsprintf(GbSeq, '%04lx', @ArgList);    // get GB string
  699.       Dec(wCode, $A0A0);
  700.       ArgList[0] := HiByte(wCode);
  701.       ArgList[1] := LoByte(wCode);
  702.       wvsprintf(AbSeq, '%02d%02d', @ArgList); // get QW string
  703.       ArgList[0] := DWord(@GbSeq);
  704.       ArgList[1] := DWord(@AbSeq);
  705.       wvsprintf(szMyStrBuf, '(%s,%s)', @ArgList);
  706.       GBARInfo.Top := sImeG.rcCandText.Top + I * sImeG.yChiCharHi;
  707.       GBARInfo.Left := sImeG.rcCandText.Left;
  708.       GBARInfo.Right := sImeG.rcCandText.Right;
  709.       GBARInfo.Bottom := sImeG.rcCandText.Bottom;
  710.       DrawText(_hDC, szMyStrBuf, lStrLen(szMyStrBuf), GBARInfo, DT_RIGHT or DT_SINGLELINE);
  711.       // Next ..
  712.       Inc(dwStart);
  713.       Inc(I);
  714.     end; // while (dwStart < dwEnd) do ..
  715.   end else
  716.   begin
  717.     ExtTextOut(_hDC, sImeG.rcCandText.Left, sImeG.rcCandText.Top + 1, ETO_OPAQUE, @sImeG.rcCandText, nil, 0, nil);
  718.     X := 0;
  719.     I := 0;
  720.     while (dwStart < dwEnd) do
  721.     begin
  722.       // display numbers
  723.       AnsiStr[0] := szDigit[I + CAND_START];
  724.       AnsiStr[1] := ':';
  725.       AnsiStr[2] := #0;
  726.       ExtTextOut(_hDC, sImeG.rcCandText.Left + X, sImeG.rcCandText.Top + 1,
  727.         ETO_CLIPPED, @sImeG.rcCandText, AnsiStr, lStrLen(AnsiStr), nil);
  728.       if (GetTextExtentPoint(_hDC, AnsiStr, lStrLen(AnsiStr), StrSize) = False) then
  729.         ZeroMemory(@StrSize, SizeOf(TSize)); // **
  730.       Inc(X, StrSize.cx);
  731.       // display chinese word and code
  732.       iLen := lStrLen(PChar(DWord(lpCandList) + lpCandList.dwOffset[dwStart]));
  733.       CopyMemory(@szStrBuf, PChar(DWord(lpCandList) + lpCandList.dwOffset[dwStart]), iLen);
  734.       J := 0;
  735.       while (J < iLen) do  // 定位到第一个英文字母, ??
  736.       begin
  737.         if (Ord(szStrBuf[J]) and $80) <> 0 then
  738.         begin
  739.           Inc(J, 2);
  740.           Continue;
  741.         end else
  742.           Break;
  743.       end;
  744.       K := J - 1; // **
  745.       J := 0;
  746.       while (J < iLen - K) do
  747.       begin
  748.         AnsiStr[J] := szStrBuf[J + K];
  749.         Inc(J);
  750.       end;
  751.       
  752.       AnsiStr[J] := #0;
  753.       szStrBuf[K] := #0;
  754.       ExtTextOut(_hDC, sImeG.rcCandText.Left + X, sImeG.rcCandText.Top + 1,
  755.         ETO_CLIPPED, @sImeG.rcCandText, szStrBuf, lStrLen(szStrBuf), nil);
  756.       if (GetTextExtentPoint(_hDC, szStrBuf, lStrLen(szStrBuf), StrSize) = False) then
  757.         ZeroMemory(@StrSize, SizeOf(TSize));
  758.       Inc(X, StrSize.cx);
  759.       ExtTextOut(_hDC, sImeG.rcCandText.Left + X, sImeG.rcCandText.Top + 1,
  760.         ETO_CLIPPED, @sImeG.rcCandText, AnsiStr, lStrLen(AnsiStr), nil);
  761.       if (GetTextExtentPoint(_hDC, AnsiStr, lStrLen(AnsiStr), StrSize) = False) then
  762.         ZeroMemory(@StrSize, SizeOf(TSize));
  763.       Inc(X, StrSize.cx);
  764.       // Next ..
  765.       Inc(dwStart);
  766.       Inc(I);
  767.     end; // while (dwStart < dwEnd) do ..
  768.   end; // else ..
  769.   // load all bitmap & draw
  770.   if (sImeG.IC_Trace <> 0) then
  771.     hCandInfBmp := LoadBitmap(HInstance, 'Candinf')
  772.   else
  773.     hCandInfBmp := 0;
  774.   hCandHBmp := LoadBitmap(HInstance, 'CandH');
  775.   hCandUBmp := LoadBitmap(HInstance, 'CandU');
  776.   hCandDBmp := LoadBitmap(HInstance, 'CandD');
  777.   hCandEBmp := LoadBitmap(HInstance, 'CandE');
  778.   hCandIconBmp := LoadBitmap(HInstance, 'CandSel');
  779.   hMemDC := CreateCompatibleDC(_hDC);
  780.   hOldBmp := SelectObject(hMemDC, hCandIconBmp);
  781.   BitBlt(_hDC, sImeG.rcCandIcon.Left, sImeG.rcCandIcon.Top,
  782.     sImeG.rcCandIcon.Right - sImeG.rcCandIcon.Left, STATUS_DIM_Y, hMemDC, 0, 0, SRCCOPY);
  783.   if (hCandInfBmp <> 0) then
  784.   begin
  785.     SelectObject(hMemDC, hCandInfBmp);
  786.     BitBlt(_hDC, sImeG.rcCandInf.Left, sImeG.rcCandInf.Top,
  787.       sImeG.rcCandInf.Right - sImeG.rcCandInf.Left, STATUS_DIM_Y, hMemDC, 0, 0, SRCCOPY);
  788.   end;
  789.   SelectObject(hMemDC, hCandHBmp);
  790.   BitBlt(_hDC, sImeG.rcCandBTH.Left, sImeG.rcCandBTH.Top,
  791.     sImeG.rcCandBTH.Right - sImeG.rcCandBTH.Left, STATUS_DIM_Y, hMemDC, 0, 0, SRCCOPY);
  792.   SelectObject(hMemDC, hCandUBmp);
  793.   BitBlt(_hDC, sImeG.rcCandBTU.Left, sImeG.rcCandBTU.Top,
  794.     sImeG.rcCandBTU.Right - sImeG.rcCandBTU.Left, STATUS_DIM_Y, hMemDC, 0, 0, SRCCOPY);
  795.   SelectObject(hMemDC, hCandDBmp);
  796.   BitBlt(_hDC, sImeG.rcCandBTD.Left, sImeG.rcCandBTD.Top,
  797.     sImeG.rcCandBTD.Right - sImeG.rcCandBTD.Left, STATUS_DIM_Y, hMemDC, 0, 0, SRCCOPY);
  798.   SelectObject(hMemDC, hCandEBmp);
  799.   BitBlt(_hDC, sImeG.rcCandBTE.Left, sImeG.rcCandBTE.Top,
  800.     sImeG.rcCandBTE.Right - sImeG.rcCandBTE.Left, STATUS_DIM_Y, hMemDC, 0, 0, SRCCOPY);
  801.   SelectObject(hMemDC, hOldBmp);
  802.   DeleteDC(hMemDC);
  803.   DeleteObject(hCandIconBmp);
  804.   DeleteObject(hCandEBmp);
  805.   DeleteObject(hCandDBmp);
  806.   DeleteObject(hCandUBmp);
  807.   DeleteObject(hCandHBmp);
  808.   DeleteObject(hCandInfBmp);
  809.   if (sImeG.fDiffSysCharSet) then DeleteObject(SelectObject(_hDC, hOldFont));
  810.   ImmUnlockIMCC(lpIMC.hPrivate);
  811. UpCandW2UnlockCandInfo:
  812.   ImmUnlockIMCC(lpIMC.hCandInfo);
  813. UpCandW2UnlockIMC:
  814.   ImmUnlockIMC(_hIMC);
  815. end;
  816.   // Candidate窗口回调
  817. function CandWndProc(hCandWnd: hWnd; uMsg: uInt; wParam: WParam; lParam: LParam): LResult; stdcall;
  818. var
  819.   ptCursor: TPoint;
  820.   _hDC: hDC;
  821.   ps: TPaintStruct;
  822. begin
  823.   Result := 0;
  824.   case (uMsg) of
  825.     WM_DESTROY:
  826.       DestroyCandWindow(hCandWnd);
  827.     WM_SETCURSOR:
  828.       CandSetCursor(hCandWnd, lParam);
  829.     WM_MOUSEMOVE:
  830.       if (GetWindowLong(hCandWnd, UI_MOVE_OFFSET) <> WINDOW_NOT_DRAG) then
  831.       begin
  832.         DrawDragBorder(hCandWnd, GetWindowLong(hCandWnd, UI_MOVE_XY), GetWindowLong(hCandWnd, UI_MOVE_OFFSET)); // 擦除
  833.         GetCursorPos(ptCursor);
  834.         SetWindowLong(hCandWnd, UI_MOVE_XY, MakeLong(ptCursor.x, ptCursor.y));
  835.         DrawDragBorder(hCandWnd, MakeLong(ptCursor.x, ptCursor.y), GetWindowLong(hCandWnd, UI_MOVE_OFFSET));    // 重绘
  836.       end else
  837.         Result := DefWindowProc(hCandWnd, uMsg, wParam, lParam);
  838.     WM_LBUTTONUP:
  839.       if (CandButtonUp(hCandWnd) = False) then Result := DefWindowProc(hCandWnd, uMsg, wParam, lParam);
  840.     WM_IME_NOTIFY:
  841.       if (wParam = IMN_SETCANDIDATEPOS) then Result := SetCandPosition(hCandWnd);
  842.     WM_PAINT:
  843.     begin
  844.       _hDC := BeginPaint(hCandWnd, ps);
  845.       PaintCandWindow(hCandWnd, _hDC);
  846.       EndPaint(hCandWnd, ps);
  847.     end;
  848.     WM_MOUSEACTIVATE:
  849.       Result := MA_NOACTIVATE;
  850.     else
  851.       Result := DefWindowProc(hCandWnd, uMsg, wParam, lParam);
  852.   end;
  853. end;
  854. end.