A resizable property sheet within a view

I have an SDI application, where the main view consists of a CTabCtrl. In order to avoid handling the page changes myself, I decided to try to use a CPropertySheet instead. This gave me some problems handling resizing of the property sheet, when the user resizes the view.
Microsoft Knowledge Base article Q143291 gave a partial answer: How to resize the CPropertySheet at startup.

I tried to manipulate the code from Q143291 so it did what I wanted. And it worked! It flickers quite a lot though, but it is good enough for me.

Please study Q143291 as well. You may find a better way of doing this. All the resizing stuff is in the subclassed CPropertySheet. And that is kind of neat, IMHO.

I have moved most of the stuff from OnInitDialog into Resize, and added
	pParent = GetParent();
	pParent->GetClientRect(&rectParent);
to the subclassed CPropertySheet Resize. The rest of the CPropertySheet stuff is from Q143291. The view stuff is mine.

Note that I don't use OK / Cancel / Apply buttons. It should be a trivial matter to move these buttons in OnInitDialog as well. You can see how to do this in Q143291.

How do you implement a resizable property sheet within a view? Check this:
1. Subclass CPropertySheet.
2. Use only one constructor:

CResizablePropertySheet::CResizablePropertySheet(CWnd* pParentWnd)
	:CPropertySheet(AFX_IDS_APP_TITLE, pParentWnd)
{
	// AddPage here
}
3. Add protected CRect m_rectPage.
4. Create public member Resize():
void CResizablePropertySheet::Resize()
{
	// Find parent
	CWnd* pParent;
	CRect rectParent;

	pParent = GetParent();
	if (pParent == NULL)
		{
		AfxMessageBox("Cannot resize property sheet. Sheet has no parent", MB_ICONEXCLAMATION | MB_OK | MB_APPLMODAL);
		return;
		}

	// Get parents client area
	pParent->GetClientRect(&rectParent);

	// Resize the sheet
	// First find relative change
	CSize sizeRelChange;
	CRect rectWindow;

	GetWindowRect(&rectWindow);
	ScreenToClient(&rectWindow);
	sizeRelChange.cx = rectWindow.Width() - rectParent.Width();
	sizeRelChange.cy = rectWindow.Height() - rectParent.Height();

	rectWindow.right -= sizeRelChange.cx;
	rectWindow.bottom -= sizeRelChange.cy;
	// Then resize the sheet
	MoveWindow(&rectWindow);

	// Resize the CTabCtrl
	CTabCtrl* pTab = GetTabControl();
	ASSERT(pTab);
	pTab->GetWindowRect(&rectWindow);
	ScreenToClient(&rectWindow);
	rectWindow.right -= sizeRelChange.cx;
	rectWindow.bottom -= sizeRelChange.cy;
	pTab->MoveWindow(&rectWindow);

	// Resize the active page
	CPropertyPage* pPage = GetActivePage();
	ASSERT(pPage);
	// Store page size in m_rectPage
	pPage->GetWindowRect(&m_rectPage);
	ScreenToClient(&m_rectPage);
	m_rectPage.right -= sizeRelChange.cx;
	m_rectPage.bottom -= sizeRelChange.cy;
	pPage->MoveWindow(&m_rectPage);
}
5. Overload OnInitDialog:
BOOL CResizablePropertySheet::OnInitDialog() 
{
	BOOL bResult = CPropertySheet::OnInitDialog();

	Resize();

	return bResult;
}

6. Define user-defined message WM_RESIZEPAGE (WM_USER + 111 or something). Add ON_MESSAGE(WM_RESIZEPAGE, OnResizePage) to the message map. Remember to define afx_msg LRESULT OnResizePage(WPARAM wParam, LPARAM lParam) in the header file. OnResizePage:

LONG CResizablePropertySheet::OnResizePage(UINT, LONG)
	{
	// Resize the page using m_rectPage, which was set in
	// Resize().
	CPropertyPage* pPage = GetActivePage();
	ASSERT(pPage);
	pPage->MoveWindow(&m_rectPage);

	return 0;
	}

7. Handle ID_APPLY_NOW (add ON_COMMAND(ID_APPLY_NOW, OnApplyNow) to the message map. Remember to define afx_msg void OnApplyNow() in the header file).
OnApplyNow:

void CResizablePropertySheet::OnApplyNow()
	{
	// The sheet resizes the page whenever the apply button is clicked.
	// So we need to resize it to what we want.
	PostMessage(WM_RESIZEPAGE);
	}
8. Overload OnNotify:
BOOL CResizablePropertySheet::OnNotify(WPARAM wParam, LPARAM lParam, LRESULT* pResult) 
{
	NMHDR* pNMHDR = (LPNMHDR) lParam;
	
	// The sheet resizes the page whenever it is activated
	// so we need to resize it to what we want
	if (pNMHDR->code == TCN_SELCHANGE)
		// user-defined message needs to be posted, not sent, because
		// page must be resized after TCN_SELCHANGE has been processed.
		PostMessage(WM_RESIZEPAGE);

	return CPropertySheet::OnNotify(wParam, lParam, pResult);
}
9. Add private member
CResizablePropertySheet* m_pResizablePropertySheet;

to your CView-derived class. Initialize this member to NULL in the constructor.
10. Override OnInitialUpdate in your CView-derived class:

void CResizableView::OnInitialUpdate() 
	{
	CView::OnInitialUpdate();

	// create the property sheet
	m_pResizablePropertySheet = new CResizablePropertySheet(this);
	if (!m_pResizablePropertySheet->Create(this, 
		WS_CHILD | WS_VISIBLE, 0))
		{
		TRACE("Cannot create property sheet!\n");
		delete m_pResizablePropertySheet;
		m_pResizablePropertySheet = NULL;
		return;
		}
	}
11. Handle WM_SIZE in your CView-derived class:
void CResizableView::OnSize(UINT nType, int cx, int cy) 
	{
	CView::OnSize(nType, cx, cy);

	// Resize property sheet
	if (m_pNetDefPropertySheet != NULL)
		m_pResizablePropertySheet->Resize();
	}

Last updated: 21 July 1998



Comments

  • New File Error Fix

    Posted by Legacy on 01/12/2004 12:00am

    Originally posted by: Jong Kyu, Lim

    When New File Create, Tab don't implement at first, only
    
    So, I append some code...
    -----------------------------------------------------------
    Before Create new Sheet, Delete Pre-Create Sheet...

    Deleting Sheet ....

    At ViewObject...

    void ViewObject::OnInitialUpdate()
    {

    if(m_pMySheet != NULL)
    {
    int nPage;
    if ( 0 != (nPage = m_pMySheet->GetPageCount()) )
    {
    m_pMySheet->RemoveALL();
    }

    delete m_pMySheet;
    }

    m_pMySheet = new CMySheet;
    .....
    }

    At SheetObject...

    Add public Function void RemoveALL() ...

    void SheetObject::RemoveALL()
    {
    for(int i = GetPageCount() -1; i >= 0; i--)
    {
    delete GetPage(i);
    RemovePage( i );
    }
    }

    Have a Good Time~

    Reply
  • automatic resizing of property pages

    Posted by Legacy on 10/16/2003 12:00am

    Originally posted by: sheila

    I have an SDI application, where the main view consists of a CTabCtrl. I've used a CPropertySheet instead of handling the page changes myself.
    For resizing the property sheet, I have used the codex files (http://www.csdn.net/Dev/Visual%20C++/source%20code/Advanced_UI/DynamicControls.shtml.htm)and have replaced CpropertySheet with cdxCDynamicPropSheet and the same for the CpropertyPage but it's not working!
    Could you let me know where the problem is?

    Reply
  • Sample project Please

    Posted by Legacy on 07/30/2002 12:00am

    Originally posted by: Sridevi

    Can you provide a sample project for this?
    That will be more helpful.

    Thanx in advance

    Reply
  • Make the controls show up

    Posted by Legacy on 11/25/2001 12:00am

    Originally posted by: Tihamer Levendovszky

    To dispaly the controls contained by the page refresh the page in the property sheet OnSize():
    SetActivePage(GetActiveIndex());

    • Thank you

      Posted by monimicki on 11/26/2004 06:33am

      Thanks to the writer of this article, it helped heaps, and also to the writer of this post, (my property sheet looked fine, but no controls on the first page until I clicked it!!) Anyway, I wanted my property sheet to be the size I wanted, not the size of the parent frame. Here's my Resize() code if anyone is interested: CRect rectsize; rectsize.SetRect(50,50,450,450); // Resize the sheet // First find relative change CSize sizeRelChange; CRect rectWindow; GetWindowRect(&rectWindow); // ScreenToClient(&rectWindow); sizeRelChange.cx = rectWindow.Width() - rectsize.Width(); sizeRelChange.cy = rectWindow.Height() - rectsize.Height(); rectWindow.right -= sizeRelChange.cx; rectWindow.bottom -= sizeRelChange.cy; // Then resize the sheet MoveWindow(&rectWindow); // Resize the CTabCtrl CTabCtrl* pTab = GetTabControl(); ASSERT(pTab); pTab->GetWindowRect(&rectWindow); ScreenToClient(&rectWindow); rectWindow.right -= sizeRelChange.cx; rectWindow.bottom -= sizeRelChange.cy; pTab->MoveWindow(&rectWindow); // Resize the active page CPropertyPage* pPage = GetActivePage(); ASSERT(pPage); // Store page size in m_rectPage pPage->GetWindowRect(&m_rectPage); // ScreenToClient(&m_rectPage); m_rectPage.right -= sizeRelChange.cx; m_rectPage.bottom -= sizeRelChange.cy; pPage->MoveWindow(&m_rectPage); MoveWindow(50,50,400,400,TRUE);

      Reply
    Reply
  • Controls don't show up

    Posted by Legacy on 08/02/1999 12:00am

    Originally posted by: Dave Richter

    Any idea why the controls I've defined for my property
    page don't show up when the app runs? I build my property
    page from a dialog containing a button and a checkbox,
    but these controls don't appear when the app runs. Any
    advice would be appreciated.

    Reply
  • Re: I am *trying* to find a good reason to use your code!

    Posted by Legacy on 05/04/1999 12:00am

    Originally posted by: George

    Try to use it as a pointing device, possibly for 2D one, like a trackball.

    BR

    Reply
  • m_pNetDefPropertySheet ???

    Posted by Legacy on 10/13/1998 12:00am

    Originally posted by: Gunz

    Sorry, what is m_pNetDefPropertySheet ???

    Reply
Leave a Comment
  • Your email address will not be published. All fields are required.

Top White Papers and Webcasts

  • Given the undeniable criticality of IT to the business, the CIO that can't deliver predictable performance, while minimizing cost, puts their business, and their job, at considerable risk. As they strive to adapt to today's infrastructure trends, these leaders are realizing the limitations of traditional approaches; monitoring, alerts, schedulers, scripting, and orchestration can't assure performance alone. This guide discusses the five stages of IT maturity and how — no matter where an organization …

  • Download this IDC report to learn how your organization can benefit from new flash architecture built for the cloud era. The IDC report examines the evolving primary flash array market with a particular emphasis on how next generation flash–driven enterprise storage architectures will take performance, scalability and infrastructure density to the next level.

Most Popular Programming Stories

More for Developers

RSS Feeds

Thanks for your registration, follow us on our social networks to keep up-to-date