Click here to Skip to main content
16,015,658 members
Articles / Desktop Programming / MFC
Article

CResizableSheet and CResizablePage

Rate me:
Please Sign up or sign in to vote.
4.90/5 (20 votes)
27 Oct 2001CPOL 409K   8.7K   96   121
Two CPropertySheet/CPropertyPage derived classes to implement resizable property sheets or wizard dialogs with MFC

CResizableSheet(Ex) and CResizablePage(Ex)

These four classes handle resizable property sheets, wizards and the wizard 97 style dialogs, and are now fully based on my ResizableLib class library (see article).

The user will have the ability to resize the dialog, with consequent rearrangement of child windows. You can control the minimum and maximum size allowed, as well as the maximized size and position of the dialog. The size grip is displayed by default, but you may turn it off. Automatic Save/Restore the dialog's size and position, along with the active page, is also supported.

Conversion of a previously existant property sheet or wizard should be very simple.

I will talk about non-Ex classes for the rest of the article, but the same concepts applies for Wizard 97 dialogs.

The Sample Applications

This is a view of the sample dialog at minimum size as a property sheet and in wizard mode:

Property sheet with smaller size and proportional resizing Wizard mode with help button and minimal size

Note that the minimum width is not the default. You may see how to do this in the next section.

This is a screenshot of the resizable version of Wizard97 sample project coming with Visual C++.

A resizable Wizard 97 dialog

Usage - Step by Step

Add the ResizableLib to your project's workspace, as explained in the relative article.

Create a property sheet or wizard dialog and do the relative associations with MFC classes, for example using the Property Sheet component, or take one you have already made which you want to be resizable. You don't need to change any window style to have the dialog resizing.

Include 'ResizableSheet.h' in the property sheet associated header file.

Search and replace all CPropertySheet occurences with CResizableSheet in both your .cpp and .h files, just as if your property sheet class was derived from CResizableSheet instead of CPropertySheet.

Include 'ResizablePage.h' in the property pages associated header file.

Search and replace all CPropertyPage occurences with CResizablePage in both your .cpp and .h files, just as if your property page classes were derived from CResizablePage instead of CPropertyPage.

The same applies for wizard dialogs, of course.

Your property sheet header file should appear like this:

// MyPropertySheet.h : header file
//

#include "MyPropertyPages.h"

/////////////////////////////////////////////////////////////////////////////
// CMyPropertySheet

#include "ResizableSheet.h"

class CMyPropertySheet : public CResizableSheet
{
    DECLARE_DYNAMIC(CMyPropertySheet)

// Construction
public:
    CMyPropertySheet(CWnd* pWndParent = NULL);

// ( other stuff )
// ...
}

In your OnInitDialog override you may change the initial settings of your property sheet, such as the minimum size and automatic save/restore, that can optionally set also the active page.

BOOL CMyPropertySheet::OnInitDialog() 
{
    CResizableSheet::OnInitDialog();
    
    // set minimal size
    CRect rc;
    GetWindowRect(&rc);

    SetMinTrackSize(CSize(GetMinWidth(), rc.Height()));

    // enable save/restore, with active page
    EnableSaveRestore(_T("Properties"), TRUE, TRUE);

    return TRUE;
}

Your property pages header file should appear like this:

// MyPropertyPages.h : header file
//

/////////////////////////////////////////////////////////////////////////////
// CMyPropertyPage1 dialog

#include "ResizablePage.h"

class CMyPropertyPage1 : public CResizablePage
{
    DECLARE_DYNCREATE(CMyPropertyPage1)
// ...
}

// and so on for the other pages ...

In each page's OnInitDialog override you only have to set a layout for your controls. You specify where to attach the top-left and bottom-right corners by horizontal/vertical percentage or using predefined constants.

BOOL CMyPropertyPage2::OnInitDialog() 
{
    CResizablePage::OnInitDialog();
    
    // preset layout
    AddAnchor(IDC_LIST1, TOP_LEFT, CSize(50,70));
    AddAnchor(IDC_PICTURE1, CSize(50,0), CSize(100,70));
    AddAnchor(IDC_GROUP1, CSize(0,70), BOTTOM_RIGHT);
    AddAnchor(IDC_CHECK1, CSize(0,85));
    AddAnchor(IDC_RADIO1, CSize(100,85));
    AddAnchor(IDC_COMBO1, CSize(100,70));
    AddAnchor(IDC_BUTTON1, BOTTOM_RIGHT);

    m_ctlEdit1.AddString(_T("Just a single item to test the "
        "listbox behavior with very long lines..."));
    m_ctlEdit1.SetHorizontalExtent(300);

    return TRUE;
}

You are ready to rebuild your project and you will have a resizable property sheet or a wizard dialog just as you wanted.

For further details, see the next section.

Class Reference

The property sheet class inherits from CResizableLayout, CResizableGrip, CResizableMinMax, CResizableState and obviously from CPropertySheet.

Image 4

The property page class inherits from CResizableLayout and obviously from CPropertyPage. The other classes are not needed.

Image 5

CResizableSheet::CResizableSheet

CResizableSheet()
CResizableSheet(UINT nIDTemplate, CWnd* pParentWnd = NULL)
CResizableSheet(LPCTSTR lpszTemplateName, CWnd* pParentWnd = NULL)

CResizablePage::CResizablePage

CResizablePage()
CResizablePage(UINT nIDTemplate, CWnd* pParentWnd = NULL)
CResizablePAge(LPCTSTR lpszTemplateName, CWnd* pParentWnd = NULL)

The first form is the default constructor.

The second and the third forms are needed to reproduce the construction scheme of a CPropertySheet/Page derived class. Since the dialog resource template is needed by the CPropertySheet/Page constructor, you have to call one of these forms of the CResizableSheet/Page constructor. This is the reason why replacing one class with the other will work.

CResizableSheet::EnableSaveRestore

void EnableSaveRestore(LPCTSTR pszSection, BOOL bRectOnly, BOOL bWithPage = FALSE)

Enables automatic save/restore on dialog's open/close operations. The first argument is the same as in CWinApp::WriteProfileString. If bRectOnly is TRUE, the minimized/maximized state is not saved/restored. The last argument is a flag for restoring the active page (active page is always saved). Should be called after all the layout settings.

If you want details on how these settings are stored, look at CWinApp::SetRegistryKey, CWinApp::m_pszProfileName, CWinApp::m_pszRegistryKey on MFC documentation.

CResizable???::???

Implemented in the various base classes, see ResizableLib article.

Member functions to set/reset maximized size and position may seem rather useless, since you don't have a maximize box in the window's caption. I left them because I think it should be possible to enable caption buttons, playing a little with window's styles.

Conclusion

I hope these classes can make some programmers' life a little easier. I also want to thank Jerzy Kaczorowski for his unique support during the port of CResizableDialog code to property sheets.

Integration with ResizableLib is now complete. This required a partial rewriting, but I hope it will benefit of all the improvements made to the library (and the bugs too).

The CVS tree is now on Source Forge.

Updates

28 Jul 2000

Initial public release.

27 Oct 2000

Fixed bug with stacked tabs.
Controls that need refresh now display correctly.
Replaced internal structure with a CArray.

13 Mar 2001

Fixed a bug with radio buttons and group boxes (thanks to Matt Philmon)
Changed copyright note

11 Jun 2001

New implementation and integration with ResizableLib

15 Jul 2001

Updated to new ResizableLib release
Complete integration with the library, now using new callback anchors
Added support for 'Wizard 97' style dialogs

28 Oct 2001

Version 1.1 (CVS Tag: SF_1_1)
Fixed a bug with CTRL+Tab while navigating Wizard dialogs
Added static build configurations to all projects

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)


Written By
Technical Lead RoboTech srl
Italy Italy
Paolo began programming at the age of 9 with a glorious Olivetti M24 (i8086) and GW-BASIC, then he played a bit with Turbo C, Turbo Pascal and Assembly (using the MS-DOS Debug). Quick BASIC and Visual Basic shortly followed, until he learned C++ in College. He tought himself MFC and Windows programming, along with some DHTML and Javascript.

Always attracted by low-level programming and Assembly, he started to appreciate the joys of templates and STL while working for his Master Thesis. For seven months he was playing with airplanes and automatic control at the Unversity of Illinois at Urbana-Champaign, where he first met QNX and embedded systems.

In his job experience he learned Java to develop user interfaces and graphical editors, and re-discovered the Eclipse IDE that he had used in its early versions with the QNX SDK. He also deepened his knowledge of Linux and embedded systems, microcontrollers firmware and embedded voice recognition, while also practicing electronics design.

He graduated in Computer Engineering (Ingegneria informatica) at the University of Pisa, Italy, in December 2003. Currently working for an electronics and robotics company (www.robotechsrl.com).

He lives in Pisa and in Follonica (GR), Italy.

Comments and Discussions

 
QuestionTabbing through controls Pin
YanezDeGomeyra21-Jul-11 5:21
YanezDeGomeyra21-Jul-11 5:21 
Hi there,

great article, thanks. It helped me a lot in propagating resizing messages across the pages in the sheet I was working on. But I have another problem, which I'm not sure is completely relevant with this thread, but I'll try anyway: my sheet is created as a child window inside a dialog (I thought I'd use the sheet's capability to swap pages with SetActive to change the contents of the dialog). I now have a problem with the keyboard navigation, which seems to be be having rather erratically. Note that the sheet is 'invisible' in that I've made it with no border, the ok/cancle/apply buttons and the tab control are also hidden.

The host dialog contains other controls so I'd like the keyboard navigation to be seamless going through the outer controls, then into the sheet's active page and then out again to the remaining controls in the dialog. At the moment, depending on what window has the focus, tabbing seems to go through a sub-group of controls, both inside and outside the sheet. Additionally, pressing the 'enter' key should do the default action of the control with the focus, for example the clicking of a button. Sometimes it doesn't.

Any idea how I could go about getting a tighter control over the tabbing and more in general, keyboard management?

Many thanks in advance,
Alberto
AnswerRe: Tabbing through controls Pin
Paolo Messina21-Jul-11 5:40
professionalPaolo Messina21-Jul-11 5:40 
GeneralRe: Tabbing through controls Pin
YanezDeGomeyra21-Jul-11 6:03
YanezDeGomeyra21-Jul-11 6:03 
GeneralRe: Tabbing through controls Pin
Paolo Messina21-Jul-11 6:46
professionalPaolo Messina21-Jul-11 6:46 
GeneralRe: Tabbing through controls Pin
YanezDeGomeyra21-Jul-11 6:56
YanezDeGomeyra21-Jul-11 6:56 
GeneralModeless PropertySheet [modified] Pin
Fariborz_576-Mar-08 4:45
Fariborz_576-Mar-08 4:45 
GeneralTab control was drawn incorrectly if the property sheet was themed under XP Pin
Dandy Cheung15-Feb-08 5:01
Dandy Cheung15-Feb-08 5:01 
GeneralRe: Tab control was drawn incorrectly if the property sheet was themed under XP Pin
Dandy Cheung15-Feb-08 14:07
Dandy Cheung15-Feb-08 14:07 
GeneralRe: Tab control was drawn incorrectly if the property sheet was themed under XP Pin
anowsober25-May-09 21:14
anowsober25-May-09 21:14 
GeneralProblem in reusing CResizableSheet derived instance Pin
dobbs@riskeng.com23-Jan-08 4:38
dobbs@riskeng.com23-Jan-08 4:38 
GeneralRe: Problem in reusing CResizableSheet derived instance Pin
Paolo Messina23-Jan-08 5:28
professionalPaolo Messina23-Jan-08 5:28 
AnswerRe: Problem in reusing CResizableSheet derived instance Pin
Paolo Messina25-Jan-08 2:46
professionalPaolo Messina25-Jan-08 2:46 
GeneralCannot Compile neither Version 1.3 of library nor dialog demo Pin
zikTronics9-Aug-07 23:02
zikTronics9-Aug-07 23:02 
AnswerRe: Cannot Compile neither Version 1.3 of library nor dialog demo Pin
Paolo Messina9-Aug-07 23:33
professionalPaolo Messina9-Aug-07 23:33 
GeneralRe: Cannot Compile neither Version 1.3 of library nor dialog demo Pin
zikTronics20-Aug-07 5:04
zikTronics20-Aug-07 5:04 
Generallack buttons in CResizableSheet Pin
hphi29-Mar-07 23:07
hphi29-Mar-07 23:07 
AnswerRe: lack buttons in CResizableSheet Pin
Paolo Messina29-Mar-07 23:51
professionalPaolo Messina29-Mar-07 23:51 
GeneralRe: lack buttons in CResizableSheet Pin
hphi30-Mar-07 1:39
hphi30-Mar-07 1:39 
AnswerRe: lack buttons in CResizableSheet Pin
Paolo Messina25-Jan-08 2:50
professionalPaolo Messina25-Jan-08 2:50 
GeneralOnSetActive lost for the first page Pin
small Smiley14-Aug-06 5:15
small Smiley14-Aug-06 5:15 
AnswerRe: OnSetActive lost for the first page Pin
Paolo Messina14-Aug-06 23:36
professionalPaolo Messina14-Aug-06 23:36 
GeneralMoving pages Pin
small Smiley10-Jul-06 6:50
small Smiley10-Jul-06 6:50 
GeneralRe: Moving pages Pin
Paolo Messina11-Jul-06 5:21
professionalPaolo Messina11-Jul-06 5:21 
GeneralRe: Moving pages Pin
small Smiley12-Jul-06 21:54
small Smiley12-Jul-06 21:54 
AnswerRe: Moving pages Pin
Paolo Messina30-Jul-06 7:07
professionalPaolo Messina30-Jul-06 7:07 

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.