Brad
Brad

Reputation: 2237

Delphi - Clean TListBox Items

I want to clean a list box by checking it against two other list boxes.

Below is the code I've got so far for this, it's VERY slow with large lists.

// not very efficient 
Function checknegative ( instring : String; ListBox : TListBox ) : Boolean;
Var
  i : Integer;
Begin
  For I := listbox.Items.Count - 1 Downto 0 Do
  Begin
    If ExistWordInString ( instring, listbox.Items.Strings [i], 
      [soWholeWord, soDown] ) = True 
    Then
    Begin
      result := True;  //True if in list, False if not.
      break; 
    End
    Else
    Begin
      result := False;
    End;
  End;
  result:=false;
End;

Function ExistWordInString ( aString, aSearchString : String;
  aSearchOptions : TStringSearchOptions ) : Boolean;
Var
  Size : Integer;
Begin
  Size := Length ( aString );
  If SearchBuf ( Pchar ( aString ), Size, 0, 0, aSearchString, aSearchOptions ) <> Nil Then
  Begin
    result := True;
  End
  Else
  Begin
    result := False;
  End;
End;

Upvotes: 2

Views: 2137

Answers (2)

mghie
mghie

Reputation: 32334

If you do anything that loops with a TStrings instance in a control it may be beneficial to create a temporary TStringList instance, assign the control items to it, then use the temporary list.

The reason for that is that the Items property in a list box, combo box or similar is implemented via a proxy class that doesn't hold the strings itself, but which uses Windows messages like LB_GETCOUNT and LB_GETTEXT to retrieve the elements directly from the native Windows control. If you access a string list item several times then the overhead of the repeated message handling will add up.

Upvotes: 4

Mason Wheeler
Mason Wheeler

Reputation: 84550

If this is working on a listbox, it's probably taking a lot of time to repaint everything every time. You can disable this behavior. Surround the outermost loop with this:

listbox.Items.BeginUpdate;
try
  //do the loop here
finally
  listbox.Items.EndUpdate;
end;

Also, you can assign a boolean directly to the evaluation of a boolean expression, which will save some time on your inner loop. So:

Function ExistWordInString ( aString, aSearchString : String; aSearchOptions : TStringSearchOptions ) : Boolean;
Var
  Size : Integer;
Begin
  Size := Length ( aString );
  result := SearchBuf ( Pchar ( aString ), Size, 0, 0, aSearchString, aSearchOptions ) <> Nil;
End;

Not sure how much of a difference that will make, though. If you make these changes and it's still too slow, try running your program through a profiler such as Sampling Profiler, which will help you see what your code is spending most of its time doing.

Upvotes: 3

Related Questions