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

输入法编程

开发平台:

Delphi

  1.  {******************************************************}
  2.  {                                                      }
  3.  {    Copyright (c) 1990-1999 Microsoft Corporation     }
  4.  {                                                      }
  5.  {    Module Name:  ToAscii.c ->>  ToAscii.pas          }
  6.  {                                                      }
  7.  {    Translator:  Liu_mazi@126.com, 2005-11-14         }
  8.  {                                                      }
  9.  {******************************************************}
  10. unit ToAscii;
  11. {$I Define.Inc}
  12. interface
  13. uses Windows, ImmDev, ImeDefs;
  14. function TranslateImeMessage(lpTransBuf: PTransMsgList; lpIMC: PInputContext; lpImcP: PPrivContext): uInt;
  15. function GBProcessKey(wCharCode: Word; lpImcP: PPrivContext): uInt;
  16. function ImeProcessKey(_hIMC: hIMC; uVirtKey: uInt; lParam: LParam; lpbKeyState: PKeyboardState): Bool; stdcall;
  17. function ImeToAsciiEx(uVirtKey, uScanCode: uInt;
  18.  lpbKeyState: PKeyboardState; lpTransBuf: PTransMsgList; fuState: uInt; _hIMC: hIMC): uInt; stdcall;
  19. implementation
  20. uses Messages, Data, DDIS, Notify, Chcand, Compose, LogText;
  21.   // 是否编码输入字符, **
  22. function IsUsedCode(wCharCode: Word): Bool;
  23. var
  24.   wFlg: Word;
  25. begin
  26.   Result := True;
  27.   for wFlg := 0 to sImeG.wNumCodes - 1 do if (wCharCode = Ord(sImeG.UsedCodes[wFlg])) then Exit;
  28.   Result := False;
  29. end;
  30.   // this key will cause the IME go to what state
  31. function GBProcessKey(wCharCode: Word; lpImcP: PPrivContext): uInt;
  32. begin
  33.   Result := CST_INVALID_INPUT;
  34.   if (lpImcP = nil) then
  35.   begin
  36.     Result := CST_INVALID;
  37.     Exit;
  38.   end;
  39.   // check space
  40.   if (wCharCode = Ord(' ')) then
  41.   begin
  42.     if (lpImcP.bSeq[0] <> #0) and (lpImcP.bSeq[1] <> #0) then
  43.     begin
  44.       Result := CST_INPUT;
  45.       Exit;
  46.     end else
  47.       if (lpImcP.bSeq[0] = #0) then
  48.       begin
  49.         Result := CST_ALPHANUMERIC;
  50.         Exit;
  51.       end else
  52.       begin
  53.         Result := CST_INVALID_INPUT;
  54.         Exit;
  55.       end;
  56.   end;
  57.   // check finalize char
  58.   if ( (wCharCode >= Ord('0')) and (wCharCode <= Ord('9')) ) or
  59.      ( (wCharCode >= Ord('a')) and (wCharCode <= Ord('f')) ) or
  60.      (  wCharCode = Ord('?') ) then
  61.   begin
  62.     if (lpImcP.bSeq[0] = #0) then
  63.     begin
  64.       if (wCharCode = Ord('?')) then // 0x0??? - 0xF??? is OK
  65.       begin
  66.         Result := CST_ALPHANUMERIC;
  67.         Exit;
  68.       end else
  69.       begin                    // there is no 0x0??? - 0x7???
  70.         lpImcP.bSeq[1] := #0;
  71.         Result := CST_INPUT;
  72.         Exit;
  73.       end;
  74.     end else
  75.       if (lpImcP.bSeq[1] = #0) then
  76.       begin
  77.         if (lpImcP.bSeq[0] >= '0') and (lpImcP.bSeq[0] <= '9') then //Area
  78.         begin
  79.           // there is less than 95 area and bigger than 0 area
  80.           if ( (lpImcP.bSeq[0] = '0') and (wCharCode = Ord('0')) ) or
  81.              ( (lpImcP.bSeq[0] = '9') and (wCharCode >= Ord('5')) ) or
  82.              ( (wCharCode >= Ord('a')) and (wCharCode <= Ord('f')) ) or
  83.              ( wCharCode = Ord('?') ) then
  84.           begin
  85.             Result := CST_INVALID_INPUT;
  86.             Exit;
  87.           end else
  88.           begin
  89.             lpImcP.bSeq[2] := #0;
  90.             Result := CST_INPUT;
  91.             Exit
  92.           end;
  93.         end;
  94.         if (lpImcP.bSeq[0] >= 'a') and (lpImcP.bSeq[0] <= 'f') then //GB
  95.         begin
  96.           // there is less than 95 area and bigger than 0 area
  97.           if ( (lpImcP.bSeq[0] = 'a') and (wCharCode = Ord('0')) ) or
  98.              ( (lpImcP.bSeq[0] = 'f') and (wCharCode = Ord('f')) ) or
  99.              ( wCharCode = Ord('?') ) then
  100.           begin
  101.             Result := CST_INVALID_INPUT;
  102.             Exit;
  103.           end else
  104.           begin
  105.             lpImcP.bSeq[2] := #0;
  106.             Result := CST_INPUT;
  107.           end;
  108.         end;
  109.       end else
  110.         if (lpImcP.bSeq[2] = #0) then
  111.         begin
  112.           if (wCharCode = Ord('?')) then
  113.           begin
  114.             Result := CST_INPUT;
  115.             Exit;
  116.           end;
  117.           if (lpImcP.bSeq[0] >= '0') and (lpImcP.bSeq[0] <= '9') then // Area
  118.           begin
  119.             if (wCharCode >= Ord('0')) and (wCharCode <= Ord('9')) then
  120.             begin
  121.               lpImcP.bSeq[3] := #0;
  122.               Result := CST_INPUT;
  123.               Exit;
  124.             end else
  125.             begin
  126.               Result := CST_INVALID_INPUT;
  127.               Exit;
  128.             end;
  129.           end;
  130.           if (lpImcP.bSeq[0] >= 'a') and (lpImcP.bSeq[0] <= 'f') then // GB
  131.           begin
  132.             if (wCharCode >= Ord('a')) and (wCharCode <= Ord('f')) then
  133.             begin
  134.               lpImcP.bSeq[3] := #0;
  135.               Result := CST_INPUT;
  136.             end else
  137.             begin
  138.               Result := CST_INVALID_INPUT;
  139.               Exit;
  140.             end;
  141.           end;
  142.         end else
  143.           if (lpImcP.bSeq[3] = #0) then
  144.           begin
  145.             if (lpImcP.bSeq[2] = '?') then
  146.             begin
  147.               if (wCharCode = Ord('?')) then
  148.               begin
  149.                 Result := CST_INPUT;
  150.                 Exit;
  151.               end else
  152.               begin
  153.                 Result := CST_INVALID_INPUT;
  154.                 Exit;
  155.               end;
  156.             end;
  157.             if (lpImcP.bSeq[0] >= '0') and (lpImcP.bSeq[0] <= '9') then //Area
  158.             begin
  159.               // there is less than 95 area and bigger than 0 area
  160.               if ( (lpImcP.bSeq[2] = '0') and (wCharCode = Ord('0')) ) or
  161.                  ( (lpImcP.bSeq[2] = '9') and (wCharCode >= Ord('5')) ) or
  162.                  ( (wCharCode >= Ord('a')) and (wCharCode <= Ord('f')) ) or
  163.                  ( (wCharCode = Ord('?')) ) then
  164.               begin
  165.                 Result := CST_INVALID_INPUT;
  166.               end else
  167.               begin
  168.                 Result := CST_INPUT;
  169.               end;
  170.             end;
  171.             if (lpImcP.bSeq[0] >= 'a') and (lpImcP.bSeq[0] <= 'f') then //GB
  172.             begin
  173.               // there is less than 95 area and bigger than 0 area
  174.               if ( (lpImcP.bSeq[2] = 'a') and (wCharCode = Ord('0')) ) or
  175.                  ( (lpImcP.bSeq[2] = 'f') and (wCharCode = Ord('f')) ) or
  176.                  ( wCharCode = Ord('?') ) then
  177.               begin
  178.                 Result := CST_INVALID_INPUT;
  179.                 Exit;
  180.               end else
  181.               begin
  182.                 Result := CST_INPUT;
  183.                 Exit;
  184.               end;
  185.             end;
  186.           end else
  187.           begin
  188.             Result := CST_INVALID_INPUT;
  189.             Exit;
  190.           end;
  191.   end else
  192.     if (wCharCode >= Ord(' ')) and (wCharCode <= Ord('~')) then
  193.     begin
  194.       Result := CST_ALPHANUMERIC;
  195.       Exit;
  196.     end else
  197.     begin
  198.       Result := CST_INVALID_INPUT;
  199.       Exit;
  200.     end;
  201. end;
  202.   // this key will cause the IME go to what state
  203. function ProcessKey(wCharCode: Word; uVirtKey: uInt; uScanCode: uInt; lpbKeyState: PKeyboardState; lpIMC: PInputContext; lpImcP: PPrivContext): uInt;
  204. var
  205.   lpGuideLine: PGuideLine;
  206.   iImeState: uInt;
  207. begin
  208.   Result := CST_INVALID;
  209.   if (lpIMC = nil) or (lpImcP = nil) then Exit;
  210.   // filter system key (alt,alt+,ctrl,shift) and fOpen, IME_CMODE_NOCONVERSION
  211.   if (uVirtKey = VK_MENU) then                // ALT key
  212.   begin
  213.     Exit;
  214.   end else
  215.     if (uScanCode and KF_ALTDOWN) <> 0 then   // ALT-xx key
  216.     begin
  217.       Exit;
  218.     end else
  219.       if (uVirtKey = VK_CONTROL) then         // CTRL key
  220.       begin
  221.         Exit;
  222.       end else
  223.         if (uVirtKey = VK_SHIFT) then         // SHIFT key
  224.         begin
  225.           Exit;;
  226.         end else
  227.           if (lpIMC.fOpen = False) then       // don't compose in close status
  228.           begin
  229.             Exit;
  230.           end else
  231.             if (lpIMC.fdwConversion and IME_CMODE_NOCONVERSION) <> 0 then
  232.             begin
  233.               if (uVirtKey = VK_CAPITAL) then // Caps on/off
  234.               begin
  235.                 Result := CST_CAPITAL;
  236.               end else
  237.                 Exit;
  238.             end else
  239.               if (uVirtKey >= VK_NUMPAD0) and (uVirtKey <= VK_DIVIDE) then
  240.               begin
  241.                 Exit;
  242.               end else
  243.               begin
  244.               end;
  245.   // Caps on/off
  246.   if  (uVirtKey = VK_CAPITAL) then
  247.   begin
  248.     Result := CST_CAPITAL;
  249.     Exit;
  250.   end;
  251.   if (lpIMC.fdwConversion and IME_CMODE_SOFTKBD <> 0) and (sImeL.dwSKWant <> 0) then
  252.   begin
  253.     if (wCharCode >= Ord(' ')) and (wCharCode <= Ord('~')) then
  254.     begin
  255.       Result := CST_SOFTKB;
  256.       Exit;
  257.     end else
  258.     begin
  259.       Exit; // return (CST_INVALID);
  260.     end;
  261.   end;
  262.   // candidate alaredy open,  <,>,pageup,pagedown,?,ECS,key
  263.   Result := CST_CHOOSE;
  264.   if (lpImcP.fdwImeMsg and MSG_ALREADY_OPEN) <> 0 then
  265.   begin
  266.     if (uVirtKey = VK_PRIOR) then     // PageUp
  267.     begin
  268.       Exit;
  269.     end else
  270.       if (uVirtKey = VK_NEXT) then    // PageDown
  271.       begin
  272.         Exit;
  273.       end else
  274.         if (wCharCode = Ord('-')) then
  275.         begin
  276.           Exit;
  277.         end else
  278.           if (wCharCode = Ord('=')) then
  279.           begin
  280.             Exit;
  281.           end else
  282.             if (uVirtKey = VK_HOME) then
  283.             begin
  284.               Exit;
  285.             end else
  286.               if (uVirtKey = VK_END) then
  287.               begin
  288.                 Exit;
  289.               end else
  290.                 if (uVirtKey = VK_ESCAPE) then // Esc
  291.                 begin
  292.                   Exit;
  293.                 end else
  294.                   if (wCharCode = Ord(' ')) then
  295.                   begin
  296.                     Exit;
  297.                   end else
  298.                   begin
  299.                   end;
  300.   end;
  301.   // candidate alaredy open, shift + num key
  302.   if (lpImcP.fdwImeMsg and MSG_ALREADY_OPEN) <> 0 then
  303.     if (wCharCode >= Ord('0')) and (wCharCode <= Ord('9')) then
  304.     begin
  305.       Exit; // return (CST_CHOOSE);
  306.     end;
  307.   // IME_CMODE_CHARCODE
  308.   if (lpIMC.fdwConversion and IME_CMODE_CHARCODE) <> 0 then    //Code Input Mode
  309.   begin
  310.     Result := CST_INVALID;
  311.     Exit;
  312.   end;
  313.   if (lpIMC.fdwConversion and IME_CMODE_NATIVE) = 0 then
  314.   begin
  315.     if (wCharCode >= Ord(' ')) and (wCharCode <= Ord('~')) then  // alphanumeric mode
  316.     begin
  317.       Result := CST_ALPHANUMERIC;
  318.       Exit;
  319.     end else
  320.     begin
  321.       Result := CST_INVALID;
  322.       Exit;
  323.     end;
  324.   end else
  325.     if (wCharCode = Ord('?'))  then
  326.     begin
  327.     end else
  328.       if (wCharCode = Ord(' ')) then
  329.       begin
  330.       end else
  331.         if (wCharCode >= Ord(' ')) and (wCharCode <= Ord('~')) then
  332.         begin
  333.           if (IsUsedCode(wCharCode) = False) and (lpImcP.iImeState <> CST_INIT) then
  334.           begin
  335.             Result := CST_INVALID_INPUT;
  336.             Exit;
  337.           end;
  338.         end;
  339.   // Esc key
  340.   if (uVirtKey = VK_ESCAPE) then
  341.   begin
  342.     lpGuideLine := ImmLockIMCC(lpIMC.hGuideLine);
  343.     if (lpGuideLine = nil) then
  344.     begin
  345.       //return (CST_INVALID);
  346.       Result := CST_INVALID;
  347.       Exit;
  348.     end;
  349.     if (lpImcP.fdwImeMsg and MSG_ALREADY_START) <> 0 then
  350.     begin
  351.       iImeState := CST_INPUT;
  352.     end else
  353.       if (lpGuideLine = nil) then
  354.       begin
  355.         iImeState := CST_INVALID;
  356.       end else
  357.         if (lpGuideLine.dwLevel = GL_LEVEL_NOGUIDELINE) then
  358.         begin
  359.           iImeState := CST_INVALID;
  360.         end else
  361.         begin
  362.           // need this key to clean information string or guideline state
  363.           iImeState := CST_INPUT;
  364.         end;
  365.     ImmUnlockIMCC(lpIMC.hGuideLine);
  366.     //return (iImeState);
  367.     Result := iImeState;
  368.     Exit;
  369.   end else
  370.     if (uVirtKey = VK_BACK) then // BackSpace Key
  371.     begin
  372.       if (lpImcP.fdwImeMsg and MSG_ALREADY_START) <> 0 then
  373.       begin
  374.         Result := CST_INPUT;
  375.         Exit;
  376.       end else
  377.       begin
  378.         Result := CST_INVALID;
  379.         Exit;
  380.       end;
  381.     end else
  382.       if (uVirtKey >= VK_NUMPAD0) and (uVirtKey <= VK_DIVIDE) then // NumPad key and Other Input vailid key
  383.       begin
  384.         // return (CST_ALPHANUMERIC);
  385.         Result := CST_ALPHANUMERIC;
  386.         Exit;
  387.       end else
  388.         if (wCharCode > Ord('~')) then
  389.         begin
  390.           Result := CST_INVALID;
  391.           Exit;
  392.         end else
  393.           if (wCharCode < Ord(' ')) then
  394.           begin
  395.             Result := CST_INVALID;
  396.             Exit;
  397.           end else
  398.             if (lpIMC.fdwConversion and IME_CMODE_EUDC) <> 0 then
  399.             begin
  400.             end else
  401.             begin
  402.             end;
  403.   if (lpIMC.fdwConversion and IME_CMODE_NATIVE) <> 0 then
  404.   begin
  405.     Result := GBProcessKey(wCharCode,lpImcP);
  406.     Exit;
  407.   end;
  408.   Result := CST_INVALID;
  409. end;
  410.   // Ime回调, if this key is need by IME?
  411. function ImeProcessKey(_hIMC: hIMC; uVirtKey: uInt; lParam: LParam; lpbKeyState: PKeyboardState): Bool; stdcall;
  412. var
  413.   lpIMC: PInputContext;
  414.   lpImcP: PPrivContext;
  415.   szAscii: array[0..3] of Char;
  416.   nChars, iRet: Integer;
  417.   fdwConversion: DWord;
  418. //  fRet: Bool;
  419. begin
  420.   Result := False;
  421.   // can't compose in NULL hIMC
  422.   if (_hIMC = 0) then Exit;
  423.   lpIMC := ImmLockIMC(_hIMC);
  424.   if (lpIMC = nil) then Exit;
  425.   lpImcP := ImmLockIMCC(lpIMC.hPrivate);
  426.   if (lpImcP = nil) then
  427.   begin
  428.     ImmUnlockIMC(_hIMC);
  429.     Exit;
  430.   end;
  431.   nChars := Windows.ToAscii(uVirtKey, HiWord(lParam), lpbKeyState^, szAscii, 0);
  432.   if (nChars = 0) then szAscii[0] := #0;
  433.   iRet := ProcessKey(Ord(szAscii[0]), uVirtKey, HiWord(lParam), lpbKeyState, lpIMC, lpImcP);
  434.   if (iRet = CST_INVALID) then
  435.   begin
  436.     //fRet = FALSE;
  437.   end else
  438.     if (iRet = CST_INPUT) and (uVirtKey = $08) and (lpImcP.iImeState = CST_INIT) then
  439.     begin
  440.       lpImcP.fdwImeMsg :=
  441.         ( (lpImcP.fdwImeMsg or MSG_END_COMPOSITION) and not(MSG_START_COMPOSITION) )
  442.         and not(MSG_IN_IMETOASCIIEX); // **
  443.       if (lpImcP.fdwImeMsg and MSG_ALREADY_OPEN) <> 0 then
  444.       begin
  445.         ClearCand(lpIMC);
  446.         lpImcP.fdwImeMsg := (lpImcP.fdwImeMsg or MSG_CLOSE_CANDIDATE) and (not MSG_OPEN_CANDIDATE);
  447.       end;
  448.       GenerateMessage(_hIMC, lpIMC, lpImcP);
  449.       //fRet = FALSE;
  450.     end else
  451.       if (uVirtKey = VK_CAPITAL) then
  452.       begin
  453.         if (lpbKeyState[VK_CAPITAL] and $01) <> 0 then
  454.         begin
  455.           // change to alphanumeric mode
  456.           fdwConversion := lpIMC.fdwConversion and not(IME_CMODE_CHARCODE or IME_CMODE_NATIVE or IME_CMODE_EUDC);
  457.           uCaps := 1;
  458.         end else
  459.         begin
  460.           // change to native mode
  461.           fdwConversion := (lpIMC.fdwConversion or IME_CMODE_NATIVE) and not(IME_CMODE_CHARCODE or IME_CMODE_EUDC);
  462.           uCaps := 0;
  463.         end;
  464.        ImmSetConversionStatus(_hIMC, fdwConversion, lpIMC.fdwSentence);
  465.        //fRet = FALSE;
  466.      end else
  467.        if (iRet = CST_ALPHANUMERIC) and
  468.           (lpIMC.fdwConversion and IME_CMODE_FULLSHAPE = 0) and
  469.           (uVirtKey = VK_SPACE) then
  470.        begin
  471.         // fRet = FALSE;
  472.        end else
  473.        begin
  474.         // fRet = TRUE;
  475.          Result := True;
  476.        end;
  477.   ImmUnlockIMCC(lpIMC.hPrivate);
  478.   ImmUnlockIMC(_hIMC);
  479. end;
  480.   // Return Value: the number of translated chars
  481. function TranslateSymbolChar(lpTransBuf: PTransMsgList; wSymbolCharCode: Word; SymbolMode: Bool): uInt;
  482. var
  483.   lpTransMsg: PTransMsg;
  484. begin
  485.   Result := 0;
  486.   lpTransMsg := @lpTransBuf.TransMsg;
  487.    // NT need to modify this!
  488.    
  489.   lpTransMsg.message := WM_CHAR;
  490.   lpTransMsg.wParam  := HiByte(wSymbolCharCode);
  491.   lpTransMsg.lParam  := 1;
  492.   Inc(lpTransMsg);
  493.   Inc(Result);
  494.   lpTransMsg.message := WM_CHAR;
  495.   lpTransMsg.wParam  := LoByte(wSymbolCharCode);
  496.   lpTransMsg.lParam  := 1;
  497.   Inc(Result);
  498.   if (SymbolMode) then
  499.   begin
  500.     lpTransMsg := @lpTransBuf.TransMsg;
  501.     lpTransMsg.message := WM_CHAR;
  502.     lpTransMsg.wParam  := HiByte(wSymbolCharCode);
  503.     lpTransMsg.lParam  := 1;
  504.     Inc(lpTransMsg);
  505.     Inc(Result);
  506.     lpTransMsg.message := WM_CHAR;
  507.     lpTransMsg.wParam  := LoByte(wSymbolCharCode);
  508.     lpTransMsg.lParam  := 1;
  509.     Inc(Result);
  510.   end;
  511. end;
  512.   // Return Value: the number of translated chars
  513. function TranslateFullChar(lpTransBuf: PTransMsgList; wCharCode: Word): uInt;
  514. var
  515.   // if your IME is possible to generate over ? messages, you need to take care about it
  516.   lpTransMsg: PTransMsg;
  517. begin
  518.   wCharCode := Swap(sImeG.wFullABC[wCharCode - Ord(' ')]);
  519.   lpTransMsg := @lpTransBuf.TransMsg;
  520.   // NT need to modify this!
  521.   lpTransMsg.message := WM_CHAR;
  522.   lpTransMsg.wParam  := HiByte(wCharCode);
  523.   lpTransMsg.lParam  := 1;
  524.   Inc(lpTransMsg);
  525.   lpTransMsg.message := WM_CHAR;
  526.   lpTransMsg.wParam  := LoByte(wCharCode);
  527.   lpTransMsg.lParam  := 1;
  528.   Result := 2; // generate two messages
  529. end;
  530.   // translate the key to WM_CHAR as keyboard driver
  531.   // Return Value: the number of translated chars
  532. function TranslateToAscii(uVirtKey, uScanCode: uInt; lpTransBuf: PTransMsgList; wCharCode: Word): uInt;
  533. var
  534.   lpTransMsg: PTransMsg;
  535. begin
  536.   lpTransMsg := @lpTransBuf.TransMsg;
  537.   if (wCharCode <> 0) then               // one char code
  538.   begin
  539.     lpTransMsg.message := WM_CHAR;
  540.     lpTransMsg.wParam  := wCharCode;
  541.     lpTransMsg.lParam  := (uScanCode shl 16) or 1;
  542.     Result := 1;
  543.   end else
  544.     Result := 0;  // no char code case
  545. end;
  546.   // Return Value: the number of translated messages
  547. function TranslateImeMessage(lpTransBuf: PTransMsgList; lpIMC: PInputContext; lpImcP: PPrivContext): uInt;
  548. var
  549.   uNumMsg, J: uInt;
  550.   bLockMsgBuf: Bool;
  551.   lpTransMsg: PTransMsg;
  552.   hMem: hIMCC;
  553.   uNumMsgLimit: uInt;
  554. begin
  555.   uNumMsg := 0;
  556.   bLockMsgBuf := False;
  557.   lpTransMsg := @lpTransBuf.TransMsg; // ++
  558.   for J := 0 to 1 do
  559.   begin
  560.     if (lpImcP.fdwImeMsg and MSG_CLOSE_CANDIDATE) <> 0 then
  561.     begin
  562.       if (lpImcP.fdwImeMsg and MSG_ALREADY_OPEN) <> 0 then
  563.       begin
  564.         if (J = 0) then
  565.         begin
  566.           Inc(uNumMsg);
  567.         end else
  568.         begin
  569.           lpTransMsg.message := WM_IME_NOTIFY;
  570.           lpTransMsg.wParam  := IMN_CLOSECANDIDATE;
  571.           lpTransMsg.lParam  := $0001;
  572.           Inc(lpTransMsg);
  573.           lpImcP.fdwImeMsg := lpImcP.fdwImeMsg and (not MSG_ALREADY_OPEN);
  574.         end;
  575.       end;
  576.     end;
  577.     if (lpImcP.fdwImeMsg and MSG_END_COMPOSITION) <> 0 then
  578.     begin
  579.       if (lpImcP.fdwImeMsg and MSG_ALREADY_START) <> 0 then
  580.       begin
  581.         if (J = 0) then
  582.         begin
  583.           Inc(uNumMsg);
  584.         end else
  585.         begin
  586.           lpTransMsg.message := WM_IME_ENDCOMPOSITION;
  587.           lpTransMsg.wParam  := 0;
  588.           lpTransMsg.lParam  := 0;
  589.           Inc(lpTransMsg);
  590.           lpImcP.fdwImeMsg := lpImcP.fdwImeMsg and (not MSG_ALREADY_START);
  591.         end;
  592.       end;
  593.     end;
  594.     if (lpImcP.fdwImeMsg and MSG_START_COMPOSITION) <> 0 then
  595.     begin
  596.       if (lpImcP.fdwImeMsg and MSG_ALREADY_START) = 0 then
  597.       begin
  598.         if (J = 0) then
  599.         begin
  600.           Inc(uNumMsg);
  601.         end else
  602.         begin
  603.           lpTransMsg.message := WM_IME_STARTCOMPOSITION;
  604.           lpTransMsg.wParam  := 0;
  605.           lpTransMsg.lParam  := 0;
  606.           Inc(lpTransMsg);
  607.           lpImcP.fdwImeMsg := lpImcP.fdwImeMsg or MSG_ALREADY_START;
  608.         end;
  609.       end;
  610.     end;
  611.     if (lpImcP.fdwImeMsg and MSG_IMN_COMPOSITIONPOS) <> 0 then
  612.     begin
  613.       if (J = 0) then
  614.       begin
  615.         Inc(uNumMsg);
  616.       end else
  617.       begin
  618.         lpTransMsg.message := WM_IME_NOTIFY;
  619.         lpTransMsg.wParam  := IMN_SETCOMPOSITIONWINDOW;
  620.         lpTransMsg.lParam  := 0;
  621.         Inc(lpTransMsg);
  622.       end;
  623.     end;
  624.     if (lpImcP.fdwImeMsg and MSG_COMPOSITION) <> 0 then
  625.     begin
  626.       if (J = 0) then
  627.       begin
  628.         Inc(uNumMsg);
  629.       end else
  630.       begin
  631.         lpTransMsg.message := WM_IME_COMPOSITION;
  632.         lpTransMsg.wParam  := lpImcP.dwCompChar;
  633.         lpTransMsg.lParam  := lpImcP.fdwGcsFlag;
  634.         Inc(lpTransMsg);
  635.       end;
  636.     end;
  637.     if (lpImcP.fdwImeMsg and MSG_GUIDELINE) <> 0 then
  638.     begin
  639.       if (J = 0) then
  640.       begin
  641.         Inc(uNumMsg);
  642.       end else
  643.       begin
  644.         lpTransMsg.message := WM_IME_NOTIFY;
  645.         lpTransMsg.wParam  := IMN_GUIDELINE;
  646.         lpTransMsg.lParam  := 0;
  647.         Inc(lpTransMsg);
  648.       end;
  649.     end;
  650.     if (lpImcP.fdwImeMsg and MSG_OPEN_CANDIDATE) <> 0 then
  651.     begin
  652.       if (lpImcP.fdwImeMsg and MSG_ALREADY_OPEN) = 0 then
  653.       begin
  654.         if (J = 0) then
  655.         begin
  656.           Inc(uNumMsg);
  657.         end else
  658.         begin
  659.           lpTransMsg.message := WM_IME_NOTIFY;
  660.           lpTransMsg.wParam  := IMN_OPENCANDIDATE;
  661.           lpTransMsg.lParam  := $0001;
  662.           Inc(lpTransMsg);
  663.           lpImcP.fdwImeMsg := lpImcP.fdwImeMsg or MSG_ALREADY_OPEN;
  664.         end;
  665.       end;
  666.     end;
  667.     if (lpImcP.fdwImeMsg and MSG_CHANGE_CANDIDATE) <> 0 then
  668.     begin
  669.       if (J = 0) then
  670.       begin
  671.         Inc(uNumMsg);
  672.       end else
  673.       begin
  674.         lpTransMsg.message := WM_IME_NOTIFY;
  675.         lpTransMsg.wParam  := IMN_CHANGECANDIDATE;
  676.         lpTransMsg.lParam  := $0001;
  677.         Inc(lpTransMsg);
  678.       end;
  679.     end;
  680.     if (lpImcP.fdwImeMsg and MSG_IMN_UPDATE_SOFTKBD) <> 0 then
  681.     begin
  682.       if (J = 0) then
  683.       begin
  684.         Inc(uNumMsg);
  685.       end else
  686.       begin
  687.         lpTransMsg.message := WM_IME_NOTIFY;
  688.         lpTransMsg.wParam  := IMN_PRIVATE;
  689.         lpTransMsg.lParam  := IMN_PRIVATE_UPDATE_SOFTKBD;
  690.         Inc(lpTransMsg);
  691.       end;
  692.     end;
  693.     if (lpImcP.fdwImeMsg and MSG_IMN_UPDATE_STATUS) <> 0 then
  694.     begin
  695.       if (J = 0) then
  696.       begin
  697.         Inc(uNumMsg);
  698.       end else
  699.       begin
  700.         lpTransMsg.message := WM_IME_NOTIFY;
  701.         lpTransMsg.wParam  := IMN_PRIVATE;
  702.         lpTransMsg.lParam  := IMN_PRIVATE_UPDATE_STATUS;
  703.         Inc(lpTransMsg);
  704.       end;
  705.     end;
  706.     if (lpImcP.fdwImeMsg and MSG_IMN_DESTROYCAND) <> 0 then
  707.     begin
  708.       if (J = 0) then
  709.       begin
  710.         Inc(uNumMsg);
  711.       end else
  712.       begin
  713.         lpTransMsg.message := WM_IME_NOTIFY;
  714.         lpTransMsg.wParam  := IMN_PRIVATE;
  715.         lpTransMsg.lParam  := IMN_PRIVATE_DESTROYCANDWIN;
  716.         Inc(lpTransMsg);
  717.       end;
  718.     end;
  719.     if (lpImcP.fdwImeMsg and MSG_BACKSPACE) <> 0 then
  720.     begin
  721.       if (J = 0) then
  722.       begin
  723.         Inc(uNumMsg);
  724.       end else
  725.       begin
  726.         lpTransMsg.message := WM_CHAR;
  727.         lpTransMsg.wParam  := $08;
  728.         lpTransMsg.lParam  := $000E;
  729.         Inc(lpTransMsg);
  730.       end;
  731.     end;
  732.     if (J = 0) then
  733.     begin
  734.       if (uNumMsg = 0) then
  735.       begin
  736.         Result := uNumMsg;
  737.         Exit;
  738.       end;
  739.       if (lpImcP.fdwImeMsg and MSG_IN_IMETOASCIIEX) <> 0 then
  740.       begin
  741.         uNumMsgLimit := lpTransBuf.uMsgCount;
  742.         if (uNumMsg <= uNumMsgLimit) then
  743.         begin
  744.           lpTransMsg := @lpTransBuf.TransMsg;
  745.           Continue;
  746.         end;
  747.       end;
  748.       // we need to use message buffer
  749.       if (lpIMC.hMsgBuf = 0) then
  750.       begin
  751.         lpIMC.hMsgBuf := ImmCreateIMCC(uNumMsg * SizeOf(TTransMsg));
  752.         lpIMC.dwNumMsgBuf := 0;
  753.       end else
  754.       begin
  755.         hMem := ImmReSizeIMCC(lpIMC.hMsgBuf, (lpIMC.dwNumMsgBuf + uNumMsg) * SizeOf(TTransMsg));
  756.         if (hMem <> 0) then
  757.         begin
  758.           if (hMem <> lpIMC.hMsgBuf) then
  759.           begin
  760.             ImmDestroyIMCC(lpIMC.hMsgBuf);
  761.             lpIMC.hMsgBuf := hMem;
  762.           end;
  763.         end else
  764.         begin
  765.           Result := 0;
  766.           Exit;
  767.         end;
  768.       end;
  769.       lpTransMsg := ImmLockIMCC(lpIMC.hMsgBuf);
  770.       if (lpTransMsg = nil) then
  771.       begin
  772.         Result := 0;
  773.         Exit;
  774.       end;
  775.       Inc(lpTransMsg, lpIMC.dwNumMsgBuf);
  776.       bLockMsgBuf := True;
  777.     end else
  778.     begin
  779.       if (bLockMsgBuf) then ImmUnlockIMCC(lpIMC.hMsgBuf);
  780.     end;
  781.   end; // for ..
  782.   Result := uNumMsg; // **
  783. end;
  784.   // Ime回调, Return Value:  the number of translated message
  785. function ImeToAsciiEx(uVirtKey, uScanCode: uInt; lpbKeyState: PKeyboardState;
  786.   lpTransBuf: PTransMsgList; fuState: uInt; _hIMC: hIMC): uInt; stdcall;
  787. var
  788.   wCharCode: Word;
  789.   lpIMC: PInputContext;
  790.   lpCompStr: PCompositionString;
  791.   lpImcP: PPrivContext;
  792.   uNumMsg: uInt;
  793.   iRet: Integer;
  794.   wSymbolCharCode, cHiByte, cLoByte: Word;
  795.   SKDataIndex: Integer;
  796.   lpCandInfo: PCandidateInfo;
  797.   lpGuideLine: PGuideLine;
  798. begin
  799.   wCharCode := HiByte(uVirtKey);
  800.   uVirtKey := LoByte(uVirtKey);
  801.   // hIMC=NULL?
  802.   if (_hIMC = 0) then
  803.   begin
  804.     Result := TranslateToAscii(uVirtKey, uScanCode, lpTransBuf, wCharCode);
  805.     Exit;
  806.   end;
  807.   // get lpIMC
  808.   lpIMC := ImmLockIMC(_hIMC);
  809.   if (lpIMC = nil) then
  810.   begin
  811.     Result := TranslateToAscii(uVirtKey, uScanCode, lpTransBuf, wCharCode);
  812.     Exit;
  813.   end;
  814.   // get lpImcP
  815.   lpImcP := ImmLockIMCC(lpIMC.hPrivate);
  816.   if (lpImcP = nil) then
  817.   begin
  818.     ImmUnlockIMC(_hIMC);
  819.     Result := TranslateToAscii(uVirtKey, uScanCode, lpTransBuf, wCharCode);
  820.     Exit;
  821.   end;
  822.   // get lpCompStr and init
  823.   if (lpImcP.fdwGcsFlag and (GCS_RESULTREAD or GCS_RESULT)) <> 0 then
  824.   begin
  825.     lpCompStr := ImmLockIMCC(lpIMC.hCompStr);
  826.     if (lpCompStr <> nil) then lpCompStr.dwResultStrLen := 0;
  827.     ImmUnlockIMCC(lpIMC.hCompStr);
  828.     lpImcP.fdwGcsFlag := 0;
  829.   end;
  830.   // Now all composition realated information already pass to app a brand new start
  831.   // init lpImcP.fdwImeMsg
  832.   lpImcP.fdwImeMsg := lpImcP.fdwImeMsg and (MSG_ALREADY_OPEN or MSG_ALREADY_START) or MSG_IN_IMETOASCIIEX;
  833.   // Process Key(wCharCode)
  834.   iRet := ProcessKey(wCharCode, uVirtKey, uScanCode, lpbKeyState, lpIMC, lpImcP);
  835.   // iRet process
  836.   // CST_ALPHANUMERIC
  837.   // CST_SYMBOL
  838.   // CST_SOFTKB
  839.   if (iRet = CST_SOFTKB) then
  840.   begin
  841.     // Mapping VK
  842.     if (uVirtKey = $20) then
  843.     begin
  844.       SKDataIndex := 0;
  845.     end else
  846.       if (uVirtKey >= $30) and (uVirtKey <= $39) then
  847.       begin
  848.         SKDataIndex := uVirtKey - $30 + 1;
  849.       end else
  850.         if (uVirtKey >= $41) and (uVirtKey <= $5A) then
  851.         begin
  852.           SKDataIndex := uVirtKey - $41 + $0B;
  853.         end else
  854.           if (uVirtKey >= $BA) and (uVirtKey <= $BF) then
  855.           begin
  856.             SKDataIndex := uVirtKey - $BA + $25;
  857.           end else
  858.             if (uVirtKey >= $DB) and (uVirtKey <= $DE) then
  859.             begin
  860.               SKDataIndex := uVirtKey - $DB + $2C;
  861.             end else
  862.               if (uVirtKey = $C0) then
  863.               begin
  864.                 SKDataIndex := $2B;
  865.               end else
  866.               begin
  867.                 SKDataIndex := 0;
  868.               end;
  869.     if (lpbKeyState[VK_SHIFT] and $80) <> 0 then
  870.     begin
  871.       cHiByte := Ord(SKLayoutS[sImeL.dwSKWant][SKDataIndex*2]) and $00FF;
  872.       cLoByte := Ord(SKLayoutS[sImeL.dwSKWant][SKDataIndex*2 + 1]) and $00FF;
  873.     end else
  874.     begin
  875.       cHiByte := Ord(SKLayout[sImeL.dwSKWant][SKDataIndex*2]) and $00FF;
  876.       cLoByte := Ord(SKLayout[sImeL.dwSKWant][SKDataIndex*2 + 1]) and $00FF;
  877.     end;
  878.     wSymbolCharCode := (cHiByte shl 8) or cLoByte;
  879.     if (wSymbolCharCode = $2020) then
  880.     begin
  881.       MessageBeep($FFFFFFFF);
  882.       uNumMsg := 0;
  883.     end else
  884.     begin
  885.       uNumMsg := TranslateSymbolChar(lpTransBuf, wSymbolCharCode, False);
  886.     end;
  887.   end else
  888.     if (iRet = CST_ALPHANUMERIC) then
  889.     begin
  890.       if (lpImcP.fdwImeMsg and MSG_ALREADY_OPEN) <> 0 then
  891.       begin
  892.         lpImcP.fdwImeMsg := (lpImcP.fdwImeMsg or MSG_CLOSE_CANDIDATE) and (not MSG_OPEN_CANDIDATE) and (not MSG_IN_IMETOASCIIEX);
  893.         GenerateMessage(_hIMC, lpIMC, lpImcP);
  894.       end;
  895.       if (lpIMC.fdwConversion and IME_CMODE_SYMBOL) <> 0 then
  896.       begin
  897.         if (wCharCode = Ord('.')) then
  898.         begin
  899.           wSymbolCharCode := Swap(PWord(PChar('。'))^);
  900.           uNumMsg := TranslateSymbolChar(lpTransBuf, wSymbolCharCode, False);
  901.         end else
  902.           if (wCharCode = Ord(',')) then
  903.           begin
  904.             wSymbolCharCode := Swap(PWord(PChar(','))^);
  905.             uNumMsg := TranslateSymbolChar(lpTransBuf, wSymbolCharCode, False);
  906.           end else
  907.             if (wCharCode = Ord(';')) then
  908.             begin
  909.               wSymbolCharCode := Swap(PWord(PChar(';'))^);
  910.               uNumMsg := TranslateSymbolChar(lpTransBuf, wSymbolCharCode, False);
  911.             end else
  912.               if (wCharCode = Ord(':')) then
  913.               begin
  914.                 wSymbolCharCode := Swap(PWord(PChar(':'))^);
  915.                 uNumMsg := TranslateSymbolChar(lpTransBuf, wSymbolCharCode, False);
  916.               end else
  917.                 if (wCharCode = Ord('?')) then
  918.                 begin
  919.                   wSymbolCharCode := Swap(PWord(PChar('?'))^);
  920.                   uNumMsg := TranslateSymbolChar(lpTransBuf, wSymbolCharCode, False);
  921.                 end else
  922.                   if (wCharCode = Ord('!')) then
  923.                   begin
  924.                     wSymbolCharCode := Swap(PWord(PChar('!'))^);
  925.                     uNumMsg := TranslateSymbolChar(lpTransBuf, wSymbolCharCode, False);
  926.                   end else
  927.                     if (wCharCode = Ord('(')) then
  928.                     begin
  929.                       wSymbolCharCode := Swap(PWord(PChar('('))^);
  930.                       uNumMsg := TranslateSymbolChar(lpTransBuf, wSymbolCharCode, False);
  931.                     end else
  932.                       if (wCharCode = Ord(')')) then
  933.                       begin
  934.                         wSymbolCharCode := Swap(PWord(PChar(')'))^);
  935.                         uNumMsg := TranslateSymbolChar(lpTransBuf, wSymbolCharCode, False);
  936.                       end else
  937.                         if (wCharCode = Ord('')) then
  938.                         begin
  939.                           wSymbolCharCode := Swap(PWord(PChar('、'))^);
  940.                           uNumMsg := TranslateSymbolChar(lpTransBuf, wSymbolCharCode, False);
  941.                         end else
  942.                           if (wCharCode = Ord('@')) then
  943.                           begin
  944.                             wSymbolCharCode := Swap(PWord(PChar('·'))^);
  945.                             uNumMsg := TranslateSymbolChar(lpTransBuf, wSymbolCharCode, False);
  946.                           end else
  947.                             if (wCharCode = Ord('&')) then
  948.                             begin
  949.                               wSymbolCharCode := Swap(PWord(PChar('—'))^);
  950.                               uNumMsg := TranslateSymbolChar(lpTransBuf, wSymbolCharCode, False);
  951.                             end else
  952.                               if (wCharCode = Ord('$')) then
  953.                               begin
  954.                                 wSymbolCharCode := Swap(PWord(PChar('¥'))^);
  955.                                 uNumMsg := TranslateSymbolChar(lpTransBuf, wSymbolCharCode, False);
  956.                               end else
  957.                                 if (wCharCode = Ord('_')) then
  958.                                 begin
  959.                                   wSymbolCharCode := Swap(PWord(PChar('—'))^);
  960.                                   uNumMsg := TranslateSymbolChar(lpTransBuf, wSymbolCharCode, True);
  961.                                 end else
  962.                                   if (wCharCode = Ord('^')) then
  963.                                   begin
  964.                                     wSymbolCharCode := Swap(PWord(PChar('…'))^);
  965.                                     uNumMsg := TranslateSymbolChar(lpTransBuf, wSymbolCharCode, True);
  966.                                   end else
  967.                                     if(wCharCode = Ord('"')) then
  968.                                     begin
  969.                                       if (lpImcP.uSYHFlg <> 0) then
  970.                                         wSymbolCharCode := Swap(PWord(PChar('”'))^)
  971.                                       else
  972.                                         wSymbolCharCode := Swap(PWord(PChar('“'))^);
  973.                                       lpImcP.uSYHFlg := lpImcP.uSYHFlg xor $00000001;
  974.                                       uNumMsg := TranslateSymbolChar(lpTransBuf, wSymbolCharCode, False);
  975.                                     end else
  976.                                       if (wCharCode = Ord('''')) then
  977.                                       begin
  978.                                         if (lpImcP.uDYHFlg <> 0) then
  979.                                           wSymbolCharCode := Swap(PWord(PChar('’'))^)
  980.                                         else
  981.                                           wSymbolCharCode := Swap(PWord(PChar('‘'))^);
  982.                                         lpImcP.uDYHFlg := lpImcP.uDYHFlg xor $00000001;
  983.                                         uNumMsg := TranslateSymbolChar(lpTransBuf, wSymbolCharCode, False);
  984.                                       end else
  985.                                         if (wCharCode = Ord('<')) then
  986.                                         begin
  987.                                           if (lpImcP.uDSMHFlg <> 0) then
  988.                                           begin
  989.                                             wSymbolCharCode := Swap(PWord(PChar('〈'))^);
  990.                                             Inc(lpImcP.uDSMHCount);
  991.                                           end else
  992.                                           begin
  993.                                             wSymbolCharCode := Swap(PWord(PChar('《'))^);
  994.                                             lpImcP.uDSMHFlg := $00000001;
  995.                                           end;
  996.                                           uNumMsg := TranslateSymbolChar(lpTransBuf, wSymbolCharCode, False);
  997.                                         end else
  998.                                           if (wCharCode = Ord('>')) then
  999.                                           begin
  1000.                                             if (lpImcP.uDSMHFlg <> 0) and (lpImcP.uDSMHCount <> 0) then
  1001.                                             begin
  1002.                                               wSymbolCharCode := Swap(PWord(PChar('〉'))^);
  1003.                                               Dec(lpImcP.uDSMHCount);
  1004.                                             end else
  1005.                                             begin
  1006.                                               wSymbolCharCode := Swap(PWord(PChar('》'))^);
  1007.                                               lpImcP.uDSMHFlg := $00000000;
  1008.                                             end;
  1009.                                             uNumMsg := TranslateSymbolChar(lpTransBuf, wSymbolCharCode, False);
  1010.                                           end else
  1011.                                           begin
  1012.                                             if (lpIMC.fdwConversion and IME_CMODE_FULLSHAPE) <> 0 then
  1013.                                             begin
  1014.                                               // convert to DBCS
  1015.                                               uNumMsg := TranslateFullChar(lpTransBuf, wCharCode);
  1016.                                             end else
  1017.                                             begin
  1018.                                               uNumMsg := TranslateToAscii(uVirtKey, uScanCode, lpTransBuf, wCharCode);
  1019.                                             end;
  1020.                                           end;
  1021.       end else
  1022.         if (lpIMC.fdwConversion and IME_CMODE_FULLSHAPE) <> 0 then
  1023.           uNumMsg := TranslateFullChar(lpTransBuf, wCharCode)  // convert to DBCS
  1024.         else
  1025.           uNumMsg := TranslateToAscii(uVirtKey, uScanCode, lpTransBuf, wCharCode);
  1026.     end else
  1027.       if (iRet = CST_CHOOSE) then
  1028.       begin
  1029.         lpCandInfo := ImmLockIMCC(lpIMC.hCandInfo);
  1030.         if (lpCandInfo = nil) then
  1031.         begin
  1032.           Result := CST_INVALID;
  1033.           Exit;
  1034.         end;
  1035.         if (uVirtKey = VK_PRIOR) then
  1036.         begin
  1037.           wCharCode := Ord('-');
  1038.         end else
  1039.           if (uVirtKey = VK_NEXT) then
  1040.           begin
  1041.             wCharCode := Ord('=');
  1042.           end else
  1043.             if (uVirtKey = VK_SPACE) then
  1044.             begin
  1045.               wCharCode := Ord('1');
  1046.             end else
  1047.               if (uVirtKey >= Ord('0')) and (uVirtKey <= Ord('9')) then // **
  1048.               begin
  1049.                 // convert shift-0 ... shift-9 to 0 ... 9
  1050.                 wCharCode := uVirtKey;
  1051.               end else
  1052.                 if (uVirtKey = VK_HOME) then
  1053.                 begin
  1054.                   wCharCode := $24;
  1055.                 end else
  1056.                   if (uVirtKey = VK_END) then
  1057.                   begin
  1058.                     wCharCode := $23;
  1059.                   end
  1060.                   else
  1061.                   begin
  1062.                   end;
  1063.         lpImcP.iImeState := CST_CHOOSE;
  1064.         ChooseCand(wCharCode, lpIMC, lpCandInfo, lpImcP);
  1065.         ImmUnlockIMCC(lpIMC.hCandInfo);
  1066.         uNumMsg := TranslateImeMessage(lpTransBuf, lpIMC, lpImcP);
  1067.       end else
  1068.         if (iRet = CST_INPUT) and ((lpIMC.fdwConversion and IME_CMODE_CHARCODE) <> 0) then
  1069.         begin
  1070.           uNumMsg := TranslateToAscii(uVirtKey, uScanCode, lpTransBuf, wCharCode);
  1071.         end else
  1072.           if (iRet = CST_INPUT) then
  1073.           begin
  1074.             // get lpCompStr & lpGuideLine
  1075.             lpCompStr := ImmLockIMCC(lpIMC.hCompStr);
  1076.             if (lpCompStr = nil) then
  1077.             begin
  1078.               Result := CST_INVALID;
  1079.               Exit;
  1080.             end;
  1081.             lpGuideLine := ImmLockIMCC(lpIMC.hGuideLine);
  1082.             if (lpGuideLine = nil) then
  1083.             begin
  1084.               ImmUnlockIMCC(lpIMC.hCompStr);
  1085.               Result := CST_INVALID;
  1086.               Exit;
  1087.             end;
  1088.             // composition
  1089.             CompWord(wCharCode, lpIMC, lpCompStr, lpImcP, lpGuideLine);
  1090.             ImmUnlockIMCC(lpIMC.hGuideLine);
  1091.             ImmUnlockIMCC(lpIMC.hCompStr);
  1092.             // generate message
  1093.             uNumMsg := TranslateImeMessage(lpTransBuf, lpIMC, lpImcP);
  1094.           end else
  1095.             if (iRet = CST_INVALID_INPUT) then
  1096.             begin
  1097.               MessageBeep($FFFFFFFF);
  1098.               uNumMsg := 0;
  1099.             end else
  1100.             begin
  1101.               uNumMsg := TranslateToAscii(uVirtKey, uScanCode, lpTransBuf, wCharCode);
  1102.             end;
  1103.   // reset lpImcP.fdwImeMsg
  1104.   lpImcP.fdwImeMsg := lpImcP.fdwImeMsg and (MSG_ALREADY_OPEN or MSG_ALREADY_START);
  1105.   lpImcP.fdwGcsFlag := lpImcP.fdwGcsFlag and (GCS_RESULTREAD or GCS_RESULT);
  1106.   ImmUnlockIMCC(lpIMC.hPrivate);
  1107.   ImmUnlockIMC(_hIMC);
  1108.   Result := uNumMsg;
  1109. end;
  1110. end.