Candui.pas
资源名称:Wingb_Mz.rar [点击查看]
上传用户:wen198501
上传日期:2013-04-01
资源大小:335k
文件大小:32k
源码类别:
输入法编程
开发平台:
Delphi
- {******************************************************}
- { }
- { Copyright (c) 1990-1999 Microsoft Corporation }
- { }
- { Module Name: Candui.c ->> Candui.pas }
- { }
- { Translator: Liu_mazi@126.com, 2005-11-17 }
- { }
- {******************************************************}
- unit Candui;
- {$I Define.Inc}
- interface
- uses Windows, ImmDev;
- function GetCandWnd(hUIWnd: hWnd): hWnd; // 返回Candidate窗口句柄
- function CandWndProc(hCandWnd: hWnd; uMsg: uInt; wParam: WParam; lParam: LParam): LResult; stdcall; // Candidate窗口回调
- procedure ShowCand(hUIWnd: hWnd; nShowCandCmd: Integer); // 显示隐藏Candidate窗口
- procedure OpenCand(hUIWnd: hWnd); // "打开"Candidate窗口
- procedure PaintCandWindow(hCandWnd: hWnd; _hDC: hDC); // 绘制Candidate窗口
- procedure CloseCand(hUIWnd: hWnd); // 隐藏Candidate窗口
- procedure CalcCandPos(_hIMC: hIMC; hUIWnd: hWnd; lpptWnd: PPoint); // 计算Candidate窗口位置
- implementation
- uses Messages, ImeDefs, Data, Notify, Ui, Uisubs, Compui, Chcand, LogText;
- // 返回Candidate窗口句柄
- function GetCandWnd(hUIWnd: hWnd): hWnd;
- var
- hUIPrivate: hGlobal;
- lpUIPrivate: PUIPriv;
- begin
- Result := 0;
- hUIPrivate := GetWindowLong(hUIWnd, IMMGWLP_PRIVATE);
- if (hUIPrivate = 0) then Exit; // can not darw candidate window
- lpUIPrivate := GlobalLock(hUIPrivate);
- if (lpUIPrivate = nil) then Exit; // can not draw candidate window
- Result := lpUIPrivate.hCandWnd;
- GlobalUnlock(hUIPrivate);
- end;
- // 计算Candidate窗口位置
- procedure CalcCandPos(_hIMC: hIMC; hUIWnd: hWnd; lpptWnd: PPoint);
- var
- ptNew, ptSTWPos: TPoint;
- hCompWnd: hWnd;
- begin
- if (sImeG.IC_Trace = 0) then // 光标跟随 = False
- begin
- ImmGetStatusWindowPos(_hIMC, @ptSTWPos);
- hCompWnd := GetCompWnd(hUIWnd);
- if IsWindow(hCompWnd) then
- begin
- ptNew.x := ptSTWPos.x + sImeG.xStatusWi + sImeL.xCompWi + 2 * UI_MARGIN;
- if (ptNew.x + sImeG.xCandWi > sImeG.rcWorkArea.Right) then
- begin
- if (ptSTWPos.x >= (sImeG.xCandWi + sImeL.xCompWi + 2 * UI_MARGIN)) then
- ptNew.x := ptSTWPos.x - sImeL.xCompWi - sImeG.xCandWi - 2 * UI_MARGIN
- else
- ptNew.x := ptSTWPos.x + sImeG.xStatusWi + UI_MARGIN;
- end;
- ptNew.y := ptSTWPos.y + sImeL.cyCompBorder - sImeG.cyCandBorder;
- if (ptNew.y + sImeG.yCandHi > sImeG.rcWorkArea.Bottom) then ptNew.y := sImeG.rcWorkArea.Bottom - sImeG.yCandHi;
- end else
- begin
- ptNew.x := ptSTWPos.x + sImeG.xStatusWi + UI_MARGIN;
- if (ptNew.x + sImeG.xCandWi >= sImeG.rcWorkArea.Right) and
- (ptSTWPos.x >= sImeG.xCandWi + UI_MARGIN) then
- begin
- ptNew.x := ptSTWPos.x - sImeG.xCandWi - UI_MARGIN;
- end;
- ptNew.y := ptSTWPos.y + sImeL.cyCompBorder - sImeG.cyCandBorder;
- if (ptNew.y + sImeG.yCandHi > sImeG.rcWorkArea.Bottom) then ptNew.y := sImeG.rcWorkArea.Bottom - sImeG.yCandHi;
- end;
- end else // 光标跟随 = True
- begin
- ptNew.x := lpptWnd.x + sImeL.xCompWi + UI_MARGIN;
- if (ptNew.x + sImeG.xCandWi > sImeG.rcWorkArea.Right) then ptNew.x := lpptWnd.x - sImeG.xCandWi - UI_MARGIN;
- ptNew.y := lpptWnd.y + sImeL.cyCompBorder - sImeG.cyCandBorder;
- if (ptNew.y + sImeG.yCandHi > sImeG.rcWorkArea.Bottom) then ptNew.y := sImeG.rcWorkArea.Bottom - sImeG.yCandHi;
- end;
- lpptWnd^ := ptNew;
- end;
- // 微调Candidate窗口位置
- procedure AdjustCandPos(_hIMC: hIMC; lpptWnd: PPoint);
- var
- lpIMC: PInputContext;
- ptFontHi: Integer;
- uEsc: uInt;
- begin
- lpIMC := ImmLockIMC(_hIMC);
- if (lpIMC = nil) then Exit;
- if (lpIMC.lfFont.A.lfHeight > 0) then
- begin
- ptFontHi := lpIMC.lfFont.A.lfHeight;
- end else
- if (lpIMC.lfFont.A.lfWidth = 0) then
- ptFontHi := sImeL.yCompHi
- else
- ptFontHi := -lpIMC.lfFont.A.lfHeight;
- if (ptFontHi > sImeL.yCompHi * 8) then ptFontHi := sImeL.yCompHi * 8;
- if (ptFontHi < sImeG.yChiCharHi) then ptFontHi := sImeG.yChiCharHi;
- // -450 to 450 index 0
- // 450 to 1350 index 1
- // 1350 to 2250 index 2
- // 2250 to 3150 index 3
- uEsc := (lpIMC.lfFont.A.lfEscapement + 450) div 900 mod 4;
- // find the location after IME do an adjustment
- ptFontHi := ptFontHi * ptInputEsc[uEsc].y;
- if (lpptWnd.y + ptFontHi + sImeG.yCandHi <= sImeG.rcWorkArea.Bottom) then
- Inc(lpptWnd.y, ptFontHi)
- else
- Dec(lpptWnd.y, ptFontHi + sImeG.yCandHi);
- ImmUnlockIMC(_hIMC);
- end;
- // 修正Candidate窗口位置
- procedure AdjustCandBoundry(lpptCandWnd: PPoint);
- begin
- if (lpptCandWnd.x < sImeG.rcWorkArea.Left) then
- begin
- lpptCandWnd.x := sImeG.rcWorkArea.Left;
- end else
- if (lpptCandWnd.x + sImeG.xCandWi > sImeG.rcWorkArea.Right) then
- begin
- lpptCandWnd.x := sImeG.rcWorkArea.Right - sImeG.xCandWi;
- end;
- if (lpptCandWnd.y < sImeG.rcWorkArea.Top) then
- begin
- lpptCandWnd.y := sImeG.rcWorkArea.Top;
- end else
- if (lpptCandWnd.y + sImeG.yCandHi > sImeG.rcWorkArea.Bottom) then
- begin
- lpptCandWnd.y := sImeG.rcWorkArea.Bottom - sImeG.yCandHi;
- end;
- end;
- // 设置Candidate窗口位置
- function SetCandPosition(hCandWnd: hWnd): LResult;
- var
- hUIWnd: hWnd;
- _hIMC: hIMC;
- lpIMC: PInputContext;
- ptNew: TPoint;
- begin
- Result := 1;
- hUIWnd := GetWindow(hCandWnd, GW_OWNER);
- if (IsWindow(hUIWnd) = False) then Exit;
- _hIMC := GetWindowLong(hUIWnd, IMMGWLP_IMC);
- if (_hIMC = 0) then Exit;
- lpIMC := ImmLockIMC(_hIMC);
- if (lpIMC = nil) then Exit;
- ptNew := lpIMC.cfCandForm[0].ptCurrentPos;
- ClientToScreen(lpIMC.hWnd, ptNew);
- if ((lpIMC.cfCandForm[0].dwStyle and CFS_FORCE_POSITION) <> 0) then
- begin
- end else
- if (lpIMC.cfCandForm[0].dwStyle = CFS_CANDIDATEPOS) then
- begin
- AdjustCandBoundry(@ptNew);
- end else
- if (lpIMC.cfCandForm[0].dwStyle = CFS_EXCLUDE) then
- begin
- if (sImeG.IC_Trace = 0) then CalcCandPos(_hIMC, hUIWnd, @ptNew);
- AdjustCandBoundry(@ptNew);
- end;
- SetWindowPos(hCandWnd, 0, ptNew.x, ptNew.y, 0, 0, SWP_NOACTIVATE or SWP_NOSIZE or SWP_NOZORDER);
- ImmUnlockIMC(_hIMC);
- Result := 0;
- end;
- // 显示隐藏Candidate窗口
- procedure ShowCand(hUIWnd: hWnd; nShowCandCmd: Integer);
- label
- ShowCand;
- var
- hUIPrivate: hGlobal;
- lpUIPrivate: PUIPriv;
- _hIMC: hIMC;
- ptSTWPos: TPoint;
- Comp_CandWndLen: Integer;
- begin
- hUIPrivate := GetWindowLong(hUIWnd, IMMGWLP_PRIVATE);
- if (hUIPrivate = 0) then Exit; // can not darw candidate window
- lpUIPrivate := GlobalLock(hUIPrivate);
- if (lpUIPrivate = nil) then Exit; // can not draw candidate window
- if (lpUIPrivate.nShowCandCmd = nShowCandCmd) then Exit; // **
- if (nShowCandCmd = SW_HIDE) then
- lpUIPrivate.fdwSetContext := lpUIPrivate.fdwSetContext and (not ISC_HIDE_CAND_WINDOW);
- if IsWindow(lpUIPrivate.hCandWnd) then
- if (lpUIPrivate.nShowCandCmd = nShowCandCmd) then // 无变化
- begin
- end else
- begin
- if (nShowCandCmd = SW_HIDE) then
- begin
- uOpenCand := 0;
- end else
- begin
- uOpenCand := 1;
- // reset status window for LINE_UI(FIX_UI)
- _hIMC := GetWindowLong(hUIWnd, IMMGWLP_IMC);
- if (_hIMC = 0) then goto ShowCand;
- ImmGetStatusWindowPos(_hIMC, @ptSTWPos);
- Comp_CandWndLen := 0;
- if (uOpenCand <> 0) then
- begin
- Inc(Comp_CandWndLen, sImeG.xCandWi + UI_MARGIN);
- if (uStartComp <> 0) then Inc(Comp_CandWndLen, sImeL.xCompWi + UI_MARGIN);
- if (ptSTWPos.x + sImeG.xStatusWi + Comp_CandWndLen > sImeG.rcWorkArea.Right) then
- PostMessage(GetCompWnd(hUIWnd), WM_IME_NOTIFY, IMN_SETCOMPOSITIONWINDOW, 0);
- end;
- end;
- ShowCand:
- ShowWindow(lpUIPrivate.hCandWnd, nShowCandCmd);
- lpUIPrivate.nShowCandCmd := nShowCandCmd;
- end;
- GlobalUnlock(hUIPrivate);
- end;
- // "打开"Candidate窗口
- procedure OpenCand(hUIWnd: hWnd);
- label
- OpenCandUnlockUIPriv;
- var
- hUIPrivate: hGlobal;
- lpUIPrivate: PUIPriv;
- _hIMC: hIMC;
- lpIMC: PInputContext;
- ptWnd, ptCaret: TPoint;
- begin
- hUIPrivate := GetWindowLong(hUIWnd, IMMGWLP_PRIVATE);
- if (hUIPrivate = 0) then Exit; // can not darw candidate window
- lpUIPrivate := GlobalLock(hUIPrivate);
- if (lpUIPrivate = nil) then Exit; // can not draw candidate window
- lpUIPrivate.fdwSetContext := lpUIPrivate.fdwSetContext or ISC_SHOWUICANDIDATEWINDOW;
- _hIMC := GetWindowLong(hUIWnd, IMMGWLP_IMC);
- if (_hIMC = 0) then goto OpenCandUnlockUIPriv;
- lpIMC := ImmLockIMC(_hIMC);
- if (lpIMC = nil) then goto OpenCandUnlockUIPriv;
- if (lpIMC.cfCandForm[0].dwIndex = 0) then
- begin
- ptWnd := lpIMC.cfCandForm[0].ptCurrentPos;
- ClientToScreen(lpIMC.hWnd, ptWnd);
- if (lpIMC.cfCandForm[0].dwStyle and CFS_FORCE_POSITION) <> 0 then
- begin
- end else
- begin
- if (lpIMC.cfCandForm[0].dwStyle = CFS_EXCLUDE) then
- begin
- AdjustCandBoundry(@ptWnd);
- if (sImeG.IC_Trace = 0) or (GetCaretPos(ptCaret) = False) then // **
- begin
- if IsWindow(GetCompWnd(hUIWnd)) then
- begin
- ptWnd.x := 0;
- ptWnd.y := 0;
- ClientToScreen(lpIMC.hWnd, ptWnd);
- Dec(ptWnd.x, sImeL.cxCompBorder + 1);
- Dec(ptWnd.y, sImeL.cyCompBorder + 1);
- end else
- begin
- ptWnd.x := sImeL.cxCompBorder + 1;
- ptWnd.y := sImeL.cyCompBorder + 1;
- end;
- CalcCandPos(_hIMC, hUIWnd, @ptWnd);
- lpIMC.cfCandForm[0].dwStyle := lpIMC.cfCandForm[0].dwStyle or CFS_CANDIDATEPOS;
- lpIMC.cfCandForm[0].ptCurrentPos := ptWnd;
- ScreenToClient(lpIMC.hWnd, lpIMC.cfCandForm[0].ptCurrentPos);
- end else
- begin
- AdjustCandPos(_hIMC, @ptWnd);
- end;
- end else
- if (lpIMC.cfCandForm[0].dwStyle = CFS_CANDIDATEPOS) then
- begin
- AdjustCandBoundry(@ptWnd);
- end else
- begin
- if (lpUIPrivate.nShowCompCmd <> SW_HIDE) then
- begin
- ptWnd.x := 0;
- ptWnd.y := 0;
- ClientToScreen(lpUIPrivate.hCompWnd, ptWnd);
- end else
- begin
- ptWnd := lpIMC.cfCompForm.ptCurrentPos;
- ClientToScreen(lpIMC.hWnd, ptWnd);
- end;
- Dec(ptWnd.x, sImeL.cxCompBorder + 1);
- Dec(ptWnd.y, sImeL.cyCompBorder + 1);
- CalcCandPos(_hIMC, hUIWnd, @ptWnd);
- lpIMC.cfCandForm[0].dwStyle := lpIMC.cfCandForm[0].dwStyle or CFS_CANDIDATEPOS;
- lpIMC.cfCandForm[0].ptCurrentPos := ptWnd;
- ScreenToClient(lpIMC.hWnd, lpIMC.cfCandForm[0].ptCurrentPos);
- end;
- end;
- end else
- begin
- // make cand windows trace comp window !
- if (lpUIPrivate.nShowCompCmd <> SW_HIDE) then
- begin
- ptWnd.x := 0;
- ptWnd.y := 0;
- ClientToScreen(lpUIPrivate.hCompWnd, ptWnd);
- end else
- begin
- ptWnd := lpIMC.cfCompForm.ptCurrentPos;
- ClientToScreen(lpIMC.hWnd, ptWnd);
- end;
- Dec(ptWnd.x, sImeL.cxCompBorder + 1);
- Dec(ptWnd.y, sImeL.cyCompBorder + 1);
- CalcCandPos(_hIMC, hUIWnd, @ptWnd);
- lpIMC.cfCandForm[0].dwStyle := lpIMC.cfCandForm[0].dwStyle or CFS_CANDIDATEPOS;
- lpIMC.cfCandForm[0].ptCurrentPos := ptWnd;
- ScreenToClient(lpIMC.hWnd, lpIMC.cfCandForm[0].ptCurrentPos);
- end;
- ImmUnlockIMC(_hIMC);
- if IsWindow(lpUIPrivate.hCandWnd) then
- begin
- SetWindowPos(lpUIPrivate.hCandWnd, 0, ptWnd.x, ptWnd.y, 0, 0, SWP_NOACTIVATE or SWP_NOSIZE or SWP_NOZORDER);
- end else
- begin
- lpUIPrivate.hCandWnd := CreateWindowEx(WS_EX_WINDOWEDGE or WS_EX_DLGMODALFRAME,
- szCandClassName, nil, WS_POPUP or WS_DISABLED, ptWnd.x, ptWnd.y,
- sImeG.xCandWi, sImeG.yCandHi, hUIWnd, 0, HInstance, nil);
- SetWindowLong(lpUIPrivate.hCandWnd, UI_MOVE_OFFSET, WINDOW_NOT_DRAG);
- SetWindowLong(lpUIPrivate.hCandWnd, UI_MOVE_XY, 0);
- end;
- ShowCand(hUIWnd, SW_SHOWNOACTIVATE);
- OpenCandUnlockUIPriv:
- GlobalUnlock(hUIPrivate);
- end;
- // 隐藏Candidate窗口
- procedure CloseCand(hUIWnd: hWnd);
- begin
- uOpenCand := 0;
- ShowCand(hUIWnd, SW_HIDE);
- end;
- // WM_DESTROY消息处理
- procedure DestroyCandWindow(hCandWnd: hWnd);
- var
- hUIPrivate: hGlobal;
- lpUIPrivate: PUIPriv;
- begin
- if (GetWindowLong(hCandWnd, UI_MOVE_OFFSET) <> WINDOW_NOT_DRAG) then // undo the drag border
- DrawDragBorder(hCandWnd, GetWindowLong(hCandWnd, UI_MOVE_XY), GetWindowLong(hCandWnd, UI_MOVE_OFFSET));
- hUIPrivate := GetWindowLong(GetWindow(hCandWnd, GW_OWNER), IMMGWLP_PRIVATE);
- if (hUIPrivate = 0) then Exit; // can not darw candidate window
- lpUIPrivate := GlobalLock(hUIPrivate);
- if (lpUIPrivate = nil) then Exit; // can not draw candidate window
- lpUIPrivate.nShowCandCmd := SW_HIDE;
- lpUIPrivate.hCandWnd := 0;
- GlobalUnlock(hUIPrivate);
- end;
- // 鼠标点击选择汉字
- procedure MouseSelectCandStr(hCandWnd: hWnd; lpCursor: PPoint);
- var
- _hIMC: hIMC;
- lpIMC: PInputContext;
- lpCandInfo: PCandiDateInfo;
- lpCandList: PCandiDateList;
- dwValue: DWord;
- begin
- _hIMC := GetWindowLong(GetWindow(hCandWnd, GW_OWNER), IMMGWLP_IMC);
- if (_hIMC = 0) then Exit;
- lpIMC := ImmLockIMC(_hIMC);
- if (lpIMC = nil) then Exit;
- if (lpIMC.hCandInfo = 0) then
- begin
- ImmUnlockIMC(_hIMC);
- Exit;
- end;
- lpCandInfo := ImmLockIMCC(lpIMC.hCandInfo);
- if (lpCandInfo = nil) then
- begin
- ImmUnlockIMC(_hIMC);
- Exit;
- end;
- dwValue := (lpCursor.y - sImeG.rcCandText.Top) div sImeG.yChiCharHi; // **
- lpCandList := PCandidateList(DWord(lpCandInfo) + lpCandInfo.dwOffset[0]);
- dwValue := dwValue + lpCandList.dwSelection div lpCandList.dwPageSize * lpCandList.dwPageSize;
- if (dwValue >= lpCandList.dwCount) then MessageBeep($FFFFFFFF) // invalid choice
- else NotifyIME(_hIMC, NI_SELECTCANDIDATESTR, 0, dwValue);
- ImmUnlockIMCC(lpIMC.hCandInfo);
- ImmUnlockIMC(_hIMC);
- end;
- // Candidate窗口翻页
- procedure CandPageDownUP(hCandWnd: hWnd; uCandDownUp: uInt);
- var
- _hIMC: hIMC;
- lpIMC: PInputContext;
- lpImcP: PPrivContext;
- lpCandInfo: PCandiDateInfo;
- // lpCandList: PCandiDateList;
- _hDC: hDC;
- hCandHpBmp, hCandUpBmp, hCandDpBmp, hCandEpBmp, hOldBmp: hBitmap;
- hMemDC: hDC;
- begin
- // change candlist
- _hIMC := GetWindowLong(GetWindow(hCandWnd, GW_OWNER), IMMGWLP_IMC);
- if (_hIMC = 0) then Exit;
- // get lpIMC
- lpIMC := ImmLockIMC(_hIMC);
- if (lpIMC = nil) then Exit;
- // get lpImcP
- lpImcP := ImmLockIMCC(lpIMC.hPrivate);
- if (lpImcP = nil) then Exit;
- // get lpCandInfo
- lpCandInfo := ImmLockIMCC(lpIMC.hCandInfo);
- if (lpCandInfo = nil) then Exit;
- // get lpCandList and init dwCount & dwSelection, 未用到, --
- // lpCandList := PCandiDateList(DWord(lpCandInfo) + lpCandInfo.dwOffset[0]);
- case (uCandDownUp) of
- uCandHome:
- begin
- ChooseCand($24, lpIMC, lpCandInfo, lpImcP);
- NotifyIME(_hIMC, NI_CHANGECANDIDATELIST, 0, 0);
- end;
- uCandUp:
- begin
- ChooseCand(Ord('-'), lpIMC, lpCandInfo, lpImcP);
- NotifyIME(_hIMC, NI_CHANGECANDIDATELIST, 0, 0);
- end;
- uCandDown:
- begin
- ChooseCand(Ord('='), lpIMC, lpCandInfo, lpImcP);
- NotifyIME(_hIMC, NI_CHANGECANDIDATELIST, 0, 0);
- end;
- uCandEnd:
- begin
- ChooseCand($0023, lpIMC, lpCandInfo, lpImcP);
- NotifyIME(_hIMC, NI_CHANGECANDIDATELIST, 0, 0);
- end;
- end;
- ImmUnlockIMCC(lpIMC.hPrivate);
- ImmUnlockIMCC(lpIMC.hCandInfo);
- ImmUnlockIMC(_hIMC);
- // draw button down
- _hDC := GetDC(hCandWnd);
- hCandHpBmp := LoadBitmap(HInstance, 'CandHp');
- hCandUpBmp := LoadBitmap(HInstance, 'CandUp');
- hCandDpBmp := LoadBitmap(HInstance, 'CandDp');
- hCandEpBmp := LoadBitmap(HInstance, 'CandEp');
- hMemDC := CreateCompatibleDC(_hDC);
- case (uCandDownUp) of
- uCandHome:
- begin
- hOldBmp := SelectObject(hMemDC, hCandHpBmp);
- BitBlt(_hDC, sImeG.rcCandBTH.Left, sImeG.rcCandBTH.Top,
- sImeG.rcCandBTH.Right - sImeG.rcCandBTH.Left, STATUS_DIM_Y, hMemDC, 0, 0, SRCCOPY);
- end;
- uCandUp:
- begin
- hOldBmp := SelectObject(hMemDC, hCandUpBmp);
- BitBlt(_hDC, sImeG.rcCandBTU.Left, sImeG.rcCandBTU.Top,
- sImeG.rcCandBTU.Right - sImeG.rcCandBTU.Left, STATUS_DIM_Y, hMemDC, 0, 0, SRCCOPY);
- end;
- uCandDown:
- begin
- hOldBmp := SelectObject(hMemDC, hCandDpBmp);
- BitBlt(_hDC, sImeG.rcCandBTD.Left, sImeG.rcCandBTD.Top,
- sImeG.rcCandBTD.Right - sImeG.rcCandBTD.Left, STATUS_DIM_Y, hMemDC, 0, 0, SRCCOPY);
- end;
- uCandEnd:
- begin
- hOldBmp := SelectObject(hMemDC, hCandEpBmp);
- BitBlt(_hDC, sImeG.rcCandBTE.Left, sImeG.rcCandBTE.Top,
- sImeG.rcCandBTE.Right - sImeG.rcCandBTE.Left, STATUS_DIM_Y, hMemDC, 0, 0, SRCCOPY);
- end;
- else hOldBmp := 0;
- end;
- SelectObject(hMemDC, hOldBmp);
- DeleteDC(hMemDC);
- DeleteObject(hCandEpBmp);
- DeleteObject(hCandDpBmp);
- DeleteObject(hCandUpBmp);
- DeleteObject(hCandHpBmp);
- ReleaseDC(hCandWnd, _hDC);
- end;
- // WM_SETCURSOR消息处理
- procedure CandSetCursor(hCandWnd: hWnd; lParam: LParam);
- var
- ptCursor: TPoint;
- rcWnd: TRect;
- _hDC, hMemDC: hDC;
- hCandHBmp, hCandUBmp, hCandDBmp, hCandEBmp, hOldBmp: hBitmap;
- begin
- if (GetWindowLong(hCandWnd, UI_MOVE_OFFSET) <> WINDOW_NOT_DRAG) then
- begin
- SetCursor(LoadCursor(0, IDC_SIZEALL));
- Exit;
- end;
- if (HiWord(lParam) = WM_LBUTTONDOWN) then
- begin
- SystemParametersInfo(SPI_GETWORKAREA, 0, @sImeG.rcWorkArea, 0);
- GetCursorPos(ptCursor);
- ScreenToClient(hCandWnd, ptCursor);
- if PtInRect(sImeG.rcCandText, ptCursor) // 文字
- and (sImeG.IC_Trace <> 0) then
- begin
- SetCursor(LoadCursor(HInstance, szHandCursor));
- MouseSelectCandStr(hCandWnd, @ptCursor);
- end else
- if PtInRect(sImeG.rcCandBTH, ptCursor) then // 首页
- begin
- CandPageDownUP(hCandWnd, uCandHome);
- end else
- if PtInRect(sImeG.rcCandBTU, ptCursor) then // 上翻
- begin
- CandPageDownUP(hCandWnd, uCandUp);
- end else
- if PtInRect(sImeG.rcCandBTD, ptCursor) then // 下翻
- begin
- CandPageDownUP(hCandWnd, uCandDown);
- end else
- if (PtInRect(sImeG.rcCandBTE, ptCursor)) then // 末页
- begin
- CandPageDownUP(hCandWnd, uCandEnd);
- end else
- begin
- SetCursor(LoadCursor(0, IDC_SIZEALL));
- SetCapture(hCandWnd);
- GetCursorPos(ptCursor);
- SetWindowLong(hCandWnd, UI_MOVE_XY, MakeLong(ptCursor.x, ptCursor.y));
- GetWindowRect(hCandWnd, rcWnd);
- SetWindowLong(hCandWnd, UI_MOVE_OFFSET, MakeLong(ptCursor.x - rcWnd.Left, ptCursor.y - rcWnd.Top));
- DrawDragBorder(hCandWnd, MakeLong(ptCursor.x, ptCursor.y), GetWindowLong(hCandWnd, UI_MOVE_OFFSET));
- end;
- end else
- if (HiWord(lParam) = WM_LBUTTONUP) then
- begin
- _hDC := GetDC(hCandWnd);
- hCandHBmp := LoadBitmap(HInstance, 'CandH');
- hCandUBmp := LoadBitmap(HInstance, 'CandU');
- hCandDBmp := LoadBitmap(HInstance, 'CandD');
- hCandEBmp := LoadBitmap(HInstance, 'CandE');
- hMemDC := CreateCompatibleDC(_hDC);
- hOldBmp := SelectObject(hMemDC, hCandHBmp);
- BitBlt(_hDC, sImeG.rcCandBTH.Left, sImeG.rcCandBTH.Top,
- sImeG.rcCandBTH.Right - sImeG.rcCandBTH.Left, STATUS_DIM_Y, hMemDC, 0, 0, SRCCOPY);
- SelectObject(hMemDC, hCandUBmp);
- BitBlt(_hDC, sImeG.rcCandBTU.Left, sImeG.rcCandBTU.Top,
- sImeG.rcCandBTU.Right - sImeG.rcCandBTU.Left, STATUS_DIM_Y, hMemDC, 0, 0, SRCCOPY);
- SelectObject(hMemDC, hCandDBmp);
- BitBlt(_hDC, sImeG.rcCandBTD.Left, sImeG.rcCandBTD.Top,
- sImeG.rcCandBTD.Right - sImeG.rcCandBTD.Left, STATUS_DIM_Y, hMemDC, 0, 0, SRCCOPY);
- SelectObject(hMemDC, hCandEBmp);
- BitBlt(_hDC, sImeG.rcCandBTE.Left, sImeG.rcCandBTE.Top,
- sImeG.rcCandBTE.Right - sImeG.rcCandBTE.Left, STATUS_DIM_Y, hMemDC, 0, 0, SRCCOPY);
- SelectObject(hMemDC, hOldBmp);
- DeleteObject(hCandEBmp);
- DeleteObject(hCandDBmp);
- DeleteObject(hCandUBmp);
- DeleteObject(hCandEBmp);
- DeleteDC(hMemDC);
- ReleaseDC(hCandWnd, _hDC);
- end else
- begin
- SystemParametersInfo(SPI_GETWORKAREA, 0, @sImeG.rcWorkArea, 0);
- GetCursorPos(ptCursor);
- ScreenToClient(hCandWnd, ptCursor);
- if PtInRect(sImeG.rcCandText, ptCursor) then
- begin
- SetCursor(LoadCursor(HInstance, szHandCursor));
- end else
- if PtInRect(sImeG.rcCandBTH, ptCursor) or
- PtInRect(sImeG.rcCandBTU, ptCursor) or
- PtInRect(sImeG.rcCandBTD, ptCursor) or
- PtInRect(sImeG.rcCandBTE, ptCursor) then
- begin
- SetCursor(LoadCursor(HInstance, szHandCursor));
- end else
- SetCursor(LoadCursor(0, IDC_SIZEALL));
- end;
- end;
- // WM_LBUTTONUP消息处理
- function CandButtonUp(hCandWnd: hWnd): Bool;
- var
- lTmpCursor, lTmpOffset: DWord;
- pt: TPoint;
- hUIWnd: hWnd;
- _hIMC: hIMC;
- lpIMC: PInputContext;
- begin
- Result := False;
- // Candidate 窗口未处于"拖拽"状态
- if (GetWindowLong(hCandWnd, UI_MOVE_OFFSET) = WINDOW_NOT_DRAG) then Exit;
- lTmpCursor := GetWindowLong(hCandWnd, UI_MOVE_XY);
- lTmpOffset := GetWindowLong(hCandWnd, UI_MOVE_OFFSET);
- // calculate the org by the offset
- pt.x := PSmallPoint(@lTmpCursor).x - PSmallPoint(@lTmpOffset).x;
- pt.y := PSmallPoint(@lTmpCursor).y - PSmallPoint(@lTmpOffset).y;
- DrawDragBorder(hCandWnd, lTmpCursor, lTmpOffset);
- SetWindowLong(hCandWnd, UI_MOVE_OFFSET, WINDOW_NOT_DRAG);
- ReleaseCapture();
- hUIWnd := GetWindow(hCandWnd, GW_OWNER);
- if IsWindow(hUIWnd) = False then Exit;
- _hIMC := GetWindowLong(hUIWnd, IMMGWLP_IMC);
- if (_hIMC = 0) then Exit;
- lpIMC := ImmLockIMC(_hIMC);
- if (lpIMC = nil) then Exit;
- AdjustCandBoundry(@pt);
- ScreenToClient(lpIMC.hWnd, pt);
- lpIMC.cfCandForm[0].dwStyle := lpIMC.cfCandForm[0].dwStyle or CFS_CANDIDATEPOS;
- lpIMC.cfCandForm[0].ptCurrentPos := pt;
- ImmUnlockIMC(_hIMC);
- PostMessage(hCandWnd, WM_IME_NOTIFY, IMN_SETCANDIDATEPOS, $0001);
- Result := True;
- end;
- // 绘制Candidate窗口
- procedure PaintCandWindow(hCandWnd: hWnd; _hDC: hDC);
- label
- UpCandW2UnlockIMC, UpCandW2UnlockCandInfo;
- var
- _hIMC: hIMC;
- lpIMC: PInputContext;
- lpCandInfo: PCandiDateInfo;
- lpCandList: PCandiDateList;
- lpImcP: PPrivContext;
- hOldFont: hGdiObj;
- dwStart, dwEnd: DWord;
- szStrBuf: array[0..2 * MAXSTRLEN + 1] of Char;
- szMyStrBuf: array[0..12] of Char;
- iLen, I, J, K, X, StrLen: Integer;
- hCandIconBmp, hCandInfBmp: hBitmap;
- hOldBmp, hCandHBmp, hCandUBmp, hCandDBmp, hCandEBmp: hBitmap;
- hMemDC: hDC;
- lfFont: TLogFont;
- rcWnd: TRect;
- wCode, wGB: Word;
- AbSeq: array[0..4] of Char;
- GbSeq: array[0..4] of Char;
- GBARInfo: TRect;
- AnsiStr: array[0..MAXCODE] of Char;
- StrSize: TSize;
- ArgList: array[0..1] of DWord;
- begin
- _hIMC := GetWindowLong(GetWindow(hCandWnd, GW_OWNER), IMMGWLP_IMC);
- if (_hIMC = 0) then Exit;
- lpIMC := ImmLockIMC(_hIMC);
- if (lpIMC = nil) then Exit;
- if (lpIMC.hCandInfo = 0) then goto UpCandW2UnlockIMC;
- lpCandInfo := ImmLockIMCC(lpIMC.hCandInfo);
- if (lpCandInfo = nil) then goto UpCandW2UnlockIMC;
- if (lpIMC.hPrivate = 0) then goto UpCandW2UnlockCandInfo;
- lpImcP := ImmLockIMCC(lpIMC.hPrivate);
- if (lpImcP = nil) then goto UpCandW2UnlockCandInfo;
- // set font
- if (sImeG.fDiffSysCharSet) then
- begin
- hOldFont := GetCurrentObject(_hDC, OBJ_FONT);
- ZeroMemory(@lfFont, SizeOf(TLogFont));
- lfFont.lfHeight := -MulDiv(12, GetDeviceCaps(_hDC, LOGPIXELSY), 72);
- lfFont.lfCharSet := NATIVE_CHARSET;
- lStrCpy(lfFont.lfFaceName, '宋体');
- SelectObject(_hDC, CreateFontIndirect(lfFont));
- end else
- hOldFont := 0;
- lpCandList := PCandiDateList(DWord(lpCandInfo) + lpCandInfo.dwOffset[0]);
- dwStart := lpCandList.dwSelection;
- dwEnd := dwStart + lpCandList.dwPageSize;
- if (dwEnd > lpCandList.dwCount) then dwEnd := lpCandList.dwCount;
- // 凹陷边框
- if (sImeG.IC_Trace <> 0) then
- begin
- GetClientRect(hCandWnd, rcWnd);
- DrawConcaveRect(_hDC, rcWnd.Left, rcWnd.Top + UI_CANDINF, rcWnd.Right - 1, rcWnd.Bottom - 1);
- end else
- begin
- GetClientRect(hCandWnd, rcWnd);
- DrawConcaveRect(_hDC, sImeG.rcCandText.Left - 1, rcWnd.Top, sImeG.rcCandText.Right + 1, rcWnd.Bottom - 1);
- end;
- // 黑字灰底
- SetTextColor(_hDC, RGB($00, $00, $00));
- SetBkColor(_hDC, RGB($C0, $C0, $C0));
- if (sImeG.IC_Trace <> 0) then
- begin
- ExtTextOut(_hDC, sImeG.rcCandText.Left, sImeG.rcCandText.Top, ETO_OPAQUE, @sImeG.rcCandText, nil, 0, nil);
- szStrBuf[0] := '1'; // **
- szStrBuf[1] := ':';
- I := 0;
- while (dwStart < dwEnd) do
- begin
- // I 行文字
- szStrBuf[0] := szDigit[I + CAND_START];
- iLen := lStrLen(PChar(DWord(lpCandList) + lpCandList.dwOffset[dwStart]));
- if (iLen > 10 * 2) then
- begin
- iLen := 10 * 2;
- CopyMemory(@szStrBuf[2], Pointer(DWord(lpCandList) + lpCandList.dwOffset[dwStart]), iLen - 2);
- szStrBuf[iLen] := '.';
- szStrBuf[iLen + 1] := '.';
- szStrBuf[iLen + 2] := #0;
- end else
- begin
- CopyMemory(@szStrBuf[2], Pointer(DWord(lpCandList) + lpCandList.dwOffset[dwStart]), iLen);
- end;
- ExtTextOut(_hDC, sImeG.rcCandText.Left,
- sImeG.rcCandText.Top + I * sImeG.yChiCharHi, 0, nil, szStrBuf, iLen + 2, nil);
- // QW/GB info
- wCode := PUnaWord(DWord(lpCandList) + lpCandList.dwOffset[dwStart])^;
- wCode := HiByte(wCode) or (LoByte(wCode) shl 8);
- ArgList[0] := wCode;
- wvsprintf(GbSeq, '%04lx', @ArgList); // get GB string
- Dec(wCode, $A0A0);
- ArgList[0] := HiByte(wCode);
- ArgList[1] := LoByte(wCode);
- wvsprintf(AbSeq, '%02d%02d', @ArgList); // get QW string
- ArgList[0] := DWord(@GbSeq);
- ArgList[1] := DWord(@AbSeq);
- wvsprintf(szMyStrBuf, '(%s,%s)', @ArgList);
- GBARInfo.Top := sImeG.rcCandText.Top + I * sImeG.yChiCharHi;
- GBARInfo.Left := sImeG.rcCandText.Left;
- GBARInfo.Right := sImeG.rcCandText.Right;
- GBARInfo.Bottom := sImeG.rcCandText.Bottom;
- DrawText(_hDC, szMyStrBuf, lStrLen(szMyStrBuf), GBARInfo, DT_RIGHT or DT_SINGLELINE);
- // Next ..
- Inc(dwStart);
- Inc(I);
- end; // while (dwStart < dwEnd) do ..
- end else
- begin
- ExtTextOut(_hDC, sImeG.rcCandText.Left, sImeG.rcCandText.Top + 1, ETO_OPAQUE, @sImeG.rcCandText, nil, 0, nil);
- X := 0;
- I := 0;
- while (dwStart < dwEnd) do
- begin
- // display numbers
- AnsiStr[0] := szDigit[I + CAND_START];
- AnsiStr[1] := ':';
- AnsiStr[2] := #0;
- ExtTextOut(_hDC, sImeG.rcCandText.Left + X, sImeG.rcCandText.Top + 1,
- ETO_CLIPPED, @sImeG.rcCandText, AnsiStr, lStrLen(AnsiStr), nil);
- if (GetTextExtentPoint(_hDC, AnsiStr, lStrLen(AnsiStr), StrSize) = False) then
- ZeroMemory(@StrSize, SizeOf(TSize)); // **
- Inc(X, StrSize.cx);
- // display chinese word and code
- iLen := lStrLen(PChar(DWord(lpCandList) + lpCandList.dwOffset[dwStart]));
- CopyMemory(@szStrBuf, PChar(DWord(lpCandList) + lpCandList.dwOffset[dwStart]), iLen);
- J := 0;
- while (J < iLen) do // 定位到第一个英文字母, ??
- begin
- if (Ord(szStrBuf[J]) and $80) <> 0 then
- begin
- Inc(J, 2);
- Continue;
- end else
- Break;
- end;
- K := J - 1; // **
- J := 0;
- while (J < iLen - K) do
- begin
- AnsiStr[J] := szStrBuf[J + K];
- Inc(J);
- end;
- AnsiStr[J] := #0;
- szStrBuf[K] := #0;
- ExtTextOut(_hDC, sImeG.rcCandText.Left + X, sImeG.rcCandText.Top + 1,
- ETO_CLIPPED, @sImeG.rcCandText, szStrBuf, lStrLen(szStrBuf), nil);
- if (GetTextExtentPoint(_hDC, szStrBuf, lStrLen(szStrBuf), StrSize) = False) then
- ZeroMemory(@StrSize, SizeOf(TSize));
- Inc(X, StrSize.cx);
- ExtTextOut(_hDC, sImeG.rcCandText.Left + X, sImeG.rcCandText.Top + 1,
- ETO_CLIPPED, @sImeG.rcCandText, AnsiStr, lStrLen(AnsiStr), nil);
- if (GetTextExtentPoint(_hDC, AnsiStr, lStrLen(AnsiStr), StrSize) = False) then
- ZeroMemory(@StrSize, SizeOf(TSize));
- Inc(X, StrSize.cx);
- // Next ..
- Inc(dwStart);
- Inc(I);
- end; // while (dwStart < dwEnd) do ..
- end; // else ..
- // load all bitmap & draw
- if (sImeG.IC_Trace <> 0) then
- hCandInfBmp := LoadBitmap(HInstance, 'Candinf')
- else
- hCandInfBmp := 0;
- hCandHBmp := LoadBitmap(HInstance, 'CandH');
- hCandUBmp := LoadBitmap(HInstance, 'CandU');
- hCandDBmp := LoadBitmap(HInstance, 'CandD');
- hCandEBmp := LoadBitmap(HInstance, 'CandE');
- hCandIconBmp := LoadBitmap(HInstance, 'CandSel');
- hMemDC := CreateCompatibleDC(_hDC);
- hOldBmp := SelectObject(hMemDC, hCandIconBmp);
- BitBlt(_hDC, sImeG.rcCandIcon.Left, sImeG.rcCandIcon.Top,
- sImeG.rcCandIcon.Right - sImeG.rcCandIcon.Left, STATUS_DIM_Y, hMemDC, 0, 0, SRCCOPY);
- if (hCandInfBmp <> 0) then
- begin
- SelectObject(hMemDC, hCandInfBmp);
- BitBlt(_hDC, sImeG.rcCandInf.Left, sImeG.rcCandInf.Top,
- sImeG.rcCandInf.Right - sImeG.rcCandInf.Left, STATUS_DIM_Y, hMemDC, 0, 0, SRCCOPY);
- end;
- SelectObject(hMemDC, hCandHBmp);
- BitBlt(_hDC, sImeG.rcCandBTH.Left, sImeG.rcCandBTH.Top,
- sImeG.rcCandBTH.Right - sImeG.rcCandBTH.Left, STATUS_DIM_Y, hMemDC, 0, 0, SRCCOPY);
- SelectObject(hMemDC, hCandUBmp);
- BitBlt(_hDC, sImeG.rcCandBTU.Left, sImeG.rcCandBTU.Top,
- sImeG.rcCandBTU.Right - sImeG.rcCandBTU.Left, STATUS_DIM_Y, hMemDC, 0, 0, SRCCOPY);
- SelectObject(hMemDC, hCandDBmp);
- BitBlt(_hDC, sImeG.rcCandBTD.Left, sImeG.rcCandBTD.Top,
- sImeG.rcCandBTD.Right - sImeG.rcCandBTD.Left, STATUS_DIM_Y, hMemDC, 0, 0, SRCCOPY);
- SelectObject(hMemDC, hCandEBmp);
- BitBlt(_hDC, sImeG.rcCandBTE.Left, sImeG.rcCandBTE.Top,
- sImeG.rcCandBTE.Right - sImeG.rcCandBTE.Left, STATUS_DIM_Y, hMemDC, 0, 0, SRCCOPY);
- SelectObject(hMemDC, hOldBmp);
- DeleteDC(hMemDC);
- DeleteObject(hCandIconBmp);
- DeleteObject(hCandEBmp);
- DeleteObject(hCandDBmp);
- DeleteObject(hCandUBmp);
- DeleteObject(hCandHBmp);
- DeleteObject(hCandInfBmp);
- if (sImeG.fDiffSysCharSet) then DeleteObject(SelectObject(_hDC, hOldFont));
- ImmUnlockIMCC(lpIMC.hPrivate);
- UpCandW2UnlockCandInfo:
- ImmUnlockIMCC(lpIMC.hCandInfo);
- UpCandW2UnlockIMC:
- ImmUnlockIMC(_hIMC);
- end;
- // Candidate窗口回调
- function CandWndProc(hCandWnd: hWnd; uMsg: uInt; wParam: WParam; lParam: LParam): LResult; stdcall;
- var
- ptCursor: TPoint;
- _hDC: hDC;
- ps: TPaintStruct;
- begin
- Result := 0;
- case (uMsg) of
- WM_DESTROY:
- DestroyCandWindow(hCandWnd);
- WM_SETCURSOR:
- CandSetCursor(hCandWnd, lParam);
- WM_MOUSEMOVE:
- if (GetWindowLong(hCandWnd, UI_MOVE_OFFSET) <> WINDOW_NOT_DRAG) then
- begin
- DrawDragBorder(hCandWnd, GetWindowLong(hCandWnd, UI_MOVE_XY), GetWindowLong(hCandWnd, UI_MOVE_OFFSET)); // 擦除
- GetCursorPos(ptCursor);
- SetWindowLong(hCandWnd, UI_MOVE_XY, MakeLong(ptCursor.x, ptCursor.y));
- DrawDragBorder(hCandWnd, MakeLong(ptCursor.x, ptCursor.y), GetWindowLong(hCandWnd, UI_MOVE_OFFSET)); // 重绘
- end else
- Result := DefWindowProc(hCandWnd, uMsg, wParam, lParam);
- WM_LBUTTONUP:
- if (CandButtonUp(hCandWnd) = False) then Result := DefWindowProc(hCandWnd, uMsg, wParam, lParam);
- WM_IME_NOTIFY:
- if (wParam = IMN_SETCANDIDATEPOS) then Result := SetCandPosition(hCandWnd);
- WM_PAINT:
- begin
- _hDC := BeginPaint(hCandWnd, ps);
- PaintCandWindow(hCandWnd, _hDC);
- EndPaint(hCandWnd, ps);
- end;
- WM_MOUSEACTIVATE:
- Result := MA_NOACTIVATE;
- else
- Result := DefWindowProc(hCandWnd, uMsg, wParam, lParam);
- end;
- end;
- end.