Flicker-Free Resizing Dialog

CResizingDialog

This resizing dialog class was inspired by the code contributed by Hans Buehler, which I have used extensively in the past. In writing this class I have attempted to fix the problem of the excessive flicker that occurs as you resize a dialog and the controls are dynamically moved around (I assume you have the "Show window contents while dragging" explorer option set).

Flickering occurs because the dialog erases it's background during WM_ERASEBKGND processing and then the control windows are drawn on top. For most controls this is unnecessary since they erase their window rectangle before drawing themselves (there are some annoying exceptions which I will get to later). The solution is to add an OnEraseBkgnd() handler to the sizing dialog class and exclude the rectangle occupied by the control window from the clipping region using CDC::ExcludeClipRect().

How to use it

  1. I use the STL implementation of vector so you'll have to ensure that you add #include <vector> to your stdafx.h file.
  2. Make your dialog class inherit from CResizingDialog instead of CDialog by adding #include "ResizingDialog.h" to your dialog header file and replacing all instances of "CDialog" with "CResizingDialog" in your dialog header and implementation files.
  3. If you haven't already done so then add a handler for WM_INITDIALOG in your dialog class, as described below.

WM_INITDIALOG

In your OnInitDialog() handler you need to do a few things. Firstly you must call the base class implementation, and secondly you need to add the controls that are to be dynamically repositioned as the dialog is resized. Here's an example of a minimal OnInitDialog() implementation.

BOOL CSampleDlg::OnInitDialog()
{
// call the base class, you must do this

    CResizingDialog::OnInitDialog();

// add sizing controls

    AddControl(IDC_EDIT1,sizeResize,sizeNone);
    AddControl(IDC_EDIT2,sizeResize,sizeNone);

    AddControl(IDOK,sizeRelative,sizeRepos);
    AddControl(IDCANCEL,sizeRelative,sizeRepos);

// OK

    return TRUE;
}

The members of CResizingDialog that you can call are as follows. 

void AddControl(const UINT resID,const eSizeType xsize,const eSizeType ysize,const bool bFlickerFree=true)

Adds a control to the list of those that will be dynamically resized. resID is the integer resource identifier of the control. xsize and ysize govern how the control will be resized or repositioned in the horizontal and vertical directions when the dialog is resized by the user. Their values are taken from the following enumeration.

sizeNone Don't resize at all 
sizeResize The control will be stretched in the appropriate direction
sizeRepos The control will be moved in the appropriate direction
sizeRelative The control will be moved proportionally in the appropriate direction

If you want the control to be resized in a flicker-free way then leave the last parameter as true. Some controls, such as group boxes and static rectangles, do not erase their own backgrounds and hence cannot be sized in a flicker free way. If you find that a control in your dialog is leaving 'trails' behind it when you resize it then set bFlickerFree to false.

void AllowSizing(const eSizeType xsize,const eSizeType ysize);

The default implementation allows resizing in both horizontal and vertical directions. You can call this function to disable sizing in any particular direction. Set xsize or ysize to either sizeNone or sizeResize to disable or enable resizing in that direction.

void HideSizeIcon(void)

The default implementation displays a small sizing icon in the bottom right corner of the dialog in order to give the user a visual cue that this dialog is resizable. If you don't want that icon to be displayed then call this function.

Downloads

Download demo project - 15 Kb
Download source - 4 Kb


Comments

  • There are no comments yet. Be the first to comment!

Leave a Comment
  • Your email address will not be published. All fields are required.

Top White Papers and Webcasts

  • With JRebel, developers get to see their code changes immediately, fine-tune their code with incremental changes, debug, explore and deploy their code with ease (both locally and remotely), and ultimately spend more time coding instead of waiting for the dreaded application redeploy to finish. Every time a developer tests a code change it takes minutes to build and deploy the application. JRebel keeps the app server running at all times, so testing is instantaneous and interactive.

  • Live Event Date: May 6, 2014 @ 1:00 p.m. ET / 10:00 a.m. PT While you likely have very good reasons for remaining on WinXP after end of support -- an estimated 20-30% of worldwide devices still are -- the bottom line is your security risk is now significant. In the absence of security patches, attackers will certainly turn their attention to this new opportunity. Join Lumension Vice President Paul Zimski in this one-hour webcast to discuss risk and, more importantly, 5 pragmatic risk mitigation techniques …

Most Popular Programming Stories

More for Developers

Latest Developer Headlines

RSS Feeds