Combobox的问题(100分)

  • 主题发起人 猎手1号
  • 开始时间

猎手1号

Unregistered / Unconfirmed
GUEST, unregistred user!
如果输入的内容不在items中,则添加到items中。
问题是如何判断。同时要求只录入一条项目的前几位,就能定位到该项目(当然droppdown
是设为true的),并且认为是在items中的。
各位有何高招?
 
if Combobox.items.indexof(Combobox.text)-1 then
Combobox.items.add(Combobox.text);

对于你想实现类似IE地址栏的自动完成的效果
下面有好几种方案,你可以试试

1)unit CompletingComboBox;

interface

uses
Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
StdCtrls;

type
TCompletingComboBox = class(TComboBox)
private
FTextCompletion: Boolean;
function GetTextCompletion: Boolean;
procedure SetTextCompletion(const Value: Boolean);
protected
// override the WndProc() so that we can trap KeyUp events.
procedure ComboWndProc(var Message: TMessage; ComboWnd: HWnd;
ComboProc: Pointer); override;
public
{ Public declarations }
published
property TextCompletion: Boolean read GetTextCompletion write SetTextCompletion;
end;

procedure Register;

implementation

procedure Register;
begin
RegisterComponents('Standard', [TCompletingComboBox]);
end;

{ TCompletingComboBox }

function TCompletingComboBox.GetTextCompletion: Boolean;
begin
Result := fTextCompletion;
end;

procedure TCompletingComboBox.SetTextCompletion(const Value: Boolean);
begin
fTextCompletion := Value;
end;

procedure TCompletingComboBox.ComboWndProc(var Message: TMessage; ComboWnd: HWnd;
ComboProc: Pointer);
var
rc, len: Integer;
begin
inherited;
case Message.Msg of
WM_KEYUP:
begin
// test to see if its a character that should not be processed.
if (Message.WParam <> 8) and (Message.WParam <> VK_DELETE) and
(Message.WParam <> VK_SHIFT) and (FTextCompletion = True) then
begin
// Use CB_FINDSTRING to locate the string in the Items property
rc := Perform(CB_FINDSTRING, -1, Integer(PChar(Caption)));
// if its in there then add the new string to the Text and
// select the portion that wasn't typed in by the user
if rc <> CB_ERR then
begin
// store the length of the current string
len := Length(Text);

// set the new string
ItemIndex := rc;

// highlight the rest of the text that was added.
SelStart := len;
SelLength := Length(Text) - len;

// return 0 to signify that the message has been handled.
Message.Result := 0;
end;
end;
end;
end; // case
end;

end.
*************************
2)Combobox的自动完成
在Combobox的OnChange或者Key事件中,写如下代码,注意,没有处理删除的情况,请自己完成。
procedure TForm1.ComboBox1Change(Sender: TObject);
var
a:integer;
Old:string;
begin
a:=-1;
Old :=ComboBox1.Text;
sendmessage(combobox1.handle,CB_SHOWDROPDOWN,1,0);
a:=SendMessage(ComboBox1.Handle, CB_SELECTSTRING,integer(@a),integer(pchar(ComboBox1.Text)));
ComboBox1.SelStart:=Length(Old);
ComboBox1.SelLength:=Length(ComboBox1.Text)-Length(Old);
ComboBox1.ItemIndex:=a;
end;
***********
3)

unit unit1
....
private
selectitem : boolean;
....

procedure TForm1.ComboBox1Change(Sender: TObject);
var
sinput, sselected : string;
i, j : integer;
begin
j := 0;
if not selectitem then
begin
selectitem := true;
exit;
end;
sinput := copy(combobox1.text, 1, combobox1.SelStart);
for i := 0 to combobox1.items.count - 1 do
if copy(combobox1.items, 1, length(sinput)) = sinput then
begin
if j = 0 then sselected := combobox1.items;
j := j + 1;
end;
if j > 0 then combobox1.Text := sselected
else combobox1.Text := sinput;
combobox1.SelStart := length(sinput);
combobox1.SelLength := length(combobox1.text) - length(sinput);
end;

procedure TForm1.FormClose(Sender: TObject; var Action: TCloseAction);
begin
application.Terminate
end;

procedure TForm1.ComboBox1KeyDown(Sender: TObject; var Key: Word;
Shift: TShiftState);
begin
if key = 8 then selectitem := false;
end;

procedure TForm1.FormShow(Sender: TObject);
begin
selectitem := true;
end;

end.

4)-----------------------------------------------------------------------

////////放在TForm1.ComboBox1KeyUp用
function ZsComboBoxVisualInput(mComboBox: TComboBox;
mCase: Boolean = True): Boolean; { ComboBox可视化输入 }
var
I, T: Integer;
begin
Result := False;
if Assigned(mComboBox) then
with mComboBox do for I := 0 to (Items.Count) do
if (Pos(Text, Items) = 1) and (Text <> Items) then
begin
T := Length(Text);
Text := Items;
SelStart := T;
SelLength := Length(Items) - T;
Result := True;
Break;
end
else if not (mCase) and (Pos(UpperCase(Text), UpperCase(Items)) = 1) and
(UpperCase(Text) <> UpperCase(Items)) then
begin
T := Length(Text);
Text := Items;
SelStart := T;
SelLength := Length(Items) - T;
Result := True;
Break;
end
end; { ZsComboBoxVisualInput }
 
if Combobox.items.indexof(Combobox.text)-1 then
Combobox.items.add(Combobox.text);
if后面不是一个逻辑判断表达式,应怎么改?
 
procedure TForm1.ComboBox1KeyDown(Sender: TObject; var Key: Word;
Shift: TShiftState);
var
bExist:boolean;
szMessage:string;
i:integer;
begin
if key=VK_RETURN then
begin
bExist:=False;
for i:=0 to combobox1.Items.Count do
begin
if trim(combobox1.Text)<>combobox1.Items then continue
else
begin
bExist:=True;
break;
end;
end;
if (bExist=False) and (trim(ComboBox1.Text)<>'') then
begin
szMessage:='是否添加'+trim(ComboBox1.Text)+'?';
if application.messagebox(pchar(szMessage),'添加',MB_OKCANCEL + MB_DEFBUTTON1 + MB_ICONQUESTION ) = IDOK then
ComboBox1.Items.Append(trim(combobox1.Text));
end;
end;
end;
 
to 猎手1号:
if Combobox.items.indexof(Combobox.text)-1 then
Combobox.items.add(Combobox.text);
if后面不是一个逻辑判断表达式,应怎么改?
不是-1而是=-1
 
惊弓之亮的根本无法解决问题,可能没有看清楚题目。
vine的那一句改为
if (Combobox1.items.indexof(Combobox1.text)=-1) and (trim(Combobox1.text)<>'') then
Combobox1.items.add(Combobox1.text);
并且将其放在onExit中,另外在onEnter中加一句Combobox1.DroppedDown:=true
在onExit中另加一句Combobox1.DroppedDown:=false;
并在onKeypress中加一句if key=#13 then selectNext(ActiveControl,true,true);
才勉强解决了问题。之所以说勉强,是因为combobox获得焦点时,偶尔并不会下拉,这样
在按TAB键时也会离开组合框,并且不会根据输入的一条项目的前几个字符自动选该定条目,
而认为是新的条目。同时,会下拉时,按TAB没有反应,不能象回车键一样先选定条目,再
移到下一控件。
各位请看看还有没有更好的解决办法。
 
又发现一个问题,如果Combobox是第一个控件,也就是说form一打开,它是第一个获得焦
点的,那么无论在form 的Create还是show中都无法使其DroppedDown:=true,因此在只输
入一个条目的前几个字符时,无法自动选定该条目。
 
又仔细看了一下,Vine的第3个方案也能解决问题,只不过用回车键时又不能跳到下一个
控件了。
 
看错了,按第3个方案,在keydown事件中加if key=13 then selectNext(ActiveControl,true,true)
就可以解决了,刚才把key=8当成了回车。
多谢Vine。
 
我的妈呀,怎么给错分了。只好再开一帖了(lid=1413493)。vine请到那里去领分吧。
 
顶部