TIP: removing flicker on windows

Um…, we probably have any workaround or trick to avoid Listbox flickering?

My suspicion is that sending the message in the same code that runs a tight loop to load the data wont allow the UI to actually receive the message and do anything with it
So you get no effect

However since you’ve not posted all the code or how you load the listbox I’m suspicious there too as I never see a listbox flicker when loading data like this
Are you calling refresh in that code ?
If so stop that :slight_smile:

[quote=328195:@changwon lee]Tried WFS code and used SendMessage method as following, but when I run below code, I can’t see any data on Listbox and in case I click the Listbox, I just can see the updated data on the Listbox.

It seems that I am doing wrong thing. Can you advise me?[/quote]

This code will not update the listbox:

[code]//no updates to listbox because there are no changes after wParam is set to 1 = true
Declare Sub SendMessage Lib “User32.dll” Alias “SendMessageW” (hWnd as Int32, msg as Int32, wParam as Int32, lParam as Int32)
Const WM_SETREDRAW = &hB
//wParam = 0 = ignore changes to Listbox1
call SendMessage(Window1.Listbox1.Handle, WM_SETREDRAW, 0,0)

//make changes to Listbox1 but ignore updates
For i As Integer = 1 To 1000
Listbox1.AddRow i.ToText
Next i

//wParam = 1 = when changes to listbox1 happen, then update listbox
call SendMessage(Window1.Listbox1.Handle, WM_SETREDRAW, 1,0)
//no changes to listbox1 yet, don’t update[/code]

The SendMessage sub with the wParam setting of 0 (false) means do not redraw the content after a change. SendMessage is told to not redraw after changes, changes are made (don’t update), then the sendmessage call is made to make changes when redrawing (1 = True). All the changes have been made so there is nothing to update when wParam is set to 1 at the last SendMessage subroutine.

If something happens to the listbox after the wParam WM_SETREDRAW value is set to true, then it will update the listbox.

This code will update the listbox:

[code]//updates listbox because "done’ has been added which is a change to Listbox1
Declare Sub SendMessage Lib “User32.dll” Alias “SendMessageW” (hWnd as Int32, msg as Int32, wParam as Int32, lParam as Int32)
Const WM_SETREDRAW = &hB
//wParam = 0 = ignore changes to Listbox1
call SendMessage(Window1.Listbox1.Handle, WM_SETREDRAW, 0,0)

//make changes to Listbox1 but ignore updates
For i As Integer = 1 To 1000
Listbox1.AddRow i.ToText
Next i

//wParam = 1 = when changes to listbox1 happen, then update listbox
call SendMessage(Window1.Listbox1.Handle, WM_SETREDRAW, 1,0)
Listbox1.AddRow “done” //here is a change - update listbox1[/code]

does an invalidate have the same effect ?
if not a refresh should

Yes, invalidate would work as long as the wParam value is set to true (1). The below code will not refresh the listbox because the api prevents the control to be updated.

[code]Declare Sub SendMessage Lib “User32.dll” Alias “SendMessageW” (hWnd as Int32, msg as Int32, wParam as Int32, lParam as Int32)
Const WM_SETREDRAW = &hB
call SendMessage(Window1.Listbox1.Handle, WM_SETREDRAW, 0,0)

For i As Integer = 1 To 1000
Listbox1.AddRow i.ToText
Next i
Listbox1.Invalidate
[/code]

The api wParam will need to be set to true and then invalidate will work with the control, shown in the below code. This code will refresh the listbox.

[code]Declare Sub SendMessage Lib “User32.dll” Alias “SendMessageW” (hWnd as Int32, msg as Int32, wParam as Int32, lParam as Int32)
Const WM_SETREDRAW = &hB
call SendMessage(Window1.Listbox1.Handle, WM_SETREDRAW, 0,0)

For i As Integer = 1 To 1000
Listbox1.AddRow i.ToText
Next i
call SendMessage(Window1.Listbox1.Handle, WM_SETREDRAW, 1,0)
Listbox1.Invalidate
[/code]

[quote=328237:@Norman Palardy]does an invalidate have the same effect ?
if not a refresh should[/quote]
I just ran some code, and it looks like wParam will need to be set to true (1) for invalidate or refresh to work.

After wParam=1, the code [Listbox1.AddRow “done”] started updating my Listbox.
Cool. Really it works.
I thought calling a method with wParam=1 would update the Listbox accordingly but it was wrong.
Changing the Listbox and Updating the Listbox is different. I didn’t know that.

Thank you everyone so much(Michel/Eugene Dakin).

@Norman Palardy
Thanks for introducing WFS code.

Thanks for the SendMessage tip.
I have some containercontrols flickering on updating. After implementing Sendmessage to postpone the screenupdate I don’t see any flickering anymore.

For the experiment I did this, where CC_TitleLabel, is a container control having some labels on a colored background )

[code]Private Sub AllowRedraw(w as CC_TitleLabel, allow as Boolean = true)
#If TargetWin32 Then
Const WM_SETREDRAW = &h000B
Declare Sub SendMessage Lib “User32” alias “SendMessageW” (hwnd As Integer, msg As Integer, wParam As Boolean, lParam As Integer)
If allow Then
SendMessage(w.handle, WM_SETREDRAW, True, 0)
w.Refresh
Else
SendMessage(w.handle, WM_SETREDRAW, False, 0)
End
#EndIf

End Sub[/code]

Well, it’s a little bit of just seeing what works in your design and what doesn’t. No general solution to combat all the flickering everywhere in your application.
The method I mentioned above for example, didn’t work for me once the same simple containercontrol is on a pagepanel.

I am not so certain in Xojo, but back in the old VB6 days, using WM_REDRAW (VB6 had a built-in call also - hmmm here is an idea for a feature request!) to stop the redraw during heavy screen updates, would also speed-up the operation significantly. It was and parhaps still is a nice added bonus.