输入法控制

来源:互联网 发布:初学者编程软件 编辑:程序博客网 时间:2024/04/28 05:01
{******************************************************************************
*
*         xxxxx系统输入法控制单元模块
*         作用:对几个输入法控制不好的控件进行单独处理
*         文件名:U_Ime.pas               版本:1.0
*         创建日期:2007-01-08            作者:张旭煜
*         最后修改:2007-01-08
*
******************************************************************************}
unit U_Ime;

interface

implementation

uses
  Windows, Forms, imm, SysUtils, Messages;

var
  sTmpClassName, sTmpIME: string; //失去焦点时的控件名称和输入法名称
  MsgHandle: hHook = 0;

//判断当前类名是否会丢失输入法
function WillLostIme(sClassName: string): boolean;
begin
  Result := (sClassName = 'TLSDBGrid')
         or (sClassName = 'TLSDateTimePicker')
         or (sClassName = 'TDBLookupComboBox')
         or (sClassName = 'TDBComboBox');
end;

//获取当前输入法
function GetCurrentIME: string;
var
  IMEHandle: THandle;
  Idx: Integer;
begin
  Result := '';
  ImeHandle := GetKeyBoardLayOut(0);
  for Idx := 0 to Pred(Screen.Imes.Count) do
    if HKL(Screen.Imes.Objects[Idx]) = ImeHandle then
      Result := Screen.Imes[Idx];
end;
//还原输入法(如果输入法无效则是空)
procedure RestoreIME;

  Procedure OpenIme(ImeName:string);//打开指定的输入法
  var
    i:Integer;
    myhkl:hkl;
  begin
    if Trim(ImeName)<>'' then
    begin
      if Screen.Imes.Count<>0 then
      begin
        i:=Screen.Imes.IndexOf(ImeName);
        if i >= 0 then
        begin
          myhkl := hkl(Screen.Imes.Objects[i]);
          ActivateKeyBoardLayOut(myhkl, KLF_ACTIVATE);
        end;
      end;
    end;
  end;

begin
  if Trim(sTmpIME) <> '' then
    OpenIme(sTmpIME);
end;

//获取当前控件类名
function GetCurCtrClass: string;
var
  pt: TPoint;
  hndCtrl: Hwnd;
  Buf: pchar;
begin
  GetCursorPos(pt);                        //屏幕取点
  hndCtrl := WindowFromPoint(pt);          //控件句柄
  getMem(Buf, 128);
  try
    if GetClassName(hndCtrl, Buf, 128) > 0 then  //获取类名
    begin
      Result := string(Buf);
    end
    else
      Result := '';
  finally
    FreeMem(Buf);
  end;
end;

function LSDMsgProc(nCode, wParam, lParam: Integer): Integer; stdcall;
var
  msgTmp: UINT;
begin
  msgTmp := PCWPRetStruct(lParam)^.message;
  with Screen.ActiveForm do
  if msgTmp = WM_SETFOCUS then   //获取焦点时记下类名
  begin
    sTmpClassName := GetCurCtrClass;
  end
  else if msgTmp = WM_KILLFOCUS then  //失去焦点点时打开输入法
  begin
    if WillLostIme(sTmpClassName) then   //如果当前控件将失去焦点的那么打开输入法
      RestoreIME
    else
      sTmpIME := GetCurrentIME;  // 记下输入法
  end;
  Result := CallNextHookEx(MsgHandle, nCode, wParam, lParam);
end;

initialization
  MsgHandle := SetWindowsHookEx(WH_CALLWNDPROCRET, LSDMsgProc, HInstance, GetCurrentThreadID);
  sTmpClassName := '';
  sTmpIME := GetCurrentIME; 
finalization
  if MsgHandle <> 0 then
    UnhookWindowsHookEx(MsgHandle);
end.