我用cime:=GetKeyboardLayout(0)取得系统当前键盘布局的一个句柄,返回一个hkl型的数据,我用LoadKeyboardLayout(PAnsiChar(cime),KLF_ACTIVATE)设置系统输入法时出现错! 
---------------------------
Debugger Exception Notification
---------------------------
Project Project1.exe raised exception class EAccessViolation with message 'Access violation at address 77DF73C7 in module 'user32.dll'. Read of address E0010804'. Process stopped. Use Step or Run to continue.
---------------------------
OK   Help   
---------------------------可能是 参数转换时的问题! 不知两个类型的数怎么正确转换;请问设置系统输入法还有其他方法吗! 现在通过:
var zz:hkl;i:integer;
begin
  zz:=getkeyboardlayout(0);
  for i:=0 to screen.Imes.Count-1 do
  if hkl(screen.Imes.Objects[i])=zz then
     showmessage(screen.Imes.Strings[i]);
end;
可以取得系统输入法的名字◎ 怎么样将系统输入设为screen.Imes.Strings[i] 呢!

解决方案 »

  1.   

    unit IME95;// 这些函式, 我通常是在 Edit 的 OnDblClick 事件中呼叫测试interfaceusesWindows, Messages, SysUtils, IMM,Classes, Graphics, Controls, Forms;// 请注意, IMM.PAS 必须置于与本单元同一目录或// 主选单 Tools | Options | Library Path 中的任一个目录// IMM.PAS 可在 Delphi 2.0 的 Source目录中找到constnHKL_LIST = 20;typeTImeUIWindow = class(TCustomControl)privateprocedure CMTextChanged(var Message: TMessage); message CM_TEXTCHANGED;protectedprocedure CreateParams(var Params: TCreateParams); override;procedure Paint; override;publicconstructor Create(AOwner: TComponent); override;procedure ShowComposition(ptWhere: TPoint; const sHint: string); virtual;// function IsHintMsg(var Msg: TMsg): Boolean; virtual;// procedure ReleaseHandle;property Caption;property Canvas;property Color;end;// 显示某一输入法的设定对话盒function ShowIMEConfigDialog(hKB: HKL): BOOL; far;// 指定某一窗口的中英输入模式procedure ToChinese(hWindows: THandle; bChinese: boolean); far;// 下一个输入法(等于仿真预设的 Ctrl + Shift)procedure NextIME; far;// 侦测目前作用中的输入法文件名称function GetImeFileName: string; far;// 切换到指定的输入法function SetActivateIme(sWanted: string): boolean; far;// 切断到中文输入法, 同时指定全/半角function ImeFullShape(hWindow: HWND; bToFullShape: BOOL): BOOL; far;// 送入一段字符串到指定的窗口procedure SendDBCSString(hFocus: HWND; const sSend: string); far;// 取得目前的拆字字根function GetImeCompositonString(hWindow: HWND): string; far;// 取得目前的拆字结果function GetImeCompositonResult(hWindow: HWND): string; far;// 取消某次的组字过程procedure CancelComposition(hWindow: THandle); far;// 设定组字字根procedure SetImeCompositonString(hWindow: THandle; const sCompStr: string); far;// 显示/不显示屏幕小键盘function ShowSoftKeyboard(hWindow: HWND; bShowIt: BOOL): BOOL; far;// 要不要相关字词功能function PhrasePredict(hWindow: HWND; bPredict: BOOL): BOOL; far;// 查询某字的组字字根function QueryCompStr(hKB: HKL; const sChinese: AnsiString): string; far;// --------------------------------------------------// --------------------------------------------------implementation// --------------------------------------------------// 指定某一窗口的中英输入模式// ToChinese(True); ==> 切换到中文输入法// ToChinese(False); ==> 切换到英数输入模式// [注意事项]// 1. 同一个 Tread 共享同一个 Input Context// 2. 可能的话, 最好应在呼叫完本程序的下一列写上:// Application.ProcessMessages;// --------------------------------------------------procedure ToChinese(hWindows: THandle; bChinese: boolean);beginif ImmIsIME(GetKeyboardLayOut(0)) <> bChinese thenImmSimulateHotKey(hWindows, IME_THotKey_IME_NonIME_Toggle);end;// --------------------------------------------------// 下一个输入法(等于仿真预设的 Ctrl + Shift)////// --------------------------------------------------procedure NextIME;beginActivateKeyboardLayout(HKL_NEXT, 0);end;// --------------------------------------------------// 切换到指定的输入法//// SetActivateIme('CHAJEI.IME'); ==> 切换到仓额输入法// SetActivateIme('Phon.ime'); ==> 切换到注音输入法// 传入空字符串时, 切换到英数输入法// --------------------------------------------------function SetActivateIme(sWanted: string): boolean;variHandleCount : integer;pList : array[1..nHKL_LIST] of HKL;szImeFileName : array[0..MAX_PATH] of char;sImeFileName : string;bInstalled : boolean;i : integer;beginResult := False;sWanted := AnsiUpperCase(sWanted);// 传入空字符串, 切成英数输入模式if Length(sWanted) = 0 thenbeginToChinese(0, False);Result := True;Exit;end;// 看看是否安装了这个输入法bInstalled := False;iHandleCount := GetKeyboardLayoutList(nHKL_LIST, pList);for i := 1 to iHandleCount dobeginImmGetIMEFileName(pList[I], szImeFileName, MAX_PATH);sImeFileName := AnsiUpperCase(StrPas(szImeFileName));if sImeFileName = sWanted thenbeginbInstalled := True;Break;end;end;// 如果这个输入法已安装了, 让那个输入法的键盘分布(KeyLayout)作用if bInstalled thenbeginActivateKeyboardLayout(pList[i], 0);Result := True;end;end; { of SetActivateIme }// --------------------------------------------------// 侦测目前作用中的输入法文件名称// 传回值为空字符串时, 表示英数输入模式//// --------------------------------------------------function GetImeFileName: string;varszImeFileName : array[0..MAX_PATH] of char;beginif ImmGetIMEFileName(GetKeyboardLayout(0), szImeFileName, MAX_PATH) <> 0 thenResult := AnsiUpperCase(StrPas(szImeFileName))elseResult := '';end;// --------------------------------------------------// 切换成中文输入法, 并且指定使用半/全角输入模式// 传回值: True: 成功 / False 切换失败// 使用示例: ImeFullShape(Form1.Handle, True); // 全角// ImeFullShape(Form1.Handle, False); // 半角// --------------------------------------------------(*这个函数也可以用以下的方式来作作看:if not ImmIsIME(GetKeyboardLayout(0)) thenImmSimulateHotKey(hWindow, IME_THOTKEY_IME_NONIME_TOGGLE);Application.ProcessMessages;ImmSimulateHotKey(hWindow, IME_THOTKEY_SHAPE_TOGGLE);*)function ImeFullShape(hWindow: HWND; bToFullShape: BOOL): BOOL;varhic : HIMC;Conversion, Sentence: DWORD;msgPeekResult : TMsg;beginResult := False;if hWindow = 0 then hWindow := GetFocus;if hWindow = 0 then Exit;// 切换成中文输入法if not ImmIsIME(GetKeyboardLayout(0)) thenImmSimulateHotKey(hWindow, IME_THOTKEY_IME_NONIME_TOGGLE);while PeekMessage(msgPeekResult, hWindow, 0, 0, PM_REMOVE) dobeginTranslateMessage(msgPeekResult);DispatchMessage(msgPeekResult);end;// 转换成半/全角输入模式hic := ImmGetContext(hWindow);if hIC = 0 then Exit;tryif not ImmGetConversionStatus(hIc, Conversion, Sentence) then Exit;if bToFullShape thenConversion := Conversion or IME_CMODE_FULLSHAPEelseConversion := Conversion and (not IME_CMODE_FULLSHAPE);if not ImmSetConversionStatus(hic, Conversion, Sentence) then Exit;Result := True;finallyImmReleaseContext(hWindow, hic);end;end; { of ImeFullShape }// --------------------------------------------------// 送入一段字符串到指定的窗口// 例如: SendDBCSString(Edit1.Handle, '测试');//// 若第一个自变量为零, 则送往目前作用中的控件// 例:// Edit1.SetFocus;// SendDBCSString(0, '测试');// --------------------------------------------------procedure SendDBCSString(hFocus: HWND; const sSend: string);varhActiveControl : HWND;i : integer;ch : byte;beginif hFocus = 0 then hFocus := GetFocus;if hFocus = 0 then Exit;i := 1;while i <= Length(sSend) dobeginch := byte(sSend[i]);// SendMessage(hFocus, WM_CHAR, ch, 0); // 这样子不行if Windows.IsDBCSLeadByte(ch) thenbeginInc(i);SendMessage(hFocus, WM_IME_CHAR, MakeWord(byte(sSend[i]), ch), 0);endelseSendMessage(hFocus, WM_IME_CHAR, word(ch), 0);Inc(i);end;end; { of SendDBCSString }// --------------------------------------------------// 取得目前的拆字字根////// --------------------------------------------------function GetImeCompositonString(hWindow: HWND): string;varhIC : HIMC;pBuf : pchar;dwBufLen : DWORD;beginResult := '';hIC := ImmGetContext(hWindow); // 取得目前 thread 的 input contextif hIC = 0 then Exit;// 查一下 Buffer 需要多大的内存才能容纳dwBufLen := ImmGetCompositionString(hIC, GCS_COMPSTR, nil, 0);if dwBufLen <= 0 then Exit;tryGetMem(pBuf, dwBufLen + 1); // 配置内存
      

  2.   

    接上面if ImmGetCompositionString(hIC, GCS_COMPSTR, pBuf, dwBufLen) > 0 thenResult := string(StrLCopy(pBuf, pBuf, dwBufLen));finallyFreeMem(pBuf, dwBufLen + 1);ImmReleaseContext(hWindow, hIC);end;end;// --------------------------------------------------// 取得拆字结果////// --------------------------------------------------function GetImeCompositonResult(hWindow: HWND): string;varhIC : HIMC;pBuf : pchar;dwBufLen : DWORD;beginResult := '';hIC := ImmGetContext(hWindow); // 取得目前 thread 的 input contextif hIC = 0 then Exit;// 查一下 Buffer 需要多大的内存才能容纳dwBufLen := ImmGetCompositionString(hIC, GCS_RESULTSTR, nil, 0);if dwBufLen <= 0 then Exit;tryGetMem(pBuf, dwBufLen + 1); // 配置内存if ImmGetCompositionString(hIC, GCS_RESULTSTR, pBuf, dwBufLen) > 0 thenResult := string(StrLCopy(pBuf, pBuf, dwBufLen));// lblComposition.Caption := StrLCopy(pBuf, pBuf, dwBufLen);finallyFreeMem(pBuf, dwBufLen + 1);ImmReleaseContext(hWindow, hIC);end;end;// --------------------------------------------------// 取消某次的组字过程////// --------------------------------------------------procedure CancelComposition(hWindow: THandle);varhIc : HIMC;beginif hWindow = 0 then hWindow := GetFocus;if hWindow = 0 then Exit;hIc := ImmGetContext(hWindow);if hIc <> 0 then ImmNotifyIme(hIc, NI_COMPOSITIONSTR, CPS_CANCEL, 0);ImmReleaseContext(hWindow, hIc);end;// --------------------------------------------------// 设定组字字根//// SetImeCompositonString(0, '金戈戈');// --------------------------------------------------procedure SetImeCompositonString(hWindow: THandle; const sCompStr: string);varhIc : HIMC;beginif hWindow = 0 then hWindow := GetFocus;if hWindow = 0 then Exit;hIc := ImmGetContext(hWindow);ImmSetCompositionString(hIc, SCS_SETSTR,pchar(sCompStr), Length(sCompStr), nil, 0);ImmReleaseContext(hWindow, hIc);end;function ShowSoftKeyboard(hWindow: HWND; bShowIt: BOOL): BOOL;varhic : HIMC;Conversion, Sentence: DWORD;msgPeekResult : TMsg;beginResult := False;if hWindow = 0 then hWindow := GetFocus;if hWindow = 0 then Exit;// 切换成中文输入法if not ImmIsIME(GetKeyboardLayout(0)) thenImmSimulateHotKey(hWindow, IME_THOTKEY_IME_NONIME_TOGGLE);while PeekMessage(msgPeekResult, hWindow, 0, 0, PM_REMOVE) dobeginTranslateMessage(msgPeekResult);DispatchMessage(msgPeekResult);end;// 要不要显示屏幕小键盘hic := ImmGetContext(hWindow);if hIC = 0 then Exit;tryif not ImmGetConversionStatus(hIc, Conversion, Sentence) then Exit;if bShowIt thenConversion := Conversion or IME_CMODE_SOFTKBDelseConversion := Conversion and (not IME_CMODE_SOFTKBD);if not ImmSetConversionStatus(hic, Conversion, Sentence) then Exit;Result := True;finallyImmReleaseContext(hWindow, hic);end;end; { of ShowSoftKeyboard }// --------------------------------------------------// 显示某一输入法的设定对话盒////// --------------------------------------------------function ShowIMEConfigDialog(hKB: HKL): BOOL;begin// 显示某一输入法的设定对话盒Result := ImmConfigureIME(hKb, 0, IME_CONFIG_GENERAL, nil);end;// --------------------------------------------------// 要不要相关字词功能////// --------------------------------------------------function PhrasePredict(hWindow: HWND; bPredict: BOOL): BOOL;varhic : HIMC;Conversion, Sentence: DWORD;msgPeekResult : TMsg;beginResult := False;if hWindow = 0 then hWindow := GetFocus;if hWindow = 0 then Exit;// 切换成中文输入法if not ImmIsIME(GetKeyboardLayout(0)) thenImmSimulateHotKey(hWindow, IME_THOTKEY_IME_NONIME_TOGGLE);while PeekMessage(msgPeekResult, hWindow, 0, 0, PM_REMOVE) dobeginTranslateMessage(msgPeekResult);DispatchMessage(msgPeekResult);end;// 要不要相关字词功能hic := ImmGetContext(hWindow);if hIC = 0 then Exit;tryif not ImmGetConversionStatus(hIc, Conversion, Sentence) then Exit;if bPredict thenSentence := Sentence or IME_SMODE_PHRASEPREDICTelseSentence := Sentence and (not IME_SMODE_PHRASEPREDICT);if not ImmSetConversionStatus(hic, Conversion, Sentence) then Exit;Result := True;finallyImmReleaseContext(hWindow, hic);end;end; { of PhrasePredict }// --------------------------------------------------// 查询某字的组字字根////// --------------------------------------------------function QueryCompStr(hKB: HKL; const sChinese: AnsiString): string;vardwGCL : DWORD;szBuffer : array[0..254] of char;iMaxKey, iStart, i: integer;beginResult := '';iMaxKey := ImmEscape(hKB, 0, IME_ESC_MAX_KEY, nil);if iMaxKey <= 0 then exit;// 看看这个输入法是否支持 Reverse Conversion 功能// 同时, 侦测需要多大的空间容纳取得的信息// comment: 下次修改时可以改成动态配置内存的方式dwGCL := ImmGetConversionList(hKB,0,pchar(sChinese),nil,0,GCL_REVERSECONVERSION);if dwGCL <= 0 then Exit; // 该输入法不支持 Reverse Conversion 功能// 取得组字字根信息, dwGCL 的值必须以上次呼叫 ImmGetConversionList// 传回值代入dwGCL := ImmGetConversionList(hKB,0,pchar(sChinese),@szBuffer,dwGCL,GCL_REVERSECONVERSION);if dwGCL > 0 thenbegin// 为什么是 24?{TCandidateList = recorddwSize: DWORD;dwStyle: DWORD;dwCount: DWORD;dwSelection: DWORD;dwPageStart: DWORD;dwPageSize: DWORD; 24-th bytedwOffset: array[1..1] of DWORD;end;}iStart := byte(szBuffer[24]);for i := iStart to iStart + iMaxKey * 2 doAppendStr(Result, szBuffer[i]);end;end;// --------------------------------------------------// { TImeUIWindow }//// --------------------------------------------------constructor TImeUIWindow.Create(AOwner: TComponent);begininherited Create(AOwner);// Color := $80FFFF;Color := clSilver;with Canvas dobeginFont.Name := '细明体';Font.Size := 12;Brush.Style := bsClear;end;end;procedure TImeUIWindow.CreateParams(var Params: TCreateParams);begininherited CreateParams(Params);with Params dobegin// Style := WS_POPUP or WS_BORDER or WS_DISABLED;Style := WS_POPUP or WS_DISABLED;WindowClass.Style := WindowClass.Style or CS_SAVEBITS;if NewStyleControls then ExStyle := WS_EX_TOOLWINDOW;end;end;procedure TImeUIWindow.Paint;varrtText, R : TRect;beginrtText := ClientRect;Inc(rtText.Left, 5);Inc(rtText.Top, 5);Canvas.Font.Color := clGray;DrawText(Canvas.Handle, PChar(Caption), -1, rtText, DT_LEFT or DT_NOPREFIX orDT_WORDBREAK);rtText := ClientRect;Inc(rtText.Left, 4);Inc(rtText.Top, 4);Canvas.Font.Color := clWhite;DrawText(Canvas.Handle, PChar(Caption), -1, rtText, DT_LEFT or DT_NOPREFIX orDT_WORDBREAK);R := ClientRect;Canvas.Pen.Color := clGray;Canvas.Rectangle(R.Left + 2, R.Top + 2, R.Right, R.Bottom);Canvas.Pen.Color := clWhite;Canvas.Rectangle(R.Left + 1, R.Top + 1, R.Right - 1, R.Bottom - 1);end;procedure TImeUIWindow.CMTextChanged(var Message: TMessage);begininherited;Width := Canvas.TextWidth(Caption) + 9;Height := Canvas.TextHeight(Caption) + 9;end;procedure TImeUIWindow.ShowComposition(ptWhere: TPoint; const sHint: string);beginCaption := sHint;if ptWhere.Y + Height > Screen.Height thenptWhere.Y := Screen.Height - Height;if ptWhere.X + Width > Screen.Width thenptWhere.X := Screen.Width - Width;SetWindowPos(Handle, HWND_TOPMOST, ptWhere.X, ptWhere.Y, 0,0, SWP_SHOWWINDOW or SWP_NOACTIVATE or SWP_NOSIZE);end;end. 
      

  3.   

    var tt:hkl;
    begin
    tt:=loadkeyboardlayout('E0010804',klf_activate);
    activatekeyboardlayout(tt,0);
    WIN2000+D6下已测试通过
    在注册表的KEYBOARDLAYOUTS查找输入法对应的编码
      

  4.   

    我认为最简单的办法是模拟键盘事件:Ctrl+Space
      

  5.   

    如果不用上面的建议,可以看看这段:
    许多Windows应用程序的中西文录入界面中,中西文的录入需要反复切换汉字
    输入法,这样使用起来非常麻烦,下面来介绍一种比较简便的解决方法。本文的
    程序设计环境为Delphi Client/Server Suit Ver 3.0(以下简称Delphi 3.0)和
    中文Windows 95。 
      1.Delphi下的Imename、Imemode属性 
      在Delphi 3.0中的Tedit、Tmemo、TmaskEdit等编辑元件在应用程序中经常使
    用,这三种元件都具有ImeName、ImeMode属性。其中ImeName属性是输入法名称,
    在对象观察器中对应一个包括当前系统中所有汉字输入法的下拉组合框;ImeMod
    e属性是输入法模式,在对象观察器中也对应一个下拉组合框,组合框中包含imC
    lose、imOpen、imChinese、imDontCare、imSAlpha、imAlpha六项内容。 
      imClose 表示输入法处于关闭状态; 
      ImOpen 表示输入法处于打开状态; 
      ImChinese 表示处于中文输入法状态; 
      ImDontCare 表示若输入法处于关闭状态则打开最近一次使用过的输入法; 
      ImSAlpha 表示输入处于半角状态; 
      ImAlpha 表示输入处于全角状态。 
      2.Delphi下汉字输入法的编程 
      在Delphi 3.0中,中西文录入界面中涉及到的输入元件都具有ImeName、Ime
    Mode属性。在设计录入界面表单时,对其中每一个元件的这两种属性赋值,系统
    就可以在元件获得焦点时自动打开或关闭所设定的汉字输入法。但是对于用户来
    说,这种编程方法一点灵活性也没有。若系统所设定的输入法不是用户所喜欢的,那么只好再通过Windows 95的输入法选择器重新选择。其实,通过在Form下放
    置一个标签及一个下拉组合框的方法就可以灵活地解决这个问题了。本文示例的
    Form中共放置了四个Label、两个Edit、一个ComboBox、一个Memo及一个Button,
    下面对这个示例作个说明。 
      (1)在Delphi中选择File | New Application菜单项生成一个新的应用程序,
    设定新窗体Form1的属性为: 
      Caption=输入法编程示例; 
      (2)在Form1中添加标签Label1、Label2、Label3及编辑框Edit1、Edit2、Me
    mo1,设定其属性为: 
      Label1.Caption=中文输入编辑框 
      Label1.Font.Size=12 
      Label2.Caption= 西文输入编辑框 
      Label2.Font.Size=12 
      Label3.Caption= 中文多行文本编辑器 
      Label3.Font.Size=12 
      Edit1.ImeMode=ImOpen 
      Edit2.ImeMode=ImDontCare(缺省值) 
      Memo1.ImeMode=ImOpen 
      编程时,一般把输入西文或以西文为主的元件的ImeMode属性设为缺省值;而
    把输入中文或以中文为主的元件的ImeMode属性设为ImOpen;ImeName属性值则在
    程序运行时由用户设定。这个方法的灵活性就在于此。另外,还需要把Edit1.Te
    xt、Edit2.Text、Memo1.Lines的值设为空。 
      (3)在Form1中添加一个标签Label4,设定其属性为: 
      Caption = 选择最喜欢的输入法 
      Font.Size=12 
      Font.Color=红色 
      (4)在Form1中添加一个下拉组合框ComboBox1,在对象观察器Object Inpect
    or中选择Events选项卡,双击OnDropDown,对此事件进行编程,其代码如下: 
      ComboBox1.Items.CommaText:=Screen.Imes.CommaText; 
      上面这个语句可以将中文Windows 95中安装的汉字输入法添加到下拉组合框
    中,它巧妙地运用了TScreen类的Imes特性,而Imes特性本碛质且桓鯰string类,其属性Commatext包含了Windows 95已安装的汉字输入法,可以将其直接赋值给
    ComboBox1的相应属性。如果直接编辑ComboBox1的属性Items来添加汉字输入法名
    称,则会在应用程序发布时,因用户机器汉字输入法的不确定性造成应用程序的
    不通用性。 
      在对象观察器中双击onExit事件,对此事件进行编程,代码如下: 
      Edit1.ImeName:=ComboBox1.Text; 
      Memo1.ImeName:=ComboBox1.Text; 
      (5)在Form1中添加一个命令按钮Button1,设置其属性为: 
      Caption=退出 
      Font.Size=12 
      双击此命令按钮,对Click事件进行编程,代码如下: 
      Close; 
      至此,整个示例的程序设计过程就完成了,保存此应用程序及表单,再进行
    编译、运行,运行后其界面如图所示。 
      3.汉字输入法的使用 
      首先在下拉组合框中选择你所喜欢的汉字输入法,将光标移到中文输入编辑
    框中就会发现所选的汉字输入法已自动出现在屏幕上;再将光标移到西文输入编
    辑框中,汉字输入法就会自动关闭;如果将光标移到中文多行文本编辑框中,则
    已选中汉字输入法又自动出现了。 
      从上面的程序中可以得出,在应用程序的录入界面中,设置一个选择输入法
    的下拉组合框,并让其控制录入界面中所有可输入项的ImeName属性,既可以做到
    在中西文录入过程中不必进行录入法的来回切换,还可以做到让用户选择自己最
    喜欢的汉字输入法,而且这样的录入界面对于用户来说也是非常友好、方便、快
    捷的