![]() |
| ||
|
|
Новости |
Поиск |
FAQ |
Статьи |
Книги |
Новости VCL
| | Форумы ЧАТ |
Орешник |
|
| |||
| |||
« предыдущая ветвь | форум | следующая ветвь »
Поиск в ListBox [D7, WinXP]
kodov © (2007-03-19 16:22:00)Здравствуйте!
Помогите пожалуйста разобраться с проблемой.
Есть код:
var
i: integer;
flag: boolean;
begin
if personslist.Items.Count=0 then
begin
showmessage('There are no elements to find');
mainform.Show;
end
else if edit1.Text='' then begin
showmessage('Enter something to find');
mainform.Show;
end;
i:=0;
flag:=false;
repeat
if Pos(LowerCase(Edit1.Text),LowerCase(personslist.Items.Strings[i]))<>0 then
begin
personslist.Selected[i]:=true;
n:=i;
flag:=true;
end;
inc(i);
until (i=personslist.Count-1) or (flag=true);
end;
Этот код работает, но когда в списке более 300 элементов,то
поиск подглючивает. Он никак не хочет находить последние несколько элементов.
Заранее спасибо.
Knight (2007-03-21 23:47:00) [21]«Да вы батенька извхащенец» © :)))
kodov (2007-03-21 23:19:00) [22]А вот еще один способ поиска в ListBox.
Ставим на форму Richedit и пишем в создании формы:
richedit1.lines:=listbox1.items;
Затем производим поиск в ricedit с помощью Finddialog.
var
Form1: TForm1;
SPos: Integer;
-------------
procedure TForm1.Button1Click(Sender: TObject);
begin
SPos := RichEdit1.SelStart;
with FindDialog1 do
begin
FindText := RichEdit1.SelText;
Position := Point(Form1.Left, Form1.Top + RichEdit1.Top + RichEdit1.Height);
Options := Options + [frHideUpDown, frHideWholeWord];
Execute;
end;
end;
procedure TForm1.FindDialog1Find(Sender: TObject);
begin
with FindDialog1 do
if frMatchCase in Options then
RichEdit1.SelStart := Pos(FindText, Copy(RichEdit1.Lines.Text, SPos + 1,
Length(RichEdit1.Lines.Text))) + SPos - 1
else
RichEdit1.SelStart := Pos(AnsiLowerCase(FindText),
AnsiLowerCase(Copy(RichEdit1.Lines.Text, SPos + 1, Length(RichEdit1.Lines.Text)))) +
SPos - 1;
if RichEdit1.SelStart >= SPos then
begin
RichEdit1.SelLength := Length(finddialog1.FindText);
SPos := RichEdit1.SelStart + RichEdit1.SelLength + 1;
end
else
if MessageDlg('Текст "' + finddialog1.FindText + '" не найден. Продолжать диалог?',
mtConfirmation, mbYesNoCancel, 0) <> mrYes then
finddialog1.CloseDialog;
RichEdit1.SetFocus;
end;
А затем, когда что-нибудь найдено в Richedit, то выделить в ListBox строку под номером таким же, как и номер выделенной строки в richedit.
Только как это осуществить?
Может кто поможет?
kodov (2007-03-21 17:53:00) [23]Огромное спасибо всем за оветы и особенно RASkov'у.
RASkov (2007-03-20 21:24:00) [24]Или примерно так:
procedure TForm1.Button2Click(Sender: TObject);
var S: String; N: Integer;
begin
{Тут всякие проверки на верность personslist.Count, Edit1.Text=''....}
S := AnsiLowerCase(Edit1.Text); //или лучше Edit1.CharCase = eclowerCase - (все немного быстрее будет)
if personslist.Tag = -1 then personslist.ItemIndex := -1;
personslist.Tag := personslist.ItemIndex + 1;
for N := personslist.Tag to personslist.Count - 1 do
if Pos(S, AnsiLowerCase(personslist.Items[N])) > 0 then begin
personslist.ItemIndex := N;
Break;
end;
if personslist.Tag = personslist.ItemIndex + 1 then begin
if personslist.Tag = 0 then ShowMessage('Не найдено: ' + Edit1.Text)
else ShowMessage('Больше не найдено: ' + Edit1.Text);
Button2.Caption := 'Найти';
personslist.Tag := -1;
end else Button2.Caption := 'Найти далее';
end;
RASkov (2007-03-20 19:34:00) [25]
with ListBox do
ItemIndex := Perform(LB_FINDSTRING, ItemIndex, LongInt(PChar(Edit1.Text)));
RASkov (2007-03-20 19:33:00) [26]> [14] kodov (20.03.07 19:27)
Если тебе подошел мой вариант(поиск с начала строки) то попробуй вот это:
procedure TForm1.Button2Click(Sender: TObject);
begin
with ListBox do
ItemIndex := ListBox.Perform(LB_FINDSTRING, ItemIndex, LongInt(PChar(Edit1.Text)));
end;
Но это не ищет вхождение строки, а только с начала....
kodov (2007-03-20 19:27:00) [27]Только что попробовал варианты, RASkov, ваш поиск действительно работает лучше моего.
Есть еще один вопрос, вот код для кнопки Найти далее.
var
i : integer;
begin
for i:=n+1 to personslist.Count-1 do
begin
if Pos(LowerCase(Edit1.Text),LowerCase(personslist.Items.Strings[i]))<>0 then
begin
personslist.Selected[i]:=true;
editbtn.Click;
n:=i;
break;
end;
end;
Проблема в том, что у меня стоит строка "Fortecstar LiFetime",
при нажатии кнопки Найти, поиск её находит, а затем где-то через 7 строк,
стоит строка "Fortecstar FTA LiFetime". Так вот, при нажатии кнопки Найти далее, поиск ни фига не хочет находить следующую строку.
Какие будут соображения по этому поводу?
Заранее благодарен.
kodov (2007-03-20 19:06:00) [28]Спасибо за ответы, попробую.
RASkov (2007-03-20 02:07:00) [29]> Точнее твоя команда работает по принципу List1.Items.IndexOf(Edit1.Text)
Сорри... понял.
Моя штука не ищет вхождение, только сначала строки...
RASkov (2007-03-20 02:04:00) [30]> [10] Knight © (19.03.07 22:55)
> Точнее твоя команда работает по принципу List1.Items.IndexOf(Edit1.Text)
function TStrings.IndexOf(const S: string): Integer;
begin
for Result := 0 to GetCount - 1 do
if CompareStrings(Get(Result), S) = 0 then Exit;
Result := -1;
end;
Ничего похожего.... Даже больше на ваш код похоже.
> а у тебя не ищет
А ты пробовал? :)
> будет ошибка если ничего не найдёно, т.к. i вылетит за пределы списка.
Ничего подобного... Сам попробуй ListBox1.ItemIndex:=ListBox1.Count+10;
(D7, WinXP SP2) на всяк....
Knight (2007-03-19 22:55:00) [31]Зато у меня ищёт и ищет правильно а у тебя не ищет. Точнее твоя команда работает по принципу List1.Items.IndexOf(Edit1.Text)
А в
end else begin
while (i
RASkov (2007-03-19 22:16:00) [32]> [8] Knight © (19.03.07 21:57)
И "твой" вариант работает медленнее :) для сравнения:
Это, по больше части, для автора вопроса...
procedure TForm1.Button1Click(Sender: TObject);
var N: Integer;
begin
ListBox1.Items.BeginUpdate; Screen.Cursor:=crHourGlass;
ListBox1.Items.Add('Строка');
for N := 0 to 50000 do ListBox1.Items.Insert(0, IntToStr(N));
ListBox1.Items.EndUpdate; Screen.Cursor:=crDefault;
end;
procedure TForm1.Button2Click(Sender: TObject);
begin
ListBox1.ItemIndex := ListBox1.Perform(LB_FINDSTRING, -1, LongInt(PChar(Edit1.Text)));
end;
procedure TForm1.Button3Click(Sender: TObject);
var
i: integer;
flag: boolean;
begin
i:=0;
flag:=False;
if ListBox1.Items.Count=0 then begin
showmessage('There are no elements to find');
Exit;
end else if edit1.Text='' then begin
showmessage('Enter something to find');
Edit1.SetFocus;
end else begin
* while (i < ListBox1.Count) and not flag do begin
* flag:=Pos(LowerCase(Edit1.Text), LowerCase(ListBox1.Items.Strings[i])) <> 0;
* if flag then begin
* ListBox1.Selected[i]:=true;
* end else inc(i);
* end;
end;
end;
Кстати можно заменить часть кода на это:
....
end else begin
while (i<ListBox1.Count) and (Pos(LowerCase(Edit1.Text), LowerCase(ListBox1.Items.Strings[i]))=0) do INC(i);
ListBox1.ItemIndex:=i;
end;
Knight (2007-03-19 21:57:00) [33]> [7] RASkov (19.03.07 21:47)
> Не работает LowerCase для русских символов (D7)
Просто не читая скопировал с варианта автора ветки Надо туда Ansi добавить.
RASkov (2007-03-19 21:47:00) [34]> [4] Knight © (19.03.07 17:48)
Не верно будет работать с русским текстом. Т.е. твой вариант не найдет - если в Edit1.Text будет = 'строка', а в ListBox'е Item со значением = 'Строка' или 'стРока'....
Не работает LowerCase для русских символов (D7)....
> [5] kodov (19.03.07 20:29)
Попробуй [3]...
Knight (2007-03-19 21:04:00) [35]Так и что? Вариант не идеальный, но работает и при количестве строк больше тысячи
kodov (2007-03-19 20:29:00) [36]Мне нужно найти первое попавшееся.
И мне нужно частичное совпадение.
Knight (2007-03-19 17:48:00) [37]Фих знает... Вроде ищет всё..
var
i: integer;
flag: boolean;
begin
i:=0;
flag:=False;
if personslist.Items.Count=0 then begin
showmessage('There are no elements to find');
mainform.Show;
end else if edit1.Text='' then begin
showmessage('Enter something to find');
mainform.Show;
end else begin
while (i<personslist.Count) and not flag do begin
flag:=Pos(LowerCase(Edit1.Text),LowerCase(personslist.Items.Strings[i]))<>0;
if flag then begin
n:=i;
personslist.Selected[i]:=true;
end else inc(i);
end;
end;
RASkov (2007-03-19 16:37:00) [38]> [0] kodov (19.03.07 16:22)
ListBox.ItemIndex := ListBox.Perform(LB_FINDSTRING, -1, LongInt(PChar(Edit1.Text)));
Elen (2007-03-19 16:36:00) [39]Наверное тебе мешает or (flag=true).Задача какая? отселектировать найденное? или найти первое попавшееся?
Степан (2007-03-19 16:35:00) [40]Можно попробовать заменить:
personslist.Countнаpersonslist.Items.Count
personslist.Items.Strings[i]наpersonslist.Items[i]
а так вроде все правильно... вроде :)