<

Still celebrating National IT Professionals Day with 3 months of free Premium Membership. Use Code ITDAY17

x

Using a Property Sheet as your Main Window

Published on
11,158 Points
4,558 Views
1 Endorsement
Last Modified:
You've seen this in Control-Panel applets, small utility programs, and even the Windows Task Manager.  A simple dialog-based program won't provide the U/I experience you want, but the document/view architecture seems too complex.Property Sheet as the Main WindowsTo give that familiar U/I to your program, use a CPropertySheet-derived object as the main window.  Individual CPropertyPages can be used to handle various categories of settings and options, and you can provide multiple views -- real-time status, lists of objects, log of activities, etc. -- in other pages.  Each page is effectively a dialog box (a "form") so you have great flexibility in your U/I design.

In this article, I'll describe what you need to do to create this type of program, and I'll throw in a few tips and tricks that are handy to know in this scenario:  We'll get rid of the Apply and Help buttons and enable minimize/restore functionality.  Here we go.

1

In Visual Studio,
Create Project...
Project Type: VisualC++ / MFC
     Template: MFC Application
          Name: MyProg
Click [Next], then..
Application Type: Dialog-based
[Finish]

2

Create some PropertyPages
In the Resource View...
Right-click My Prog
Select Add > Resource
Click on Dialog to open it up.
Select IDD_PROPPAGE_LARGE
Click [New]
Creating the PagesIn the Dialog Editor, set
Caption: General
          ID: IDD_PgGeneral

Add some Controls:A Page with Some Controls

3

Create a CPropertyPage-derived object for that property page:
In the Dialog Editor, double-click on the title bar of the property page to bring up the Class Wizard. Set...
Class Name: CPgGeneral
 Base Class: CPropertyPage
Deriving from CPropertyPage

4

Repeat steps 2 and 3 for each property page
Three Pages in This Example

5

Open up the application main CPP file (MyProg.cpp)
Add these #include lines at the top:
#include "PgGeneral.h"
#include "PgSettings.h"
#include "PgActivityLog.h"

Open in new window

Now, locate the InitInstance() function, and near the bottom of it, replace the key start-up sequence as follows:
// replace these lines
//	CMyProgDlg dlg;             
//	m_pMainWnd = &dlg;
//	INT_PTR nResponse = dlg.DoModal();
// ... with these

	CPropertySheet cSheet( L"WonderProg" );
	CPgGeneral     cPgGeneral;
	CPgSettings    cPgSettings;
	CPgActivityLog cPgActivityLog;

	cSheet.AddPage( &cPgGeneral );
	cSheet.AddPage( &cPgSettings );
	cSheet.AddPage( &cPgActivityLog );

	int nResponse= cSheet.DoModal(); // run your entire program
	if (nResponse == IDOK)
      ... etc...

Open in new window

You now have a program that has a PropertySheet as its main window.  You can delete the two files MyProgDlg.cpp and MyProgDlg.h and you can remove the resource IDD_MYPROG_DIALOGThe Example Program Using the base CPropertySheet object
But Wait! There's More!

We used CPropertySheet's default functionality, but you will want make a few adjustments because this is your main window and you want want to exert some control over various aspects of the User Interface.

Get Rid of the Help and Apply Buttons
==============================
For instance, let's say that you want to get rid of the "Help" and "Apply" buttons.  We'll derive a class that does that:

1

In the Class View...
Right-click MyProg
Select Add > Class
Choose MFC Class
Click [Add]

2

In Class Wizard,
Class Name: CSheetMain
 Base class: CPropertySheet
[Finish]
Deriving from CPropertySheet

3

Right-click the SheetMain item in the Class View
Choose Properties
Click the diamond-shaped Overrides icon.
Click OnInitDialog and choose <Add OnInitDialog>
Put this code into your CSheetMain::OnInitDialog() function:
BOOL CSheetMain::OnInitDialog()
{
    BOOL bResult = CPropertySheet::OnInitDialog();

    //----------------- Some setup for the PropertySheet buttons

    GetDlgItem(IDHELP)->ShowWindow(SW_HIDE); // so wonderful, no help is needed!

    //----------------- move the two remaining buttons to the right
    CRect rcBtn, rcDlg;
    GetWindowRect( &rcDlg );    

    CButton* pBtn= (CButton*)GetDlgItem( IDCANCEL );
    pBtn->GetWindowRect( &rcBtn );
    ScreenToClient( &rcBtn );
    int nOffset= (rcDlg.Width()-12)- rcBtn.right;
    rcBtn.OffsetRect(nOffset,0);
    pBtn->MoveWindow( &rcBtn, TRUE /*fRepaint*/ ); 
	
    pBtn= (CButton*)GetDlgItem( IDOK );
    pBtn->GetWindowRect( &rcBtn );
    ScreenToClient( &rcBtn );
    rcBtn.OffsetRect(nOffset,0);
    pBtn->MoveWindow( &rcBtn, TRUE /*fRepaint*/ ); 

    return bResult;
}

Open in new window

And modify your constructor to be:
CSheetMain::CSheetMain(LPCTSTR pszCaption, CWnd* pParentWnd, UINT iSelectPage)
	:CPropertySheet(pszCaption, pParentWnd, iSelectPage)
{
    m_psh.dwFlags |= PSH_NOAPPLYNOW ;
    m_psh.dwFlags &= ~PSH_HASHELP; 
}

Open in new window

4

Next, go back to MyProg.cpp and set it to use the derived object rather than the base object:
#include "SheetMain.h" // at the top and...
...
    // ...in InitInstance()
    CSheetMain  cSheet( L"WonderProg" );   
    //CPropertySheet cSheet( L"WonderProg" );

Open in new window

Moving the Buttons in OnInitDialog()
Enable Your App to Minimize to the Taskbar
===================================
Since this is your main window, you will want to let your user minimize it normally --  so that it will show an icon in the Taskbar, just like a real program!  It's not particularly obvious how to do that, so here's the trick.  First, change the CSheetMain() constructor like this:
CSheetMain::CSheetMain(LPCTSTR pszCaption, CWnd* pParentWnd, UINT iSelectPage)
	:CPropertySheet(pszCaption, pParentWnd, iSelectPage)
{
    HICON hIcon= AfxGetApp()->LoadIcon(IDR_MAINFRAME);
    m_psh.hIcon= hIcon;
    m_psh.dwFlags |= PSH_NOAPPLYNOW |PSH_USEHICON ;
    m_psh.dwFlags &= ~PSH_HASHELP; 
}

Open in new window

That gives your program an icon to display on the title bar and in the taskbar when it's minimized.  Now to enable the Minimize/Restore functionality, add this code to the bottom of your CSheetMain::OnInitDialog() function:
    CMenu* pSysMenu = GetSystemMenu( FALSE );
    pSysMenu->AppendMenu(MF_STRING, SC_MINIMIZE , L"Minimize");
    pSysMenu->AppendMenu(MF_STRING, SC_RESTORE  , L"Restore");

    ModifyStyle( 0, WS_MINIMIZEBOX  );

Open in new window

The finished product is illustrated by Fig 1.1 at the top of this article.

=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
If you liked this article and want to see more from this author,  please click the Yes button near the:
      Was this article helpful?
label that is just below and to the right of this text.   Thanks!
=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
1
Comment
Author:DanRollins
[X]
Welcome to Experts Exchange

Add your voice to the tech community where 5M+ people just like you are talking about what matters.

  • Help others & share knowledge
  • Earn cash & points
  • Learn & ask questions
0 Comments

Featured Post

Free Tool: Path Explorer

An intuitive utility to help find the CSS path to UI elements on a webpage. These paths are used frequently in a variety of front-end development and QA automation tasks.

One of a set of tools we're offering as a way of saying thank you for being a part of the community.

Join & Write a Comment

This is Part 3 in a 3-part series on Experts Exchange to discuss error handling in VBA code written for Excel. Part 1 of this series discussed basic error handling code using VBA. http://www.experts-exchange.com/videos/1478/Excel-Error-Handlin…
This course is ideal for IT System Administrators working with VMware vSphere and its associated products in their company infrastructure. This course teaches you how to install and maintain this virtualization technology to store data, prevent vuln…

Keep in touch with Experts Exchange

Tech news and trends delivered to your inbox every month