UserGuide

Windows UI Guidelines

From Xojo Documentation

Starting with Xojo 2018r1, the Windows framework has had a significant overhaul to reduce flicker inherent to native Win32 controls. This page contains tips on how you can update your existing projects to improve UI performance on Windows.

Transparent Property for Controls

UI controls now have a Transparent property which determines whether the control is transparent on Microsoft Windows. The default is False for new controls added to layouts. For existing projects and controls, this property is set to True for maximum compatibility.

However, controls that have Transparent set to True require more drawing, use more memory and are thus slower. For best results you should set the Transparent property to False for as many controls as possible.

ContainerControl DoubleBuffer Property

Set this property to True to reduce flicker on Microsoft Windows when the ContainerControl is scrolled. This will cause slower rendering. Otherwise you can leave this to False.

Avoid Overlapping Controls

The easiest thing you can do to prevent flickering is to not overlap any controls. Overlapped controls result in more requests to redraw the controls which results in flickering.

Use a Canvas

For best results, display any graphics using the Paint event of a Canvas control. Stay away from using the Window.Backdrop property, the Window.Paint event, the Canvas.Backdrop property or the ImageWell control. Although those techniques work fine in certain situations, they often lead to improper drawing or slower performance in more complex window layouts.

You should check your usage of the DoubleBuffer property. In many cases you will find you can leave it set to off (False) for best performance. With these tweaks, you can do all your drawing in the Paint event using the supplied graphics object parameter: g.

fa-info-circle-32.png
Do not do any drawing directly to the old Canvas.Graphics or Windows.Graphics properties. This ability was deprecated in 2011 and has been removed starting with 2018r3.

You can have separate methods that update the graphics, but they need to be called from the Paint event with the graphics object supplied to the methods as a parameter. Another technique is to have a Picture property that you use to draw you graphics to and then in the Paint event handler you draw the Picture to the Canvas to display it.

When you want the Canvas to update itself, redrawing any changes to your graphics, you call the Invalidate method:

Canvas1.Invalidate(False)

You can also call the Refresh method:

Canvas1.Refresh(False)

The difference is that Invalidate tells the Canvas to update itself when it gets a redraw request from the operating system. The Refresh method tells the Canvas to update itself immediately. Normally you want to use Invalidate as it results in fewer draw requests, improving performance.

To reduce any chance of flicker, both of the above commands pass False for the EraseBackground parameter (which defaults to True) so that the Canvas is not erased before its updated contents are drawn.

By using these techniques, you can create stable, flicker-free graphics in your Windows applications.

Remove or Update Older Code

If you previously had specialized code in your app to help minimize Windows flicker, you should try removing it as the code may now prove to be unnecessary and cause worse performance.

Freeze Drawing

In certain situations you may find it helpful to force screen redrawing to happen all at once, rather than a portion of the screen at a time as is the Windows default. You can use this code to manage that:

Const WM_SETREDRAW = 11
Declare Sub SendMessage Lib "User32" Alias "SendMessageW" _
(hwnd As Integer, msg As UInt32, wParam As Integer, lParam As Integer)

// Prevent redraw
SendMessage(pagePanel1.Handle, WM_SETREDRAW, 0, 0)

// Switch pages

// Restore redrawing
SendMessage(pagePanel1.Handle, WM_SETREDRAW, 1, 0)

// After that you'll have to refresh the contents, PagePanel1.Refresh may not be enough,
// if not then you can use this code
// Quickly mark all children for repainting
Const RDW_INVALIDATE = 1
Const RDW_ALLCHILDREN = &h80
Const RDW_UPDATENOW = &h100

Declare Function RedrawWindow Lib "User32" _
(hwnd As Integer, updateRect As Ptr, updateRgn As Ptr, flags As UInt32) As Boolean
Call RedrawWindow(pagePanel1.Handle, Nil, Nil, RDW_INVALIDATE + RDW_ALLCHILDREN + RDW_UPDATENOW)

Virtual Machines

Many people run Windows in Virtual Machines for testing. If you do so you'll want to ensure that you have the best performance possible. Xojo apps use Direct2D for all screen drawing and not all VM software has properly accelerated graphics drivers for this.

In particular, VMware Fusion has rather poor performance when "Accelerate 3D Graphics" is enabled in the Display preferences. For best performance you should make sure that option is turned off.

Alternatively, Parallels Desktop and VirtualBox both seem to have better graphics performance with Direct2D and Xojo apps.