View Issue Details

IDProjectCategoryView StatusLast Update
0028146LazarusLCLpublic2016-11-27 19:58
ReporterwpAssigned ToJuha Manninen 
PrioritynormalSeverityminorReproducibilitysometimes
Status closedResolutionfixed 
Platformx386-win32OSWin 7OS Version
Product Version1.4Product Build 
Target Version1.6Fixed in Version1.6 
Summary0028146: Flicker in TListbox
DescriptionThe first/last visible line of a listbox flickers when the scrollbar is moved up or down quickly.

The flicker can be avoided if the WMErasebackground message is handled without performing the erase action.

This is a regression in version 1.4 because the issue was not present in version 1.2.6. Possibly it is related to r47451 where some changes in the background erasing process were made.
Steps To ReproduceRun attached demo. It shows two listboxes. The left one is a standard owner-drawn listbox. Drag the scrollbar to the center, and then drag it up and down quickly. Occasional flickering of the top and bottom lines will be seen.

The right listbox overrides the WMEraseBackground message such that no repaint of the background occurs. There is no flicker.

Run the demo in an older Lazarus version (I tested down to 1.0): they do not show any flicker. Therefore, I consider this to be a regression introduced in version 1.4.
Additional InformationThe flicker may be difficult to see. Please see the forum thread (http://forum.lazarus.freepascal.org/index.php/topic,28464.msg178098.html#msg178098) for more details. I am attaching also the demo "Listbox_Test" of the OP which slows down painting of the listbox items to enhance the flicker effect.

According to the OP, the flicker occurs only on Windows.
TagsNo tags attached.
Fixed in Revisionr49170, r49561, r50131
LazTarget-
WidgetsetWin32/Win64
Attached Files
  • listbox_flicker1.zip (4,666 bytes)
  • ListBox_Test.zip (2,865 bytes)
  • win32wsstdctrls.pp.patch (1,539 bytes)
    Index: lcl/interfaces/win32/win32wsstdctrls.pp
    ===================================================================
    --- lcl/interfaces/win32/win32wsstdctrls.pp	(revision 49165)
    +++ lcl/interfaces/win32/win32wsstdctrls.pp	(working copy)
    @@ -583,6 +583,9 @@
       WindowInfo: PWin32WindowInfo;
       NCCreateParams: PNCCreateParams;
       LMessage: TLMessage;
    +  Count: LResult;
    +  Top: Integer;
    +  ARect: TRect;
     begin
       case Msg of
         WM_NCCREATE:
    @@ -609,6 +612,26 @@
             LMessage.Result := 0;
             Exit(DeliverMessage(WindowInfo^.WinControl, LMessage));
           end;
    +    WM_ERASEBKGND:
    +      // Avoid unnecessary background paints to avoid flickering of the listbox
    +      begin
    +        WindowInfo := GetWin32WindowInfo(Window);
    +        Count := SendMessage(Window, LB_GETCOUNT, 0, 0);
    +        if Assigned(WindowInfo^.WinControl) and
    +          (TCustomListBox(WindowInfo^.WinControl).Columns < 2) and
    +          (Count <> LB_ERR) and (SendMessage(Window, LB_GETITEMRECT, Count - 1, Windows.LParam(@ARect)) <> LB_ERR) then
    +        begin
    +          Top := ARect.Bottom;
    +          Windows.GetClientRect(Window, ARect);
    +          ARect.Top := Top;
    +          if not IsRectEmpty(ARect) then
    +            Windows.FillRect(HDC(WParam), ARect, WindowInfo^.WinControl.Brush.Reference.Handle);
    +          Result := 1;
    +        end
    +        else
    +          Result := CallDefaultWindowProc(Window, Msg, WParam, LParam);
    +        Exit;
    +      end;
       end;
       // normal processing
       Result := WindowProc(Window, Msg, WParam, LParam);
    
    win32wsstdctrls.pp.patch (1,539 bytes)
  • win32wsstdctrls.pp-new.patch (581 bytes)
    Index: win32wsstdctrls.pp
    ===================================================================
    --- win32wsstdctrls.pp	(revision 49559)
    +++ win32wsstdctrls.pp	(working copy)
    @@ -613,7 +613,8 @@
             Exit(DeliverMessage(WindowInfo^.WinControl, LMessage));
           end;
         WM_ERASEBKGND:
    -      if WindowsVersion <= wvXP then   // Standardbehavior for XP
    +      if (WindowsVersion <= wvXP) or not ThemeServices.ThemesEnabled then
    +        // Standardbehavior for XP, or no themes
             Result := CallDefaultWindowProc(Window, Msg, WParam, LParam)
           else
           begin
    
  • win32wsstdctrls.laz144.patch (1,425 bytes)
    Index: lcl/interfaces/win32/win32wsstdctrls.pp
    ===================================================================
    --- lcl/interfaces/win32/win32wsstdctrls.pp	(revision 50095)
    +++ lcl/interfaces/win32/win32wsstdctrls.pp	(working copy)
    @@ -613,13 +613,19 @@
             Exit(DeliverMessage(WindowInfo^.WinControl, LMessage));
           end;
         WM_ERASEBKGND:
    -      if (WindowsVersion <= wvXP) or not ThemeServices.ThemesEnabled then
    -        // Standardbehavior for XP, or no themes
    -        Result := CallDefaultWindowProc(Window, Msg, WParam, LParam)
    -      else
           begin
    +        WindowInfo := GetWin32WindowInfo(Window);
    +        if ((WindowsVersion <= wvServer2003) or not ThemeServices.ThemesEnabled) then
    +        begin
    +          if Assigned(WindowInfo^.WinControl) and not
    +             (TCustomListbox(WindowInfo^.WinControl).Style in [lbOwnerDrawFixed, lbOwnerDrawVariable])
    +          then begin
    +            // Standard behavior for XP/WinServer2003, no themes, no OwnerDraw
    +            Result := CallDefaultWindowProc(Window, Msg, WParam, LParam);
    +            exit;
    +          end
    +        end;
             // Avoid unnecessary background paints to avoid flickering of the listbox
    -        WindowInfo := GetWin32WindowInfo(Window);
             Count := SendMessage(Window, LB_GETCOUNT, 0, 0);
             if Assigned(WindowInfo^.WinControl) and
               (TCustomListBox(WindowInfo^.WinControl).Columns < 2) and
    

Relationships

related to 0027261 closedJuha Manninen Patch - Adding WS_EX_LAYOUTRTL support to SendPaintMessage 
related to 0028275 resolvedJuha Manninen incorrect painting listbox 

Activities

wp

2015-05-20 22:13

developer  

listbox_flicker1.zip (4,666 bytes)

wp

2015-05-20 22:14

developer  

ListBox_Test.zip (2,865 bytes)

Juha Manninen

2015-05-20 23:41

developer   ~0083862

r47451 is pure refactoring. Did you really test it causes the problem?
My gut feeling says the problem is somewhere else.

wp

2015-05-21 00:02

developer   ~0083864

No it just caught my eye when looking through the recent svn log messages after having seen that WMEraseBackground can fix the problem.

Juha Manninen

2015-05-21 00:25

developer   ~0083865

Could somebody please bisect and find which revision caused the problem.

wp

2015-05-21 01:28

developer   ~0083866

r47325 is ok, r47326 fails

Balázs Székely

2015-05-21 07:18

developer   ~0083871

Last edited: 2015-05-21 07:55

View 4 revisions

It was introduced with this issue:
http://bugs.freepascal.org/view.php?id=27261
Still not as dramatic as other people say, but is definitely there(ListBox_Test.zip). I see no difference in listbox_flicker1.zip

Juha Manninen

2015-05-22 22:52

developer   ~0083920

Somebody must provide a patch to fix this one. I don't know enough WinAPI to fix it myself.
I also committed the patch from the related issue to prevent it from being ignored. LCL-Win is not very actively maintained now.

wp

2015-05-22 22:58

developer   ~0083921

Catching the WM_EraseBackground message fixes it. I could create a patch with it. I am not 100% sure however if the root cause is not somewhere else. I'll investigate further in the next days.

wp

2015-05-25 17:24

developer  

win32wsstdctrls.pp.patch (1,539 bytes)
Index: lcl/interfaces/win32/win32wsstdctrls.pp
===================================================================
--- lcl/interfaces/win32/win32wsstdctrls.pp	(revision 49165)
+++ lcl/interfaces/win32/win32wsstdctrls.pp	(working copy)
@@ -583,6 +583,9 @@
   WindowInfo: PWin32WindowInfo;
   NCCreateParams: PNCCreateParams;
   LMessage: TLMessage;
+  Count: LResult;
+  Top: Integer;
+  ARect: TRect;
 begin
   case Msg of
     WM_NCCREATE:
@@ -609,6 +612,26 @@
         LMessage.Result := 0;
         Exit(DeliverMessage(WindowInfo^.WinControl, LMessage));
       end;
+    WM_ERASEBKGND:
+      // Avoid unnecessary background paints to avoid flickering of the listbox
+      begin
+        WindowInfo := GetWin32WindowInfo(Window);
+        Count := SendMessage(Window, LB_GETCOUNT, 0, 0);
+        if Assigned(WindowInfo^.WinControl) and
+          (TCustomListBox(WindowInfo^.WinControl).Columns < 2) and
+          (Count <> LB_ERR) and (SendMessage(Window, LB_GETITEMRECT, Count - 1, Windows.LParam(@ARect)) <> LB_ERR) then
+        begin
+          Top := ARect.Bottom;
+          Windows.GetClientRect(Window, ARect);
+          ARect.Top := Top;
+          if not IsRectEmpty(ARect) then
+            Windows.FillRect(HDC(WParam), ARect, WindowInfo^.WinControl.Brush.Reference.Handle);
+          Result := 1;
+        end
+        else
+          Result := CallDefaultWindowProc(Window, Msg, WParam, LParam);
+        Exit;
+      end;
   end;
   // normal processing
   Result := WindowProc(Window, Msg, WParam, LParam);
win32wsstdctrls.pp.patch (1,539 bytes)

wp

2015-05-25 17:29

developer   ~0083995

The attached patch applies the WM_ERASEBACKGROUND handling of TCheckListbox also to TCustomListbox. This fixes the issue for single-column listboxes. Multi-column listboxes still show some flickering (BTW: the same with TCheckListbox), but i did not find a way to avoid this without introducing other painting artefacts. Since listboxes are only rarely used in the multi-column mode I think this is a viable workaround.

Juha Manninen

2015-05-26 00:31

developer   ~0083998

Applied, thanks.

wp

2015-05-26 20:25

developer   ~0084023

Thanks. Will it make it into 1.4.2?

wp

2015-07-18 22:59

developer   ~0084985

No, this patch is bad, it breaks background painting of listboxes with the standard style. See http://forum.lazarus.freepascal.org/index.php/topic,29060.msg183135.html#msg183135: Run "examples/fontenum/fontenumerator.lpi" and scroll the center font listbox down for at least one page.

wp

2015-07-20 12:49

developer  

win32wsstdctrls.pp-new.patch (581 bytes)
Index: win32wsstdctrls.pp
===================================================================
--- win32wsstdctrls.pp	(revision 49559)
+++ win32wsstdctrls.pp	(working copy)
@@ -613,7 +613,8 @@
         Exit(DeliverMessage(WindowInfo^.WinControl, LMessage));
       end;
     WM_ERASEBKGND:
-      if WindowsVersion <= wvXP then   // Standardbehavior for XP
+      if (WindowsVersion <= wvXP) or not ThemeServices.ThemesEnabled then
+        // Standardbehavior for XP, or no themes
         Result := CallDefaultWindowProc(Window, Msg, WParam, LParam)
       else
       begin

wp

2015-07-20 12:50

developer   ~0084999

Uploaded a new patch which takes care of the standard style painting issue.

Juha Manninen

2015-07-22 10:42

developer   ~0085013

Applied the patch, please test.

wp

2015-10-19 19:40

developer   ~0086718

Last edited: 2015-10-19 19:43

View 2 revisions

According to a discussion in the forum (http://forum.lazarus.freepascal.org/index.php/topic,28464.msg190710.html#msg190710) user ncs-sniper reports that flicker comes back in Laz 1.4.4 on Windows XP.

The attached patch is based on an idea of ncs-sniper and fixes the flickering issue without touching the other cases.

wp

2015-10-19 19:41

developer  

win32wsstdctrls.laz144.patch (1,425 bytes)
Index: lcl/interfaces/win32/win32wsstdctrls.pp
===================================================================
--- lcl/interfaces/win32/win32wsstdctrls.pp	(revision 50095)
+++ lcl/interfaces/win32/win32wsstdctrls.pp	(working copy)
@@ -613,13 +613,19 @@
         Exit(DeliverMessage(WindowInfo^.WinControl, LMessage));
       end;
     WM_ERASEBKGND:
-      if (WindowsVersion <= wvXP) or not ThemeServices.ThemesEnabled then
-        // Standardbehavior for XP, or no themes
-        Result := CallDefaultWindowProc(Window, Msg, WParam, LParam)
-      else
       begin
+        WindowInfo := GetWin32WindowInfo(Window);
+        if ((WindowsVersion <= wvServer2003) or not ThemeServices.ThemesEnabled) then
+        begin
+          if Assigned(WindowInfo^.WinControl) and not
+             (TCustomListbox(WindowInfo^.WinControl).Style in [lbOwnerDrawFixed, lbOwnerDrawVariable])
+          then begin
+            // Standard behavior for XP/WinServer2003, no themes, no OwnerDraw
+            Result := CallDefaultWindowProc(Window, Msg, WParam, LParam);
+            exit;
+          end
+        end;
         // Avoid unnecessary background paints to avoid flickering of the listbox
-        WindowInfo := GetWin32WindowInfo(Window);
         Count := SendMessage(Window, LB_GETCOUNT, 0, 0);
         if Assigned(WindowInfo^.WinControl) and
           (TCustomListBox(WindowInfo^.WinControl).Columns < 2) and

Juha Manninen

2015-10-20 23:00

developer   ~0086759

I applied the new patch, thanks.

Issue History

Date Modified Username Field Change
2015-05-20 22:13 wp New Issue
2015-05-20 22:13 wp Status new => assigned
2015-05-20 22:13 wp Assigned To => Juha Manninen
2015-05-20 22:13 wp File Added: listbox_flicker1.zip
2015-05-20 22:14 wp File Added: ListBox_Test.zip
2015-05-20 22:15 wp Additional Information Updated View Revisions
2015-05-20 23:41 Juha Manninen Note Added: 0083862
2015-05-20 23:41 Juha Manninen Status assigned => feedback
2015-05-21 00:02 wp Note Added: 0083864
2015-05-21 00:02 wp Status feedback => assigned
2015-05-21 00:24 wp OS => Win 7
2015-05-21 00:24 wp Platform => x386-win32
2015-05-21 00:25 Juha Manninen Note Added: 0083865
2015-05-21 01:28 wp Note Added: 0083866
2015-05-21 07:18 Balázs Székely Note Added: 0083871
2015-05-21 07:19 Balázs Székely Note Edited: 0083871 View Revisions
2015-05-21 07:23 Balázs Székely Note Edited: 0083871 View Revisions
2015-05-21 07:55 Balázs Székely Note Edited: 0083871 View Revisions
2015-05-21 08:55 Juha Manninen Relationship added related to 0027261
2015-05-22 22:52 Juha Manninen Note Added: 0083920
2015-05-22 22:58 wp Note Added: 0083921
2015-05-25 17:24 wp File Added: win32wsstdctrls.pp.patch
2015-05-25 17:29 wp Note Added: 0083995
2015-05-26 00:31 Juha Manninen Fixed in Revision => r49170
2015-05-26 00:31 Juha Manninen Note Added: 0083998
2015-05-26 00:31 Juha Manninen Status assigned => resolved
2015-05-26 00:31 Juha Manninen Resolution open => fixed
2015-05-26 20:25 wp Note Added: 0084023
2015-05-26 20:25 wp Status resolved => closed
2015-06-12 15:49 wp Relationship added related to 0028275
2015-07-18 22:59 wp Note Added: 0084985
2015-07-18 22:59 wp Status closed => assigned
2015-07-18 22:59 wp Resolution fixed => reopened
2015-07-20 12:49 wp File Added: win32wsstdctrls.pp-new.patch
2015-07-20 12:50 wp Note Added: 0084999
2015-07-22 10:42 Juha Manninen Fixed in Revision r49170 => r49170, r49561
2015-07-22 10:42 Juha Manninen Note Added: 0085013
2015-07-22 10:42 Juha Manninen Status assigned => resolved
2015-07-22 10:42 Juha Manninen Resolution reopened => fixed
2015-07-22 11:41 wp Status resolved => closed
2015-07-22 11:41 wp Target Version => 1.4.4
2015-10-19 19:40 wp Note Added: 0086718
2015-10-19 19:40 wp Status closed => assigned
2015-10-19 19:40 wp Resolution fixed => reopened
2015-10-19 19:40 wp Target Version 1.4.4 => 1.4.6
2015-10-19 19:41 wp File Added: win32wsstdctrls.laz144.patch
2015-10-19 19:43 wp Note Edited: 0086718 View Revisions
2015-10-20 23:00 Juha Manninen Fixed in Revision r49170, r49561 => r49170, r49561, r50131
2015-10-20 23:00 Juha Manninen Note Added: 0086759
2015-10-20 23:00 Juha Manninen Status assigned => resolved
2015-10-20 23:00 Juha Manninen Resolution reopened => fixed
2015-10-22 11:23 wp Status resolved => closed
2016-11-27 19:57 Bart Broersma Status closed => assigned
2016-11-27 19:57 Bart Broersma Resolution fixed => reopened
2016-11-27 19:57 Bart Broersma Target Version 1.4.6 => 1.6
2016-11-27 19:57 Bart Broersma Status assigned => resolved
2016-11-27 19:57 Bart Broersma Resolution reopened => fixed
2016-11-27 19:58 Bart Broersma Status resolved => closed
2016-11-27 19:58 Bart Broersma Fixed in Version => 1.6