Ui.pas
资源名称:Wingb_Mz.rar [点击查看]
上传用户:wen198501
上传日期:2013-04-01
资源大小:335k
文件大小:34k
源码类别:
输入法编程
开发平台:
Delphi
- {******************************************************}
- { }
- { Copyright (c) 1990-1999 Microsoft Corporation }
- { }
- { Module Name: Ui.c ->> Ui.pas }
- { }
- { Translator: Liu_mazi@126.com, 2005-11-17 }
- { }
- {******************************************************}
- unit Ui;
- {$I Define.Inc}
- interface
- uses Windows;
- function UIWndProc(hUIWnd: hWnd; uMsg: uInt; wParam: WParam; lParam: LParam): LResult; stdcall; // UI窗口回调
- procedure DrawConvexRect(_hDC: hDC; x1, y1, x2, y2: Integer); // 绘制凸出边框
- procedure DrawConvexRectP(_hDC: hDC; x1, y1, x2, y2: Integer); // 绘制凸出边框
- procedure DrawConcaveRect(_hDC: hDC; x1, y1, x2, y2: Integer); // 绘制凹陷边框
- implementation
- uses Messages, ImmDev, ImeDefs, Init, Data, DDIS, Notify, Statusui, Compui, Candui, LogText;
- // IMN_PRIVATE_CMENUDESTROYED处理
- procedure CMenuDestroyed(hUIWnd: hWnd);
- var
- hUIPrivate: hGlobal;
- lpUIPrivate: PUIPriv;
- begin
- hUIPrivate := GetWindowLong(hUIWnd, IMMGWLP_PRIVATE);
- if (hUIPrivate = 0) then Exit;
- lpUIPrivate := GlobalLock(hUIPrivate);
- if (lpUIPrivate = nil) then Exit;
- lpUIPrivate.hCMenuWnd := 0;
- GlobalUnlock(hUIPrivate);
- end;
- // IMN_PRIVATE_SOFTKEYMENUDESTROYED处理
- procedure SoftkeyMenuDestroyed(hUIWnd: hWnd);
- var
- hUIPrivate: hGlobal;
- lpUIPrivate: PUIPriv;
- begin
- hUIPrivate := GetWindowLong(hUIWnd, IMMGWLP_PRIVATE);
- if (hUIPrivate = 0) then Exit;
- lpUIPrivate := GlobalLock(hUIPrivate);
- if (lpUIPrivate = nil) then Exit;
- lpUIPrivate.hSoftkeyMenuWnd := 0;
- GlobalUnlock(hUIPrivate);
- end;
- // WM_CREATE消息处理
- procedure CreateUIWindow(hUIWnd: hWnd);
- var
- hUIPrivate: hGlobal;
- begin
- {$IfDef Debug}
- ImeLog('CreateUIWindow ..');
- {$EndIf}
- // create storage for UI setting
- hUIPrivate := GlobalAlloc(GHND, SizeOf(TUIPriv));
- if (hUIPrivate = 0) then Exit;
- SetWindowLong(hUIWnd, IMMGWLP_PRIVATE, hUIPrivate);
- // set the default position for UI window, it is hide now, **
- SetWindowPos(hUIWnd, 0, 0, 0, 0, 0, SWP_NOACTIVATE or SWP_NOZORDER);
- ShowWindow(hUIWnd, SW_SHOWNOACTIVATE);
- end;
- // WM_DESTROY消息处理
- procedure DestroyUIWindow(hUIWnd: hWnd);
- var
- hUIPrivate: hGlobal;
- lpUIPrivate: PUIPriv;
- begin
- {$IfDef Debug}
- ImeLog('DestroyUIWindow ..');
- {$EndIf}
- hUIPrivate := GetWindowLong(hUIWnd, IMMGWLP_PRIVATE);
- if (hUIPrivate = 0) then Exit;
- lpUIPrivate := GlobalLock(hUIPrivate);
- if (lpUIPrivate = nil) then Exit;
- // destroy ContextMenuWnd
- if IsWindow(lpUIPrivate.hCMenuWnd) then
- begin
- SetWindowLong(lpUIPrivate.hCMenuWnd, CMENU_HUIWND, 0);
- SendMessage(lpUIPrivate.hCMenuWnd, WM_USER_DESTROY, 0, 0); // **, 恐怕用Post来不及..
- end;
- // destroy SoftkeyMenuWnd
- if IsWindow(lpUIPrivate.hSoftkeyMenuWnd) then
- begin
- SetWindowLong(lpUIPrivate.hSoftkeyMenuWnd, SOFTKEYMENU_HUIWND, 0);
- SendMessage(lpUIPrivate.hSoftkeyMenuWnd, WM_USER_DESTROY, 0, 0); // **, 恐怕用Post来不及..
- end;
- // composition window need to be destroyed
- if IsWindow(lpUIPrivate.hCompWnd) then DestroyWindow(lpUIPrivate.hCompWnd);
- // candidate window need to be destroyed
- if IsWindow(lpUIPrivate.hCandWnd) then DestroyWindow(lpUIPrivate.hCandWnd);
- // status window need to be destroyed
- if IsWindow(lpUIPrivate.hStatusWnd) then DestroyWindow(lpUIPrivate.hStatusWnd);
- // soft keyboard window need to be destroyed
- if IsWindow(lpUIPrivate.hSoftKbdWnd) then ImmDestroySoftKeyboard(lpUIPrivate.hSoftKbdWnd);
- GlobalUnlock(hUIPrivate);
- // free storage for UI settings
- GlobalFree(hUIPrivate);
- end;
- // 显示隐藏软键盘
- procedure ShowSoftKbd(hUIWnd: hWnd; nShowSoftKbdCmd: Integer; lpImcP: PPrivContext);
- var
- hUIPrivate: hGlobal;
- lpUIPrivate: PUIPriv;
- J: uInt;
- begin
- hUIPrivate := GetWindowLong(hUIWnd, IMMGWLP_PRIVATE);
- if (hUIPrivate = 0) then Exit; // can not darw status window
- lpUIPrivate := GlobalLock(hUIPrivate);
- if (lpUIPrivate = nil) then Exit; // can not draw status window
- for J := IDM_SKL1 to IDM_SKL13 do CheckMenuItem(sImeL.hSKMenu, J, MF_UNCHECKED); // **
- if IsWindow(lpUIPrivate.hSoftKbdWnd) and (lpUIPrivate.nShowSoftKbdCmd <> nShowSoftKbdCmd) then
- begin
- ImmShowSoftKeyboard(lpUIPrivate.hSoftKbdWnd, nShowSoftKbdCmd);
- lpUIPrivate.nShowSoftKbdCmd := nShowSoftKbdCmd;
- end;
- GlobalUnlock(hUIPrivate);
- end;
- // 计算软键盘位置
- procedure CheckSoftKbdPosition(lpUIPrivate: PUIPriv; lpIMC: PInputContext);
- var
- fPortionBits: uInt; // = 0;
- fPortionTest: uInt;
- xPortion, yPortion, nPortion: Integer;
- rcWnd: TRect;
- begin
- // portion of dispaly
- // 0 1
- // 2 3
- fPortionBits := 0;
- if IsWindow(lpUIPrivate.hCompWnd) then
- begin
- GetWindowRect(lpUIPrivate.hCompWnd, rcWnd);
- if (rcWnd.Left > sImeG.rcWorkArea.Right div 2) then xPortion := 1 else xPortion := 0;
- if (rcWnd.Top > sImeG.rcWorkArea.Bottom div 2) then yPortion := 1 else yPortion := 0;
- fPortionBits := fPortionBits or ($0001 shl (yPortion * 2 + xPortion));
- end;
- if IsWindow(lpUIPrivate.hStatusWnd) then
- begin
- GetWindowRect(lpUIPrivate.hStatusWnd, rcWnd);
- if (rcWnd.Left > sImeG.rcWorkArea.Right div 2) then xPortion := 1 else xPortion := 0;
- if (rcWnd.Top > sImeG.rcWorkArea.Bottom div 2) then yPortion := 1 else yPortion := 0;
- fPortionBits := fPortionBits or ($0001 shl (yPortion * 2 + xPortion));
- end;
- GetWindowRect(lpUIPrivate.hSoftKbdWnd, rcWnd);
- // start from portion 3
- nPortion := 3;
- fPortionTest := $0008;
- while (fPortionTest <> 0) do
- begin
- if (fPortionTest and fPortionBits <> 0) then
- begin
- Dec(nPortion);
- fPortionTest := fPortionTest shr 1;
- end else
- begin
- if (nPortion mod 2 <> 0) then // 左半部分
- lpIMC.ptSoftKbdPos.x := sImeG.rcWorkArea.Right - (rcWnd.Right - rcWnd.Left) - UI_MARGIN
- else
- lpIMC.ptSoftKbdPos.x := sImeG.rcWorkArea.Left;
- if (nPortion div 2 <> 0) then // 下半部分
- lpIMC.ptSoftKbdPos.y := sImeG.rcWorkArea.Bottom - (rcWnd.Bottom - rcWnd.Top) - UI_MARGIN
- else
- lpIMC.ptSoftKbdPos.y := sImeG.rcWorkArea.Top;
- lpIMC.fdwInit := lpIMC.fdwInit or INIT_SOFTKBDPOS;
- Break;
- end;
- end;
- end;
- // 设置软键盘数据
- procedure SetSoftKbdData(hSoftKbdWnd: hWnd; lpIMC: PInputContext);
- var
- J, K: Integer;
- lpSoftKbdData: PSoftKbdData;
- lpImcP: PPrivContext;
- hsSoftKbdData: hGlobal;
- bVirtKey: Byte;
- cHiByte, cLoByte: Word;
- begin
- lpImcP := ImmLockIMCC(lpIMC.hPrivate);
- if (lpImcP = nil) then Exit;
- hsSoftKbdData := GlobalAlloc(GHND, SizeOf(TSoftKbdData) * 2); // **
- if (hsSoftKbdData = 0) then
- begin
- ImmUnlockIMCC(lpIMC.hPrivate);
- Exit;
- end;
- lpSoftKbdData := GlobalLock(hsSoftKbdData);
- if (lpSoftKbdData = nil) then // can not draw soft keyboard window
- begin
- ImmUnlockIMCC(lpIMC.hPrivate);
- Exit;
- end;
- lpSoftKbdData.uCount := 2;
- K := 1;
- for J := 0 to 47 do
- begin
- bVirtKey := VirtKey48Map[J];
- if (bVirtKey = 0) then Continue;
- cHiByte := Ord(SKLayout[sImeL.dwSKWant][J * 2]) and $00FF;
- cLoByte := Ord(SKLayout[sImeL.dwSKWant][J * 2 + 1]) and $00FF;
- lpSoftKbdData.wCode[0][bVirtKey] := (cHiByte shl 8) or cLoByte;
- cHiByte := Ord(SKLayoutS[sImeL.dwSKWant][J * 2]) and $00FF;
- cLoByte := Ord(SKLayoutS[sImeL.dwSKWant][J * 2 + 1]) and $00FF;
- lpSoftKbdData.wCode[K][bVirtKey] := (cHiByte shl 8) or cLoByte;
- end;
- SendMessage(hSoftKbdWnd, WM_IME_CONTROL, IMC_SETSOFTKBDDATA, Integer(lpSoftKbdData));
- GlobalUnlock(hsSoftKbdData);
- // free storage for UI settings
- GlobalFree(hsSoftKbdData);
- ImmUnlockIMCC(lpIMC.hPrivate);
- end;
- // "更新"软键盘
- procedure UpdateSoftKbd(hUIWnd: hWnd);
- var
- _hIMC: hIMC;
- lpIMC: PInputContext;
- lpImcP: PPrivContext;
- hUIPrivate: hGlobal;
- lpUIPrivate: PUIPriv;
- begin
- _hIMC := GetWindowLong(hUIWnd, IMMGWLP_IMC);
- if (_hIMC = 0) then Exit;
- lpIMC := ImmLockIMC(_hIMC);
- if (lpIMC = nil) then Exit;
- hUIPrivate := GetWindowLong(hUIWnd, IMMGWLP_PRIVATE);
- if (hUIPrivate = 0) then // can not darw soft keyboard window
- begin
- ImmUnlockIMC(_hIMC);
- Exit;
- end;
- lpUIPrivate := GlobalLock(hUIPrivate);
- if (lpUIPrivate = nil) then // can not draw soft keyboard window
- begin
- ImmUnlockIMC(_hIMC);
- Exit;
- end;
- lpImcP := ImmLockIMCC(lpIMC.hPrivate);
- if (lpImcP = nil) then
- begin
- GlobalUnlock(hUIPrivate);
- ImmUnlockIMC(_hIMC);
- Exit;
- end;
- if (lpIMC.fdwConversion and IME_CMODE_SOFTKBD) = 0 then
- begin
- if IsWindow(lpUIPrivate.hSoftKbdWnd) then
- begin
- ImmDestroySoftKeyboard(lpUIPrivate.hSoftKbdWnd);
- lpUIPrivate.hSoftKbdWnd := 0;
- end;
- lpUIPrivate.nShowSoftKbdCmd := SW_HIDE;
- end else
- if (lpIMC.fOpen = False) then
- begin
- if (lpUIPrivate.nShowSoftKbdCmd <> SW_HIDE) then ShowSoftKbd(hUIWnd, SW_HIDE, nil);
- end else
- begin
- if (IsWindow(lpUIPrivate.hSoftKbdWnd) = False) then
- lpUIPrivate.hSoftKbdWnd := ImmCreateSoftKeyboard(SOFTKEYBOARD_TYPE_C1, hUIWnd, 0, 0);
- if (lpIMC.fdwInit and INIT_SOFTKBDPOS) = 0 then CheckSoftKbdPosition(lpUIPrivate, lpIMC);
- SetSoftKbdData(lpUIPrivate.hSoftKbdWnd, lpIMC);
- lpUIPrivate.fdwSetContext := lpUIPrivate.fdwSetContext or ISC_SHOW_SOFTKBD;
- if (lpUIPrivate.nShowSoftKbdCmd = SW_HIDE) then
- begin
- SetWindowPos(lpUIPrivate.hSoftKbdWnd, 0,
- lpIMC.ptSoftKbdPos.x, lpIMC.ptSoftKbdPos.y, 0, 0, SWP_NOACTIVATE or SWP_NOSIZE or SWP_NOZORDER);
- // only show, if the application want to show it
- if (lpUIPrivate.fdwSetContext and ISC_SHOW_SOFTKBD) <> 0 then ShowSoftKbd(hUIWnd, SW_SHOWNOACTIVATE, lpImcP);
- end;
- end;
- ImmUnlockIMCC(lpIMC.hPrivate);
- GlobalUnlock(hUIPrivate);
- ImmUnlockIMC(_hIMC);
- end;
- // IMN_SOFTKBDDESTROYED处理
- procedure SoftKbdDestroyed(hUIWnd: hWnd);
- var
- hUIPrivate: HGlobal;
- lpUIPrivate: PUIPriv;
- begin
- hUIPrivate := GetWindowLong(hUIWnd, IMMGWLP_PRIVATE);
- if (hUIPrivate = 0) then Exit;
- lpUIPrivate := GlobalLock(hUIPrivate);
- if (lpUIPrivate = nil) then Exit;
- lpUIPrivate.hSoftKbdWnd := 0;
- GlobalUnlock(hUIPrivate);
- end;
- // 打开关闭Status窗口
- procedure StatusWndMsg(hUIWnd: hWnd; fOn: Bool);
- var
- hUIPrivate: hGlobal;
- _hIMC: hIMC;
- hStatusWnd: hWnd;
- lpUIPrivate: PUIPriv;
- fdwSetContext: DWord;
- begin
- hUIPrivate := GetWindowLong(hUIWnd, IMMGWLP_PRIVATE);
- if (hUIPrivate = 0) then Exit;
- lpUIPrivate := GlobalLock(hUIPrivate);
- if (lpUIPrivate = nil) then Exit;
- _hIMC := GetWindowLong(hUIWnd, IMMGWLP_IMC);
- if (_hIMC = 0) then
- begin
- GlobalUnlock(hUIPrivate);
- Exit;
- end;
- if (fOn = True) then
- begin
- lpUIPrivate.fdwSetContext := lpUIPrivate.fdwSetContext or ISC_OPEN_STATUS_WINDOW;
- if (IsWindow(lpUIPrivate.hStatusWnd) = False) then OpenStatus(hUIWnd); // 重建
- end else
- begin
- lpUIPrivate.fdwSetContext := lpUIPrivate.fdwSetContext and (not ISC_OPEN_STATUS_WINDOW);
- end;
- hStatusWnd := lpUIPrivate.hStatusWnd;
- GlobalUnlock(hUIPrivate);
- if (IsWindow(hStatusWnd) = False) then Exit;
- if (fOn = False) then
- begin
- fdwSetContext := lpUIPrivate.fdwSetContext and (ISC_SHOWUICOMPOSITIONWINDOW or ISC_HIDE_COMP_WINDOW);
- if (fdwSetContext = ISC_HIDE_COMP_WINDOW) then ShowComp(hUIWnd, SW_HIDE);
- fdwSetContext := lpUIPrivate.fdwSetContext and (ISC_SHOWUICANDIDATEWINDOW or ISC_HIDE_CAND_WINDOW);
- if (fdwSetContext = ISC_HIDE_CAND_WINDOW) then ShowCand(hUIWnd, SW_HIDE);
- fdwSetContext := lpUIPrivate.fdwSetContext and (ISC_SHOW_SOFTKBD or ISC_HIDE_SOFTKBD);
- if (fdwSetContext = ISC_HIDE_SOFTKBD) then
- begin
- lpUIPrivate.fdwSetContext := lpUIPrivate.fdwSetContext and (not ISC_HIDE_SOFTKBD);
- ShowSoftKbd(hUIWnd, SW_HIDE, nil);
- end;
- ShowStatus(hUIWnd, SW_HIDE);
- end else
- if (_hIMC <> 0) then ShowStatus(hUIWnd, SW_SHOWNOACTIVATE) else ShowStatus(hUIWnd, SW_HIDE);
- end;
- // 显示隐藏Ime界面
- procedure ShowUI(hUIWnd: hWnd; nShowCmd: Integer);
- label
- ShowUIUnlockIMCC;
- var
- _hIMC: hIMC;
- lpIMC: PInputContext;
- lpImcP: PPrivContext;
- hUIPrivate: hGlobal;
- lpUIPrivate: PUIPriv;
- begin
- lpIMC := nil;
- lpImcP := nil;
- if (nShowCmd <> SW_HIDE) then
- begin
- _hIMC := GetWindowLong(hUIWnd, IMMGWLP_IMC);
- if (_hIMC = 0) then
- begin
- nShowCmd := SW_HIDE;
- end else
- begin
- lpIMC := ImmLockIMC(_hIMC);
- if (lpIMC = nil) then
- begin
- nShowCmd := SW_HIDE;
- end else
- begin
- lpImcP := ImmLockIMCC(lpIMC.hPrivate);
- if (lpImcP = nil) then
- begin
- ImmUnlockIMC(_hIMC);
- nShowCmd := SW_HIDE;
- end;
- end;
- end;
- end else
- _hIMC := 0; // ++
- if (nShowCmd = SW_HIDE) then
- begin
- ShowStatus(hUIWnd, nShowCmd);
- ShowComp(hUIWnd, nShowCmd);
- ShowCand(hUIWnd, nShowCmd);
- ShowSoftKbd(hUIWnd, nShowCmd, nil);
- Exit;
- end;
- hUIPrivate := GetWindowLong(hUIWnd, IMMGWLP_PRIVATE);
- if (hUIPrivate = 0) then goto ShowUIUnlockIMCC; // can not darw status window
- lpUIPrivate := GlobalLock(hUIPrivate);
- if (lpUIPrivate = nil) then goto ShowUIUnlockIMCC; // can not draw status window
- lpUIPrivate.fdwSetContext := lpUIPrivate.fdwSetContext or ISC_SHOWUICOMPOSITIONWINDOW;
- // Composition窗口
- if (lpUIPrivate.fdwSetContext and ISC_SHOWUICOMPOSITIONWINDOW <> 0) and
- (lpImcP.fdwImeMsg and MSG_ALREADY_START <> 0) then
- begin
- if IsWindow(lpUIPrivate.hCompWnd) then
- begin
- if (lpUIPrivate.nShowCompCmd <> SW_HIDE) then
- RedrawWindow(lpUIPrivate.hCompWnd, nil, 0, RDW_FRAME or RDW_INVALIDATE or RDW_ERASE);
- if (sImeG.IC_Trace <> 0) then // modify 95.7.17
- SendMessage(lpUIPrivate.hCompWnd, WM_IME_NOTIFY, IMN_SETCOMPOSITIONWINDOW, 0);
- if (lpUIPrivate.nShowCompCmd = SW_HIDE) then ShowComp(hUIWnd, nShowCmd);
- end else
- StartComp(hUIWnd);
- end else
- begin
- if (lpUIPrivate.nShowCompCmd <> SW_HIDE) then
- if (lpUIPrivate.fdwSetContext and ISC_OPEN_STATUS_WINDOW) <> 0 then
- lpUIPrivate.fdwSetContext := lpUIPrivate.fdwSetContext or ISC_HIDE_COMP_WINDOW
- else
- ShowComp(hUIWnd, SW_HIDE);
- end;
- // Candidate窗口
- if (lpUIPrivate.fdwSetContext and ISC_SHOWUICANDIDATEWINDOW <> 0) and
- (lpImcP.fdwImeMsg and MSG_ALREADY_OPEN <> 0) then
- begin
- if IsWindow(lpUIPrivate.hCandWnd) then
- begin
- if (lpUIPrivate.nShowCandCmd <> SW_HIDE) then
- RedrawWindow(lpUIPrivate.hCandWnd, nil, 0, RDW_FRAME or RDW_INVALIDATE or RDW_ERASE);
- if (sImeG.IC_Trace <> 0) then
- SendMessage(lpUIPrivate.hCandWnd, WM_IME_NOTIFY, IMN_SETCANDIDATEPOS, 1);
- if (lpUIPrivate.nShowCandCmd = SW_HIDE) then ShowCand(hUIWnd, nShowCmd);
- end else
- OpenCand(hUIWnd);
- end else
- begin
- if (lpUIPrivate.nShowCandCmd <> SW_HIDE) then
- if (lpUIPrivate.fdwSetContext and ISC_OPEN_STATUS_WINDOW) <> 0 then
- lpUIPrivate.fdwSetContext := lpUIPrivate.fdwSetContext or ISC_HIDE_CAND_WINDOW
- else
- ShowCand(hUIWnd, SW_HIDE);
- end;
- // Status窗口
- if (lpUIPrivate.fdwSetContext and ISC_OPEN_STATUS_WINDOW) <> 0 then
- begin
- if (IsWindow(lpUIPrivate.hStatusWnd) = False) then OpenStatus(hUIWnd);
- if (lpUIPrivate.nShowStatusCmd <> SW_HIDE) then
- RedrawWindow(lpUIPrivate.hStatusWnd, nil, 0, RDW_FRAME or RDW_INVALIDATE or RDW_ERASE);
- SendMessage(lpUIPrivate.hStatusWnd, WM_IME_NOTIFY, IMN_SETSTATUSWINDOWPOS, 0);
- ShowStatus(hUIWnd, nShowCmd);
- end else
- if IsWindow(lpUIPrivate.hStatusWnd) then DestroyWindow(lpUIPrivate.hStatusWnd);
- // 处于关闭状态
- if (lpIMC.fOpen = False) then
- begin
- if (lpUIPrivate.nShowCompCmd <> SW_HIDE) then ShowSoftKbd(hUIWnd, SW_HIDE, nil);
- end else
- if (lpUIPrivate.fdwSetContext and ISC_SHOW_SOFTKBD <> 0) and
- (lpIMC.fdwConversion and IME_CMODE_SOFTKBD <> 0) then
- begin
- if (IsWindow(lpUIPrivate.hSoftKbdWnd) = False) then
- begin
- UpdateSoftKbd(hUIWnd);
- end else
- if (lpUIPrivate.nShowSoftKbdCmd = SW_HIDE) then
- begin
- ShowSoftKbd(hUIWnd, nShowCmd, lpImcP);
- end else
- if (lpUIPrivate.hIMC <> _hIMC) then // **
- UpdateSoftKbd(hUIWnd)
- else
- RedrawWindow(lpUIPrivate.hSoftKbdWnd, nil, 0, RDW_FRAME or RDW_INVALIDATE);
- end else
- begin
- if (lpUIPrivate.nShowSoftKbdCmd <> SW_HIDE) then
- if (lpUIPrivate.fdwSetContext and ISC_OPEN_STATUS_WINDOW) <> 0 then
- lpUIPrivate.fdwSetContext := lpUIPrivate.fdwSetContext or ISC_HIDE_SOFTKBD
- else
- ShowSoftKbd(hUIWnd, SW_HIDE, nil);
- end;
- // we switch to this hIMC
- lpUIPrivate.hIMC := _hIMC;
- GlobalUnlock(hUIPrivate);
- ShowUIUnlockIMCC:
- ImmUnlockIMCC(lpIMC.hPrivate);
- ImmUnlockIMC(_hIMC);
- end;
- // IMN_GUIDELINE处理
- procedure ShowGuideLine(hUIWnd: hWnd);
- var
- _hIMC: hIMC;
- lpIMC: PInputContext;
- lpGuideLine: PGuideLine;
- begin
- _hIMC := GetWindowLong(hUIWnd, IMMGWLP_IMC);
- if (_hIMC = 0) then Exit;
- lpIMC := ImmLockIMC(_hIMC);
- if (lpIMC = nil) then Exit;
- lpGuideLine := ImmLockIMCC(lpIMC.hGuideLine);
- if (lpGuideLine <> nil) then
- if (lpGuideLine.dwLevel = GL_LEVEL_ERROR) then
- begin
- MessageBeep($FFFFFFFF);
- MessageBeep($FFFFFFFF);
- end else
- if (lpGuideLine.dwLevel = GL_LEVEL_WARNING) then MessageBeep($FFFFFFFF);
- ImmUnlockIMCC(lpIMC.hGuideLine);
- ImmUnlockIMC(_hIMC);
- end;
- // IMN_PRIVATE_UPDATE_STATUS处理
- function UpdateStatusWindow(hUIWnd: hWnd): Bool;
- var
- hStatusWnd: hWnd;
- begin
- Result := False;
- hStatusWnd := GetStatusWnd(hUIWnd);
- if (IsWindow(hStatusWnd) = False) then Exit;
- InvalidateRect(hStatusWnd, @sImeG.rcStatusText, True);
- UpdateWindow(hStatusWnd);
- Result := True;
- end;
- // WM_IME_NOTIFY消息处理
- procedure NotifyUI(hUIWnd: hWnd; wParam: WParam; lParam: LParam);
- var
- hStatusWnd, hCandWnd, hCompWnd: hWnd;
- _hDC: hDC;
- rcRect: TRect;
- begin
- case (wParam) of
- IMN_OPENSTATUSWINDOW: // 打开Status窗口
- StatusWndMsg(hUIWnd, True);
- IMN_CLOSESTATUSWINDOW: // 关闭Status窗口
- StatusWndMsg(hUIWnd, False);
- IMN_OPENCANDIDATE: // 打开Candidate窗口
- if (lParam and $00000001) <> 0 then OpenCand(hUIWnd);
- IMN_CHANGECANDIDATE: // 更新Candidate窗口
- if (lParam and $00000001) <> 0 then
- begin
- hCandWnd := GetCandWnd(hUIWnd);
- if (IsWindow(hCandWnd) = False) then Exit;
- _hDC := GetDC(hCandWnd);
- PaintCandWindow(hCandWnd, _hDC);
- ReleaseDC(hCandWnd, _hDC);
- end;
- IMN_CLOSECANDIDATE: // 关闭Candidate窗口
- if (lParam and $00000001) <> 0 then CloseCand(hUIWnd);
- IMN_SETSENTENCEMODE:
- ;
- IMN_SETOPENSTATUS, // 设置输入法状态
- IMN_SETCONVERSIONMODE: // 改变输入法状态
- begin
- hStatusWnd := GetStatusWnd(hUIWnd);
- if (IsWindow(hStatusWnd) = False) then Exit;
- rcRect := sImeG.rcStatusText;
- // off by 1
- Inc(rcRect.Right);
- Inc(rcRect.Bottom);
- RedrawWindow(hStatusWnd, @rcRect, 0, RDW_INVALIDATE);
- end;
- IMN_SETCOMPOSITIONFONT:
- // we are not going to change font, but an IME can do this if it want
- ;
- IMN_SETCOMPOSITIONWINDOW: // 设置Composition窗口
- begin
- hCompWnd := GetCompWnd(hUIWnd);
- if IsWindow(hCompWnd) then PostMessage(hCompWnd, WM_IME_NOTIFY, wParam, lParam);
- end;
- IMN_SETCANDIDATEPOS: // 设置Candidate窗口
- begin
- hCandWnd := GetCandWnd(hUIWnd);
- if IsWindow(hCandWnd) then PostMessage(hCandWnd, WM_IME_NOTIFY, wParam, lParam);
- end;
- IMN_SETSTATUSWINDOWPOS: // 设置Status窗口
- begin
- hStatusWnd := GetStatusWnd(hUIWnd);
- if IsWindow(hStatusWnd) then PostMessage(hStatusWnd, WM_IME_NOTIFY, wParam, lParam);
- end;
- IMN_GUIDELINE: // 错误信息处理
- ShowGuideLine(hUIWnd);
- IMN_PRIVATE: // 自定义Ime通知
- begin
- case (lParam) of
- IMN_PRIVATE_UPDATE_SOFTKBD: UpdateSoftKbd(hUIWnd);
- IMN_PRIVATE_UPDATE_STATUS: UpdateStatusWindow(hUIWnd);
- IMN_PRIVATE_DESTROYCANDWIN: SendMessage(GetCandWnd(hUIWnd), WM_DESTROY, 0, 0);
- IMN_PRIVATE_CMENUDESTROYED: CMenuDestroyed(hUIWnd);
- IMN_PRIVATE_SOFTKEYMENUDESTROYED: SoftkeyMenuDestroyed(hUIWnd);
- end;
- end;
- IMN_SOFTKBDDESTROYED: // 软键盘被销毁
- SoftKbdDestroyed(hUIWnd);
- end;
- end;
- // WM_PAINT处理
- function UIPaint(hUIWnd: hWnd): LResult;
- var
- ps: TPaintStruct;
- sMsg: TMsg;
- hUIPrivate: hGlobal;
- lpUIPrivate: PUIPriv;
- begin
- Result := 0;
- // for safety
- BeginPaint(hUIWnd, ps);
- EndPaint(hUIWnd, ps);
- // some application will not remove the WM_PAINT messages
- PeekMessage(sMsg, hUIWnd, WM_PAINT, WM_PAINT, PM_REMOVE or PM_NOYIELD);
- hUIPrivate := GetWindowLong(hUIWnd, IMMGWLP_PRIVATE);
- if (hUIPrivate = 0) then Exit;
- lpUIPrivate := GlobalLock(hUIPrivate);
- if (lpUIPrivate = nil) then Exit;
- if (lpUIPrivate.fdwSetContext and ISC_SETCONTEXT_UI) <> 0 then
- ShowUI(hUIWnd, SW_SHOWNOACTIVATE)
- else
- ShowUI(hUIWnd, SW_HIDE);
- GlobalUnlock(hUIPrivate);
- end;
- // 激活休眠输入法
- procedure SetContext(hUIWnd: hWnd; fOn: Bool; lShowUI: LParam);
- label
- SetShowStatus;
- var
- _hIMC: hIMC;
- lpIMC: PInputContext;
- lpImcP: PPrivContext;
- hUIPrivate: hGlobal;
- lpUIPrivate: PUIPriv;
- fdwSetContext, fdwConversion: DWord;
- _hKey, hKeyCurrVersion, hKeyGB: hKey;
- Buf: array[0..MAX_PATH] of Char;
- bcData, ValueType, ValueSize, retCode: DWord;
- ui_Mode: Integer;
- lpbKeyState: TKeyboardState;
- ptSTFixPos, ptNew, ptSTWPos: TPoint;
- begin
- _hIMC := GetWindowLong(hUIWnd, IMMGWLP_IMC);
- if (_hIMC = 0) then Exit;
- lpIMC := ImmLockIMC(_hIMC);
- if (lpIMC = nil) then Exit;
- hUIPrivate := GetWindowLong(hUIWnd, IMMGWLP_PRIVATE);
- if (hUIPrivate = 0) then
- begin
- ImmUnlockIMC(_hIMC);
- Exit;
- end;
- lpUIPrivate := GlobalLock(hUIPrivate);
- if (lpUIPrivate = nil) then
- begin
- ImmUnlockIMC(_hIMC);
- Exit;
- end;
- if (fOn = True) then
- begin
- lpUIPrivate.fdwSetContext := lpUIPrivate.fdwSetContext and not(ISC_SHOWUIALL or ISC_HIDE_SOFTKBD);
- lpUIPrivate.fdwSetContext := lpUIPrivate.fdwSetContext or (lShowUI and ISC_SHOWUIALL) or ISC_SHOW_SOFTKBD;
- bcData := 256;
- if (RegOpenKeyEx(HKEY_CURRENT_USER, 'Control PanelInput Method', 0, KEY_ENUMERATE_SUB_KEYS or KEY_EXECUTE or KEY_QUERY_VALUE, _hKey) <> ERROR_SUCCESS) then
- begin
- goto SetShowStatus;
- end;
- if (RegQueryValueEx(_hKey, 'show status', nil, nil, @Buf, @bcData) <> ERROR_SUCCESS) then
- begin
- lpUIPrivate.fdwSetContext := lpUIPrivate.fdwSetContext or ISC_OPEN_STATUS_WINDOW;
- goto SetShowStatus;
- end;
- if (Buf[0] = '1') then
- lpUIPrivate.fdwSetContext := lpUIPrivate.fdwSetContext or ISC_OPEN_STATUS_WINDOW
- else
- lpUIPrivate.fdwSetContext := lpUIPrivate.fdwSetContext and (not ISC_OPEN_STATUS_WINDOW);
- SetShowStatus:
- RegCloseKey(_hKey);
- fdwSetContext := lpUIPrivate.fdwSetContext and (ISC_SHOWUICOMPOSITIONWINDOW or ISC_HIDE_COMP_WINDOW);
- if (fdwSetContext = ISC_HIDE_COMP_WINDOW) then
- begin
- ShowComp(hUIWnd, SW_HIDE);
- end else
- if ((fdwSetContext and ISC_HIDE_COMP_WINDOW) <> 0) then
- begin
- lpUIPrivate.fdwSetContext := lpUIPrivate.fdwSetContext and (not ISC_HIDE_COMP_WINDOW);
- end else
- begin
- end;
- fdwSetContext := lpUIPrivate.fdwSetContext and (ISC_SHOWUICANDIDATEWINDOW or ISC_HIDE_CAND_WINDOW);
- if (fdwSetContext = ISC_HIDE_CAND_WINDOW) then
- begin
- ShowCand(hUIWnd, SW_HIDE);
- end else
- if ((fdwSetContext and ISC_HIDE_CAND_WINDOW) = 0) then
- begin
- lpUIPrivate.fdwSetContext := lpUIPrivate.fdwSetContext and (not ISC_HIDE_CAND_WINDOW);
- end else
- begin
- end;
- if (lpIMC.cfCandForm[0].dwIndex <> 0) then lpIMC.cfCandForm[0].dwStyle := CFS_DEFAULT;
- lpImcP := ImmLockIMCC(lpIMC.hPrivate);
- if (lpImcP = nil) then
- begin
- GlobalUnlock(hUIPrivate);
- ImmUnlockIMC(_hIMC);
- Exit;
- end;
- // init ime properties & reset context
- retCode := OpenReg_PathSetup(@hKeyCurrVersion);
- if (retCode <> ERROR_SUCCESS) then
- begin
- wvsprintf(Buf, 'Error: RegOpenKeyEx = %d', @retCode);
- MessageBox(lpIMC.hWnd, Buf, szWarnTitle, MB_OK or MB_ICONINFORMATION);
- Exit;
- end;
- // query 光标跟随 value
- retCode := OpenReg_User(hKeyCurrVersion, szImeRegName, @hKeyGB);
- ValueSize := SizeOf(DWord);
- RegQueryValueEx(hKeyGB, szTrace, nil, @ValueType, @sImeG.IC_Trace, @ValueSize);
- RegCloseKey(hKeyGB);
- RegCloseKey(hKeyCurrVersion);
- if (sImeG.IC_Trace <> SaTC_Trace) then // **
- begin
- lpImcP.iImeState := CST_INIT;
- CompCancel(_hIMC, lpIMC);
- // init fields of hPrivate
- lpImcP.fdwImeMsg := 0;
- lpImcP.dwCompChar := 0;
- lpImcP.fdwGcsFlag := 0;
- lpImcP.uSYHFlg := $00000000;
- lpImcP.uDYHFlg := $00000000;
- // change compwnd size
- // init fields of hIMC
- lpIMC.fOpen := True;
- SendMessage(GetCandWnd(hUIWnd), WM_DESTROY, 0, 0);
- // set cand window data
- if (sImeG.IC_Trace <> 0) then
- begin
- ui_Mode := BOX_UI;
- end else
- begin
- ui_Mode := LIN_UI;
- ptSTFixPos.x := 0;
- ptSTFixPos.y := sImeG.rcWorkArea.Bottom - sImeG.yStatusHi;
- ImmSetStatusWindowPos(_hIMC, @ptSTFixPos);
- end;
- InitCandUIData(GetSystemMetrics(SM_CXBORDER), GetSystemMetrics(SM_CYBORDER), ui_Mode);
- end;
- SaTC_Trace := sImeG.IC_Trace;
- // init Caps
- GetKeyboardState(lpbKeyState);
- if (lpbKeyState[VK_CAPITAL] and $01) <> 0 then
- begin
- // 10.11 add
- uCaps := 1;
- // change to alphanumeric mode
- fdwConversion := lpIMC.fdwConversion and not(IME_CMODE_CHARCODE or IME_CMODE_NATIVE or IME_CMODE_EUDC);
- end else
- begin
- // change to native mode
- if (uCaps = 1) then
- fdwConversion := (lpIMC.fdwConversion or IME_CMODE_NATIVE) and not(IME_CMODE_CHARCODE or IME_CMODE_EUDC)
- else
- fdwConversion := lpIMC.fdwConversion;
- uCaps := 0;
- end;
- ImmSetConversionStatus(_hIMC, fdwConversion, lpIMC.fdwSentence);
- if (lpIMC.cfCompForm.dwStyle and CFS_FORCE_POSITION <> 0) and (sImeG.IC_Trace <> 0) then
- begin
- ImmGetStatusWindowPos(_hIMC, @ptSTWPos);
- ptNew.x := ptSTWPos.x + sImeG.xStatusWi + ui_Margin;
- if (ptSTWPos.x + sImeG.xStatusWi + sImeG.xCandWi + sImeL.xCompWi + 2 * ui_Margin) >= sImeG.rcWorkArea.Right then
- begin
- ptNew.x := ptSTWPos.x - sImeL.xCompWi - ui_Margin;
- end;
- Inc(ptNew.x, sImeL.cxCompBorder);
- ptNew.y := ptSTWPos.y + sImeL.cyCompBorder;
- lpIMC.cfCompForm.ptCurrentPos := ptNew;
- ScreenToClient(lpIMC.hWnd, lpIMC.cfCompForm.ptCurrentPos);
- lpIMC.cfCompForm.dwStyle := CFS_DEFAULT;
- end;
- end else
- lpUIPrivate.fdwSetContext := lpUIPrivate.fdwSetContext and (not ISC_SETCONTEXT_UI);
- GlobalUnlock(hUIPrivate);
- UIPaint(hUIWnd);
- ImmUnlockIMC(_hIMC);
- end;
- // IMC_GETCOMPOSITIONWINDOW处理
- function GetCompWindow(hUIWnd: hWnd; lpCompForm: PCompositionForm): LResult;
- var
- hCompWnd: hWnd;
- rcCompWnd: TRect;
- begin
- Result := 1;
- hCompWnd := GetCompWnd(hUIWnd);
- if IsWindow(hCompWnd) = False then Exit;
- if (GetWindowRect(hCompWnd, rcCompWnd) = False) then Exit;
- lpCompForm.dwStyle := CFS_POINT or CFS_RECT;
- lpCompForm.ptCurrentPos := PPoint(@rcCompWnd)^;
- lpCompForm.rcArea := rcCompWnd;
- Result := 0;
- end;
- // UI窗口回调
- function UIWndProc(hUIWnd: hWnd; uMsg: uInt; wParam: WParam; lParam: LParam): LResult; stdcall;
- var
- hCompWnd, hStatusWnd: hWnd;
- rcRect, rcStatusWnd: TRect;
- _hIMC: hIMC;
- lpIMC: PInputContext;
- lpImcP: PPrivContext;
- ptPos: TPoint;
- begin
- {$IfDef Debug}
- ImeLog('UIWndProc, uMsg:' + Int2Hex(uMsg) + ', wParam:' + Int2Hex(wParam) + ', lParam:' + Int2Hex(lParam));
- {$EndIf}
- Result := 0;
- case (uMsg) of
- WM_CREATE:
- CreateUIWindow(hUIWnd);
- WM_DESTROY:
- DestroyUIWindow(hUIWnd);
- WM_IME_STARTCOMPOSITION: // you can create a window as the composition window here
- StartComp(hUIWnd);
- WM_IME_COMPOSITION: // 编码(Composition)状态改变
- begin
- if (sImeG.IC_Trace = 0) then
- begin
- end else
- if (lParam and GCS_RESULTSTR) <> 0 then
- begin
- MoveDefaultCompPosition(hUIWnd);
- end else
- begin
- end;
- hCompWnd := GetCompWnd(hUIWnd);
- if IsWindow(hCompWnd) then
- begin
- rcRect := sImeL.rcCompText;
- // off by 1
- Inc(rcRect.Right, 1);
- Inc(rcRect.Bottom, 1);
- RedrawWindow(hCompWnd, @rcRect, 0, RDW_INVALIDATE);
- end;
- end;
- WM_IME_ENDCOMPOSITION: // you can destroy the composition window here
- EndComp(hUIWnd);
- WM_IME_NOTIFY: // Ime通知消息组
- NotifyUI(hUIWnd, wParam, lParam);
- WM_IME_SETCONTEXT: // 激活/休眠输入法
- begin
- SetContext(hUIWnd, Bool(wParam), lParam);
- if (wParam <> 0) and (GetWindowLong(hUIWnd, IMMGWLP_IMC) <> 0) then
- SetWindowPos(hUIWnd, 0, 0, 0, 0, 0, SWP_NOSIZE or SWP_NOACTIVATE or SWP_NOMOVE);
- end;
- WM_IME_CONTROL: // Ime控制消息组
- case (wParam) of
- IMC_GETCANDIDATEPOS: // not implemented yet
- begin
- Result := 1;
- end;
- IMC_GETCOMPOSITIONFONT: // not implemented yet
- begin
- Result := 1;
- end;
- IMC_GETCOMPOSITIONWINDOW: // 取Composition窗口位置
- begin
- Result := GetCompWindow(hUIWnd, PCompositionForm(lParam));
- end;
- IMC_GETSTATUSWINDOWPOS: // 取Status窗口位置
- begin
- hStatusWnd := GetStatusWnd(hUIWnd);
- if IsWindow(hStatusWnd) = False then Exit;
- if (GetWindowRect(hStatusWnd, rcStatusWnd) = False) then Exit;
- Result := MakeLResult(rcStatusWnd.Left, rcStatusWnd.Top);
- end;
- IMC_SETSTATUSWINDOWPOS: // 设Status窗口位置
- begin
- Result := 1;
- ptPos.x := PSmallPoint(@lParam).x;
- ptPos.y := PSmallPoint(@lParam).y;
- _hIMC := GetWindowLong(hUIWnd, IMMGWLP_IMC);
- if (_hIMC = 0) then Exit;
- if (ImmSetStatusWindowPos(_hIMC, @ptPos) = False) then Exit;
- // set comp window position when TraceCuer
- lpIMC := ImmLockIMC(_hIMC);
- if (lpIMC = nil) then Exit;
- lpImcP := ImmLockIMCC(lpIMC.hPrivate);
- if (lpImcP = nil) then Exit;
- if (sImeG.IC_Trace = 0) then
- begin
- lpIMC.cfCompForm.dwStyle := CFS_RECT;
- lpIMC.cfCompForm.ptCurrentPos.x := ptPos.x + sImeG.xStatusWi + ui_Margin;
- lpIMC.cfCompForm.ptCurrentPos.y := ptPos.y;
- CopyRect(lpIMC.cfCompForm.rcArea, sImeG.rcWorkArea);
- ScreenToClient(lpIMC.hWnd, lpIMC.cfCompForm.ptCurrentPos);
- // set composition window to the new poosition
- PostMessage(GetCompWnd(hUIWnd), WM_IME_NOTIFY, IMN_SETCOMPOSITIONWINDOW, 0);
- end;
- ImmUnlockIMCC(lpIMC.hPrivate);
- ImmUnlockIMC(_hIMC);
- Result := 0;
- end;
- else begin
- Result := 1;
- end;
- end;
- WM_IME_COMPOSITIONFULL:
- ;
- WM_IME_SELECT: // 选中新的输入法
- SetContext(hUIWnd, Bool(wParam), 0);
- WM_MOUSEACTIVATE:
- Result := MA_NOACTIVATE;
- WM_PAINT:
- Result := UIPaint(hUIWnd);
- else
- Result := DefWindowProc(hUIWnd, uMsg, wParam, lParam);
- end;
- end;
- // 绘制凸出边框
- procedure DrawConvexRect(_hDC: hDC; x1, y1, x2, y2: Integer);
- var
- _hPen, hOldPen: hPen;
- begin
- SelectObject(_hDC, GetStockObject(LTGRAY_BRUSH));
- SelectObject(_hDC, GetStockObject(WHITE_PEN));
- MoveToEx(_hDC, x1, y1, nil);
- LineTo(_hDC, x2, y1);
- MoveToEx(_hDC, x1, y1, nil);
- LineTo(_hDC, x1, y2);
- _hPen := CreatePen(PS_SOLID, 1, RGB(128, 128, 128));
- hOldPen := SelectObject(_hDC, _hPen);
- MoveToEx(_hDC, x2 - 1, y2 - 1, nil);
- LineTo(_hDC, x2 - 1, y1);
- MoveToEx(_hDC, x2 - 1, y2 - 1, nil);
- LineTo(_hDC, x1, y2 - 1);
- SelectObject(_hDC, hOldPen);
- DeleteObject(_hPen);
- end;
- // 绘制凸出边框
- procedure DrawConvexRectP(_hDC: hDC; x1, y1, x2, y2: Integer);
- var
- _hPen, hOldPen: hPen;
- begin
- SelectObject(_hDC, GetStockObject(LTGRAY_BRUSH));
- SelectObject(_hDC, GetStockObject(WHITE_PEN));
- MoveToEx(_hDC, x1, y1, nil);
- LineTo(_hDC, x2 - 1, y1);
- MoveToEx(_hDC, x1, y1, nil);
- LineTo(_hDC, x1, y2 - 1);
- _hPen := CreatePen(PS_SOLID, 1, RGB(0, 0, 0));
- hOldPen := SelectObject(_hDC, _hPen);
- MoveToEx(_hDC, x2 - 1, y2 - 1, nil);
- LineTo(_hDC, x2 - 1, y1);
- MoveToEx(_hDC, x2 - 1, y2 - 1, nil);
- LineTo(_hDC, x1, y2 - 1);
- SelectObject(_hDC, hOldPen);
- DeleteObject(_hPen);
- end;
- // 绘制凹陷边框
- procedure DrawConcaveRect(_hDC: hDC; x1, y1, x2, y2: Integer);
- var
- hLtPen, OldPen: hPen;
- begin
- hLtPen := CreatePen(PS_SOLID, 1, $00808080);
- OldPen := SelectObject(_hDC, hLtPen);
- MoveToEx(_hDC, x1, y1, nil);
- LineTo(_hDC, x2, y1);
- MoveToEx(_hDC, x1, y1, nil);
- LineTo(_hDC, x1, y2);
- SelectObject(_hDC, GetStockObject(WHITE_PEN));
- MoveToEx(_hDC, x2, y2, nil);
- LineTo(_hDC, x2, y1 - 1);
- MoveToEx(_hDC, x2, y2, nil);
- LineTo(_hDC, x1 - 1, y2);
- SelectObject(_hDC, OldPen);
- DeleteObject(hLtPen);
- end;
- end.