A CPropertySheetView Class?
madmagi@gnn.com Sunday, May 12, 1996 VC++ 4.1 W95/WNT 3.51+ We need to implement a property sheet view, with the ability to add pages to the view. In investigating the MFC internals we have not found an easy way to perform this. Any help would be greatly appreciated. madmagi "Wouldn't a wizard be better here?" "I call it a wizard blizzard"
MICHAEL@datatree.com Tuesday, May 14, 1996 [Mini-digest: 4 responses] michael says... Use Component Gallery to add Property Sheets and Property Pages. Select menu items Insert -> Component. Review the VC++ 4.1 sample files in \SAMPLES\GENERAL\PROPDLG for additional help. -----From: MJDALAL--------------- propview.txt ------------------------- Notes. 1. This is for MFC 4.0. Your mileage will undoubtedly vary with other versions of MFC. 2. The debugger reports that two exceptions occur in COMCTL32.DLL during the creation/use of the class (I have been told that these are something to do with Win95 vs NT and can be ignored.) 3. You have to derive a class from CPropertySheetView to actually add pages to the CPropertySheet. My code does this in the constructor of the derived class. (I'm not using the standard template mechanism to create the view, so all the data my pages need is accessible at this point). 4. It works for me... No warranties, no support. Bug reports welcome, but please remember that I'm producing applications not class libraries for a living... So don't expect an immediate acknowledgement or the addition of new features. However, if you send money.. $:-) -- Mike -- --------------- propview.h ---------------------------- #ifndef _PROPVIEW_H #define _PROPVIEW_H // ==================================================================== // // CPropSheetView // // This class represents a view that consists of a (modeless) CPropertySheet // // Derive from it to add pages. // // Mike Bell, April 96 // ==================================================================== class CPropSheetView : public CView { protected: CPropSheetView(); // protected constructor used by dynamic creation DECLARE_DYNCREATE(CPropSheetView) // Attributes public: // Operations public: // Provide access to underlying CPropertySheet int GetPageCount() const; CPropertyPage* GetActivePage() const; int GetActiveIndex() const; CPropertyPage* GetPage(int nPage) const; int GetPageIndex(CPropertyPage* pPage); BOOL SetActivePage(int nPage); BOOL SetActivePage(CPropertyPage* pPage); void AddPage(CPropertyPage* pPage); void RemovePage(CPropertyPage* pPage); void RemovePage(int nPage); // Overrides // ClassWizard generated virtual function overrides //{{AFX_VIRTUAL(CPropSheetView) public: virtual BOOL Create(LPCTSTR lpszClassName, LPCTSTR lpszWindowName, DWORD dwStyle, const RECT& rect, CWnd* pParentWnd, UINT nID, CCreateContext* pContext = NULL); protected: virtual void OnDraw(CDC* pDC); // overridden to draw this view //}}AFX_VIRTUAL // Implementation protected: virtual ~CPropSheetView(); #ifdef _DEBUG virtual void AssertValid() const; virtual void Dump(CDumpContext& dc) const; #endif // Generated message map functions protected: //{{AFX_MSG(CPropSheetView) afx_msg void OnSize(UINT nType, int cx, int cy); //}}AFX_MSG DECLARE_MESSAGE_MAP() protected: CPropertySheet m_propSheet; // The property sheet }; #endif // _PROPVIEW_H -------------------- propview.cpp ----------------------- // ==================================================================== // // CPropSheetView // // A class which is a view and displays a property sheet. // // IMPLEMENTATION NOTES // // 1. The intention is to // provide an equivalent to CFormView, but if you look at how that class // is implemented, you find a number of hidden APIs are used to // accomplish the desired effect. // // 2. The above is accomplished by creating a CPropertySheet and arranging // for it to fully occupy the area of the CView. This is // accomplished via the Create and OnSize calls. The initial size of the // frame window is adjusted to match the size of the property sheet // // 3. A possible problem is that COMCTL32.DLL throws an Access Violation // exception on the first creation of the property sheet. I can't find // a reason for this. However, it appears (at the moment) to be harmless. // It may even be a feature. Rumour has it that it relates to Win95 vs // WinNT // // Mike Bell, April 96 #include "stdafx.h" #include "qy.h" #include "propview.h" #ifdef _DEBUG #define new DEBUG_NEW #undef THIS_FILE static char THIS_FILE[] = __FILE__; #endif // ==================================================================== // CPropSheetView // ==================================================================== IMPLEMENT_DYNCREATE(CPropSheetView, CView) CPropSheetView::CPropSheetView() { // Derived classes should call AddPage here } CPropSheetView::~CPropSheetView() { } // ==================================================================== // CPropSheetView CPropertySheet wrappers // ==================================================================== int CPropSheetView::GetPageCount() const { return m_propSheet.GetPageCount(); }; CPropertyPage* CPropSheetView::GetActivePage() const { return m_propSheet.GetActivePage(); }; int CPropSheetView::GetActiveIndex() const { return m_propSheet.GetActiveIndex(); }; CPropertyPage* CPropSheetView::GetPage(int nPage) const { return m_propSheet.GetPage( nPage ); }; int CPropSheetView::GetPageIndex(CPropertyPage* pPage) { return m_propSheet.GetPageIndex( pPage ); }; BOOL CPropSheetView::SetActivePage(int nPage) { return m_propSheet.SetActivePage( nPage ); }; BOOL CPropSheetView::SetActivePage(CPropertyPage* pPage) { return m_propSheet.SetActivePage( pPage ); }; void CPropSheetView::AddPage( CPropertyPage* pPage ) { m_propSheet.AddPage( pPage ); }; void CPropSheetView::RemovePage( CPropertyPage* pPage ) { m_propSheet.RemovePage( pPage ); }; void CPropSheetView::RemovePage(int nPage) { m_propSheet.RemovePage( nPage ); }; BEGIN_MESSAGE_MAP(CPropSheetView, CView) //{{AFX_MSG_MAP(CPropSheetView) ON_WM_SIZE() ON_WM_SETFOCUS() //}}AFX_MSG_MAP END_MESSAGE_MAP() // ==================================================================== // CPropSheetView drawing void CPropSheetView::OnDraw(CDC* pDC) { CDocument* pDoc = GetDocument(); // Completely eclipsed by m_propSheet (we hope!) }; // ==================================================================== // CPropSheetView diagnostics #ifdef _DEBUG void CPropSheetView::AssertValid() const { CView::AssertValid(); } void CPropSheetView::Dump(CDumpContext& dc) const { CView::Dump(dc); } #endif //_DEBUG // ==================================================================== // CPropSheetView overrides // ==================================================================== // // What we are trying to do here is: // (a) create the default view CWnd // (b) create a property sheet that is a child of this view // (c) Adjust the size of the parent frame so that it matches // the normal size of the child // // BOOL CPropSheetView::Create(LPCTSTR lpszClassName, LPCTSTR lpszWindowName, DWORD dwStyle, const RECT& rect, CWnd* pParentWnd, UINT nID, CCreateContext* pContext) { if (!CWnd::Create(lpszClassName, lpszWindowName, dwStyle|WS_CLIPCHILDREN, rect, pParentWnd, nID, pContext)) { return FALSE; } if (!m_propSheet.Create( this, // DS_MODALFRAME| DS_3DLOOK|DS_CONTEXTHELP| DS_SETFONT| WS_CHILD|WS_VISIBLE )) { return FALSE; } // Adjust initial size of frame to match the property sheet CRect rectIdeal; m_propSheet.GetWindowRect( rectIdeal ); CFrameWnd* pFrame = GetParentFrame(); ASSERT_VALID(pFrame); // Calc frame size given pFrame->CalcWindowRect( rectIdeal ); // client pFrame->SetWindowPos( NULL, 0,0, rectIdeal.Width(), rectIdeal.Height(), SWP_NOMOVE|SWP_NOZORDER|SWP_NOACTIVATE); return TRUE; }; // ==================================================================== // CPropSheetView message handlers // ==================================================================== // // Position the property sheet size (if it exists) to cover // the entire area of the view // void CPropSheetView::OnSize(UINT nType, int cx, int cy) { if (IsWindow(m_propSheet.m_hWnd)) { // May not have been created when first called! m_propSheet.SetWindowPos( NULL, 0, 0, cx, cy, SWP_NOZORDER|SWP_NOACTIVATE ); } CView::OnSize(nType, cx, cy); }; // We don't want the focus, so give it to our CPropertySheet // to handle void CPropSheetView::OnSetFocus(CWnd* pOldWnd) { CView::OnSetFocus(pOldWnd); m_propSheet.SetFocus(); }; ------------------------------------------------------------------------------- -- Hope this helps, :-) Manish Dalal mjdalal@bechtel.com -----From: John Moulder This question keeps on coming up... Make the property sheet a modeless child window of the CView object. I do this and it works fine. I have developed an MDI property sheet. This is a modeless property sheet that is a child window of a CView derived class in an MDI child window. The window hierarchy is: MDI child window | + - AfxFrameOrView window (the view) | + - Modeless Property sheet | + - Tab control (to switch between pages) | - Property page | | | + control(s) in each page | + - Property page(s)... class CMDIPropertySheetView : public CView { protected: // property sheet CMyPropertySheet m_PropSheet; // pages for property sheet CMyPageOne m_Page1; CMyPageTwo m_Page2; CMyPageThree m_Page3; // etc } In my CPropertySheet derived class I reimplemented the RecalcLayout() to resize the view owning the sheet to be just big enough to enclose the sheet. The property sheet window is placed in the client area of the view window. The reimplemented RecalcLayout() is called from the CPropertySheet::OnCreate(). I found that I had to reimplement the original CPropertySheet::OnCreate() to do various things specific to my implementation. When the CView window changes size (remember it is an MDI child window) I resize the property sheet to fit the MDI child window (View). My environment is windows 3.1, MSVC 1.5x, MFC 2.??, MFC CPropertySheet (16 bit). Hope this helps. -----From: "David W. Gillett" What I have done is implement a trivial CFormView-derivative with a modeless CPropertySheet-derivative as a child. Resize the sheet (drop its lower edge) to encompass the buttons (initially invisible and disabled because the sheet is modeless), and resize the view to fit the sheet. I expose most of the public methods of the child CPropertySheet as methods of the derived CPropertySheetView class, including of course AddPage(). My child sheet is actually of a class derived from CPropertySheet (in order to add the DS_CONTROL and WS_EX_CONTROLPARENT styles in its OnInitDialog). The only tricky bit is to hook up the OK/Cancel buttons so they both get signalled to the pages, and dismiss the view. I don't actually enable/show the sheet's buttons, but provide OK and Cancel buttons on a dialog template for the CFormView, move and resize them to sit right over the hidden/disabled property sheet buttons, and use PressButton() to notify the sheet when they are clicked (and invoke the sheet logic which notifies the pages in turn). Those handlers will need to call any final code in specific derived view classes. CPropertyPage objects may be members of these derived classes, or not. Dave
| Вернуться в корень Архива |