Click here to Skip to main content
15,867,568 members
Articles / Desktop Programming / WTL
Article

Resizable dialogs, form views and property sheets for WTL

Rate me:
Please Sign up or sign in to vote.
4.79/5 (9 votes)
7 Jul 20026 min read 172.8K   2.8K   38   28
Implementation of resizable dialogs, form views and property sheets for WTL

Resizable Form View

Introduction

These classes provides an easy way to implement in WTL, resizable windows with layout management of the children. Support is provided for:
  • Form views
  • Dialogs
  • Property Sheet and property pages
Furthermore, support is also provided for using property sheet as child windows.

How to use the classes in your WTL application

Resizeable form views

  • Include the file LayoutMgr.h in the header file of your dialog class and add the file LayoutMgr.cpp to your project.
  • Derive your form view class from CResizableFormViewImpl instead of CDialogImpl.
  • Add the message map of CResizableFormViewImpl before your own message handlers.
  • Override the DefineLayout method in order to set the layout constraints.
  • Define the array _controlsToClip which defines the controls which should be clipped when painting the dialog.
Your class should look like:
C++
class MyFormView : public CResizableFormViewImpl<MyFormView>
{
public:
	typedef CResizableFormViewImpl<MyFormView> dlgBase;
	...
	BEGIN_MSG_MAP(MyFormView)
		CHAIN_MSG_MAP(dlgBase)
		...
	END_MSG_MAP()
	...
	virtual void DefineLayout();
	static const UINT _controlsToClip[];
};	

Resizeable dialogs

  • Include the file LayoutMgr.h in the header file of your dialog class and add the file LayoutMgr.cpp to your project.
  • Derive your dialog class from CResizableDialogImpl instead of CDialogImpl.
  • Add the message map of CResizableDialogImpl before your own message handlers.
  • Override the DefineLayout method in order to set the layout constraints.
  • Define the array _controlsToClip which defines the controls which should be clipped when painting the dialog.
  • In the call to CResizableDialogImpl constructor, you can change the value of the flag useHandle. If this flag is set to true (default value), a sizing gripper is displayed in the lower right corner of the dialog.
  • Your class should look like:
    C++
    class MyDialog : public CResizableDialogImpl<MyDialog>
    {
    public:
    	typedef CResizableDialogImpl<MyDialog> dlgBase;
    	...
    	BEGIN_MSG_MAP(MyDialog)
    		CHAIN_MSG_MAP(dlgBase)
    		...
    	END_MSG_MAP()
    	...
    	virtual void DefineLayout();
    	static const UINT _controlsToClip[];
    };	

    Resizeable property sheet

    • Include the file LayoutMgr.h in the header files of your property sheet and property pages classes and add the file LayoutMgr.cpp to your project.
    • For the property sheet:
      • If you want to use your property sheet:
        • as a popup window:
          • Derive your property sheet class from CPopupResizablePropertySheetImpl instead of CPropertySheetImpl.
          • In the call to CPopupResizablePropertySheetImpl constructor, you can change the value of the flag useHandle. If this flag is set to true (default value), a sizing gripper is displayed in the lower right corner of the property sheet.
        • as a child window:
          • Derive your property sheet from CChildResizablePropertySheetImpl instead of CPropertySheetImpl.
          • Pass the ID of the control which will serve as a place holder for the property sheet to the call of the constructor of CChildResizablePropertySheetImpl.
          • Call the method Create in the parent window for creating the property sheet.
      • Add the message map of CPopupResizablePropertySheetImpl or CChildResizablePropertySheetImpl before your own message handlers.
    • For the property pages:
    • Property sheets don't receive any WM_INITDIALOG message. If you want to do something just after the initialisation of the property sheet, you can override the method OnInitDialog.
    Your property sheet class should look like:
    C++
    class MyPropertySheet : public CPopupResizablePropertySheetImpl<MyPropertySheet>
    {
    public:
    	typedef CPopupResizablePropertySheetImpl<MyPropertySheet> dlgBase;
    	...
    	BEGIN_MSG_MAP(MyPropertySheet)
    		CHAIN_MSG_MAP(dlgBase)
    		...
    	END_MSG_MAP()
    	...
    };	
    Your propety page classes should look like:
    C++
    class MyPropertyPage : public CResizablePropertyPageImpl<MyPropertyPage>
    {
    public:
    	typedef CResizablePropertyPageImpl<MyPropertyPage> dlgBase;
    	...
    	BEGIN_MSG_MAP(MyPropertyPage)
    		CHAIN_MSG_MAP(dlgBase)
    		...
    	END_MSG_MAP()
    	...
    	virtual void DefineLayout();
    	static const UINT _controlsToClip[];
    };	

    Setting the layout constraints

    In order to layout the children when the dialog is resized, you must override the DefineLayout method. This method is called during the initialisation of the dialog and allow to define the geometrical relationships between the child window which will alow to move and resize them in the desired way.

    The way of setting layout constraints is inspired by the methods of the XmForm widget of Motif (quite old stuff... Image 2). It's a little tedious, but very simple and efficient.

    Constraints are defined by attaching the sides of a child window to the side of another child window or to one of the side of the parent window.

    • By default all the sides of a child window are without any constraint (method AttachNone). It means that when the dialog is resized, the child window is neither resized nor moved:

      No constraints

    • A side of a child window can be attach to the same side of the parent window (method AttachForm). For example the following code:
      C++
      AttachForm(IDC_1, ATTACH_RIGHT);
      
      will have the following effect:

      AttachForm(ATTACH_RIGHT)

      And the following code:
      C++
      AttachForm(IDC_1, ATTACH_LEFT);
      AttachForm(IDC_1, ATTACH_RIGHT);
      
      will have the following effect:

      AttachForm(ATTACH_LEFT & ATTACH_RIGHT)

      The horizontal or the vertical center of the child window can be attached to the parent window. For example the following code:
      C++
      AttachForm(IDC_1, ATTACH_HCENTER);
      
      will have the following effect:

      AttachForm(ATTACH_HCENTER)

    • A side of a child window can be attach to the opposite side of the parent window (method AttachOppositeForm). For example the following code:
      C++
      AttachOppositeForm(IDC_1, ATTACH_LEFT);
      
      will have the following effect:

      AttachOppositeForm(ATTACH_LEFT)

    • A side of a child window can be attach to the opposite side of another child window (method AttachWidget). For example the following code:
      C++
      AttachForm(IDC_1, ATTACH_HCENTER);
      AttachWidget(IDC_2, ATTACH_LEFT, IDC_1);
      
      will have the following effect:

      AttachWidget

    • A side of a child window can be attach to the same side of another child window (method AttachOppositeWidget). For example the following code:
      C++
      AttachForm(IDC_1, ATTACH_LEFT);
      AttachForm(IDC_1, ATTACH_RIGHT);
      AttachOppositeWidget(IDC_2, ATTACH_LEFT, IDC_1);
      AttachOppositeWidget(IDC_2, ATTACH_RIGHT, IDC_1);
      
      will have the following effect:

      AttachOppositeWidget

      The horizontal or the vertical center of the child window can be attached to the same side of another child window. For example the following code:
      C++
      AttachForm(IDC_1, ATTACH_LEFT);
      AttachForm(IDC_1, ATTACH_RIGHT);
      AttachOppositeWidget(IDC_2, ATTACH_HCENTER, IDC_1);
      
      will have the following effect:

      AttachOppositeWidget(ATTACH_HCENTER)

    • A side of a child window can be attach to an invisible grid which is resized with the parent window (method AttachPosition). For example the following code:
      C++
      SetNPositions(3);
      AttachPosition(IDC_1, ATTACH_LEFT, 0);
      AttachPosition(IDC_1, ATTACH_RIGHT, 1);
      AttachPosition(IDC_2, ATTACH_LEFT, 1);
      AttachPosition(IDC_2, ATTACH_RIGHT, 2);
      AttachPosition(IDC_3, ATTACH_LEFT, 2);
      AttachPosition(IDC_3, ATTACH_RIGHT, 3);
      
      will have the following effect:

      AttachPosition

    Avoiding screen flickering

    When a dialog is resized, the whole client are is filled with the background color, before the child window are painted. This causes screen flickering.

    What's need to be done is to clip the children windows before painting the dialog background. Dialogs can have the WS_CLIPCHILDREN window style which ensure that all the dialog children are clipped before painting. But in most of the cases, it's not possible to use this style because controls like static controls don't paint their background themselves.

    To avoid this, the WM_ERASEBKGND message is handled by all the CResizableXXXImpl classes. The classes excludes all the controls which IDs are in the _controlsToClip array, from the DC used for painting the background. So for avoiding screen flickering, you just have to "override" the _controlsToClip array.

    Your classes should look like:

    C++
    class MyDialog : public CResizableDialogImpl<MyDialog>
    {
    	...
    	static const UINT _controlsToClip[];
    };	
    
    const UINT MyDialog::_controlsToClip[] = 
    {
    	IDC_IMG,
    	IDOK,
    	...
    	0
    };

    NB

    The current code handles incorrectly the clipping of some controls when using Windows XP themes (the problems occur with tab controls and scrolled windows). Therefore, the automatic clipping of children control is disallowed when using Windows XP

    Hosting ActiveX controls

    If your dialog hosts ActiveX controls, use:

    • CAxResizableDialogImpl instead of CResizableDialogImpl
    • CAxResizableFormViewImpl instead of CResizableFormViewImpl
    • CAxResizablePropertyPageImpl instead of CResizablePropertyPageImpl

    Minimum size of the dialogs

    In order to avoid to deal with dialogs of size 10x10 pixels, a minimum size for the dialogs and FormViews is set.

    • For dialogs, the minimum size is the size of the dialog template (the size set in the dialog editor). The user is not able to resize the dialog window under this minimum size.
    • For FormViews, the minimum size is the size of the dialog template (the size set in the dialog editor). If the user resizes the view under this minimum size, scrollbars are shown.
    • For "popup" property sheet, the minimum size is the size of the property sheet just after creation. This size should be the maximum size of the dialog templates of the property pages.

    Latest Updates

    • 9th July 2002
      • Fixed some class name clashes appearing when using WTL7 & ATL7
      • Replaced the SizeGrip window by a standard scrollbar as suggested by Daniel Bowen
      • Added the Unattach methods for removing a control from the list of windows managed by the layout manager
      • Added a maximum size. The maximum size information is only used if _maxWindowSize.cx or _maxWindowSize.cy is greater than 0
      • Implements a workaround an ATL7 bug which prevents ActiveX controls to be initialised in CAxPropertySheetImpl
      • Disabled the clipping code when working with Windows XP
    • 7th September 2001
      • Added support for hosting ActiveX controls.
      • Changed the user messages from arbitrary constants to registered messages
    • 22nd May 2001
      • Fixed the way minimum sizes and scrollbars are handled in FormViews

    Serge Image 12.

    License

    This article has no explicit license attached to it but may contain usage terms in the article text or the download files themselves. If in doubt please contact the author via the discussion board below.

    A list of licenses authors might use can be found here


    Written By
    Web Developer
    United Kingdom United Kingdom
    This member has not yet provided a Biography. Assume it's interesting and varied, and probably something to do with programming.

    Comments and Discussions

     
    QuestionLayoutMgr and WTL 7.1 Pin
    LotharLanger8-Sep-05 4:54
    LotharLanger8-Sep-05 4:54 
    QuestionCan this be used on non-WTL stuff too? Pin
    Coruscant12-Apr-05 22:28
    Coruscant12-Apr-05 22:28 
    GeneralFixing Screen Flciker On XP Pin
    JBurkey21-Oct-04 7:52
    JBurkey21-Oct-04 7:52 
    GeneralDoes anybody know how to remove the form paint Pin
    OuTPuT11-Sep-03 4:24
    OuTPuT11-Sep-03 4:24 
    QuestionDoes this work with listview elements??? Pin
    lamarama12-Feb-03 11:55
    lamarama12-Feb-03 11:55 
    Questiona little too complicated!? Pin
    ChauJohnthan9-Nov-02 23:21
    ChauJohnthan9-Nov-02 23:21 
    GeneralHelp need from MFC to WTL Pin
    Anonymous23-Sep-02 10:23
    Anonymous23-Sep-02 10:23 
    GeneralSmall bug. Pin
    17-May-02 8:22
    suss17-May-02 8:22 
    GeneralRe: Small bug. Pin
    Serge Weinstock8-Jul-02 0:05
    Serge Weinstock8-Jul-02 0:05 
    GeneralUse built-in gripper instead of SizeGrip Pin
    Daniel Bowen27-Nov-01 12:47
    Daniel Bowen27-Nov-01 12:47 
    GeneralRe: Use built-in gripper instead of SizeGrip Pin
    Serge Weinstock16-Dec-01 22:28
    Serge Weinstock16-Dec-01 22:28 
    GeneralBug followed from CScrollImpl Pin
    Maksim Pyatkovskiy17-Oct-01 3:03
    Maksim Pyatkovskiy17-Oct-01 3:03 
    GeneralRe: Bug followed from CScrollImpl Pin
    Serge Weinstock17-Oct-01 9:55
    Serge Weinstock17-Oct-01 9:55 
    GeneralScalable Dialog Class Pin
    Alfie Weinie14-Sep-01 6:20
    Alfie Weinie14-Sep-01 6:20 
    GeneralAnother approach Pin
    Sven Axelsson10-Sep-01 5:52
    Sven Axelsson10-Sep-01 5:52 
    GeneralRe: Another approach Pin
    Serge Weinstock10-Sep-01 8:51
    Serge Weinstock10-Sep-01 8:51 
    QuestionDoes anybody have experience with scalable dialogs? Pin
    Alfie Weinie7-Sep-01 14:09
    Alfie Weinie7-Sep-01 14:09 
    AnswerRe: Does anybody have experience with scalable dialogs? Pin
    Todd Smith7-Sep-01 19:19
    Todd Smith7-Sep-01 19:19 
    Are you looking for a solution to the Small vs. Large font problem with dialogs? If so I came up with a bit of code the other day to handle this. I use it in an ATL dialog project.
    AnswerRe: Does anybody have experience with scalable dialogs? Pin
    Serge Weinstock10-Sep-01 3:19
    Serge Weinstock10-Sep-01 3:19 
    GeneralRe: Does anybody have experience with scalable dialogs? Pin
    Alfie Weinie10-Sep-01 6:46
    Alfie Weinie10-Sep-01 6:46 
    GeneralRe: Does anybody have experience with scalable dialogs? Pin
    Serge Weinstock10-Sep-01 8:21
    Serge Weinstock10-Sep-01 8:21 
    GeneralA very handy class! But... Pin
    6-Sep-01 6:28
    suss6-Sep-01 6:28 
    GeneralRe: A very handy class! But... Pin
    Serge Weinstock7-Sep-01 2:59
    Serge Weinstock7-Sep-01 2:59 
    GeneralChild ResizableFormView Pin
    2-Jul-01 7:55
    suss2-Jul-01 7:55 
    GeneralA slight funkiness Pin
    Darren Schroeder20-May-01 15:55
    Darren Schroeder20-May-01 15:55 

    General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

    Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.