ToAscii.pas
资源名称:Wingb_Mz.rar [点击查看]
上传用户:wen198501
上传日期:2013-04-01
资源大小:335k
文件大小:38k
源码类别:
输入法编程
开发平台:
Delphi
- {******************************************************}
- { }
- { Copyright (c) 1990-1999 Microsoft Corporation }
- { }
- { Module Name: ToAscii.c ->> ToAscii.pas }
- { }
- { Translator: Liu_mazi@126.com, 2005-11-14 }
- { }
- {******************************************************}
- unit ToAscii;
- {$I Define.Inc}
- interface
- uses Windows, ImmDev, ImeDefs;
- function TranslateImeMessage(lpTransBuf: PTransMsgList; lpIMC: PInputContext; lpImcP: PPrivContext): uInt;
- function GBProcessKey(wCharCode: Word; lpImcP: PPrivContext): uInt;
- function ImeProcessKey(_hIMC: hIMC; uVirtKey: uInt; lParam: LParam; lpbKeyState: PKeyboardState): Bool; stdcall;
- function ImeToAsciiEx(uVirtKey, uScanCode: uInt;
- lpbKeyState: PKeyboardState; lpTransBuf: PTransMsgList; fuState: uInt; _hIMC: hIMC): uInt; stdcall;
- implementation
- uses Messages, Data, DDIS, Notify, Chcand, Compose, LogText;
- // 是否编码输入字符, **
- function IsUsedCode(wCharCode: Word): Bool;
- var
- wFlg: Word;
- begin
- Result := True;
- for wFlg := 0 to sImeG.wNumCodes - 1 do if (wCharCode = Ord(sImeG.UsedCodes[wFlg])) then Exit;
- Result := False;
- end;
- // this key will cause the IME go to what state
- function GBProcessKey(wCharCode: Word; lpImcP: PPrivContext): uInt;
- begin
- Result := CST_INVALID_INPUT;
- if (lpImcP = nil) then
- begin
- Result := CST_INVALID;
- Exit;
- end;
- // check space
- if (wCharCode = Ord(' ')) then
- begin
- if (lpImcP.bSeq[0] <> #0) and (lpImcP.bSeq[1] <> #0) then
- begin
- Result := CST_INPUT;
- Exit;
- end else
- if (lpImcP.bSeq[0] = #0) then
- begin
- Result := CST_ALPHANUMERIC;
- Exit;
- end else
- begin
- Result := CST_INVALID_INPUT;
- Exit;
- end;
- end;
- // check finalize char
- if ( (wCharCode >= Ord('0')) and (wCharCode <= Ord('9')) ) or
- ( (wCharCode >= Ord('a')) and (wCharCode <= Ord('f')) ) or
- ( wCharCode = Ord('?') ) then
- begin
- if (lpImcP.bSeq[0] = #0) then
- begin
- if (wCharCode = Ord('?')) then // 0x0??? - 0xF??? is OK
- begin
- Result := CST_ALPHANUMERIC;
- Exit;
- end else
- begin // there is no 0x0??? - 0x7???
- lpImcP.bSeq[1] := #0;
- Result := CST_INPUT;
- Exit;
- end;
- end else
- if (lpImcP.bSeq[1] = #0) then
- begin
- if (lpImcP.bSeq[0] >= '0') and (lpImcP.bSeq[0] <= '9') then //Area
- begin
- // there is less than 95 area and bigger than 0 area
- if ( (lpImcP.bSeq[0] = '0') and (wCharCode = Ord('0')) ) or
- ( (lpImcP.bSeq[0] = '9') and (wCharCode >= Ord('5')) ) or
- ( (wCharCode >= Ord('a')) and (wCharCode <= Ord('f')) ) or
- ( wCharCode = Ord('?') ) then
- begin
- Result := CST_INVALID_INPUT;
- Exit;
- end else
- begin
- lpImcP.bSeq[2] := #0;
- Result := CST_INPUT;
- Exit
- end;
- end;
- if (lpImcP.bSeq[0] >= 'a') and (lpImcP.bSeq[0] <= 'f') then //GB
- begin
- // there is less than 95 area and bigger than 0 area
- if ( (lpImcP.bSeq[0] = 'a') and (wCharCode = Ord('0')) ) or
- ( (lpImcP.bSeq[0] = 'f') and (wCharCode = Ord('f')) ) or
- ( wCharCode = Ord('?') ) then
- begin
- Result := CST_INVALID_INPUT;
- Exit;
- end else
- begin
- lpImcP.bSeq[2] := #0;
- Result := CST_INPUT;
- end;
- end;
- end else
- if (lpImcP.bSeq[2] = #0) then
- begin
- if (wCharCode = Ord('?')) then
- begin
- Result := CST_INPUT;
- Exit;
- end;
- if (lpImcP.bSeq[0] >= '0') and (lpImcP.bSeq[0] <= '9') then // Area
- begin
- if (wCharCode >= Ord('0')) and (wCharCode <= Ord('9')) then
- begin
- lpImcP.bSeq[3] := #0;
- Result := CST_INPUT;
- Exit;
- end else
- begin
- Result := CST_INVALID_INPUT;
- Exit;
- end;
- end;
- if (lpImcP.bSeq[0] >= 'a') and (lpImcP.bSeq[0] <= 'f') then // GB
- begin
- if (wCharCode >= Ord('a')) and (wCharCode <= Ord('f')) then
- begin
- lpImcP.bSeq[3] := #0;
- Result := CST_INPUT;
- end else
- begin
- Result := CST_INVALID_INPUT;
- Exit;
- end;
- end;
- end else
- if (lpImcP.bSeq[3] = #0) then
- begin
- if (lpImcP.bSeq[2] = '?') then
- begin
- if (wCharCode = Ord('?')) then
- begin
- Result := CST_INPUT;
- Exit;
- end else
- begin
- Result := CST_INVALID_INPUT;
- Exit;
- end;
- end;
- if (lpImcP.bSeq[0] >= '0') and (lpImcP.bSeq[0] <= '9') then //Area
- begin
- // there is less than 95 area and bigger than 0 area
- if ( (lpImcP.bSeq[2] = '0') and (wCharCode = Ord('0')) ) or
- ( (lpImcP.bSeq[2] = '9') and (wCharCode >= Ord('5')) ) or
- ( (wCharCode >= Ord('a')) and (wCharCode <= Ord('f')) ) or
- ( (wCharCode = Ord('?')) ) then
- begin
- Result := CST_INVALID_INPUT;
- end else
- begin
- Result := CST_INPUT;
- end;
- end;
- if (lpImcP.bSeq[0] >= 'a') and (lpImcP.bSeq[0] <= 'f') then //GB
- begin
- // there is less than 95 area and bigger than 0 area
- if ( (lpImcP.bSeq[2] = 'a') and (wCharCode = Ord('0')) ) or
- ( (lpImcP.bSeq[2] = 'f') and (wCharCode = Ord('f')) ) or
- ( wCharCode = Ord('?') ) then
- begin
- Result := CST_INVALID_INPUT;
- Exit;
- end else
- begin
- Result := CST_INPUT;
- Exit;
- end;
- end;
- end else
- begin
- Result := CST_INVALID_INPUT;
- Exit;
- end;
- end else
- if (wCharCode >= Ord(' ')) and (wCharCode <= Ord('~')) then
- begin
- Result := CST_ALPHANUMERIC;
- Exit;
- end else
- begin
- Result := CST_INVALID_INPUT;
- Exit;
- end;
- end;
- // this key will cause the IME go to what state
- function ProcessKey(wCharCode: Word; uVirtKey: uInt; uScanCode: uInt; lpbKeyState: PKeyboardState; lpIMC: PInputContext; lpImcP: PPrivContext): uInt;
- var
- lpGuideLine: PGuideLine;
- iImeState: uInt;
- begin
- Result := CST_INVALID;
- if (lpIMC = nil) or (lpImcP = nil) then Exit;
- // filter system key (alt,alt+,ctrl,shift) and fOpen, IME_CMODE_NOCONVERSION
- if (uVirtKey = VK_MENU) then // ALT key
- begin
- Exit;
- end else
- if (uScanCode and KF_ALTDOWN) <> 0 then // ALT-xx key
- begin
- Exit;
- end else
- if (uVirtKey = VK_CONTROL) then // CTRL key
- begin
- Exit;
- end else
- if (uVirtKey = VK_SHIFT) then // SHIFT key
- begin
- Exit;;
- end else
- if (lpIMC.fOpen = False) then // don't compose in close status
- begin
- Exit;
- end else
- if (lpIMC.fdwConversion and IME_CMODE_NOCONVERSION) <> 0 then
- begin
- if (uVirtKey = VK_CAPITAL) then // Caps on/off
- begin
- Result := CST_CAPITAL;
- end else
- Exit;
- end else
- if (uVirtKey >= VK_NUMPAD0) and (uVirtKey <= VK_DIVIDE) then
- begin
- Exit;
- end else
- begin
- end;
- // Caps on/off
- if (uVirtKey = VK_CAPITAL) then
- begin
- Result := CST_CAPITAL;
- Exit;
- end;
- if (lpIMC.fdwConversion and IME_CMODE_SOFTKBD <> 0) and (sImeL.dwSKWant <> 0) then
- begin
- if (wCharCode >= Ord(' ')) and (wCharCode <= Ord('~')) then
- begin
- Result := CST_SOFTKB;
- Exit;
- end else
- begin
- Exit; // return (CST_INVALID);
- end;
- end;
- // candidate alaredy open, <,>,pageup,pagedown,?,ECS,key
- Result := CST_CHOOSE;
- if (lpImcP.fdwImeMsg and MSG_ALREADY_OPEN) <> 0 then
- begin
- if (uVirtKey = VK_PRIOR) then // PageUp
- begin
- Exit;
- end else
- if (uVirtKey = VK_NEXT) then // PageDown
- begin
- Exit;
- end else
- if (wCharCode = Ord('-')) then
- begin
- Exit;
- end else
- if (wCharCode = Ord('=')) then
- begin
- Exit;
- end else
- if (uVirtKey = VK_HOME) then
- begin
- Exit;
- end else
- if (uVirtKey = VK_END) then
- begin
- Exit;
- end else
- if (uVirtKey = VK_ESCAPE) then // Esc
- begin
- Exit;
- end else
- if (wCharCode = Ord(' ')) then
- begin
- Exit;
- end else
- begin
- end;
- end;
- // candidate alaredy open, shift + num key
- if (lpImcP.fdwImeMsg and MSG_ALREADY_OPEN) <> 0 then
- if (wCharCode >= Ord('0')) and (wCharCode <= Ord('9')) then
- begin
- Exit; // return (CST_CHOOSE);
- end;
- // IME_CMODE_CHARCODE
- if (lpIMC.fdwConversion and IME_CMODE_CHARCODE) <> 0 then //Code Input Mode
- begin
- Result := CST_INVALID;
- Exit;
- end;
- if (lpIMC.fdwConversion and IME_CMODE_NATIVE) = 0 then
- begin
- if (wCharCode >= Ord(' ')) and (wCharCode <= Ord('~')) then // alphanumeric mode
- begin
- Result := CST_ALPHANUMERIC;
- Exit;
- end else
- begin
- Result := CST_INVALID;
- Exit;
- end;
- end else
- if (wCharCode = Ord('?')) then
- begin
- end else
- if (wCharCode = Ord(' ')) then
- begin
- end else
- if (wCharCode >= Ord(' ')) and (wCharCode <= Ord('~')) then
- begin
- if (IsUsedCode(wCharCode) = False) and (lpImcP.iImeState <> CST_INIT) then
- begin
- Result := CST_INVALID_INPUT;
- Exit;
- end;
- end;
- // Esc key
- if (uVirtKey = VK_ESCAPE) then
- begin
- lpGuideLine := ImmLockIMCC(lpIMC.hGuideLine);
- if (lpGuideLine = nil) then
- begin
- //return (CST_INVALID);
- Result := CST_INVALID;
- Exit;
- end;
- if (lpImcP.fdwImeMsg and MSG_ALREADY_START) <> 0 then
- begin
- iImeState := CST_INPUT;
- end else
- if (lpGuideLine = nil) then
- begin
- iImeState := CST_INVALID;
- end else
- if (lpGuideLine.dwLevel = GL_LEVEL_NOGUIDELINE) then
- begin
- iImeState := CST_INVALID;
- end else
- begin
- // need this key to clean information string or guideline state
- iImeState := CST_INPUT;
- end;
- ImmUnlockIMCC(lpIMC.hGuideLine);
- //return (iImeState);
- Result := iImeState;
- Exit;
- end else
- if (uVirtKey = VK_BACK) then // BackSpace Key
- begin
- if (lpImcP.fdwImeMsg and MSG_ALREADY_START) <> 0 then
- begin
- Result := CST_INPUT;
- Exit;
- end else
- begin
- Result := CST_INVALID;
- Exit;
- end;
- end else
- if (uVirtKey >= VK_NUMPAD0) and (uVirtKey <= VK_DIVIDE) then // NumPad key and Other Input vailid key
- begin
- // return (CST_ALPHANUMERIC);
- Result := CST_ALPHANUMERIC;
- Exit;
- end else
- if (wCharCode > Ord('~')) then
- begin
- Result := CST_INVALID;
- Exit;
- end else
- if (wCharCode < Ord(' ')) then
- begin
- Result := CST_INVALID;
- Exit;
- end else
- if (lpIMC.fdwConversion and IME_CMODE_EUDC) <> 0 then
- begin
- end else
- begin
- end;
- if (lpIMC.fdwConversion and IME_CMODE_NATIVE) <> 0 then
- begin
- Result := GBProcessKey(wCharCode,lpImcP);
- Exit;
- end;
- Result := CST_INVALID;
- end;
- // Ime回调, if this key is need by IME?
- function ImeProcessKey(_hIMC: hIMC; uVirtKey: uInt; lParam: LParam; lpbKeyState: PKeyboardState): Bool; stdcall;
- var
- lpIMC: PInputContext;
- lpImcP: PPrivContext;
- szAscii: array[0..3] of Char;
- nChars, iRet: Integer;
- fdwConversion: DWord;
- // fRet: Bool;
- begin
- Result := False;
- // can't compose in NULL hIMC
- if (_hIMC = 0) then Exit;
- lpIMC := ImmLockIMC(_hIMC);
- if (lpIMC = nil) then Exit;
- lpImcP := ImmLockIMCC(lpIMC.hPrivate);
- if (lpImcP = nil) then
- begin
- ImmUnlockIMC(_hIMC);
- Exit;
- end;
- nChars := Windows.ToAscii(uVirtKey, HiWord(lParam), lpbKeyState^, szAscii, 0);
- if (nChars = 0) then szAscii[0] := #0;
- iRet := ProcessKey(Ord(szAscii[0]), uVirtKey, HiWord(lParam), lpbKeyState, lpIMC, lpImcP);
- if (iRet = CST_INVALID) then
- begin
- //fRet = FALSE;
- end else
- if (iRet = CST_INPUT) and (uVirtKey = $08) and (lpImcP.iImeState = CST_INIT) then
- begin
- lpImcP.fdwImeMsg :=
- ( (lpImcP.fdwImeMsg or MSG_END_COMPOSITION) and not(MSG_START_COMPOSITION) )
- and not(MSG_IN_IMETOASCIIEX); // **
- if (lpImcP.fdwImeMsg and MSG_ALREADY_OPEN) <> 0 then
- begin
- ClearCand(lpIMC);
- lpImcP.fdwImeMsg := (lpImcP.fdwImeMsg or MSG_CLOSE_CANDIDATE) and (not MSG_OPEN_CANDIDATE);
- end;
- GenerateMessage(_hIMC, lpIMC, lpImcP);
- //fRet = FALSE;
- end else
- if (uVirtKey = VK_CAPITAL) then
- begin
- if (lpbKeyState[VK_CAPITAL] and $01) <> 0 then
- begin
- // change to alphanumeric mode
- fdwConversion := lpIMC.fdwConversion and not(IME_CMODE_CHARCODE or IME_CMODE_NATIVE or IME_CMODE_EUDC);
- uCaps := 1;
- end else
- begin
- // change to native mode
- fdwConversion := (lpIMC.fdwConversion or IME_CMODE_NATIVE) and not(IME_CMODE_CHARCODE or IME_CMODE_EUDC);
- uCaps := 0;
- end;
- ImmSetConversionStatus(_hIMC, fdwConversion, lpIMC.fdwSentence);
- //fRet = FALSE;
- end else
- if (iRet = CST_ALPHANUMERIC) and
- (lpIMC.fdwConversion and IME_CMODE_FULLSHAPE = 0) and
- (uVirtKey = VK_SPACE) then
- begin
- // fRet = FALSE;
- end else
- begin
- // fRet = TRUE;
- Result := True;
- end;
- ImmUnlockIMCC(lpIMC.hPrivate);
- ImmUnlockIMC(_hIMC);
- end;
- // Return Value: the number of translated chars
- function TranslateSymbolChar(lpTransBuf: PTransMsgList; wSymbolCharCode: Word; SymbolMode: Bool): uInt;
- var
- lpTransMsg: PTransMsg;
- begin
- Result := 0;
- lpTransMsg := @lpTransBuf.TransMsg;
- // NT need to modify this!
- lpTransMsg.message := WM_CHAR;
- lpTransMsg.wParam := HiByte(wSymbolCharCode);
- lpTransMsg.lParam := 1;
- Inc(lpTransMsg);
- Inc(Result);
- lpTransMsg.message := WM_CHAR;
- lpTransMsg.wParam := LoByte(wSymbolCharCode);
- lpTransMsg.lParam := 1;
- Inc(Result);
- if (SymbolMode) then
- begin
- lpTransMsg := @lpTransBuf.TransMsg;
- lpTransMsg.message := WM_CHAR;
- lpTransMsg.wParam := HiByte(wSymbolCharCode);
- lpTransMsg.lParam := 1;
- Inc(lpTransMsg);
- Inc(Result);
- lpTransMsg.message := WM_CHAR;
- lpTransMsg.wParam := LoByte(wSymbolCharCode);
- lpTransMsg.lParam := 1;
- Inc(Result);
- end;
- end;
- // Return Value: the number of translated chars
- function TranslateFullChar(lpTransBuf: PTransMsgList; wCharCode: Word): uInt;
- var
- // if your IME is possible to generate over ? messages, you need to take care about it
- lpTransMsg: PTransMsg;
- begin
- wCharCode := Swap(sImeG.wFullABC[wCharCode - Ord(' ')]);
- lpTransMsg := @lpTransBuf.TransMsg;
- // NT need to modify this!
- lpTransMsg.message := WM_CHAR;
- lpTransMsg.wParam := HiByte(wCharCode);
- lpTransMsg.lParam := 1;
- Inc(lpTransMsg);
- lpTransMsg.message := WM_CHAR;
- lpTransMsg.wParam := LoByte(wCharCode);
- lpTransMsg.lParam := 1;
- Result := 2; // generate two messages
- end;
- // translate the key to WM_CHAR as keyboard driver
- // Return Value: the number of translated chars
- function TranslateToAscii(uVirtKey, uScanCode: uInt; lpTransBuf: PTransMsgList; wCharCode: Word): uInt;
- var
- lpTransMsg: PTransMsg;
- begin
- lpTransMsg := @lpTransBuf.TransMsg;
- if (wCharCode <> 0) then // one char code
- begin
- lpTransMsg.message := WM_CHAR;
- lpTransMsg.wParam := wCharCode;
- lpTransMsg.lParam := (uScanCode shl 16) or 1;
- Result := 1;
- end else
- Result := 0; // no char code case
- end;
- // Return Value: the number of translated messages
- function TranslateImeMessage(lpTransBuf: PTransMsgList; lpIMC: PInputContext; lpImcP: PPrivContext): uInt;
- var
- uNumMsg, J: uInt;
- bLockMsgBuf: Bool;
- lpTransMsg: PTransMsg;
- hMem: hIMCC;
- uNumMsgLimit: uInt;
- begin
- uNumMsg := 0;
- bLockMsgBuf := False;
- lpTransMsg := @lpTransBuf.TransMsg; // ++
- for J := 0 to 1 do
- begin
- if (lpImcP.fdwImeMsg and MSG_CLOSE_CANDIDATE) <> 0 then
- begin
- if (lpImcP.fdwImeMsg and MSG_ALREADY_OPEN) <> 0 then
- begin
- if (J = 0) then
- begin
- Inc(uNumMsg);
- end else
- begin
- lpTransMsg.message := WM_IME_NOTIFY;
- lpTransMsg.wParam := IMN_CLOSECANDIDATE;
- lpTransMsg.lParam := $0001;
- Inc(lpTransMsg);
- lpImcP.fdwImeMsg := lpImcP.fdwImeMsg and (not MSG_ALREADY_OPEN);
- end;
- end;
- end;
- if (lpImcP.fdwImeMsg and MSG_END_COMPOSITION) <> 0 then
- begin
- if (lpImcP.fdwImeMsg and MSG_ALREADY_START) <> 0 then
- begin
- if (J = 0) then
- begin
- Inc(uNumMsg);
- end else
- begin
- lpTransMsg.message := WM_IME_ENDCOMPOSITION;
- lpTransMsg.wParam := 0;
- lpTransMsg.lParam := 0;
- Inc(lpTransMsg);
- lpImcP.fdwImeMsg := lpImcP.fdwImeMsg and (not MSG_ALREADY_START);
- end;
- end;
- end;
- if (lpImcP.fdwImeMsg and MSG_START_COMPOSITION) <> 0 then
- begin
- if (lpImcP.fdwImeMsg and MSG_ALREADY_START) = 0 then
- begin
- if (J = 0) then
- begin
- Inc(uNumMsg);
- end else
- begin
- lpTransMsg.message := WM_IME_STARTCOMPOSITION;
- lpTransMsg.wParam := 0;
- lpTransMsg.lParam := 0;
- Inc(lpTransMsg);
- lpImcP.fdwImeMsg := lpImcP.fdwImeMsg or MSG_ALREADY_START;
- end;
- end;
- end;
- if (lpImcP.fdwImeMsg and MSG_IMN_COMPOSITIONPOS) <> 0 then
- begin
- if (J = 0) then
- begin
- Inc(uNumMsg);
- end else
- begin
- lpTransMsg.message := WM_IME_NOTIFY;
- lpTransMsg.wParam := IMN_SETCOMPOSITIONWINDOW;
- lpTransMsg.lParam := 0;
- Inc(lpTransMsg);
- end;
- end;
- if (lpImcP.fdwImeMsg and MSG_COMPOSITION) <> 0 then
- begin
- if (J = 0) then
- begin
- Inc(uNumMsg);
- end else
- begin
- lpTransMsg.message := WM_IME_COMPOSITION;
- lpTransMsg.wParam := lpImcP.dwCompChar;
- lpTransMsg.lParam := lpImcP.fdwGcsFlag;
- Inc(lpTransMsg);
- end;
- end;
- if (lpImcP.fdwImeMsg and MSG_GUIDELINE) <> 0 then
- begin
- if (J = 0) then
- begin
- Inc(uNumMsg);
- end else
- begin
- lpTransMsg.message := WM_IME_NOTIFY;
- lpTransMsg.wParam := IMN_GUIDELINE;
- lpTransMsg.lParam := 0;
- Inc(lpTransMsg);
- end;
- end;
- if (lpImcP.fdwImeMsg and MSG_OPEN_CANDIDATE) <> 0 then
- begin
- if (lpImcP.fdwImeMsg and MSG_ALREADY_OPEN) = 0 then
- begin
- if (J = 0) then
- begin
- Inc(uNumMsg);
- end else
- begin
- lpTransMsg.message := WM_IME_NOTIFY;
- lpTransMsg.wParam := IMN_OPENCANDIDATE;
- lpTransMsg.lParam := $0001;
- Inc(lpTransMsg);
- lpImcP.fdwImeMsg := lpImcP.fdwImeMsg or MSG_ALREADY_OPEN;
- end;
- end;
- end;
- if (lpImcP.fdwImeMsg and MSG_CHANGE_CANDIDATE) <> 0 then
- begin
- if (J = 0) then
- begin
- Inc(uNumMsg);
- end else
- begin
- lpTransMsg.message := WM_IME_NOTIFY;
- lpTransMsg.wParam := IMN_CHANGECANDIDATE;
- lpTransMsg.lParam := $0001;
- Inc(lpTransMsg);
- end;
- end;
- if (lpImcP.fdwImeMsg and MSG_IMN_UPDATE_SOFTKBD) <> 0 then
- begin
- if (J = 0) then
- begin
- Inc(uNumMsg);
- end else
- begin
- lpTransMsg.message := WM_IME_NOTIFY;
- lpTransMsg.wParam := IMN_PRIVATE;
- lpTransMsg.lParam := IMN_PRIVATE_UPDATE_SOFTKBD;
- Inc(lpTransMsg);
- end;
- end;
- if (lpImcP.fdwImeMsg and MSG_IMN_UPDATE_STATUS) <> 0 then
- begin
- if (J = 0) then
- begin
- Inc(uNumMsg);
- end else
- begin
- lpTransMsg.message := WM_IME_NOTIFY;
- lpTransMsg.wParam := IMN_PRIVATE;
- lpTransMsg.lParam := IMN_PRIVATE_UPDATE_STATUS;
- Inc(lpTransMsg);
- end;
- end;
- if (lpImcP.fdwImeMsg and MSG_IMN_DESTROYCAND) <> 0 then
- begin
- if (J = 0) then
- begin
- Inc(uNumMsg);
- end else
- begin
- lpTransMsg.message := WM_IME_NOTIFY;
- lpTransMsg.wParam := IMN_PRIVATE;
- lpTransMsg.lParam := IMN_PRIVATE_DESTROYCANDWIN;
- Inc(lpTransMsg);
- end;
- end;
- if (lpImcP.fdwImeMsg and MSG_BACKSPACE) <> 0 then
- begin
- if (J = 0) then
- begin
- Inc(uNumMsg);
- end else
- begin
- lpTransMsg.message := WM_CHAR;
- lpTransMsg.wParam := $08;
- lpTransMsg.lParam := $000E;
- Inc(lpTransMsg);
- end;
- end;
- if (J = 0) then
- begin
- if (uNumMsg = 0) then
- begin
- Result := uNumMsg;
- Exit;
- end;
- if (lpImcP.fdwImeMsg and MSG_IN_IMETOASCIIEX) <> 0 then
- begin
- uNumMsgLimit := lpTransBuf.uMsgCount;
- if (uNumMsg <= uNumMsgLimit) then
- begin
- lpTransMsg := @lpTransBuf.TransMsg;
- Continue;
- end;
- end;
- // we need to use message buffer
- if (lpIMC.hMsgBuf = 0) then
- begin
- lpIMC.hMsgBuf := ImmCreateIMCC(uNumMsg * SizeOf(TTransMsg));
- lpIMC.dwNumMsgBuf := 0;
- end else
- begin
- hMem := ImmReSizeIMCC(lpIMC.hMsgBuf, (lpIMC.dwNumMsgBuf + uNumMsg) * SizeOf(TTransMsg));
- if (hMem <> 0) then
- begin
- if (hMem <> lpIMC.hMsgBuf) then
- begin
- ImmDestroyIMCC(lpIMC.hMsgBuf);
- lpIMC.hMsgBuf := hMem;
- end;
- end else
- begin
- Result := 0;
- Exit;
- end;
- end;
- lpTransMsg := ImmLockIMCC(lpIMC.hMsgBuf);
- if (lpTransMsg = nil) then
- begin
- Result := 0;
- Exit;
- end;
- Inc(lpTransMsg, lpIMC.dwNumMsgBuf);
- bLockMsgBuf := True;
- end else
- begin
- if (bLockMsgBuf) then ImmUnlockIMCC(lpIMC.hMsgBuf);
- end;
- end; // for ..
- Result := uNumMsg; // **
- end;
- // Ime回调, Return Value: the number of translated message
- function ImeToAsciiEx(uVirtKey, uScanCode: uInt; lpbKeyState: PKeyboardState;
- lpTransBuf: PTransMsgList; fuState: uInt; _hIMC: hIMC): uInt; stdcall;
- var
- wCharCode: Word;
- lpIMC: PInputContext;
- lpCompStr: PCompositionString;
- lpImcP: PPrivContext;
- uNumMsg: uInt;
- iRet: Integer;
- wSymbolCharCode, cHiByte, cLoByte: Word;
- SKDataIndex: Integer;
- lpCandInfo: PCandidateInfo;
- lpGuideLine: PGuideLine;
- begin
- wCharCode := HiByte(uVirtKey);
- uVirtKey := LoByte(uVirtKey);
- // hIMC=NULL?
- if (_hIMC = 0) then
- begin
- Result := TranslateToAscii(uVirtKey, uScanCode, lpTransBuf, wCharCode);
- Exit;
- end;
- // get lpIMC
- lpIMC := ImmLockIMC(_hIMC);
- if (lpIMC = nil) then
- begin
- Result := TranslateToAscii(uVirtKey, uScanCode, lpTransBuf, wCharCode);
- Exit;
- end;
- // get lpImcP
- lpImcP := ImmLockIMCC(lpIMC.hPrivate);
- if (lpImcP = nil) then
- begin
- ImmUnlockIMC(_hIMC);
- Result := TranslateToAscii(uVirtKey, uScanCode, lpTransBuf, wCharCode);
- Exit;
- end;
- // get lpCompStr and init
- if (lpImcP.fdwGcsFlag and (GCS_RESULTREAD or GCS_RESULT)) <> 0 then
- begin
- lpCompStr := ImmLockIMCC(lpIMC.hCompStr);
- if (lpCompStr <> nil) then lpCompStr.dwResultStrLen := 0;
- ImmUnlockIMCC(lpIMC.hCompStr);
- lpImcP.fdwGcsFlag := 0;
- end;
- // Now all composition realated information already pass to app a brand new start
- // init lpImcP.fdwImeMsg
- lpImcP.fdwImeMsg := lpImcP.fdwImeMsg and (MSG_ALREADY_OPEN or MSG_ALREADY_START) or MSG_IN_IMETOASCIIEX;
- // Process Key(wCharCode)
- iRet := ProcessKey(wCharCode, uVirtKey, uScanCode, lpbKeyState, lpIMC, lpImcP);
- // iRet process
- // CST_ALPHANUMERIC
- // CST_SYMBOL
- // CST_SOFTKB
- if (iRet = CST_SOFTKB) then
- begin
- // Mapping VK
- if (uVirtKey = $20) then
- begin
- SKDataIndex := 0;
- end else
- if (uVirtKey >= $30) and (uVirtKey <= $39) then
- begin
- SKDataIndex := uVirtKey - $30 + 1;
- end else
- if (uVirtKey >= $41) and (uVirtKey <= $5A) then
- begin
- SKDataIndex := uVirtKey - $41 + $0B;
- end else
- if (uVirtKey >= $BA) and (uVirtKey <= $BF) then
- begin
- SKDataIndex := uVirtKey - $BA + $25;
- end else
- if (uVirtKey >= $DB) and (uVirtKey <= $DE) then
- begin
- SKDataIndex := uVirtKey - $DB + $2C;
- end else
- if (uVirtKey = $C0) then
- begin
- SKDataIndex := $2B;
- end else
- begin
- SKDataIndex := 0;
- end;
- if (lpbKeyState[VK_SHIFT] and $80) <> 0 then
- begin
- cHiByte := Ord(SKLayoutS[sImeL.dwSKWant][SKDataIndex*2]) and $00FF;
- cLoByte := Ord(SKLayoutS[sImeL.dwSKWant][SKDataIndex*2 + 1]) and $00FF;
- end else
- begin
- cHiByte := Ord(SKLayout[sImeL.dwSKWant][SKDataIndex*2]) and $00FF;
- cLoByte := Ord(SKLayout[sImeL.dwSKWant][SKDataIndex*2 + 1]) and $00FF;
- end;
- wSymbolCharCode := (cHiByte shl 8) or cLoByte;
- if (wSymbolCharCode = $2020) then
- begin
- MessageBeep($FFFFFFFF);
- uNumMsg := 0;
- end else
- begin
- uNumMsg := TranslateSymbolChar(lpTransBuf, wSymbolCharCode, False);
- end;
- end else
- if (iRet = CST_ALPHANUMERIC) then
- begin
- if (lpImcP.fdwImeMsg and MSG_ALREADY_OPEN) <> 0 then
- begin
- lpImcP.fdwImeMsg := (lpImcP.fdwImeMsg or MSG_CLOSE_CANDIDATE) and (not MSG_OPEN_CANDIDATE) and (not MSG_IN_IMETOASCIIEX);
- GenerateMessage(_hIMC, lpIMC, lpImcP);
- end;
- if (lpIMC.fdwConversion and IME_CMODE_SYMBOL) <> 0 then
- begin
- if (wCharCode = Ord('.')) then
- begin
- wSymbolCharCode := Swap(PWord(PChar('。'))^);
- uNumMsg := TranslateSymbolChar(lpTransBuf, wSymbolCharCode, False);
- end else
- if (wCharCode = Ord(',')) then
- begin
- wSymbolCharCode := Swap(PWord(PChar(','))^);
- uNumMsg := TranslateSymbolChar(lpTransBuf, wSymbolCharCode, False);
- end else
- if (wCharCode = Ord(';')) then
- begin
- wSymbolCharCode := Swap(PWord(PChar(';'))^);
- uNumMsg := TranslateSymbolChar(lpTransBuf, wSymbolCharCode, False);
- end else
- if (wCharCode = Ord(':')) then
- begin
- wSymbolCharCode := Swap(PWord(PChar(':'))^);
- uNumMsg := TranslateSymbolChar(lpTransBuf, wSymbolCharCode, False);
- end else
- if (wCharCode = Ord('?')) then
- begin
- wSymbolCharCode := Swap(PWord(PChar('?'))^);
- uNumMsg := TranslateSymbolChar(lpTransBuf, wSymbolCharCode, False);
- end else
- if (wCharCode = Ord('!')) then
- begin
- wSymbolCharCode := Swap(PWord(PChar('!'))^);
- uNumMsg := TranslateSymbolChar(lpTransBuf, wSymbolCharCode, False);
- end else
- if (wCharCode = Ord('(')) then
- begin
- wSymbolCharCode := Swap(PWord(PChar('('))^);
- uNumMsg := TranslateSymbolChar(lpTransBuf, wSymbolCharCode, False);
- end else
- if (wCharCode = Ord(')')) then
- begin
- wSymbolCharCode := Swap(PWord(PChar(')'))^);
- uNumMsg := TranslateSymbolChar(lpTransBuf, wSymbolCharCode, False);
- end else
- if (wCharCode = Ord('')) then
- begin
- wSymbolCharCode := Swap(PWord(PChar('、'))^);
- uNumMsg := TranslateSymbolChar(lpTransBuf, wSymbolCharCode, False);
- end else
- if (wCharCode = Ord('@')) then
- begin
- wSymbolCharCode := Swap(PWord(PChar('·'))^);
- uNumMsg := TranslateSymbolChar(lpTransBuf, wSymbolCharCode, False);
- end else
- if (wCharCode = Ord('&')) then
- begin
- wSymbolCharCode := Swap(PWord(PChar('—'))^);
- uNumMsg := TranslateSymbolChar(lpTransBuf, wSymbolCharCode, False);
- end else
- if (wCharCode = Ord('$')) then
- begin
- wSymbolCharCode := Swap(PWord(PChar('¥'))^);
- uNumMsg := TranslateSymbolChar(lpTransBuf, wSymbolCharCode, False);
- end else
- if (wCharCode = Ord('_')) then
- begin
- wSymbolCharCode := Swap(PWord(PChar('—'))^);
- uNumMsg := TranslateSymbolChar(lpTransBuf, wSymbolCharCode, True);
- end else
- if (wCharCode = Ord('^')) then
- begin
- wSymbolCharCode := Swap(PWord(PChar('…'))^);
- uNumMsg := TranslateSymbolChar(lpTransBuf, wSymbolCharCode, True);
- end else
- if(wCharCode = Ord('"')) then
- begin
- if (lpImcP.uSYHFlg <> 0) then
- wSymbolCharCode := Swap(PWord(PChar('”'))^)
- else
- wSymbolCharCode := Swap(PWord(PChar('“'))^);
- lpImcP.uSYHFlg := lpImcP.uSYHFlg xor $00000001;
- uNumMsg := TranslateSymbolChar(lpTransBuf, wSymbolCharCode, False);
- end else
- if (wCharCode = Ord('''')) then
- begin
- if (lpImcP.uDYHFlg <> 0) then
- wSymbolCharCode := Swap(PWord(PChar('’'))^)
- else
- wSymbolCharCode := Swap(PWord(PChar('‘'))^);
- lpImcP.uDYHFlg := lpImcP.uDYHFlg xor $00000001;
- uNumMsg := TranslateSymbolChar(lpTransBuf, wSymbolCharCode, False);
- end else
- if (wCharCode = Ord('<')) then
- begin
- if (lpImcP.uDSMHFlg <> 0) then
- begin
- wSymbolCharCode := Swap(PWord(PChar('〈'))^);
- Inc(lpImcP.uDSMHCount);
- end else
- begin
- wSymbolCharCode := Swap(PWord(PChar('《'))^);
- lpImcP.uDSMHFlg := $00000001;
- end;
- uNumMsg := TranslateSymbolChar(lpTransBuf, wSymbolCharCode, False);
- end else
- if (wCharCode = Ord('>')) then
- begin
- if (lpImcP.uDSMHFlg <> 0) and (lpImcP.uDSMHCount <> 0) then
- begin
- wSymbolCharCode := Swap(PWord(PChar('〉'))^);
- Dec(lpImcP.uDSMHCount);
- end else
- begin
- wSymbolCharCode := Swap(PWord(PChar('》'))^);
- lpImcP.uDSMHFlg := $00000000;
- end;
- uNumMsg := TranslateSymbolChar(lpTransBuf, wSymbolCharCode, False);
- end else
- begin
- if (lpIMC.fdwConversion and IME_CMODE_FULLSHAPE) <> 0 then
- begin
- // convert to DBCS
- uNumMsg := TranslateFullChar(lpTransBuf, wCharCode);
- end else
- begin
- uNumMsg := TranslateToAscii(uVirtKey, uScanCode, lpTransBuf, wCharCode);
- end;
- end;
- end else
- if (lpIMC.fdwConversion and IME_CMODE_FULLSHAPE) <> 0 then
- uNumMsg := TranslateFullChar(lpTransBuf, wCharCode) // convert to DBCS
- else
- uNumMsg := TranslateToAscii(uVirtKey, uScanCode, lpTransBuf, wCharCode);
- end else
- if (iRet = CST_CHOOSE) then
- begin
- lpCandInfo := ImmLockIMCC(lpIMC.hCandInfo);
- if (lpCandInfo = nil) then
- begin
- Result := CST_INVALID;
- Exit;
- end;
- if (uVirtKey = VK_PRIOR) then
- begin
- wCharCode := Ord('-');
- end else
- if (uVirtKey = VK_NEXT) then
- begin
- wCharCode := Ord('=');
- end else
- if (uVirtKey = VK_SPACE) then
- begin
- wCharCode := Ord('1');
- end else
- if (uVirtKey >= Ord('0')) and (uVirtKey <= Ord('9')) then // **
- begin
- // convert shift-0 ... shift-9 to 0 ... 9
- wCharCode := uVirtKey;
- end else
- if (uVirtKey = VK_HOME) then
- begin
- wCharCode := $24;
- end else
- if (uVirtKey = VK_END) then
- begin
- wCharCode := $23;
- end
- else
- begin
- end;
- lpImcP.iImeState := CST_CHOOSE;
- ChooseCand(wCharCode, lpIMC, lpCandInfo, lpImcP);
- ImmUnlockIMCC(lpIMC.hCandInfo);
- uNumMsg := TranslateImeMessage(lpTransBuf, lpIMC, lpImcP);
- end else
- if (iRet = CST_INPUT) and ((lpIMC.fdwConversion and IME_CMODE_CHARCODE) <> 0) then
- begin
- uNumMsg := TranslateToAscii(uVirtKey, uScanCode, lpTransBuf, wCharCode);
- end else
- if (iRet = CST_INPUT) then
- begin
- // get lpCompStr & lpGuideLine
- lpCompStr := ImmLockIMCC(lpIMC.hCompStr);
- if (lpCompStr = nil) then
- begin
- Result := CST_INVALID;
- Exit;
- end;
- lpGuideLine := ImmLockIMCC(lpIMC.hGuideLine);
- if (lpGuideLine = nil) then
- begin
- ImmUnlockIMCC(lpIMC.hCompStr);
- Result := CST_INVALID;
- Exit;
- end;
- // composition
- CompWord(wCharCode, lpIMC, lpCompStr, lpImcP, lpGuideLine);
- ImmUnlockIMCC(lpIMC.hGuideLine);
- ImmUnlockIMCC(lpIMC.hCompStr);
- // generate message
- uNumMsg := TranslateImeMessage(lpTransBuf, lpIMC, lpImcP);
- end else
- if (iRet = CST_INVALID_INPUT) then
- begin
- MessageBeep($FFFFFFFF);
- uNumMsg := 0;
- end else
- begin
- uNumMsg := TranslateToAscii(uVirtKey, uScanCode, lpTransBuf, wCharCode);
- end;
- // reset lpImcP.fdwImeMsg
- lpImcP.fdwImeMsg := lpImcP.fdwImeMsg and (MSG_ALREADY_OPEN or MSG_ALREADY_START);
- lpImcP.fdwGcsFlag := lpImcP.fdwGcsFlag and (GCS_RESULTREAD or GCS_RESULT);
- ImmUnlockIMCC(lpIMC.hPrivate);
- ImmUnlockIMC(_hIMC);
- Result := uNumMsg;
- end;
- end.