Property Sheet Inside Property Page

SheetInSheet

Environment: VC6

You can use embedded property sheet in your application. I use “Creating a Property Sheet Inside a Dialog” by Zafir Anjum, as start solution.

1st step.

You must derive class from CPropertyPage and add CPropertySheet member to this class:

class CPropertyPageWithPropertySheet : public CPropertyPage
{

...
public:
	virtual BOOL UpdateData(BOOL bSaveAndValidate);
	virtual void AddPage(CPropertyPage *pPage);
...

...
// Implementation
protected:
	CPropertySheet m_internal_sheet;
	// Generated message map functions
	//{{AFX_MSG(CPropertyPageWithPropertySheet)
	virtual BOOL OnInitDialog();
	//}}AFX_MSG
	DECLARE_MESSAGE_MAP()
...

};

2nd step.

Override OnInitDialog() for configure property page and start it Create() method:

BOOL CPropertyPageWithPropertySheet::OnInitDialog()
{
	CPropertyPage::OnInitDialog();

	// TODO: Add extra initialization here
	m_internal_sheet.EnableStackedTabs( FALSE );
	m_internal_sheet.Create(this, WS_CHILD | WS_VISIBLE , 0);
	m_internal_sheet.ModifyStyleEx (0, WS_EX_CONTROLPARENT);
	m_internal_sheet.ModifyStyle( 0, WS_TABSTOP );

	// move to left upper corner
	m_internal_sheet.SetWindowPos( NULL, 0, 0, 0, 0,
                        SWP_NOZORDER | SWP_NOSIZE | SWP_NOACTIVATE );


	return TRUE;  // return TRUE unless you set the focus to a control
	              // EXCEPTION: OCX Property Pages should return FALSE
}

3rd step.

After this you can add property pages to CPropertySheet member. For this I use AddPage() function:

void CPropertyPageWithPropertySheet::AddPage(CPropertyPage *pPage)
{
	m_internal_sheet.AddPage(pPage);
}

4th step.

For data exchange and validation you must override UpdateData() function in your dialog class and derived CPropertyPage class:

BOOL CPropertyPageWithPropertySheet::UpdateData(BOOL bSaveAndValidate)
{
	if(!CPropertyPage::UpdateData(bSaveAndValidate))
		return FALSE;
	// check property sheet. Need when OK button pressed in main dialog
	return m_internal_sheet.GetActivePage()->UpdateData(bSaveAndValidate);
}

… and add change to DoDataExchange():

void CPropertyPageWithPropertySheet::DoDataExchange(CDataExchange* pDX)
{
	CPropertyPage::DoDataExchange(pDX);
	//{{AFX_DATA_MAP(CPropertyPageWithPropertySheet)
		// NOTE: the ClassWizard will add DDX and DDV calls here
	//}}AFX_DATA_MAP

	// this need for check data when user change tab in parent property sheet
	if(m_internal_sheet)
		if(!m_internal_sheet.GetActivePage()->UpdateData(pDX->m_bSaveAndValidate))
			pDX->Fail();
}

This code responds for validation, when user changes tabs in parent property sheet.

5th step.

Also you must add calls m_page_with_sheetXX.UpdateData( ) in parent dialog overrided UpdateData() function:

BOOL CPs_in_psDlg::UpdateData(BOOL bSaveAndValidate)
{
	if(!CDialog::UpdateData(bSaveAndValidate))
		return FALSE;

	// check addition property sheet in property pages
	if(m_page_with_sheet0)
		if(!m_page_with_sheet0.UpdateData(bSaveAndValidate))
			return FALSE;
	if(m_page_with_sheet1)
		if(!m_page_with_sheet1.UpdateData(bSaveAndValidate))
			return FALSE;

	// check main property sheet. Need when OK button pressed in main dialog
	return m_sheet.GetActivePage()->UpdateData(bSaveAndValidate);
}

Downloads

Download demo project – 19 Kb

More by Author

Must Read