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

输入法编程

开发平台:

Delphi

  1.  {******************************************************}
  2.  {                                                      }
  3.  {    Copyright (c) 1990-1999 Microsoft Corporation     }
  4.  {                                                      }
  5.  {    Module Name:  Init.c  ->>  Init.pas               }
  6.  {                                                      }
  7.  {    Translator:  Liu_mazi@126.com, 2005-11-13         }
  8.  {                                                      }
  9.  {******************************************************}
  10. unit Init;
  11. {$I Define.Inc}
  12. interface
  13. uses Windows;
  14. procedure ImeInit(fdwReason: DWord); // DLL 回调
  15. procedure InitCandUIData(cxBorder, cyBorder, uiMode: Integer); // 初始化 Cand 数据
  16. implementation
  17. uses ImmDev, ImeDefs, Data, DDIS, Ui, Uisubs, Candui, Compui, Statusui, LogText;
  18.   // 初始化 Status 数据
  19. procedure InitStatusUIData(cxBorder, cyBorder: Integer);
  20. var
  21.   iContentHi: Integer;
  22. begin
  23.   // iContentHi is to get the maximum value of predefined STATUS_DIM_Y and a real Chinese character's height in the current HDC.
  24.   iContentHi := STATUS_DIM_Y;
  25.   if (iContentHi < sImeG.yChiCharHi) then iContentHi := sImeG.yChiCharHi;
  26.   // right bottom of status
  27.   sImeG.rcStatusText.Left := 0;
  28.   sImeG.rcStatusText.Top := 0;
  29.   sImeG.rcStatusText.Right := sImeG.rcStatusText.Left + lStrLen(szImeName) * sImeG.xChiCharWi div 2 + STATUS_NAME_MARGIN + STATUS_DIM_X * 4;
  30.   sImeG.rcStatusText.Bottom := sImeG.rcStatusText.Top + iContentHi;
  31.   sImeG.xStatusWi := STATUS_DIM_X * 4 + STATUS_NAME_MARGIN + lStrLen(szImeName) * sImeG.xChiCharWi div 2 + 6 * cxBorder;
  32.   sImeG.yStatusHi := iContentHi + 6 * cxBorder;
  33.   // left bottom of imeicon bar
  34.   sImeG.rcImeIcon.Left := sImeG.rcStatusText.Left;
  35.   sImeG.rcImeIcon.Top := sImeG.rcStatusText.Top;
  36.   sImeG.rcImeIcon.Right := sImeG.rcImeIcon.Left + STATUS_DIM_X;
  37.   sImeG.rcImeIcon.Bottom := sImeG.rcImeIcon.Top + iContentHi;
  38.   // left bottom of imename bar
  39.   sImeG.rcImeName.Left := sImeG.rcImeIcon.Right;
  40.   sImeG.rcImeName.Top := sImeG.rcStatusText.Top;
  41.   sImeG.rcImeName.Right := sImeG.rcImeName.Left + lStrLen(szImeName) * sImeG.xChiCharWi div 2 + STATUS_NAME_MARGIN;
  42.   sImeG.rcImeName.Bottom := sImeG.rcImeName.Top + iContentHi;
  43.   // middle bottom of Shape bar
  44.   sImeG.rcShapeText.Left := sImeG.rcImeName.Right;
  45.   sImeG.rcShapeText.Top := sImeG.rcStatusText.Top;
  46.   sImeG.rcShapeText.Right := sImeG.rcShapeText.Left + STATUS_DIM_X;
  47.   sImeG.rcShapeText.Bottom := sImeG.rcShapeText.Top + iContentHi;
  48.   // middle bottom of Symbol bar
  49.   sImeG.rcSymbol.Left := sImeG.rcShapeText.Right;
  50.   sImeG.rcSymbol.Top := sImeG.rcStatusText.Top;
  51.   sImeG.rcSymbol.Right := sImeG.rcSymbol.Left + STATUS_DIM_X;
  52.   sImeG.rcSymbol.Bottom := sImeG.rcSymbol.Top + iContentHi;
  53.   // right bottom of SK bar
  54.   sImeG.rcSKText.Left := sImeG.rcSymbol.Right;
  55.   sImeG.rcSKText.Top := sImeG.rcStatusText.Top;
  56.   sImeG.rcSKText.Right := sImeG.rcSKText.Left + STATUS_DIM_X;
  57.   sImeG.rcSKText.Bottom := sImeG.rcSKText.Top + iContentHi;
  58. end;
  59.   // 初始化 Candidates 数据
  60. procedure InitCandUIData(cxBorder, cyBorder, uiMode: Integer);
  61. var
  62.   iContentHi: Integer;
  63. begin
  64.   // iContentHi is to get the maximum value of predefined COMP_TEXT_Y and a real Chinese character's height in the current HDC.
  65.   iContentHi := COMP_TEXT_Y;
  66.   if (iContentHi < sImeG.yChiCharHi) then iContentHi := sImeG.yChiCharHi;
  67.   sImeG.cxCandBorder := cxBorder * 2;
  68.   sImeG.cyCandBorder := cyBorder * 2;
  69.   // Candidates 界面风格 (单行长条/多行方框)
  70.   if (uiMode = LIN_UI) then
  71.   begin
  72.     sImeG.rcCandIcon.Left := 0;
  73.     sImeG.rcCandIcon.Top := cyBorder + 2;
  74.     sImeG.rcCandIcon.Right := sImeG.rcCandIcon.Left + UI_CANDICON;
  75.     sImeG.rcCandIcon.Bottom := sImeG.rcCandIcon.Top + UI_CANDICON;
  76.     sImeG.rcCandText.Left := sImeG.rcCandIcon.Right + 3;
  77.     sImeG.rcCandText.Top :=  cyBorder;
  78.     sImeG.rcCandText.Right := sImeG.rcCandText.Left + UI_CANDSTR;
  79.     sImeG.rcCandText.Bottom := sImeG.rcCandText.Top + iContentHi;
  80.     sImeG.rcCandBTH.Top := cyBorder * 4;
  81.     sImeG.rcCandBTH.Left := sImeG.rcCandText.Right + 5;
  82.     sImeG.rcCandBTH.Right := sImeG.rcCandBTH.Left + UI_CANDBTW;
  83.     sImeG.rcCandBTH.Bottom := sImeG.rcCandBTH.Top + UI_CANDBTH;
  84.     sImeG.rcCandBTU.Top := cyBorder * 4;
  85.     sImeG.rcCandBTU.Left := sImeG.rcCandBTH.Right;
  86.     sImeG.rcCandBTU.Right := sImeG.rcCandBTU.Left + UI_CANDBTW;
  87.     sImeG.rcCandBTU.Bottom := sImeG.rcCandBTU.Top + UI_CANDBTH;
  88.     sImeG.rcCandBTD.Top := cyBorder * 4;
  89.     sImeG.rcCandBTD.Left := sImeG.rcCandBTU.Right;
  90.     sImeG.rcCandBTD.Right := sImeG.rcCandBTD.Left + UI_CANDBTW;
  91.     sImeG.rcCandBTD.Bottom := sImeG.rcCandBTD.Top + UI_CANDBTH;
  92.     sImeG.rcCandBTE.Top := cyBorder * 4;
  93.     sImeG.rcCandBTE.Left := sImeG.rcCandBTD.Right;
  94.     sImeG.rcCandBTE.Right := sImeG.rcCandBTE.Left + UI_CANDBTW;
  95.     sImeG.rcCandBTE.Bottom := sImeG.rcCandBTE.Top + UI_CANDBTH;
  96.     sImeG.xCandWi := sImeG.rcCandBTE.Right + sImeG.cxCandBorder * 2 + cxBorder * 4;
  97.     sImeG.yCandHi := sImeG.rcCandText.Bottom + sImeG.cyCandBorder * 2 + cyBorder * 4;
  98.   end else
  99.   begin
  100.     sImeG.rcCandText.Left := cxBorder;
  101.     sImeG.rcCandText.Top := 2 * cyBorder + UI_CANDINF;
  102.     if (sImeG.xChiCharWi * 9 > (UI_CANDICON * 6 + UI_CANDBTH * 4)) then
  103.       sImeG.rcCandText.Right := sImeG.rcCandText.Left + sImeG.xChiCharWi * 9
  104.     else
  105.       sImeG.rcCandText.Right := sImeG.rcCandText.Left + (UI_CANDICON * 6 + UI_CANDBTH * 4);
  106.     sImeG.rcCandText.Bottom := sImeG.rcCandText.Top + sImeG.yChiCharHi * CANDPERPAGE;
  107.     sImeG.xCandWi := sImeG.rcCandText.Right + sImeG.cxCandBorder * 2 + cxBorder * 4;
  108.     sImeG.yCandHi := sImeG.rcCandText.Bottom + sImeG.cyCandBorder * 2 + cyBorder * 4;
  109.     sImeG.rcCandIcon.Left := cxBorder;
  110.     sImeG.rcCandIcon.Top := cyBorder + 2;
  111.     sImeG.rcCandIcon.Right := sImeG.rcCandIcon.Left + UI_CANDICON;
  112.     sImeG.rcCandIcon.Bottom := sImeG.rcCandIcon.Top + UI_CANDICON;
  113.     sImeG.rcCandInf.Left := sImeG.rcCandIcon.Right;
  114.     sImeG.rcCandInf.Top := cyBorder + 3;
  115.     sImeG.rcCandInf.Right := sImeG.rcCandInf.Left + UI_CANDICON * 5;
  116.     sImeG.rcCandInf.Bottom := sImeG.rcCandInf.Top + UI_CANDBTH;
  117.     sImeG.rcCandBTE.Top := cyBorder * 5;
  118.     sImeG.rcCandBTE.Right := sImeG.rcCandText.Right + cxBorder;
  119.     sImeG.rcCandBTE.Bottom := sImeG.rcCandBTE.Top + UI_CANDBTH;
  120.     sImeG.rcCandBTE.Left := sImeG.rcCandBTE.Right - UI_CANDBTW;
  121.     sImeG.rcCandBTD.Top := cyBorder * 5;
  122.     sImeG.rcCandBTD.Right := sImeG.rcCandBTE.Left;
  123.     sImeG.rcCandBTD.Bottom := sImeG.rcCandBTD.Top + UI_CANDBTH;
  124.     sImeG.rcCandBTD.Left := sImeG.rcCandBTD.Right - UI_CANDBTW;
  125.     sImeG.rcCandBTU.Top := cyBorder * 5;
  126.     sImeG.rcCandBTU.Right := sImeG.rcCandBTD.Left;
  127.     sImeG.rcCandBTU.Bottom := sImeG.rcCandBTU.Top + UI_CANDBTH;
  128.     sImeG.rcCandBTU.Left := sImeG.rcCandBTU.Right - UI_CANDBTW;
  129.     sImeG.rcCandBTH.Top := cyBorder * 5;
  130.     sImeG.rcCandBTH.Right := sImeG.rcCandBTU.Left;
  131.     sImeG.rcCandBTH.Bottom := sImeG.rcCandBTH.Top + UI_CANDBTH;
  132.     sImeG.rcCandBTH.Left := sImeG.rcCandBTH.Right - UI_CANDBTW;
  133.   end;
  134. end;
  135.   // 初始化全局数据
  136. procedure InitImeGlobalData();
  137. var
  138.   cxBorder, cyBorder: Integer;
  139.   ui_Mode: Integer;
  140.   _hDC: hDC;
  141.   hOldFont: hGdiObj;
  142.   lfFont: TLogFont;
  143.   szChiChar: array[0..4] of Char;
  144.   lTextSize: TSize;
  145.   hResData: hGlobal;
  146.   dwSize: DWord;
  147.   hKeyIMESetting: hKey;
  148.   lRet: DWord;
  149. begin
  150.   // get the Ime Reg Name
  151.   LoadString(HInstance, IDS_IMEREGNAME, szImeRegName, MAX_PATH);
  152.   // get the Ime Name
  153.   LoadString(HInstance, IDS_IMENAME_QW, szImeName, MAX_PATH);
  154.   // get the UI class name
  155.   LoadString(HInstance, IDS_IMEUICLASS, szUIClassName, CLASS_LEN);
  156.   // get the composition class name
  157.   LoadString(HInstance, IDS_IMECOMPCLASS, szCompClassName, CLASS_LEN);
  158.   // get the candidate class name
  159.   LoadString(HInstance, IDS_IMECANDCLASS, szCandClassName, CLASS_LEN);
  160.   // get the status class name
  161.   LoadString(HInstance, IDS_IMESTATUSCLASS, szStatusClassName, CLASS_LEN);
  162.   // get the ContextMenu class name
  163.   LoadString(HInstance, IDS_IMECMENUCLASS, szCMenuClassName, CLASS_LEN);
  164.   // get the softkeyboard Menu class name
  165.   LoadString(HInstance, IDS_IMESOFTKEYMENUCLASS, szSoftkeyMenuClassName, CLASS_LEN);
  166.   // work area
  167.   SystemParametersInfo(SPI_GETWORKAREA, 0, @sImeG.rcWorkArea, 0);
  168.   // border
  169.   cxBorder := GetSystemMetrics(SM_CXBORDER);
  170.   cyBorder := GetSystemMetrics(SM_CYBORDER);
  171.   // get the Chinese char
  172.   LoadString(HInstance, IDS_CHICHAR, szChiChar, SizeOf(szChiChar));
  173.   // init ime charact
  174.   lStrCpy(sImeG.UsedCodes, '0123456789abcdef');
  175.   sImeG.wNumCodes := lStrLen(sImeG.UsedCodes);
  176.   sImeG.IC_Enter := 0;
  177.   sImeG.IC_Trace := 0;
  178.   // get size of Chinese char
  179.   _hDC := GetDC(0);
  180.   hOldFont := GetCurrentObject(_hDC, OBJ_FONT);
  181.   GetObject(hOldFont, SizeOf(TLogFont), @lfFont); // 未用到??
  182.   sImeG.fDiffSysCharSet := True;
  183.   ZeroMemory(@lfFont, SizeOf(TLogFont));
  184.   lfFont.lfHeight := - MulDiv(12, GetDeviceCaps(_hDC, LOGPIXELSY), 72);
  185.   lfFont.lfCharSet := NATIVE_CHARSET;
  186.   lStrCpy(lfFont.lfFaceName, '宋体');
  187.   SelectObject(_hDC, CreateFontIndirect(lfFont)); // 创建字体并选入
  188.   if (GetTextExtentPoint(_hDC, szChiChar, lStrLen(szChiChar), lTextSize) = False) then // 尺寸
  189.     ZeroMemory(@lTextSize, SizeOf(TSize));
  190.   if (sImeG.rcWorkArea.Right < 2 * UI_MARGIN) then
  191.   begin
  192.     sImeG.rcWorkArea.Left := 0;
  193.     sImeG.rcWorkArea.Right := GetDeviceCaps(_hDC, HORZRES);
  194.   end;
  195.   if (sImeG.rcWorkArea.Bottom < 2 * UI_MARGIN) then
  196.   begin
  197.     sImeG.rcWorkArea.Top := 0;
  198.     sImeG.rcWorkArea.Bottom := GetDeviceCaps(_hDC, VERTRES);
  199.   end;
  200.   if (sImeG.fDiffSysCharSet) then DeleteObject(SelectObject(_hDC, hOldFont));
  201.   ReleaseDC(0, _hDC);
  202.   // get text metrics to decide the width & height of composition window these IMEs always use system font to show
  203.   sImeG.xChiCharWi := lTextSize.cx;
  204.   sImeG.yChiCharHi := lTextSize.cy;
  205.   if (sImeG.IC_Trace <> 0) then ui_Mode := BOX_UI else ui_Mode := LIN_UI;
  206.   InitCandUIData(cxBorder, cyBorder, ui_Mode);
  207.   InitStatusUIData(cxBorder, cyBorder);
  208.   // load full ABC table
  209.   hResData := LoadResource(HInstance, FindResource(HInstance, 'FULLABC', RT_RCDATA));
  210.   PFullABC(@sImeG.wFullABC)^ := PFullABC(LockResource(hResData))^;
  211.   UnlockResource(hResData);
  212.   FreeResource(hResData);
  213.   // full shape space
  214.   sImeG.wFullSpace := sImeG.wFullABC[0];
  215.   LoadString(HInstance, IDS_STATUSERR, sImeG.szStatusErr, SizeOf(sImeG.szStatusErr));
  216.   sImeG.cbStatusErr := lStrLen(sImeG.szStatusErr);
  217.   sImeG.iCandStart := CAND_START;
  218.   // get the UI offset for near caret operation
  219.   RegCreateKey(HKEY_CURRENT_USER, szRegIMESetting, hKeyIMESetting);
  220.   dwSize := SizeOf(DWord);
  221.   lRet := RegQueryValueEx(hKeyIMESetting, szPara, nil, nil, PByte(@sImeG.iPara), @dwSize);
  222.   if (lRet <> ERROR_SUCCESS) then
  223.   begin
  224.     sImeG.iPara := 0;
  225.     RegSetValueEx(hKeyIMESetting, szPara, 0, REG_BINARY, PByte(@sImeG.iPara), SizeOf(DWord));
  226.   end;
  227.   dwSize := SizeOf(DWord);
  228.   lRet := RegQueryValueEx(hKeyIMESetting, szPerp, nil, nil, PByte(@sImeG.iPerp), @dwSize);
  229.   if (lRet <> ERROR_SUCCESS) then
  230.   begin
  231.     sImeG.iPerp := sImeG.yChiCharHi;
  232.     RegSetValueEx(hKeyIMESetting, szPerp, 0, REG_BINARY, PByte(@sImeG.iPerp), SizeOf(DWord));
  233.   end;
  234.   dwSize := SizeOf(DWord);
  235.   lRet := RegQueryValueEx(hKeyIMESetting, szParaTol, nil, nil, PByte(@sImeG.iParaTol), @dwSize);
  236.   if (lRet <> ERROR_SUCCESS) then
  237.   begin
  238.     sImeG.iParaTol := sImeG.xChiCharWi * 4;
  239.     RegSetValueEx(hKeyIMESetting, szParaTol, 0, REG_BINARY, PByte(@sImeG.iParaTol), SizeOf(DWord));
  240.   end;
  241.   dwSize := SizeOf(DWord);
  242.   lRet := RegQueryValueEx(hKeyIMESetting, szPerpTol, nil, nil, PByte(@sImeG.iPerpTol), @dwSize);
  243.   if (lRet <> ERROR_SUCCESS) then
  244.   begin
  245.     sImeG.iPerpTol := lTextSize.cy;
  246.     RegSetValueEx(hKeyIMESetting, szPerpTol, 0, REG_BINARY, PByte(@sImeG.iPerpTol), SizeOf(Integer));
  247.   end;
  248.   RegCloseKey(hKeyIMESetting);
  249. end;                                                                 
  250.   // 初始化局部数据
  251. function InitImeLocalData(): Bool;
  252. var
  253.   cxBorder, cyBorder, iContentHi: Integer;
  254. begin
  255.   // iContentHi is to get the maximum value of predefined COMP_TEXT_Y and a real Chinese character's height in the current HDC.
  256.   iContentHi := COMP_TEXT_Y;
  257.   if (iContentHi < sImeG.yChiCharHi) then iContentHi := sImeG.yChiCharHi;
  258.   sImeL.nMaxKey := 4;
  259.   // border + raising edge + sunken edge
  260.   cxBorder := GetSystemMetrics(SM_CXBORDER);
  261.   cyBorder := GetSystemMetrics(SM_CYBORDER);
  262.   // text position relative to the composition window
  263.   sImeL.cxCompBorder := cxBorder * 2;
  264.   sImeL.cyCompBorder := cyBorder * 2;
  265.   sImeL.rcCompText.Left := cxBorder;
  266.   sImeL.rcCompText.Top := cyBorder;
  267.   sImeL.rcCompText.Right := sImeL.rcCompText.Left + sImeG.xChiCharWi * ((sImeL.nMaxKey + 2) div 2);
  268.   sImeL.rcCompText.Bottom := sImeL.rcCompText.Top + iContentHi;
  269.   // set the width & height for composition window
  270.   sImeL.xCompWi := sImeL.rcCompText.Right + sImeL.cxCompBorder * 2 + cxBorder * 4;
  271.   sImeL.yCompHi := sImeL.rcCompText.Bottom + sImeL.cyCompBorder * 2 + cyBorder * 4;
  272.   // default position of composition window
  273.   sImeL.ptDefComp.x := sImeG.rcWorkArea.Right - sImeL.xCompWi - cxBorder * 2;
  274.   sImeL.ptDefComp.y := sImeG.rcWorkArea.Bottom - sImeL.yCompHi - cyBorder * 2;
  275.   sImeL.fModeConfig := MODE_CONFIG_QUICK_KEY or MODE_CONFIG_PREDICT;
  276.   Result := False;
  277. end;
  278.   // Ime 注册表访问
  279. procedure RegisterIme();
  280. var
  281.   hKeyCurrVersion, hKeyGB: hKey;
  282.   retCode, ValueType, ValueSize, dwDisposition, Value: DWord;
  283. //  Buf: array[0..LINE_LEN] of Char;
  284. begin
  285.   retCode := OpenReg_PathSetup(@hKeyCurrVersion);
  286.   if (retCode <> ERROR_SUCCESS) then RegCreateKey(HKEY_CURRENT_USER, REGSTR_PATH_SETUP, hKeyCurrVersion);
  287.   retCode := OpenReg_User(hKeyCurrVersion, szImeRegName, @hKeyGB);
  288.   if (retCode <> ERROR_SUCCESS) then
  289.   begin
  290.     RegCreateKeyEx(hKeyCurrVersion, szImeRegName, 0, nil,
  291.       REG_OPTION_NON_VOLATILE, KEY_ALL_ACCESS, nil, hKeyGB, @dwDisposition);
  292.     Value := 1;
  293.     RegSetValueEx(hKeyGB, szTrace, 0, REG_DWORD, PByte(@Value), SizeOf(DWord));
  294.   end;
  295.   ValueSize := SizeOf(DWord);
  296.   if (RegQueryValueEx(hKeyGB, szTrace, nil, PDWord(@ValueType), PByte(@sImeG.IC_Trace), @ValueSize) <> ERROR_SUCCESS) then
  297.   begin
  298.     Value := 1;
  299.     RegSetValueEx(hKeyGB, szTrace, 0, REG_DWORD, PByte(@Value), SizeOf(DWord));
  300.     RegQueryValueEx(hKeyGB, szTrace, nil, PDWord(@ValueType), PByte(@sImeG.IC_Trace), @ValueSize);
  301.   end;
  302.   RegCloseKey(hKeyGB);
  303.   RegCloseKey(hKeyCurrVersion);
  304. end;
  305.   // 注册 Ime 窗口类
  306. procedure RegisterImeClass();
  307. var
  308.   wcWndCls: TWndClassEx;
  309. begin
  310.   // IME UI class
  311.   // Register IME UI class
  312.   wcWndCls.cbSize        := SizeOf(TWndClassEx);
  313.   wcWndCls.cbClsExtra    := 0;
  314.   wcWndCls.cbWndExtra    := SizeOf(DWord) * 2; // **
  315.   wcWndCls.hIcon         := LoadImage(HInstance, MakeIntResource(IDI_IME), IMAGE_ICON, 32, 32, LR_DEFAULTCOLOR);
  316.   wcWndCls.hInstance     := HInstance;
  317.   wcWndCls.hCursor       := LoadCursor(0, IDC_ARROW);
  318.   wcWndCls.hbrBackground := GetStockObject(NULL_BRUSH);
  319.   wcWndCls.lpszMenuName  := nil;
  320.   wcWndCls.hIconSm       := LoadImage(HInstance, MakeIntResource(IDI_IME), IMAGE_ICON, 16, 16, LR_DEFAULTCOLOR);
  321.   // IME UI class
  322.   if (GetClassInfoEx(HInstance, szUIClassName, wcWndCls) = False) then
  323.   begin
  324.     wcWndCls.style         := CS_IME;
  325.     wcWndCls.lpfnWndProc   := @UIWndProc;
  326.     wcWndCls.lpszClassName := szUIClassName;
  327.     RegisterClassEx(wcWndCls);
  328.   end;
  329.   // **
  330.   wcWndCls.style         := CS_IME or CS_HREDRAW or CS_VREDRAW;
  331.   wcWndCls.hbrBackground := GetStockObject(LTGRAY_BRUSH);
  332.   // IME composition class
  333.   // register IME composition class
  334.   if (GetClassInfoEx(HInstance, szCompClassName, wcWndCls) = False) then
  335.   begin
  336.     wcWndCls.lpfnWndProc   := @CompWndProc;
  337.     wcWndCls.lpszClassName := szCompClassName;
  338.     RegisterClassEx(wcWndCls);
  339.   end;
  340.   // IME candidate class
  341.   // register IME candidate class
  342.   if (GetClassInfoEx(HInstance, szCandClassName, wcWndCls) = False) then
  343.   begin
  344.     wcWndCls.lpfnWndProc   := @CandWndProc;
  345.     wcWndCls.lpszClassName := szCandClassName;
  346.     RegisterClassEx(wcWndCls);
  347.   end;
  348.   // IME status class
  349.   // register IME status class
  350.   if (GetClassInfoEx(HInstance, szStatusClassName, wcWndCls) = False) then
  351.   begin
  352.     wcWndCls.lpfnWndProc   := @StatusWndProc;
  353.     wcWndCls.lpszClassName := szStatusClassName;
  354.     RegisterClassEx(wcWndCls);
  355.   end;
  356.   // IME context menu class
  357.   if (GetClassInfoEx(HInstance, szCMenuClassName, wcWndCls) = False) then
  358.   begin
  359.     wcWndCls.style         := 0;
  360.     wcWndCls.hbrBackground := GetStockObject(NULL_BRUSH);
  361.     wcWndCls.lpfnWndProc   := @ContextMenuWndProc;
  362.     wcWndCls.lpszClassName := szCMenuClassName;
  363.     RegisterClassEx(wcWndCls);
  364.   end;
  365.   // IME softkeyboard menu class
  366.   if (GetClassInfoEx(hInstance, szSoftkeyMenuClassName, wcWndCls) = False) then
  367.   begin
  368.     wcWndCls.style         := 0;
  369.     wcWndCls.hbrBackground := GetStockObject(NULL_BRUSH);
  370.     wcWndCls.lpfnWndProc   := @SoftkeyMenuWndProc;
  371.     wcWndCls.lpszClassName := szSoftkeyMenuClassName;
  372.     RegisterClassEx(wcWndCls);
  373.   end;
  374. end;
  375.   // 注销 Ime 窗口类
  376. procedure UnregisterImeClass();
  377. var
  378.   wcWndCls: TWndClassEx;
  379. begin
  380.   if GetClassInfoEx(HInstance, szCMenuClassName, wcWndCls) then
  381.     UnregisterClass(szCMenuClassName, HInstance);
  382.   if GetClassInfoEx(HInstance, szSoftkeyMenuClassName, wcWndCls) then
  383.     UnregisterClass(szSoftkeyMenuClassName, HInstance);
  384.   if GetClassInfoEx(HInstance, szStatusClassName, wcWndCls) then
  385.     UnregisterClass(szStatusClassName, HInstance);
  386.   if GetClassInfoEx(HInstance, szCandClassName, wcWndCls) then
  387.     UnregisterClass(szCandClassName, HInstance);
  388.   if GetClassInfoEx(HInstance, szCompClassName, wcWndCls) then
  389.     UnregisterClass(szCompClassName, HInstance);
  390.   if GetClassInfoEx(HInstance, szUIClassName, wcWndCls) then
  391.     if UnregisterClass(szUIClassName, HInstance) then
  392.     begin
  393.       DestroyIcon(wcWndCls.hIcon);
  394.       DestroyIcon(wcWndCls.hIconSm);
  395.     end;
  396. end;
  397.   // DLL 回调
  398. procedure ImeInit(fdwReason: DWord);
  399. begin
  400.   case (fdwReason) of
  401.     DLL_PROCESS_ATTACH: // 进入进程空间
  402.     begin
  403.       InitImeGlobalData();
  404.       InitImeLocalData();
  405.       RegisterImeClass();
  406.       RegisterIme();      
  407.     end;
  408.     DLL_PROCESS_DETACH: // 退出进程空间
  409.     begin
  410.       UnregisterImeClass();
  411.     end;
  412.   end;
  413. end;
  414. end.