Notes

Attila support for property pages is defined by four classes.

template <typename Base>
class CPropertySheetT
	: public Base
typedef CPropertySheetT<CWindow> CPropertySheet;

This class defines client-side support for property sheets.
That is, it wraps an HWND belonging to a property sheet in
the same way that ATLControls::CEditT wraps an HWND that
belongs to an edit control.  All of the PSM_ messages defined
up to and including _WIN32_IE == 0x0500 are supported.

The CPropertySheet typedef will mostly be used from within
property pages, which will be able to do things like this.

	CPropertySheet sheet = GetParent();
	sheet.Changed(*this);

template <typename TDeriving, typename TBase = CWindow>
class CPropertyPageImpl :
	public PROPSHEETPAGE,
	public CDialogImplBaseT<TBase>

This class implements a property page.  Classes deriving
from this class need only define a symbol "IDD", for instance

    enum { IDD = IDD_FIRST_PAGE };

in order to work with the property sheet implementation.

template <typename TDeriving, typename TBase = CWindow>
class CAxPropertyPageImpl
	: public CPropertyPageImpl<TDeriving, TBase>

CAxPropertyPageImpl adds support to the base property page for
containing ActiveX controls.

template <typename TDeriving, typename TBase = CWindow>
class CPropertySheetImpl :
	public PROPSHEETHEADER,
	public CWindowImplBaseT< CPropertySheetT<TBase> >,
	public CMsgTranslator

#define BEGIN_PROPPAGE_MAP(sheet)
#define     PROPPAGE_ENTRY(page)
#define END_PROPPAGE_MAP()

CPropertySheetImpl implements a property sheet.  The macros
are used to specify starting pages within the property sheet.
Pages may be added and removed after the property sheet has
become visible by using the AddPage, InsertPage and RemovePage
functions.  (Before IE 5, InsertPage isn't available and
property sheets can't be resized to accomodate larger pages
added after the Sheet is created.)


Sample usage:

class CFirstPage : public CPropertyPageImpl<CFirstPage>
{
public:
	BEGIN_MSG_MAP(CFirstPage)
		MESSAGE_HANDLER(WM_LBUTTONDOWN, OnLButtonDown)
	END_MSG_MAP()
	enum { IDD = IDD_FIRST_PAGE };

	LRESULT OnLButtonDown(UINT, WPARAM, LPARAM, BOOL&)
	{
		MessageBox("Ouch!");
		return 0;
	}
};

class CSecondPage : public CPropertyPageImpl<CSecondPage>
{
public:
	BEGIN_MSG_MAP(CSecondPage)
	END_MSG_MAP()
	enum { IDD = IDD_SECOND_PAGE };
};

class CMyPropertySheet : public CPropertySheetImpl<CMyPropertySheet>
{
public:
	typedef CPropertySheetImpl<CMyPropertySheet> baseClass;
	CMyPropertySheet() : baseClass("My Properties") {}

	BEGIN_PROPPAGE_MAP(CMyPropertySheet)
		PROPPAGE_ENTRY(m_page1)
		PROPPAGE_ENTRY(m_page2)
	END_PROPPAGE_MAP()

private:
	CFirstPage  m_page1;
	CSecondPage m_page2;
	CThirdPage  m_page3;
};

LRESULT CMyFrameWindow::OnShowProperties()
{
	CMyPropertySheet sheet("My Properties");
	if (sheet.DoModal() == IDOK)
		MessageBox("Ok!");
	return 0;
}
