我还是把我的关于此问题的文章贴出来,供大家传阅.
不用重启实现输入法顺序调整
朱三元
在很多电脑报刊杂志上刊登过调整输入法顺序的方法,其原理是更改注册表中键盘设置的顺序,无论是手工还是编程来实现,作者在最后还得补充一句:重启后才有效。在当前流行的各种设置软件如:超级兔子魔法设置,优化大师等也都必须重启。难道就不能实现实时调整? 本人经过摸索,掌握了输入法设置的有关特性,实现了实时调整。
实现原理:在Windows系统中,输入法是与键盘布局(keyboard layout)相对应的。(详情请见有关文章)首先,用获取当前所装的键盘布局,放到数组中,将数组中的键盘布局的句柄按要求调整顺序,然后,卸载当前所有的输入法,最后,按调整后的顺序重新装载输入法。
要实现实时调整,须使用到下面的API函数:
1. BOOL UnloadKeyboardLayout( ; //卸载指定的键盘布局;该函数只是将其从键盘列表中删除,并不卸载与之对应的文件,;
; ; HKL hkl // 键盘布局的句柄;
;
;
函数返回:如果成功,返回非0值
2. HKL LoadKeyboardLayout( ;//装载新的键盘布局;
; ; LPCTSTR pwszKLID, // 键盘布局的名称;
; ; UINT Flags // 装载键盘布局的选项;
;
;
函数返回: ;如果成功,返回安装的键盘布局的句柄, 否则返回NULL。
(超级的下一版本应能有此功能,因我已告诉其作者)
下面的源程序在win9x/win2000下编译通过:
unit Unit1;
interface
uses
; Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
; ComCtrls, StdCtrls, Buttons,shellapi,Imm,Registry, ExtCtrls;
CONST nHKL_LIST=20;
type
; LangDescription=record
; ; sID,sCode,sName:string;
; end;
; TLangDescription=array of LangDescription;
; TImeItem = record
; ; MainIndex:Integer;
; ; ImeDescription:string;
; ; KeyBoardLayout:HKL;
; end;
; TImeItemArray=array of TImeItem;
; TForm1 = class(TForm)
; ; ListView1: TListView;
; ; upBitBtn: TBitBtn;
; ; downBitBtn: TBitBtn;
; ; Button1: TButton;
; ; Panel1: TPanel;
; ; procedure FormCreate(Sender: TObject);
; ; procedure ButtonClick(Sender:TObject);
; ; procedure ApplyUpdate(Sender:Tobject);
; ; procedure ListView1SelectItem(Sender: TObject; Item: TListItem; Selected: Boolean);
private
; Function GetLangSet():Boolean;
; Function WriteRegistry():boolean;
; Procedure GetAndDislpayCurrentLangSet;
; procedure FillInListView;
; ; ;{ Private declarations }
public
; ; { Public declarations }
; end;
var
; Form1: TForm1;
; LangSet:TLangDescription;
; TImeItemList:TImeItemArray;
; ImeCounter,CurrentPos:integer;
; ListItem: TListItem;
implementation
{$R *.DFM}
procedure TForm1.FormCreate(Sender: TObject);
begin
; if not GetLangSet() then begin
; ; ShowMessage('Error in accessing Registry.');
; ; Halt;
; end;
; GetAndDislpayCurrentLangSet;
; ListView1.Columns[0].Width := ColumnTextWidth;
; FillinListView;
end;
Function TForm1.GetLangSet():Boolean; //获取系统所支持所所有西文输入法
var
; Reg: TRegistry;
; Val:TStringList;
; i,j,iPos:Integer;
; str1: string;
begin
; Reg:=TRegistry.Create;
; try
; ; Val:=TStringList.Create;
; ; try
; ; ; Reg.RootKey:=HKey_Classes_Root;
; ; ; if not Reg.OpenKey('/MIME/DATABASE/RFC1766',False) then
; ; ; ; result:=false
; ; ; else ;begin
; ; ; ; Reg.GetValueNames(Val);
; ; ; ; SetLength(Langset,Val.Count);
; ; ; ; for i:=0 to Val.Count-1 do ;begin
; ; ; ; ; LangSet
.sID:=val.strings;
; ; ; ; ; str1:=Reg.ReadString(Val.Strings);
; ; ; ; ; LangSet.sCode:=UpCase(str1[1])+LowerCase(str1[2]);
; ; ; ; ; iPos:=AnsiPos(';',str1);
; ; ; ; ; for j:=iPos+1 to length(str1) do LangSet.sName:=LangSet.sName+str1[j];
; ; ; ; end;
; ; ; ; Result:=True;
; ; ; end;
; ; finally
; ; ; Val.Free;
; ; end;
; finally
; ; Reg.Free;
; end;
end;
procedure TForm1.GetAndDislpayCurrentLangSet;
var ;i,j: integer;
; pList: array[0..nHKL_List] of HKL;
; buff: array[0..Max_Path] of char;
; s: string;
begin
; ImeCounter:= GetKeyboardLayoutList(nHKL_LIST, pList);
; Setlength(TImeItemList,ImeCounter);
; for i:=0 to ImeCounter-1 do begin
; ; if ;not ImmIsIME(plist) then ; begin //西文输入法
; ; ; ;Plist:=PList and $ffff;
; ; ; ;for j:=low(LangSet) to high(Langset) do ;if LangSet[j].sID=IntToHex(Plist mod $10000,4) then break;
; ; ; ;s:=LangSet[j].sName;
; ; ; ;end
; ; else begin ;//中文输入法
; ; ; ImmGetDescription(pList, Buff, MAX_PATH);
; ; ; s := string(buff);
; ; end;
; ; with TImeItemList do begin
; ; ; MainIndex:=i;
; ; ; ImeDescription:=s;
; ; ; KeyBoardLayout:=pList;
; ; end;
; end;
end;
procedure TForm1.FillInListView;
var i:integer;
begin
; with ListView1 do
; ; for i:=0 to ImeCounter-1 do begin
; ; ; ; ListItem := Items.Add;
; ; ; ; Listitem.Caption :=TImeItemList.ImeDescription;
; ; end;
end;
procedure TForm1.ButtonClick(Sender:TObject);
var i,step:integer;
begin
;if Sender=upBitBtn then step:=-1 else Step:=1; //代码重用
;If ((CurrentPos<ImeCounter-1) and (step=1)) or ((CurrentPos>0) and (Step=-1)) then begin
; ;for i:=0 to ImeCounter-1 do begin
; ; ; if (TimeItemList.MainIndex=CurrentPos) then
; ; ; ; ; TImeItemList.MainIndex :=TImeItemList.MainIndex +Step
; ; ; else ;if TimeItemList.MainIndex=CurrentPos+Step then
; ; ; ; ; TImeItemList.MainIndex :=TImeItemList.MainIndex -Step
; ; end;
; ; for i:=0 to ImeCounter-1 do begin
; ; ; if TimeItemList.MainIndex=CurrentPos then
; ; ; ; with ;ListView1 do begin
; ; ; ; ; ListItem:=Items.Item[CurrentPos];
; ; ; ; ; ListItem.Caption:=TImeItemList.ImeDescription;
; ; ; ; end
; ; ; else if TimeItemList.MainIndex=CurrentPos+Step then
; ; ; ; ;with ;ListView1 do begin
; ; ; ; ; ListItem:=Items.Item[CurrentPos+Step];
; ; ; ; ; ListItem.Caption:=TImeItemList.ImeDescription;
; ; ; ; ;end;
; ; end;
; ; CurrentPos:=CurrentPos+Step;
; end;
; ListView1.setfocus;
; with ;ListView1 do begin
; ; ; ListItem:=Items.Item[CurrentPos];
; ; ; listItem.selected:=true;
; ; ; ListItem.focused:=true;
; end;
end;
procedure TForm1.ApplyUpdate(Sender:Tobject);
var Kblayout: array [0..8] of char;
; ; i,k: integer;
; ; blModiReg:Boolean;
begin
; if Application.MessageBox('是否保留该配置,以便下次开机继续有效?','提醒:',
; ; ; ; MB_YESNO) = IDYES then blModiReg:=True else blModiReg:=False;
; for i := low(TImeItemList) to High(TImeItemList) do ;// 卸载输入法
; ; UnLoadKeyBoardLayout(TImeItemList.KeyBoardLayout);
; for i := high(TImeItemList) ;downto low(TImeItemList) do begin ;//重新装载输入法
; ; k:=0;
; ; while (TImeItemList[k].MainIndex<>i) and (k<=Imecounter-1)do inc(k);
; ; if k<> ImeCounter then begin
; ; ; strPCopy(Kblayout, inttohex(TImeItemList[k].KeyBoardLayout,8));
; ; ; LoadKeyBoardLayout(Kblayout,KLF_ACTIVATE+KLF_REPLACELANG+KLF_REORDER);
; ; end;
; end;
; if blModiReg then WriteRegistry;
end;
Function TForm1.writeRegistry():boolean;
var Reg: TRegistry;
; ; i,j:Integer;
begin
; Reg:=TRegistry.Create;
; try
; ; ; Reg.RootKey:=HKey_Current_User;
; ; ; i:=0;
; ; ; while ;Reg.OpenKey('/Keyboard Layout/Preload/'+inttostr(i+1),False) do begin
; ; ; ; j:=0;
; ; ; ; while (TImeItemList[j].MainIndex<>i) and (j<=Imecounter-1)do inc(j);
; ; ; ; Reg.writestring('',inttohex(TImeItemList[j].KeyBoardLayout,8));
; ; ; ; inc(i);
; ; ; ; reg.closekey;
; ; ; end;
; ; ; if i=ImeCounter then result:=true else result:=false;
; finally
; ; Reg.Free;
; end;
end;
procedure TForm1.ListView1SelectItem(Sender: TObject; Item: TListItem; Selected: Boolean);
begin
; CurrentPos:=Item.index;
end;
end.