Click here to Skip to main content
Click here to Skip to main content

Resizable dialogs, form views and property sheets for WTL

, 7 Jul 2002
Rate this:
Please Sign up or sign in to vote.
Implementation of resizable dialogs, form views and property sheets for WTL
<!-- Download Links -->

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:
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:
    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:
    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:
    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... ). 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:
      	AttachForm(IDC_1, ATTACH_RIGHT);
      
      will have the following effect:

      AttachForm(ATTACH_RIGHT)

      And the following code:
      	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:
      	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:
      	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:
      	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:
      	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:
      	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:
      	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:

    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 .

    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

    Share

    About the Author

    Serge Weinstock
    Web Developer
    United Kingdom United Kingdom
    No Biography provided

    Comments and Discussions

     
    GeneralRe: Use built-in gripper instead of SizeGrip PinmemberSerge Weinstock16-Dec-01 23:28 
    GeneralBug followed from CScrollImpl PinmemberMaks Pyatkovsky17-Oct-01 4:03 
    GeneralRe: Bug followed from CScrollImpl PinmemberSerge Weinstock17-Oct-01 10:55 
    GeneralScalable Dialog Class PinmemberAlfie Weinie14-Sep-01 7:20 
    GeneralAnother approach PinmemberSven Axelsson10-Sep-01 6:52 
    GeneralRe: Another approach PinmemberSerge Weinstock10-Sep-01 9:51 
    QuestionDoes anybody have experience with scalable dialogs? PinmemberAlfie Weinie7-Sep-01 15:09 
    AnswerRe: Does anybody have experience with scalable dialogs? PinmemberTodd Smith7-Sep-01 20:19 
    AnswerRe: Does anybody have experience with scalable dialogs? PinmemberSerge Weinstock10-Sep-01 4:19 
    GeneralRe: Does anybody have experience with scalable dialogs? PinmemberAlfie Weinie10-Sep-01 7:46 

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

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

    | Advertise | Privacy | Terms of Use | Mobile
    Web04 | 2.8.1411028.1 | Last Updated 8 Jul 2002
    Article Copyright 2001 by Serge Weinstock
    Everything else Copyright © CodeProject, 1999-2014
    Layout: fixed | fluid