Recent

Author Topic: Unexpected behavior of SelectAll method in TListBox  (Read 1422 times)

jamie

  • Hero Member
  • *****
  • Posts: 3526
Re: Unexpected behavior of SelectAll method in TListBox
« Reply #15 on: April 18, 2020, 02:18:32 am »
OK, well that is problem... However, I found a work around without changing the ListBox code...

Code: Pascal  [Select][+][-]
  1. OldIndex := ListBox.ItemIndex;
  2. ListBox.SelectAll;
  3. ListBox.Selected[OldIndex]:= True;
  4.  

that works..
or you can simply set the Selected[0] := True which is the top
etc..

but in any case it is taking the last index that was set as the selected and scrolling into view..
this little hack seems to fix it without changing the LCL code.
The only true wisdom is knowing you know nothing

jamie

  • Hero Member
  • *****
  • Posts: 3526
Re: Unexpected behavior of SelectAll method in TListBox
« Reply #16 on: April 18, 2020, 02:48:14 am »
Ok, I got a combo of yours and mine that seems to work

Log the TopIndex;
Items.beginUpdate

SelectAll;
TopIndex := LoggedValue;
items.EndUpdate;

that seems to be stable and the scroll stays put...

EDIT:
BTW, this seems to be Delphi Compatible!
Code: Pascal  [Select][+][-]
  1. Var
  2.   TI :Integer;
  3. Begin
  4.   TI := ListBox1.TopIndex;         {need to get the current top index that is showing}
  5.   Listbox1.Items.BeginUpdate;    {freeze any Widget to OS Updating }
  6.   ListBox1.SelectAll;                   {Older Delphi didn't have this, had to loop it ourselves  }
  7.   ListBox1.TopIndex := TI;         { Restore the TopIndex }
  8.   ListBox1.Items.EndUpdate;                {Now let the Widget update everything }
  9.  

No Scroll ListBox SelectALL…

« Last Edit: April 18, 2020, 04:08:02 am by jamie »
The only true wisdom is knowing you know nothing

simone

  • Sr. Member
  • ****
  • Posts: 356
Re: Unexpected behavior of SelectAll method in TListBox
« Reply #17 on: April 18, 2020, 11:06:30 am »
Thanks for hints. Since it seems to be a bug of LCL under Windows OS, I opened a new issue in bugtracker.
Microsoft Windows 10 64 bit - Lazarus 2.0.10

jamie

  • Hero Member
  • *****
  • Posts: 3526
Re: Unexpected behavior of SelectAll method in TListBox
« Reply #18 on: April 18, 2020, 01:31:10 pm »
Well actually the way its written overall in the LCL is incorrect for any target.

The implementation for a SelectAll should be done at the widget level where It can simply call it's equal or
implement it there for others that don't have it at the OS level..
The only true wisdom is knowing you know nothing

Bart

  • Hero Member
  • *****
  • Posts: 3909
    • Bart en Mariska's Webstek
Re: Unexpected behavior of SelectAll method in TListBox
« Reply #19 on: June 07, 2020, 05:06:35 pm »
See my remark in the bugtracker for a solution on LCL impelmentation level.
The SendMessage solution requires we have a default WS implementation, so Win32 can override this.
Also it won't work for > 65536 items in a ListBox, so we need a fallback for that as well.

Bart

ASerge

  • Hero Member
  • *****
  • Posts: 1671
Re: Unexpected behavior of SelectAll method in TListBox
« Reply #20 on: June 08, 2020, 06:46:13 pm »
Also it won't work for > 65536 items in a ListBox, so we need a fallback for that as well.
Something like this (not tested):
Code: Pascal  [Select][+][-]
  1. class procedure TWin32WSCustomListBox.SelectRange(const ACustomListBox: TCustomListBox;
  2.   ALow, AHigh: integer; ASelected: boolean); override;
  3. var
  4.   ListBoxWnd: HWND;
  5. begin
  6.   ListBoxWnd := ACustomListBox.Handle;
  7.   if AHigh <= High(Word) then // LB_SELITEMRANGE+MAKELPARAM limitation
  8.     if SendMessage(ListBoxWnd, LB_SELITEMRANGE, Ord(ASelected),
  9.       MAKELPARAM(ALow, AHigh) <> LB_ERR then
  10.     begin
  11.       Exit;
  12.     end;
  13.   SendMessage(ListBoxWnd, WM_SETREDRAW, 0, 0);
  14.   try
  15.     inherited;
  16.   finally
  17.     SendMessage(ListBoxWnd, WM_SETREDRAW, 1, 0);
  18.     RedrawWindow(ListBoxWnd, nil, 0, RDW_INVALIDATE or RDW_ALLCHILDREN or RDW_ERASE);
  19.   end;
  20. end;

jamie

  • Hero Member
  • *****
  • Posts: 3526
Re: Unexpected behavior of SelectAll method in TListBox
« Reply #21 on: June 08, 2020, 10:59:23 pm »
All the Redrawing code should not be needed. Windows already sends notices to the app after doing this..

Code: Pascal  [Select][+][-]
  1.  SendMessage(ListBox1.Handle, LB_SELITEMRANGE,1,MakeLong(0,ListBox1.Count-1));  
  2.  

For example the above will select all of it and notified the app with proper messages.

 There is one note however, if the user should pass a -1 for the ranges the code in the widget should adjust the values to the proper ranges..

 For example if the High Value is -1 then it should change the value to the ListBox.Count-1;

 Doing it this way the coder does not need to include the max list range of the listbox, it will just adjust it for them..

 I don't think the windows API likes seeing a value past what is actually in there so this should only happen if the coder past a -1..
The only true wisdom is knowing you know nothing

Bart

  • Hero Member
  • *****
  • Posts: 3909
    • Bart en Mariska's Webstek
Re: Unexpected behavior of SelectAll method in TListBox
« Reply #22 on: June 09, 2020, 02:08:22 pm »
When I have the time I will try to implement this.
It needs testers voor WinCE, once implemented.

Further discussions in the bugtracker please.

Bart

ASerge

  • Hero Member
  • *****
  • Posts: 1671
Re: Unexpected behavior of SelectAll method in TListBox
« Reply #23 on: June 09, 2020, 04:25:44 pm »
All the Redrawing code should not be needed. Windows already sends notices to the app after doing this..
If you are referring to the code I have given, please note that redraw is called if the old method is used.

Bart

  • Hero Member
  • *****
  • Posts: 3909
    • Bart en Mariska's Webstek
Re: Unexpected behavior of SelectAll method in TListBox
« Reply #24 on: June 10, 2020, 12:06:09 pm »
I implemented this in r63336, r63337, rr63338, r63339.
@All: thanks for pointing me to the solution.

Please test.

Can somebody please test the implementation in WinCE.
In theory it should work, but I cannot test this myself.

Bart

ASerge

  • Hero Member
  • *****
  • Posts: 1671
Re: Unexpected behavior of SelectAll method in TListBox
« Reply #25 on: June 10, 2020, 05:48:58 pm »
Please test.
This code works fine (of course, the first case works faster):
Code: Pascal  [Select][+][-]
  1. procedure FillListBoxWithSelect(ListBox: TListBox; const ItemsCount: SizeInt);
  2. var
  3.   i: SizeInt;
  4. begin
  5.   ListBox.Items.BeginUpdate;
  6.   try
  7.     ListBox.Clear;
  8.     for i := 0 to ItemsCount - 1 do
  9.       ListBox.Items.Append(IntToStr(i));
  10.   finally
  11.     ListBox.Items.EndUpdate;
  12.   end;
  13.   ListBox.ItemIndex := ItemsCount - 1;
  14.   ListBox.SelectAll;
  15. end;
  16.  
  17. procedure TForm1.Button1Click(Sender: TObject);
  18. begin
  19.   FillListBoxWithSelect(ListBox1, 65000);
  20. end;
  21.  
  22. procedure TForm1.Button2Click(Sender: TObject);
  23. begin
  24.   FillListBoxWithSelect(ListBox1, 66000);
  25. end;
  26.  
  27. procedure TForm1.FormCreate(Sender: TObject);
  28. begin
  29.   ListBox1.MultiSelect := True;
  30. end;

 

TinyPortal © 2005-2018