function Tfrmaddry.GetPYIndexChar(hzchar:string):char;//HZCHAR是单个汉字,
begin
case WORD(hzchar[1]) shl 8 + WORD(hzchar[2]) of
$B0A1..$B0C4:result:='A';
$B0C5..$B2C0:result:='B';
$B2C1..$B4ED:result:='C';
$B4EE..$B6E9:result:='D';
$B6EA..$B7A1:result:='E';
$B7A2..$B8C0:result:='F';
$B8C1..$B9FD:result:='G';
$B9FE..$BBF6:result:='H';
$BBF7..$BFA5:result:='J';
$BFA6..$C0AB:result:='K';
$C0AC..$C2E7:result:='L';
$C2E8..$C4C2:result:='M';
$C4C3..$C5B5:result:='N';
$C5B6..$C5BD:result:='O';
$C5BE..$C6D9:result:='P';
$C6DA..$C8BA:result:='Q';
$C8BB..$C8F5:result:='R';
$C8F6..$CBF9:result:='S';
$CBFA..$CDD9:result:='T';
$CDDA..$CEF3:result:='W';
$CEF4..$D188:result:='X';
$D1B9..$D4D0:result:='Y';
$D4D1..$D7F9:result:='Z';
else
result:=char(0);
end;
end;
begin
case WORD(hzchar[1]) shl 8 + WORD(hzchar[2]) of
$B0A1..$B0C4:result:='A';
$B0C5..$B2C0:result:='B';
$B2C1..$B4ED:result:='C';
$B4EE..$B6E9:result:='D';
$B6EA..$B7A1:result:='E';
$B7A2..$B8C0:result:='F';
$B8C1..$B9FD:result:='G';
$B9FE..$BBF6:result:='H';
$BBF7..$BFA5:result:='J';
$BFA6..$C0AB:result:='K';
$C0AC..$C2E7:result:='L';
$C2E8..$C4C2:result:='M';
$C4C3..$C5B5:result:='N';
$C5B6..$C5BD:result:='O';
$C5BE..$C6D9:result:='P';
$C6DA..$C8BA:result:='Q';
$C8BB..$C8F5:result:='R';
$C8F6..$CBF9:result:='S';
$CBFA..$CDD9:result:='T';
$CDDA..$CEF3:result:='W';
$CEF4..$D188:result:='X';
$D1B9..$D4D0:result:='Y';
$D4D1..$D7F9:result:='Z';
else
result:=char(0);
end;
end;
这里有个关于它的使用方法:按拼音检索
type
TForm1 = class(TForm)
Edit1: TEdit;
ListBox1: TListBox;
ListBox2: TListBox;
Label2: TLabel;
Label1: TLabel;
procedure Edit1Change(Sender: TObject);
private
{ Private declarations }
public
{ Public declarations }
end;var
Form1: TForm1;implementationfunction GetCharInd(zzchar:string):char;
begin
case WORD(zzchar[1]) shl 8+WORD(zzchar[2]) of
$B0A1..$B0C4:result:='A';
$B0C5..$B2C0:result:='B';
$B2C1..$B4ED:result:='C';
$B4EE..$B6E9:result:='D';
$B6EA..$B7A1:result:='E';
$B7A2..$B8C0:result:='F';
$B8C1..$B9FD:result:='G';
$B9FE..$BBF6:result:='H';
$BBF7..$BFA5:result:='J';
$BFA6..$C0AB:result:='K';
$C0AC..$C2E7:result:='L';
$C2E8..$C4C2:result:='M';
$C4C3..$C5B5:result:='N';
$C5B6..$C5BD:result:='O';
$C5BE..$C6D9:result:='P';
$C6DA..$C8BA:result:='Q';
$C8BB..$C8F5:result:='R';
$C8F6..$CBF9:result:='S';
$CBFA..$CDD9:result:='T';
$CDDA..$CEF3:result:='W';
$CEF4..$D188:result:='X';
$D1B9..$D4D0:result:='Y';
$D4D1..$D7F9:result:='Z';
else
result:=#0;
end;
end;function DisByStrInd(ListBoxStr:TListBox;StrInd:string):string;
label NotFound;
var
zzchar :string;
i,j:integer;
begin
for i:=0 to ListBoxStr.Items.Count-1 do
begin
for j:=1 to Length(StrInd) do
begin
zzchar:=ListBoxStr.Items[i][2*j-1]+ListBoxStr.Items[i][2*j];
if (StrInd[j]<>'?') and (UpperCase(StrInd[j])<>GetCharInd(zzchar))
then goto NotFound;
end;
if result='' then result:=ListBoxStr.Items[i]
else result:=result+#13+ListBoxStr.Items[i];
NotFound:
end;
end;{$R *.DFM}procedure TForm1.Edit1Change(Sender: TObject);
var
SelStr:string;
begin
SelStr:='';
ListBox2.Items.Text:=DisByStrInd(listBox1,Edit1.Text);
end;end.
var
I: Integer;
const
cMinGBCByte = 161; //最小国标字节
cMaxGBCByte = 254; //最大国标字节 function f(mStr): Integer;
begin
Result := (Ord(mStr[1]) - cMinGBCByte + 1) * 100 +
Ord(mStr[2]) - cMinGBCByte + 1
end;
begin
I := f(mStr); //区位码//如果mStr不是一个汉字我可不管
case I of
1601..1636:
Result := 'A';
1637..1832:
Result := 'B';
1833..2078:
Result := 'C';
2079..2273:
Result := 'D';
2274..2301:
Result := 'E';
2302..2432:
Result := 'F';
2433..2593:
Result := 'G';
2594.. 2786:
Result := 'H';
2787..3105:
Result := 'J';
3106..3211:
Result := 'K';
3212..3471:
Result := 'L';
3472..3634:
Result := 'M';
3635..3721:
Result := 'N';
3722..3729:
Result := 'O';
3730..3857:
Result := 'P';
3858..4026:
Result := 'Q';
4027..4085:
Result := 'R';
4086..4389:
Result := 'S';
4390..4557:
Result := 'T';
4558..4683:
Result := 'W';
4694..4924:
Result := 'X';
4925..5248:
Result := 'Y';
5249..5589:
Result := 'Z';
else
Result := '_';
end;
end; { ZsWordStrCnToShort }
likepc.51.net
首先,二级字库中的汉字是按部首笔画排列的。(二级字库?可能很多人没听说过吧。)
其次,如果是在gbk标准中扩展的汉字,更没这么简单的规律可循。
case I of
//...
2594 .. 2786, 8032{鹄}: //自己加
Result := 'H';
//...
else
Result := '_';
end;最好的方法是从[全拼]输入法里起
case I of
//...
2594 .. 2786, 8032{鹄}: //自己加
Result := 'H';
//...
else
Result := '_';
end;最好的方法是从[全拼]输入法里取
如果是二级字库就自己加一下
//........
2594..2786, 8032{鹄}:
Result := 'H';
//........
当然这样会很麻烦,最好的方法还是从[全拼]输入法中取
慢点发火,告诉大家更好更妙的做法。
要真正处理汉字排序问题,还是应该用win2000。
是这样的,win2000对多种语言的支持非常好了。比如就支持汉字的正确排序。在控制面版中的区域设置中设置好好排序的依据,比如说是拼音还是笔画排序。然后,只要调用其标准的api函数比如lstrcmp,是能返回正确的判断结果的。这包括对原gb2312的一级字库、二级字库的正确处理,对gbk字符集的正确处理。你再也不用为内码排列与需要的次序不一样而担心。
如果要取汉字的拼音首字母,那也很简单,作个数组,记录26个字母对应的第一个汉字,然后将需要的汉字与这26个汉字比较就可以了。
首先,修改控制面版中的汉字排序设置后,需要重新登录才能起作用。
其次,delphi将lstrcmp等函数申明在windows.pas文件中,你可直接调用。
需要功能更多的比较函数,可以使用CompareString
无须输入法支持,能自动识别单字节字符。不是用“内建字库+比较汉字”的方法,速度极快,有详细说明。想要可e-mail我。
有兴趣的话可以e-mail给我讨论。多音字一般返回“较常用”的那个(没有办法的办法?),再说了,
一般反查拼音、五笔多用于数据库汉字字段的查询,只要首码即可,
多音字问题不算太碍事,如“觉”(jiao、jue)首码一样。上面提到的dll文件即是专为此而做的,可以传入汉字字符串(夹杂英文、数字、全角字符都行,可以选择是否过滤掉),返回拼音(完整拼音)、五笔首码串(串长度也可设定),但没有特别地处理多音字,也不太好处理。
如果有源码,我很愿意得到一份:[email protected]
Name=全拼
MaxCodes=12
MaxElement=1
UsedCodes=abcdefghijklmnopqrstuvwxyz
WildChar=?
NumRules=3
[Rule]
ca4=p10+p20+p30+p40
ce2=p10+p20
ce3=p10+p20+p30
[Text]
啊a
阿a
呵a he
吖a
嗄a
腌a yan
锕a
錒a ke
阿爸aba
阿昌achang
把\windows\system\winpy.mb逆转换成.txt文件,格式如上,遍历这个文件,其实就是实现自己的拼音输入法,用拼音查汉字,或汉字查拼音都行,获的头字母简直太简单了。
\windows\system\imggen.exe 进行转换
在win2000中,调用api函数lstrcmp,什么问题都解决了。不管你是gb2312中的一级、二级字库,还是gbk字库,简体,繁体,都能正确排序,而且还可以由用户选择是按拼音还是笔画排序。
功能强大、完备,实现起来又异常简单,为啥不用?
以前的贴子:
function QueryCompStr(hKB: HKL; const sChinese: AnsiString): string;
var
dwGCL: DWORD;
szBuffer: array[0..254] of char;
iMaxKey, iStart, i: integer;
begin
Result := '';
iMaxKey := ImmEscape(hKB, 0, IME_ESC_MAX_KEY, nil);
if iMaxKey <= 0 then exit; dwGCL := ImmGetConversionList(hKB,0,pchar(sChinese),nil,0,GCL_REVERSECONVERSION);
if dwGCL <= 0 then Exit; dwGCL := ImmGetConversionList(hKB,0,pchar(sChinese),@szBuffer,dwGCL,GCL_REVERSECONVERSION); if dwGCL > 0 then
begin
iStart := byte(szBuffer[24]);
for i := iStart to iStart + iMaxKey * 2 do
AppendStr(Result, szBuffer[i]);
end;
end;但是上面的程序有问题,解决如下: ------------------------------------------------------------
在QueryCompStr中做如下修改就好(test in:win98 se+delphi5)
dwGCL := dwGCL+sizeof(TCandidateList); //add this line then ok,编码查询功能只支持单字,不支持词组。
dwGCL := ImmGetConversionList(hKB,0,pchar(sChinese),@szBuffer,dwGCL,GCL_REVERSECONVERSION);
----------------------------------------------------------------
按照pqx给我的答案,问题已解决部分,但用这种方法并不是所有的输入法都能查出,而用Windows自已的编码查询功能(右击输入法提示条,设置->编码查询,选择相应的输入法)则都能查出来,这是为什么呢?(如"王码五笔4.0"就查不出,而微软的"王码五笔86版"、"王码五笔98版"则都能查到。)
反查编码的的例子可以到 http://www.mildragon.com 的"学习园地"下载。本例是改自台湾钱达智先生的一个例子QRYCOMP(可以在Delphi深度历险中下载)。
*********
var
iHandleCount: integer;
pList: array[1..nHKL_LIST] of HKL;
szImeName: array[0..254] of char;
i: integer;
sFound: string;
begin
lstComposition.Items.Clear;
iHandleCount := GetKeyboardLayoutList(nHKL_LIST, pList);
for i := 1 to iHandleCount do
begin
if ImmEscape(pList[i], 0, IME_ESC_IME_NAME, @szImeName) > 0 then
begin
sFound := QueryCompStr(pList[i], edtExam.Text);
if sFound <> '' then
lstComposition.Items.Add(StrPas(szImeName) + ': ' + sFound);
end;
end;
顺便问一下:要文本文件查找字符时有哪种好得算法?
如果把文本文件作为字符串资源文件。那么在字符串资源文件中又是如何查找字符呢?