📄 nbcombobox.pas
字号:
unit NBComboBox;
interface
uses
Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
StdCtrls;
type
TExComboBox = class(TComboBox)
private
{ Private declarations }
iPreItemIndex:integer;
strPreKey:string;
stlMixStrs:TStringList; //ComboBox的英文字符与汉字拼音首字符的混合字符串组
iChangeCount:integer; //判断change的次数.
strInput:string; //捕捉ComboBox.style=csDropDownList时输入的字符串
a:integer;
protected
{ Protected declarations }
//冒泡排序
procedure BubbleSort(var stlMixStrings:TStringList);
//得到字符的ASCII码
function GetASCII(str:string):integer;
//把含有中文的字符串转化为含该中文拼音首字符的字符串。
function AllChiToEng(str:string):string;
//得到汉字的拼音首字符
function GetPYIndexChar( hzchar:string):char;
//覆盖父类OnDropDown事件的派遣方法DropDown.
procedure DropDown;override;
//清空用户输入的字符串
procedure Click;override;
//初始化iPreItemIndex跟strPreKey.
procedure DoExit;override;
//用来捕捉用户输入。
procedure KeyPress(var Key: Char); override;
public
{ Public declarations }
constructor Create(AOwner:TComponent);override;
destructor Destroy;override;
published
{ Published declarations }
end;
procedure Register;
implementation
procedure Register;
begin
RegisterComponents('Standard', [TExComboBox]);
end;
constructor TExComboBox.Create(AOwner:TComponent);
begin
inherited Create(AOwner);
//self.Style := csDropDownList;
self.Style := csDropDown;
strInput := '';
iPreItemIndex := 0;
strPreKey := '';
stlMixStrs := TStringlist.Create;
iChangeCount := 0;
end;
procedure TExComboBox.DoExit;
begin
inherited;
iPreItemIndex := 0;
strPreKey := '';
end;
destructor TExComboBox.Destroy;
begin
stlMixStrs.Free;
inherited Destroy;
end;
procedure TExComboBox.BubbleSort(var stlMixStrings:TStringList);
var
i,j,iStrCount:integer;
bNoSwap:boolean; //未交换标志。
strTemp:string;
begin
iStrCount := stlMixStrings.Count;
for i:=0 to (iStrCount-2) do
begin
bNoSwap := true;
//for j:=(iStrCount-2) to i do //pascal无这种语法,要用while.
j:=iStrCount-2;
while j>=i do
begin
if ((stlMixStrings.Strings[j+1])<(stlMixStrings.Strings[j])) then
begin
//妙!!排拼音首字符顺序的同时改变ComboBox的字符串顺序!
strTemp := stlMixStrings.Strings[j+1];
stlMixStrings.Strings[j+1] := stlMixStrings.Strings[j];
stlMixStrings.Strings[j] := strTemp;
//bNoSwap := false;
strTemp := self.Items.Strings[j+1];
self.Items.Strings[j+1] := self.Items.Strings[j];
self.Items.Strings[j] := strTemp;
bNoSwap := false;
end;
j := j-1;
end;
if (bNoSwap) then break;
end;
end;
function TExComboBox.GetASCII(str:string):integer;
begin
if str='a' then result:=97
else if str='b' then result:=98
else if str='c' then result:=99
else if str='d' then result:=100
else if str='e' then result:=101
else if str='f' then result:=102
else if str='g' then result:=103
else if str='h' then result:=104
else if str='i' then result:=105
else if str='j' then result:=106
else if str='k' then result:=107
else if str='l' then result:=108
else if str='m' then result:=109
else if str='n' then result:=110
else if str='o' then result:=111
else if str='p' then result:=112
else if str='q' then result:=113
else if str='r' then result:=114
else if str='s' then result:=115
else if str='t' then result:=116
else if str='u' then result:=117
else if str='v' then result:=118
else if str='w' then result:=119
else if str='x' then result:=120
else if str='y' then result:=121
else if str='z' then result:=122
else if str=' ' then result:=32
else if str='!' then result:=33
else if str='"' then result:=34
else if str='#' then result:=35
else if str='$' then result:=36
else if str='%' then result:=37
else if str='&' then result:=38
else if str='''' then result:=39
else if str='(' then result:=40
else if str=')' then result:=41
else if str='*' then result:=42
else if str='+' then result:=43
else if str=',' then result:=44
else if str='-' then result:=45
else if str='.' then result:=46
else if str='/' then result:=47
else if str='0' then result:=48
else if str='1' then result:=49
else if str='2' then result:=50
else if str='3' then result:=51
else if str='4' then result:=52
else if str='5' then result:=53
else if str='6' then result:=54
else if str='7' then result:=55
else if str='8' then result:=56
else if str='9' then result:=57
else if str=':' then result:=58
else if str=';' then result:=59
else if str='<' then result:=60
else if str='=' then result:=61
else if str='>' then result:=62
else if str='?' then result:=63
else if str='@' then result:=64
else if str='A' then result:=65
else if str='B' then result:=66
else if str='C' then result:=67
else if str='D' then result:=68
else if str='E' then result:=69
else if str='F' then result:=70
else if str='G' then result:=71
else if str='H' then result:=72
else if str='I' then result:=73
else if str='J' then result:=74
else if str='K' then result:=75
else if str='L' then result:=76
else if str='M' then result:=77
else if str='N' then result:=78
else if str='O' then result:=79
else if str='P' then result:=80
else if str='Q' then result:=81
else if str='R' then result:=82
else if str='S' then result:=83
else if str='T' then result:=84
else if str='U' then result:=85
else if str='V' then result:=86
else if str='W' then result:=87
else if str='X' then result:=88
else if str='Y' then result:=89
else if str='Z' then result:=90
else if str='[' then result:=91
else if str='\' then result:=92
else if str=']' then result:=93
else if str='^' then result:=94
else if str='_' then result:=95
else if str='`' then result:=96
else if str='{' then result:=123
else if str='|' then result:=124
else if str='}' then result:=125
else if str='~' then result:=126
else result := -1;
end;
function TExComboBox.AllChiToEng(str:string):string;
var
i,iStrLength:integer;
strPYFirChar:string;
strMixString:string; //包含英文字符跟拼音首字符的字符串
hzChar:string; //汉字字符
begin
strMixString := '';
iStrLength:= Length(str);
i := 1;
while i<= iStrLength do
begin
if (GetASCII(str[i])=-1) then //第i位置是汉字(应该用str1[i],不能用copy(str1,1,1))。
begin
hzChar := str[i]+str[i+1];
strPYFirChar := GetPYIndexChar(hzChar);
strMixString:=strMixString+strPYFirChar;
i := i+2;
end
else if (GetASCII(str[i])<>-1) then //第i位置是英文。
begin
strMixString := strMixString+str[i];
i := i+1;
end;
end;
result := strMixString;
end;
function TExComboBox.GetPYIndexChar( hzchar:string):char;
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;
procedure TExComboBox.DropDown;
var
i:integer;
begin
if iChangeCount=0 then
begin
stlMixStrs := TStringList.Create;
for i:= 0 to self.Items.Count-1 do
begin
stlMixStrs.Add(AllChiToEng(self.items.Strings[i]));
end;
//冒泡排序stlMixStrs的同时调整的combo字符串的顺序
BubbleSort(stlMixStrs);
end;
inc(iChangeCount);
inherited;
end;
procedure TExComboBox.KeyPress(var Key: Char);
var
i,j,CurIndex:integer;
begin
CurIndex := 0;
//先给字符串排顺
if iChangeCount=0 then
begin
stlMixStrs := TStringList.Create;
for i:= 0 to self.Items.Count-1 do
begin
stlMixStrs.Add(AllChiToEng(self.items.Strings[i]));
end;
//冒泡排序stlMixStrs的同时调整的combo字符串的顺序
BubbleSort(stlMixStrs);
end;
inc(iChangeCount);
//搜索匹配字符串
for i:= 0 to self.Items.Count-1 do
begin
if copy(stlMixStrs.Strings[i],1,1)=lowercase(char(Key)) then
begin
if strPreKey=lowercase(char(Key)) then //本次键入字符跟上次相同,处理循环搜索问题。
begin
if i=iPreItemIndex then//搜索上次匹配字符串的下一个匹配字符串。
begin
//查看下一字符串匹配否?
if (i+1)<= self.Items.Count-1 then//禁止下标出界
begin
if copy(stlMixStrs.Strings[i+1],1,1)=lowercase(char(Key)) then//匹配
begin
self.ItemIndex := i+1;
CurIndex := i+1;
//当选中若干匹配字符串的最后一个字符串时,
//如果strPreKey=lowercase(char(Key)),那么
//选中若干匹配字符串的第一个字符串
if i+1=self.Items.Count-1 then //考虑最后一个字符串。
begin
iPreItemIndex := 0;
strPreKey := '';
end
else
begin
iPreItemIndex := i+1;
strPreKey := lowercase(char(Key));
end;
break;
end
else //不匹配。从第一个字符串搜索至i位置。
begin
for j:= 0 to i do
begin
if copy(stlMixStrs.Strings[j],1,1)=lowercase(char(Key)) then
begin
self.ItemIndex := j;
CurIndex :=j;
iPreItemIndex := j;
strPreKey := lowercase(char(Key));
break; //跳出内层循环
end
end;
end;
end;
break; //跳出外层循环。
end;
end
else //本次键入字符跟上次不同。
begin
self.ItemIndex := i;
CurIndex := i;
iPreItemIndex := i;
strPreKey := lowercase(char(Key));
break;
end;
end;
end;
if self.Items.Count > 0 then
self.Text := self.Items.Strings[CurIndex];
Key:=char($0); //重点注意:每次键入字符后要清!!!!!!!!!!
inherited;
end;
procedure TExComboBox.Click;
begin
inherited;
end;
end.
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -