TIP: removing flicker on windows

HI, not my code but i found it almost by accident so i thought i would share it.
when updating a listbox on windows you get the flickering as it redraws.
conventional wisdom is to make it invisible before the load then make it visible afterwards.

if you add this to a module

Sub LockWindow(hw as integer)
  #if TargetWin32 Then
    Declare Sub LockWindowUpdate Lib "user32" (ByVal hWnd As Integer)
    LockWindowUpdate hw
  #endif
End Sub

you can then do :-

lockwindow listbox.handle

load your data

lockwindow 0

this doesn’t make it invisible but it stops it being updated so no flicker

which is clever enough, but i also discovered that if you need to popup a control over your listbox (or i guess any other control)
you can use it to stop the flickering effect.

i have a listbox subclass that has lookup columns which display another listbox subclass and this effect has worked really well

anyways, maybe you knew all about it, but if not, enjoy!

Very useful. Thanks for sharing.

Very good, thanks so much.

I wish to experiment with this method to solve some flicker problem.
There is one drawback on using this method: you can only lock one window at time.
Or, perhaps, you can lock more than one, but when you unlock, I think the behavior it’s not defined. It will probably unlock all locked windows.

yes, it only locks a single window, but for me that is enough

it seems designed to allow drag and drop to not be affected by controls beneath the drag,
i’m not using it as intended, but it seems to work great for me in this scenario.

I have not tried these, but a quick Google reveals…

From:-
http://msdn.microsoft.com/en-us/library/windows/desktop/dd145034(v=vs.85).aspx

…“The purpose of the LockWindowUpdate function is to permit drag/drop feedback to be drawn over a window without interference from the window itself. The intent is that the window is locked when feedback is drawn and unlocked when feedback is complete. LockWindowUpdate is not intended for general-purpose suppression of window redraw. Use the WM_SETREDRAW message to disable redrawing of a particular window.”…

Use of WM_SETREDRAW is explained in:-

http://msdn.microsoft.com/en-us/library/windows/desktop/dd145219(v=vs.85).aspx

Good Stuff Chris.
i will maybe have a try with that as well.

[quote=45490:@Chris Carter]Use the WM_SETREDRAW message to disable redrawing of a particular window."…

Use of WM_SETREDRAW is explained in:-

http://msdn.microsoft.com/en-us/library/windows/desktop/dd145219(v=vs.85).aspx [/quote]

That seems interesting, thanks Chris!

If anyone gets around to implementing the “WM_SETREDRAW” I would love to do some further testing with it. I mostly only have flickering problems when resizing a window or scrolling content.

Not finished testing, but seems working.
But it will need a RedrawWindow call too after restoring redraw:

Sub AllowRedraw(w as Window)
  
  #if targetWin32
    
    const WM_SETREDRAW = &h000B
    
    declare sub SendMessage lib "User32" alias "SendMessageW" (hwnd As integer, msg As integer, wParam As Boolean, lParam as Integer)
    
    ' SendMessage(
    ' (HWND) hWnd,
    ' WM_SETREDRAW,
    ' (WPARAM) wParam,
    ' (LPARAM) lParam
    ' );
    
    SendMessage(w.handle, WM_SETREDRAW, true, 0)
    
  #endif
  
End Sub
Sub BlockRedraw(w as Window)
  
  #if targetWin32
    
    const WM_SETREDRAW = &h000B
    
    declare sub SendMessage lib "User32" alias "SendMessageW" (hwnd As integer, msg As integer, wParam As Boolean, lParam as Integer)
    
    ' SendMessage(
    ' (HWND) hWnd,
    ' WM_SETREDRAW,
    ' (WPARAM) wParam,
    ' (LPARAM) lParam
    ' );
    
    SendMessage(w.handle, WM_SETREDRAW, false, 0)
    
  #endif
  
End Sub

Hi Massimo, where is the code for RedrawWindow ?? and how and where do we use this functions??

I have still to write it :wink:
For use, please read here: http://msdn.microsoft.com/en-us/library/windows/desktop/dd145219(v=vs.85).aspx

sorry… i thought u have finish.

look like i need to call this function where i want to allow or block the redraw on a window that has listbox.

well… im glad i started this thread :wink:

the new functions blockRedraw/allowRedraw are much better.

on my listbox a call to listbox.refresh immediately after the call to allowRedraw seems to work just fine.

I’ll have to check WFS and add this code if it’s not there already. Nice work.

(I’m curious why the conversation is in Pro. Wouldn’t everyone benefit from this?)

This seems not the case for me. That’s why I said a call to RedrawWindow may be needed.

Sub AllowRedraw(extends w as Window, allow as Boolean = true) #if targetWin32 If allow then const WM_SETREDRAW = &h000B declare sub SendMessage lib "User32" alias "SendMessageW" (hwnd As integer, msg As integer, wParam As Boolean, lParam as Integer) ' SendMessage((HWND) hWnd, WM_SETREDRAW, (WPARAM) wParam, (LPARAM) lParam); SendMessage(w.handle, WM_SETREDRAW, true, 0) w.Refresh else const WM_SETREDRAW = &h000B declare sub SendMessage lib "User32" alias "SendMessageW" (hwnd As integer, msg As integer, wParam As Boolean, lParam as Integer) ' SendMessage( (HWND) hWnd, WM_SETREDRAW, (WPARAM) wParam,(LPARAM) lParam); SendMessage(w.handle, WM_SETREDRAW, false, 0) end #endif End Sub

Here’s a condensed version of what Massimo wrote. It does it in one method:
Simply call:
myWindow.AllowRedraw(false)
//Flickering stuff here
myWindow.AllowRedraw(true)

I also included a w.Refresh when you turn on allowRedraw, I don’t know if this will suffice for RedrawWindow command or not - Anyone know?

nice update Mr Nash.

btw this is in the pro channel because thats where I’ve been asking questions about the listbox lately, i agree it would benefit all windows users, maybe it can be moved to the windows channel?

what about this? even more condense

Sub AllowRedraw(extends w as Window, allow as Boolean = true)
  #if targetWin32
    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

FYI - this is covered in Aarons book page 418
Lots of VERY useful stuff in there for Windows users