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

CResizableSheet and CResizablePage

By , 27 Oct 2001
 

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.

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

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)

About the Author

Paolo Messina
Software Developer RoboTech srl
Italy Italy
Member
Paolo began programming at the age of 9 with a glorious 8086 and GW-BASIC, then he played a bit with C, ASM and Pascal. He tought himself MFC and Windows programming, to exploit his studies of C++. Always attracted by low-level programming and Assembly, he's beginning to appreciate the joys of templates and STL. At work he changed his mind about Java, discovered Eclipse IDE, and now think it's cool.
 
He lives in Follonica, Italy.
 
He has been abroad in the U.S. to work on his final thesis before graduating. For seven months he was playing with airplanes and automatic control at the Unversity of Illinois at Urbana-Champaign.
 
He graduated in Computer Science Engineering at the University of Pisa, Italy, in December 2003.
 
Currently working for an edutainment robotics company (www.robotechsrl.com).

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.
Search this forum  
    Spacing  Noise  Layout  Per page   
GeneralRe: Problem in reusing CResizableSheet derived instancememberPaolo Messina23 Jan '08 - 5:28 
Hi Rich,
 
The latest version has the same issue. I'm going to investigate it further, I'll keep you informed.
 
Paolo
 
------
Why spend 2 minutes doing it by hand when you can spend all night plus most of the following day writing a system to do it for you? - (Chris Maunder)

AnswerRe: Problem in reusing CResizableSheet derived instancememberPaolo Messina25 Jan '08 - 2:46 
Hi Rich,
 
I didn't code the library classes with "window reuse" in mind. I don't even know if it's a recommended practice in general, but I guess it should be supported, at least for dialogs.
The problem is that the instance data should be re-initialized for each new window, and ResizableLib classes didn't do that.
 
Actually, I implemented a fix that resets the internal state when the window is destroyed. You may download an experimental version, with a modified demo project, from:
http://resizablelib.sourceforge.net/RszLib_Test1.zip[^]
 
Paolo
 
------
Why spend 2 minutes doing it by hand when you can spend all night plus most of the following day writing a system to do it for you? - (Chris Maunder)

GeneralCannot Compile neither Version 1.3 of library nor dialog demomemberzikTronics9 Aug '07 - 23:02 
Hello !
 
I just downloaded the version 1.3 of the library and tried to compile it. The compiler immediately gave me these errors :
ResizableLayout.cpp(323) : error C2065: 'WC_STATIC' : undeclared identifier
ResizableLayout.cpp(365) : error C2065: 'WC_LISTBOX' : undeclared identifier
ResizableLayout.cpp(407) : error C2065: 'WC_BUTTON' : undeclared identifier
 
I have no trace nor any clue of what these MACRO should be ...
Please help me on this issue.
 
For testing, I defined these macro to some text and it compiled fine.
I then tried to compile the dialog demo project. Bardaf, does not compile neither .... :
"SecondDialog.cpp(72) : error C2065: 'ANCHOR' : undeclared identifier"
Gees, am I missing to common standard include file or the author had some problems dealing with versioning ?
I defined ANCHOR(x,y) to be CSize(x,y) and it all compiled fine, but these are just workarounds ...
 
Thanx for your help.
 
Tronics.
AnswerRe: Cannot Compile neither Version 1.3 of library nor dialog demomemberPaolo Messina9 Aug '07 - 23:33 
zikTronics wrote:
ResizableLayout.cpp(323) : error C2065: 'WC_STATIC' : undeclared identifier
ResizableLayout.cpp(365) : error C2065: 'WC_LISTBOX' : undeclared identifier
ResizableLayout.cpp(407) : error C2065: 'WC_BUTTON' : undeclared identifier
 
I have no trace nor any clue of what these MACRO should be ...

 
Please see http://www.codeproject.com/dialog/ResizableLib.asp?msg=320658#xx320658xx[^]
 
As for the other issues, I don't have any clue. Just make sure you are using the same version for the library and the demo projects. And why don't you try the latest version?
 
Paolo
 
------
Why spend 2 minutes doing it by hand when you can spend all night plus most of the following day writing a system to do it for you? - (Chris Maunder)

GeneralRe: Cannot Compile neither Version 1.3 of library nor dialog demomemberzikTronics20 Aug '07 - 5:04 
Thank you for your reponse, Paolo !
 
All the problems probably come from an old SDK version that I use.
I avoided using the latest version because it is in alpha version. You mentioned it is an incomplete version in your description ('Present and Future - Alpha Release 1.4a').
 
Anyhow, as I could play around with your library, let me congratulate you for the work ! Thanx.
 
Bye!
 
Tronics
Generallack buttons in CResizableSheetmemberhphi29 Mar '07 - 23:07 
Hello,
 
I've create a ResizableSheet derived class hold in a Resizable FormView.
The buttons IDS_NEXT, IDS_BACK, Cancel-Buttons lacks.
 
Can somebody help me?
AnswerRe: lack buttons in CResizableSheetmemberPaolo Messina29 Mar '07 - 23:51 
Pleas see:
http://msdn2.microsoft.com/en-us/library/ms907365.aspx[^]
 
And especially:
Modeless property sheets displayed with a call to Create do not have OK, Cancel, Apply Now, and Help buttons as modal property sheets do. Desired buttons must be created by the user.

 
------
Why spend 2 minutes doing it by hand when you can spend all night plus most of the following day writing a system to do it for you? - (Chris Maunder)

GeneralRe: lack buttons in CResizableSheetmemberhphi30 Mar '07 - 1:39 
Thanks for your promptly answer.
 
Where I must create this buttons?
 
In
- FormView - Resource,
- in PropertySheet-Class or
- in PropertyPages?
 
Can somebody send me any informations?
AnswerRe: lack buttons in CResizableSheetmemberPaolo Messina25 Jan '08 - 2:50 
Just in case anyone is still interested in the matter, have a look at:
Knowledge Base Q146916[^]
 
------
Why spend 2 minutes doing it by hand when you can spend all night plus most of the following day writing a system to do it for you? - (Chris Maunder)

GeneralOnSetActive lost for the first pagemembersmall Smiley14 Aug '06 - 5:15 
In my application (VC8, Windows XP) the OnSetActive message does not come, because
the window is not "visible" at the time of RSZSUP_SHEETPAGEEXHACK.
I´ve commentet out
//if (pWnd->IsWindowVisible())
so it seems to work, but i´m not sure Confused | :confused: if this is the correct way.

AnswerRe: OnSetActive lost for the first pagememberPaolo Messina14 Aug '06 - 23:36 
Well, I don't remember all that stuff, some time has passed since I wrote that, but you're right: I don't see why I was using IsWindowVisible to determine which page was the active one.
 
My suggestion is to compare pWnd->m_hWnd and GetActivePage()->GetSafeHwnd() instead. Can you try that and report if it still works?
 
With your solution all the pages gets activated in turn, and I don't know if the order of activation leads to a correct result every time. Most of all, I'm not sure that they should all get the activation at all. I guess the system behavior that we lose with the hack is just a single page activation, so that behavior is the one to recover.
 
Paolo
 
------
Why spend 2 minutes doing it by hand when you can spend all night plus most of the following day writing a system to do it for you? - (Chris Maunder)

GeneralMoving pagesmembersmall Smiley10 Jul '06 - 6:50 

I am trying use this lib with a existing project. This project moves the pages down in OnPageChanging in order to make space for a user-drawn Page header. The page header is drawn in sheet class. It works fine so far, but there is one problem: When I use your lib, the pages are moved back to the original position. I am not using Wisard97 style, because my page header is bigger than the Wizard97 style, an using the Wizard97 draws some rest parts of the tabcontrol. How can i manage to draw a userdefined header or frame for a page, or how can i prevent the lib to move the pages back?
GeneralRe: Moving pagesmemberPaolo Messina11 Jul '06 - 5:21 
Try to make space for the header before the library's OnInitDialog is called, such as in:
BOOL CMyPropertySheet::OnInitDialog() 
{
	// make room for the header (move tab control and pages)

	CResizableSheet::OnInitDialog();
 
	...
}
 
Hope this helps,
Paolo
 
------
Why spend 2 minutes doing it by hand when you can spend all night plus most of the following day writing a system to do it for you? - (Chris Maunder)

GeneralRe: Moving pagesmembersmall Smiley12 Jul '06 - 21:54 
I don´t understand how to make room there, the pages/tab control do not exist before CResizableSheet::OnInitDialog. Can the method CalcSizeExtra can be used for that somehow?
AnswerRe: Moving pagesmemberPaolo Messina30 Jul '06 - 7:07 
You're right, but you need to move the controls on the sheet before the library stores their initial position and size. This is done in CResizableSheet::PresetLayout, which is called in CResizableSheet::OnInitDialog. What you can do is to call yourself PresetLayout in your sheet's OnInitDialog, replacing the library's implementation:
BOOL CMyPropertySheet::OnInitDialog() 
{
	// skip the base class
	BOOL bResult = CPropertySheet::OnInitDialog();
 
	// ... move controls / make room here ...

	// set the initial size as the min track size
	CRect rc;
	GetWindowRect(&rc);
	SetMinTrackSize(rc.Size());
 
	// initialize layout
	PresetLayout();
	m_bLayoutDone = TRUE;
 
	return bResult;
}

 
------
Why spend 2 minutes doing it by hand when you can spend all night plus most of the following day writing a system to do it for you? - (Chris Maunder)

GeneralVC Designer Issuesmembersmall Smiley7 Jul '06 - 1:16 
Roll eyes | :rolleyes: If the macro 'CPropertyPageEx' is used as a base class in a derivation, the class wizard/designer cannot show events/methods, that can be used from the base class CPropertyPage.
(MFCVer >= 7: #define CPropertyPageEx CPropertyPage)
class CResizablePageEx : public CPropertyPageEx, public CResizableLayout.
 
I´d recommend to use this derivation for VC7/VC8 projects:
class CResizablePageEx : public CPropertyPage, public CResizableLayout
 
The base class should not be a specified by a MACRO definition. Big Grin | :-D
GeneralLinking problemsmembersbuonocore18 Aug '05 - 2:14 
Hi,
I tried to use your intersting code in a project of mine having PropertySheet but I had Linking problems:
 
Linking...
libcmt.lib(crt0dat.obj) : error LNK2005: _exit already defined in msvcrt.lib(MSVCRT.dll)
libcmt.lib(crt0dat.obj) : error LNK2005: __exit already defined in msvcrt.lib(MSVCRT.dll)
libcmt.lib(crt0init.obj) : error LNK2005: ___xc_z already defined in msvcrt.lib(cinitexe.obj)
libcmt.lib(crt0init.obj) : error LNK2005: ___xc_a already defined in msvcrt.lib(cinitexe.obj)
libcmt.lib(crt0init.obj) : error LNK2005: ___xi_z already defined in msvcrt.lib(cinitexe.obj)
libcmt.lib(crt0init.obj) : error LNK2005: ___xi_a already defined in msvcrt.lib(cinitexe.obj)
libcmt.lib(winxfltr.obj) : error LNK2005: __XcptFilter already defined in msvcrt.lib(MSVCRT.dll)
LINK : warning LNK4098: defaultlib "msvcrt.lib" conflicts with use of other libs; use /NODEFAULTLIB:library
LINK : warning LNK4098: defaultlib "libcmt.lib" conflicts with use of other libs; use /NODEFAULTLIB:library
libcmt.lib(crt0.obj) : error LNK2001: unresolved external symbol _main
Release/awnc.exe : fatal error LNK1120: 1 unresolved externals
Error executing link.exe.
 
Moreover, is possible to use only your 'ResizableLib.lib' and the header files 'Resizeblexxx.h' insted of including the whole project of yours in my workspace?
Thanks a lot
 
SB
GeneralRe: Linking problemsmemberPaolo Messina19 Aug '05 - 8:40 
sbuonocore wrote:
I tried to use your intersting code in a project of mine having PropertySheet but I had Linking problems
 
This is usually caused by different settings in the library and application projects for runtime libraries. It looks like your project is linking with static libraries, while the library is linking to the runtime DLLs.
 
I have set up different build configurations for the various combinations of Unicode/ANSI and Static/Dynamic runtime libraries. If you use the same naming convention on VC++ 6.0, it will pick up the correct configuration for the build. In VC++ .NET you can customize the build configuration associations, I'm not sure about VC++ 6.0 but I guess there's a similar option (I never tried).
 
sbuonocore wrote:
Moreover, is possible to use only your 'ResizableLib.lib' and the header files 'Resizeblexxx.h' insted of including the whole project of yours in my workspace?
 
It should be possible, picking up the correct LIB file from the various build directories (the one that matches your project configuration).
Having different names for the LIB file, based on the configuration, is on my TODO list...
 
Cheers,
Paolo
 
------
Why spend 2 minutes doing it by hand when you can spend all night plus most of the following day writing a system to do it for you? - (Chris Maunder)

General3 problems with 1.4alpha now...memberPeter SJöström12 Jul '05 - 5:33 
1) I have a Dialog based application where the main window has been changed to a CPropertySheet. I inheret CResizableSheet instead and when I start the application, it runs at almost 100 % CPU. I can't find why...
 
2) I have an owner draw report list view in the pages. This doesn't paint at all, hints on what messages are missing, deferred or what?
 
3) For the bottom section under the pages I have a few controls that I move with the window size myself. These get overdrawn by the Resizable framework so they sometimes show, sometimes don't show. Where would I control this?
GeneralRe: 3 problems with 1.4alpha now...memberPeter SJöström13 Jul '05 - 2:57 
I solved problem 3), it was my own fault.
GeneralCan't compile with 1.4alphamemberPeter SJöström6 Jul '05 - 5:26 
AddAnchor(IDC_LIST1, TOP_LEFT, CSize(50,70));
 
AddAnchor doesn't have the CSize() argument and refuses to compile. Does 1.4alpha support percentage in some way, or is it limited to anchoring to edges?
GeneralRe: Can't compile with 1.4alphamemberPaolo Messina6 Jul '05 - 5:45 
Peter SJöström wrote:
AddAnchor doesn't have the CSize() argument and refuses to compile. Does 1.4alpha support percentage in some way, or is it limited to anchoring to edges?
 
No, I just made a new class for anchors, no more CSize, it should be ANCHOR(50,70) or something. Look at the ResizableLayout.h file.
 
Cheers,
Paolo
 
------
Why spend 2 minutes doing it by hand when you can spend all night plus most of the following day writing a system to do it for you? - (Chris Maunder)

GeneralRe: Can't compile with 1.4alphamemberPeter SJöström6 Jul '05 - 6:46 
Thanks!
 
Many thanks for the class, it saves a boat load of time fo me! Laugh | :laugh:
QuestionHow Can I Fit Sheet to max page?memberFireEmissary26 May '05 - 16:48 
I Create by PropertySheet.(C Program)
And Find difficult adjust the Dialog Resource Size because Sheet not
fit to Max Dialog Template.
 

..........How Can I improve it?Thanks
GeneralAccess Violation with Windows Mememberferro@winandweb.it9 Apr '05 - 9:57 
Dear Paolo Messina,
I have debug your Property Sheet demo with Windows Me, and I see that the DoModal() causes access violation:
"First-chance exception in Demo.exe: 0xC0000005: Access Violation"
This not happen with Windows 2000/XP.
I don't know how change your source code, may you help me? OMG | :OMG:
Thank you very much,
Roberto Ferro
ferro@winandweb.it
 
Robi

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

Permalink | Advertise | Privacy | Mobile
Web01 | 2.6.130523.1 | Last Updated 27 Oct 2001
Article Copyright 2000 by Paolo Messina
Everything else Copyright © CodeProject, 1999-2013
Terms of Use
Layout: fixed | fluid