Top.Mail.Ru
Мастера DELPHI, Delphi programming community Титульная страница Поиск, карта сайта Написать письмо 
| Новости | Поиск | FAQ | Статьи | Книги | Новости VCL |
| Форумы ЧАТ | Орешник | KOL и MCK |
Форумы -» Основная («Начинающим»)/ Базы / WinAPI / Компоненты / Сети / Media / Игры / Corba и COM / KOL / FreePascal / .Net / Прочее / RSDN.ORG

« предыдущая ветвь | форум | следующая ветвь »

Поиск в ListBox [D7, WinXP]


Страницы:   1 2

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]

а так вроде все правильно... вроде :)


Страницы:   1 2

Наверх

Титульная страница Поиск, карта сайта Написать письмо