Windows UI guidelines

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.

If you are going to place a control on top of another control, it is recommended that you only do so on top of DesktopWindow, DesktopCanvas, DesktopRectangle, DesktopOval and DesktopContainer. Controls should not be partially overlapping but always be placed completely within the bounds of these controls. Placement in any other way or on any other control will result in transparency being unsupported.

DesktopContainer.Composited property

Set this property to True to reduce flicker on Microsoft Windows when the DesktopContainer 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 DesktopCanvas control. Stay away from using the DesktopWindow.Backdrop property, the DesktopWindow.Paint event, the DesktopCanvas.Backdrop property or the DesktopImageViewer control. Although those techniques work fine in certain situations, they often lead to improper drawing or slower performance in more complex window layouts.

With these tweaks, you can do all your drawing in the Paint event using the supplied graphics object parameter: g.

Note

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 Refresh method:

Canvas1.Refresh

or

Canvas1.Refresh(True)

Refresh tells the Canvas to update itself when it gets a redraw request from the operating system. Passing True to the Refresh method tells the Canvas to update itself immediately. Normally you want to use Refresh(False) as it results in fewer draw requests, improving performance.

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.

WinAPILib

The open-source WinAPILib project provides Declares to Windows-specific features and might be worth considering for your Windows projects.