Recent

Author Topic: TShellListView empty space artifact after setting .Mask  (Read 807 times)

anse

  • New Member
  • *
  • Posts: 39
  • Bugmonkey
    • HeidiSQL
TShellListView empty space artifact after setting .Mask
« on: December 01, 2025, 05:13:59 pm »
Hi all,

Windows 11, Lazarus 4.2, FPC 3.2.2
I have a TShellListView and a combobox where I can select the file mask for it, either *.* or *.txt
When i scroll down and select a file, then set a different mask, the list shows an empty space artifact at the top scoll position. It disappears aftert scrolling up and down several times.
On a quick test with Ubuntu gtk2, that issue does not appear.

The list has only default properties set. Codewise I do nothing really special:

Code: Pascal  [Select][+][-]
  1. procedure TForm1.comboMaskChange(Sender: TObject);
  2. begin
  3.   ShellListView1.Root:='c:\temp';
  4.   ShellListView1.Mask:=comboMask.Text;
  5. end;
  6.  

The artifact shows like the attached image.

I already tried to wrap the two lines in .Begin/EndUpdate, added a .Refresh and a .Repaint - nothing helped here.

wp

  • Hero Member
  • *****
  • Posts: 13264
Re: TShellListView empty space artifact after setting .Mask
« Reply #1 on: December 01, 2025, 08:15:46 pm »
I can reproduce this with these steps:
- Set ShellListView.Root to some directory which has more items than can be shown in the unscrolled listview.
- When the directory is shown, scroll down by at least 1 item.
- Change the mask to any filter. Even *.* is working, and even when the test program started with this same mask.
--> The screen is empty

When I now drag the window vertically out of the screen as much as possible and drag it back the missing items are back (at least those which had been scrolled below the screen bottom)!

jamie

  • Hero Member
  • *****
  • Posts: 7382
Re: TShellListView empty space artifact after setting .Mask
« Reply #2 on: December 02, 2025, 01:07:01 am »
I can't get that to fail on my Win10 machine however, looking at the sources, it tells me that a list population is done twice, one after the other by setting the root or mask and in this case, its scanning twice not once.

 a Lot of going on here in that code so its hard to say but maybe a file caching issue with Win11 when collection items.

the only thing I can think of at this time is maybe the Message queue to refresh the ListView is over writing the last one before it gets a chance to process. Windows does put low priority on some Gui stuff.


Jamie
« Last Edit: December 02, 2025, 01:09:49 am by jamie »
The only true wisdom is knowing you know nothing

jamie

  • Hero Member
  • *****
  • Posts: 7382
Re: TShellListView empty space artifact after setting .Mask
« Reply #3 on: December 02, 2025, 01:18:25 am »
I think a method needs to be added to the control, for example "SetMaskAndRooT"

Where the mask or Root property gets set at it's lowest level but does not clear anything in the control yet then
when setting the other item it would then do list update so this only happens once!

Jamie.
The only true wisdom is knowing you know nothing

jamie

  • Hero Member
  • *****
  • Posts: 7382
Re: TShellListView empty space artifact after setting .Mask
« Reply #4 on: December 02, 2025, 04:03:23 am »
Seems to me an issue with the scrollbars not getting reset maybe..

Anyways, I tried it with ssAutoBoth in the OI, I played with it and I didn't see the effects afterwards.

I also added a method to the class locally. You can look at it where I first set both Root and mask strings without calling the Setter property, then Build the list, this way it gets done once.

Code: Pascal  [Select][+][-]
  1. unit Unit1;
  2.  
  3. {$mode objfpc}{$H+}
  4.  
  5. interface
  6.  
  7. uses
  8.   Windows,Classes, SysUtils, Forms, Controls, Graphics, Dialogs, ShellCtrls, StdCtrls;
  9.  
  10. type
  11.  
  12. { TShellListView }
  13.  
  14. TShellListView = Class(ShellCtrls.TShellListView)
  15.   Procedure SetMaskAndRoot(aMask,Aroot:String);
  16. end;
  17.  
  18.   { TForm1 }
  19.  
  20.   TForm1 = class(TForm)
  21.     ComboBox1: TComboBox;
  22.     ShellListView1: TShellListView;
  23.     procedure ComboBox1Change(Sender: TObject);
  24.   private
  25.  
  26.   public
  27.  
  28.   end;
  29.  
  30. var
  31.   Form1: TForm1;
  32.  
  33. implementation
  34.  
  35. {$R *.lfm}
  36.  
  37. { TShellListView }
  38.  
  39. procedure TShellListView.SetMaskAndRoot(aMask, Aroot: String);
  40. Type
  41.   TS = ^String;
  42. Var
  43.   S:TS;
  44. begin
  45.   S := @Mask;
  46.   S^:=aMask;
  47.   S := @Root;
  48.   S^ := ARoot;
  49.   clear;
  50.   Items.Clear;
  51.   PopulateWithRoot;
  52. end;
  53.  
  54. { TForm1 }
  55.  
  56. procedure TForm1.ComboBox1Change(Sender: TObject);
  57. begin
  58.   {Set your Scrollbars in the OI to ssAutoBoth}
  59.   ShellListView1.SetMaskAndRoot(combobox1.Text,'c:\Lazarus64');
  60. end;
  61.  
  62. end.
  63.  
  64.  

You can implement the local hack I did in your project. It must be done in the same unit you are using the control in.

I think It loads faster this way, at least that is what I see.

Jamie
The only true wisdom is knowing you know nothing

anse

  • New Member
  • *
  • Posts: 39
  • Bugmonkey
    • HeidiSQL
Re: TShellListView empty space artifact after setting .Mask
« Reply #5 on: December 02, 2025, 06:25:14 am »
Hey Jamie,

thanks a lot for your quick tests. I did it exactly like you mentioned above. But that SetMaskAndRoot works exactly like before, with creating the empty space after the second call to it.

Also played with ScrollBars in the OI, and even I see other issues with ssHorizontal and ssVertical, showing the other/unwanted scrollbar as well. Only ssNone seems to not create that space, but that's probably normal :)

And yes, the list, or especially the scrollbars flash a few times, as if it was updated more than once.

Other ideas?

wp

  • Hero Member
  • *****
  • Posts: 13264
Re: TShellListView empty space artifact after setting .Mask
« Reply #6 on: December 02, 2025, 11:52:37 am »
A workaround is to force scrolling to the top before setting the Mask:
Code: Pascal  [Select][+][-]
  1. procedure TForm1.ComboBox1Change(Sender: TObject);
  2. begin
  3.   if ShellListView1.Items.Count > 0 then
  4.     ShellListView1.Items[0].MakeVisible(true);
  5.   ShellListView1.Mask := ComboBox1.Text;
  6. end;

anse

  • New Member
  • *
  • Posts: 39
  • Bugmonkey
    • HeidiSQL
Re: TShellListView empty space artifact after setting .Mask
« Reply #7 on: December 02, 2025, 05:57:27 pm »
Yea definitely a workaround. But that does not work when the filtered list after setting the Mask has only a few items and no scrollbar is visible.

I tend to report it as an issue on gitlab.com/groups/freepascal.org/lazarus/

BrunoK

  • Hero Member
  • *****
  • Posts: 747
  • Retired programmer
Re: TShellListView empty space artifact after setting .Mask
« Reply #8 on: December 02, 2025, 08:03:30 pm »
Code: Pascal  [Select][+][-]
  1. procedure TForm1.ComboBox1Change(Sender: TObject);
  2. begin
  3.   ShellListView1.Mask := ComboBox1.Text;
  4.   if ShellListView1.Items.Count > 0 then
  5.     ShellListView1.Items[0].MakeVisible(true);
  6. end;
I would suggest first apply mask so items are updated

anse

  • New Member
  • *
  • Posts: 39
  • Bugmonkey
    • HeidiSQL
Re: TShellListView empty space artifact after setting .Mask
« Reply #9 on: December 02, 2025, 08:28:03 pm »
Ah, now I get the point of wp's workaround: it has to scroll to top before setting Mask or Root. The empty space only appears afterwards, when the scroll bar was not at the top position before. I think I mixed that up today.

So, yes, wp's workaround indeed works. Thanks a lot!

wp

  • Hero Member
  • *****
  • Posts: 13264
Re: TShellListView empty space artifact after setting .Mask
« Reply #10 on: December 03, 2025, 12:41:26 am »
Yes, the idea was based on your observation that scrolling is necessary for the bug to occur - therefore: scroll the listview back to the top before setting the mask. The only problem was that I wrote my code in a bit misleading way. Better:
Code: Pascal  [Select][+][-]
  1.     procedure TForm1.ComboBox1Change(Sender: TObject);
  2.     begin
  3.       if ShellListView1.Items.Count > 0 then   // nothing to do when there are no items...
  4.       begin
  5.         ShellListView1.Items[0].MakeVisible(true);
  6.         ShellListView1.Mask := ComboBox1.Text;
  7.       end;
  8.     end;

But of course, this is just a workaround. Something is missing in the win32/64 widgetset code which causes this behaviour. I would have thought that the issue itself is already in TCustomListView because TShellListview does not touch scrolling at all. But the attached test project demonstrates that this is not true: the Listview works correctly when it is populated by some given strings, scrolled down, then re-populated with the same strings but filtered such that only strings beginning with 'a' are accepted - the listview displays the filtered list correctly, no blank part. Or did is miss something when writing this project?

jamie

  • Hero Member
  • *****
  • Posts: 7382
Re: TShellListView empty space artifact after setting .Mask
« Reply #11 on: December 03, 2025, 01:05:11 am »
Even with the workaround, it still does it here but not unless you change the listing mask a few times and keep refreshing it.

At first start, it all works but after a while it starts doing it again through mask changes or root changes.

It appears to me there is some sort of resource leak that is building up.

are all the Icon handles property disposed of from the system when clearing the list?

Jamie
The only true wisdom is knowing you know nothing

jamie

  • Hero Member
  • *****
  • Posts: 7382
Re: TShellListView empty space artifact after setting .Mask
« Reply #12 on: December 03, 2025, 02:08:50 am »
Yes, there is something wrong with the release of resources each time the list gets updated.

I reran that test app to watch it slowly degrade to the point where it no longer showed any icons.

I think a RecreateWindow needs to be done each time the list if redone to release all the icons assigned to the control.

Currently, that test app no longer shows icons.

Most likely need to restart the system. Definitely a resource leak.

Jamie
The only true wisdom is knowing you know nothing

anse

  • New Member
  • *
  • Posts: 39
  • Bugmonkey
    • HeidiSQL
Re: TShellListView empty space artifact after setting .Mask
« Reply #13 on: December 03, 2025, 11:04:38 am »
... the listview displays the filtered list correctly, no blank part. Or did is miss something when writing this project?

No empty space with your project here as well. On Windows 11 by the way. Supports your assumption that TShellListView owns the empty space issue, not TCustomListView.

I also assigned an empty image list so no icons are displayed. Which makes no difference, the empty space still is there. So I assume the icons have no relevance for the issue.

jamie

  • Hero Member
  • *****
  • Posts: 7382
Re: TShellListView empty space artifact after setting .Mask
« Reply #14 on: December 03, 2025, 11:50:45 am »
I suspect there is an issue with the widget for 64 bit because I just ran a test in 32 bit and all works as it should with the system icons showing and it does not seem to have any side effects after several iterations of reloading the list with different mask and roots.

 You don't need have any of the local icons images assigned for the icons to appear, they appear regardless if things are working, maybe.

 This reminds me of bad pointers cause by bad implementation of the windows file for example.

  jamie
The only true wisdom is knowing you know nothing

 

TinyPortal © 2005-2018