Click here to Skip to main content
Licence 
First Posted 19 May 2001
Views 127,146
Bookmarked 33 times

Resizable dialogs, form views and property sheets for WTL

By | 7 Jul 2002 | Article
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:
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

    About the Author

    Serge Weinstock

    Web Developer

    United Kingdom United Kingdom

    Member



    Sign Up to vote   Poor Excellent
    Add a reason or comment to your vote: x
    Votes of 3 or less require a comment

    Comments and Discussions

     
    You must Sign In to use this message board. (secure sign-in)
     
    Search this forum  
     FAQ
        Noise  Layout  Per page   
      Refresh
    QuestionLayoutMgr and WTL 7.1 PinmemberLotharLanger4:54 8 Sep '05  
    Hi Serge,
     
    great article and congratulations ... your resizable classes are ready to use. Only one thing that most likely has to do with WTL 7.1:
    So I compiled your example project usind Visual Studio .Net 2003 and WTL 7.1 and there was just one change I had to do, 'WTL::_U_STRINGorID' to 'ATL::_U_STRINGorID' in LayoutMgr.h.
    But now there is a misbehaviour of ActiveX controls. The controls in your form view as well as the 'CAxResizablePropertyPageImpl' - derived dialogs appear to have a shadow on the screen, a double existence ... which can be kind of annoying.
    Unfortunately the AX ctrls are the point I was looking for when I came across your article.
     
    Is there an easy fix to this thing or where would I most likely have to look at ?
     
    Thanks,
    Lothar
    QuestionCan this be used on non-WTL stuff too? PinmemberCoruscant22:28 12 Apr '05  
    GeneralFixing Screen Flciker On XP PinmemberStagger Lee7:52 21 Oct '04  
    GeneralDoes anybody know how to remove the form paint PinmemberOuTPuT4:24 11 Sep '03  
    QuestionDoes this work with listview elements??? Pinmemberlamarama11:55 12 Feb '03  
    Questiona little too complicated!? Pinmemberjohnthan23:21 9 Nov '02  
    GeneralHelp need from MFC to WTL PinsussAnonymous10:23 23 Sep '02  
    GeneralSmall bug. PinmemberGeorge20058:22 17 May '02  
    GeneralRe: Small bug. PinmemberSerge Weinstock0:05 8 Jul '02  
    GeneralUse built-in gripper instead of SizeGrip PinmemberDaniel Bowen12:47 27 Nov '01  
    GeneralRe: Use built-in gripper instead of SizeGrip PinmemberSerge Weinstock22:28 16 Dec '01  
    GeneralBug followed from CScrollImpl PinmemberMaks Pyatkovsky3:03 17 Oct '01  
    GeneralRe: Bug followed from CScrollImpl PinmemberSerge Weinstock9:55 17 Oct '01  
    GeneralScalable Dialog Class PinmemberAlfie Weinie6:20 14 Sep '01  
    GeneralAnother approach PinmemberSven Axelsson5:52 10 Sep '01  
    GeneralRe: Another approach PinmemberSerge Weinstock8:51 10 Sep '01  
    QuestionDoes anybody have experience with scalable dialogs? PinmemberAlfie Weinie14:09 7 Sep '01  
    AnswerRe: Does anybody have experience with scalable dialogs? PinmemberTodd Smith19:19 7 Sep '01  
    AnswerRe: Does anybody have experience with scalable dialogs? PinmemberSerge Weinstock3:19 10 Sep '01  
    GeneralRe: Does anybody have experience with scalable dialogs? PinmemberAlfie Weinie6:46 10 Sep '01  
    GeneralRe: Does anybody have experience with scalable dialogs? PinmemberSerge Weinstock8:21 10 Sep '01  
    GeneralA very handy class! But... PinmemberMaksym6:28 6 Sep '01  
    GeneralRe: A very handy class! But... PinmemberSerge Weinstock2:59 7 Sep '01  
    GeneralChild ResizableFormView PinmemberAnonymous7:55 2 Jul '01  
    GeneralA slight funkiness PinmemberDarren Schroeder15:55 20 May '01  

    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.

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