//+------------------------------------------------------------------------- // // Microsoft Windows // // Copyright (C) Microsoft Corporation, 1998 - 1998 // // File: proppage.h // //-------------------------------------------------------------------------- #ifndef _PROPPAGE_H #define _PROPPAGE_H // proppage.h : header file // /////////////////////////////////////////////////////////////////////////////// // FORWARD DECLARATIONS class CTreeNode; class CContainerNode; class CComponentDataObject; class CPropertyPageHolderBase; class CPropertyPageBase; class CPropertyPageHolderTable; class CWatermarkInfo; typedef CList< CPropertyPageBase*, CPropertyPageBase* > CPropertyPageBaseList; //////////////////////////////////////////////////////////////////// // CHiddenWndBase : Utility Hidden Window class CHiddenWndBase : public CWindowImpl { public: DECLARE_WND_CLASS(L"DNSMgrHiddenWindow") BOOL Create(HWND hWndParent = NULL); BEGIN_MSG_MAP(CHiddenWndBase) END_MSG_MAP() }; ///////////////////////////////////////////////////////////////////////////// // CSheetWnd class CSheetWnd : public CHiddenWndBase { public: static const UINT s_SheetMessage; static const UINT s_SelectPageMessage; CSheetWnd(CPropertyPageHolderBase* pHolder) { m_pHolder = pHolder;} BEGIN_MSG_MAP(CSheetWnd) MESSAGE_HANDLER( WM_CLOSE, OnClose ) MESSAGE_HANDLER( CSheetWnd::s_SheetMessage, OnSheetMessage ) MESSAGE_HANDLER( CSheetWnd::s_SelectPageMessage, OnSelectPageMessage ) CHAIN_MSG_MAP(CHiddenWndBase) END_MSG_MAP() LRESULT OnClose(UINT nMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled); LRESULT OnSheetMessage(UINT nMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled); LRESULT OnSelectPageMessage(UINT nMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled); private: CPropertyPageHolderBase* m_pHolder; }; ///////////////////////////////////////////////////////////////////////////// // CCloseDialogInfo class CCloseDialogInfo { public: CCloseDialogInfo() { m_hWnd = NULL; m_dwFlags = 0x0; } BOOL CloseDialog(BOOL bCheckForMsgBox); static BOOL CCloseDialogInfo::CloseMessageBox(HWND hWndParent); HWND m_hWnd; DWORD m_dwFlags; }; ///////////////////////////////////////////////////////////////////////////// // CCloseDialogInfoStack template class CCloseDialogInfoStack { public: CCloseDialogInfoStack() { m_nTop = 0; // first empty m_bForcedClose = FALSE; } BOOL IsEmpty() { return m_nTop <= 0; } BOOL Push(HWND hWnd, DWORD dwFlags) { ASSERT(hWnd != NULL); ASSERT(::IsWindow(hWnd)); if (m_nTop >= nSize) return FALSE; m_arr[m_nTop].m_hWnd = hWnd; m_arr[m_nTop].m_dwFlags = dwFlags; m_nTop++; return TRUE; } BOOL Pop() { if (m_bForcedClose) return TRUE; // going away if (m_nTop <= 0) return FALSE; m_nTop--; return TRUE; } void ForceClose(HWND hWndPage) { if (m_bForcedClose) { return; // avoid reentrancy } m_bForcedClose = TRUE; if (m_nTop > 0) { // have a stack to unwind BOOL bOutermost = TRUE; while (m_nTop > 0) { VERIFY(m_arr[m_nTop-1].CloseDialog(bOutermost)); bOutermost = FALSE; m_nTop--; } } else { // empty stack, but might have a message box HWND hWndSheet = ::GetParent(hWndPage); ASSERT(hWndSheet != NULL); if (CCloseDialogInfo::CloseMessageBox(hWndSheet)) VERIFY(::PostMessage(hWndSheet, WM_COMMAND, IDCANCEL, 0)); } } private: UINT m_nTop; CCloseDialogInfo m_arr[nSize]; BOOL m_bForcedClose; }; ///////////////////////////////////////////////////////////////////////////// // CPropertyPageHolderBase class CPropertyPageHolderBase { public: // construction CPropertyPageHolderBase(CContainerNode* pContNode, CTreeNode* pNode, CComponentDataObject* pComponentData); virtual ~CPropertyPageHolderBase(); // initialization // common void Attach(CPropertyPageHolderBase* pContHolder); BOOL EnableSheetControl(UINT nCtrlID, BOOL bEnable); // property sheet only static HRESULT CreateModelessSheet(CTreeNode* pNode, CComponentDataObject* pComponentData); HRESULT CreateModelessSheet(CTreeNode* pCookieNode); HRESULT CreateModelessSheet(LPPROPERTYSHEETCALLBACK pSheetCallback, LONG_PTR hConsoleHandle); void SetStartPageCode(int nStartPageCode) { m_nStartPageCode = nStartPageCode;} // wizard only HRESULT DoModalWizard(); INT_PTR DoModalDialog(LPCTSTR pszCaption); // helpers // common void SetSheetWindow(HWND hSheetWindow); void SetSheetTitle(LPCWSTR lpszSheetTitle); void SetSheetTitle(UINT nStringFmtID, CTreeNode* pNode); void AddRef(); void Release(); DWORD GetRefCount() { return m_nCreatedCount;} CComponentDataObject* GetComponentData() { ASSERT(m_pComponentData != NULL); return m_pComponentData;} HWND GetMainWindow() { return m_hMainWnd;} // get/set for the node we are working on CTreeNode* GetTreeNode() { return m_pNode;} void SetTreeNode(CTreeNode* pNode) { m_pNode = pNode; } // get/set for the container we refer to CContainerNode* GetContainerNode() { return m_pContNode; } void SetContainerNode(CContainerNode* pContNode) { ASSERT(pContNode != NULL); m_pContNode = pContNode; } BOOL IsWizardMode(); BOOL IsModalSheet(); void ForceDestroy(); // forcefull shut down running sheet void AddPageToList(CPropertyPageBase* pPage); BOOL RemovePageFromList(CPropertyPageBase* pPage, BOOL bDeleteObject); // property sheet only BOOL PushDialogHWnd(HWND hWndModalDlg); BOOL PopDialogHWnd(); void CloseModalDialogs(HWND hWndPage); DWORD NotifyConsole(CPropertyPageBase* pPage); // notify console of property changes void AcknowledgeNotify(); // acknowledge from the console virtual BOOL OnPropertyChange(BOOL bScopePane, long* pChangeMask); // execute from main thread // wizard only BOOL SetWizardButtons(DWORD dwFlags); BOOL SetWizardButtonsFirst(BOOL bValid) { return SetWizardButtons(bValid ? PSWIZB_NEXT : 0); } BOOL SetWizardButtonsMiddle(BOOL bValid) { return SetWizardButtons(bValid ? (PSWIZB_BACK|PSWIZB_NEXT) : PSWIZB_BACK); } BOOL SetWizardButtonsLast(BOOL bValid) { return SetWizardButtons(bValid ? (PSWIZB_BACK|PSWIZB_FINISH) : (PSWIZB_BACK|PSWIZB_DISABLEDFINISH)); } HRESULT AddPageToSheet(CPropertyPageBase* pPage); HRESULT AddPageToSheetRaw(HPROPSHEETPAGE hPage); HRESULT RemovePageFromSheet(CPropertyPageBase* pPage); HRESULT AddAllPagesToSheet(); protected: // common virtual HRESULT OnAddPage(int, CPropertyPageBase*) { return S_OK; } // property sheet only virtual void OnSheetMessage(WPARAM, LPARAM) {} virtual int OnSelectPageMessage(long) { return -1;} // wizard only void SetWatermarkInfo(CWatermarkInfo* pWatermarkInfo); private: void DeleteAllPages(); void FinalDestruct(); // attributes private: // common CString m_szSheetTitle; // title for the sheet/wizard window CPropertyPageBaseList m_pageList; // list of property page objects CPropertyPageHolderBase* m_pContHolder; // prop page holder that migh contain this CComponentDataObject* m_pComponentData; // cached pointer to CComponentDataImplementation HWND m_hMainWnd; // cached MMC frame window, if present protected: BOOL m_bWizardMode; // Wizard Mode (i.e. not modeless property sheet) BOOL m_bAutoDelete; // delete itself when refcount goes to zero BOOL m_bAutoDeletePages; // explicitely delete the property page C++ objects enum { useDefault, forceOn, forceOff } m_forceContextHelpButton; // setting for the [?] button private: DWORD m_nCreatedCount; // count of how many pages got actually created CTreeNode* m_pNode; // node the pages (or the wizard) refer to CContainerNode* m_pContNode; // container node the pages (or the wizard) refer to HWND m_hSheetWindow; // window handle to the sheet (thread safe) // property sheet only LONG_PTR m_hConsoleHandle; // handle for notifications to console HANDLE m_hEventHandle; // syncronization handle for property notifications CSheetWnd* m_pSheetWnd; // hidden window CWnd object for messages int m_nStartPageCode; // starting page code (not necessarily the page #) CCloseDialogInfoStack<5> m_dlgInfoStack; // modal dialogs stack (to close them down) // wizard only IPropertySheetCallback* m_pSheetCallback; // cached pointer to add/remove pages CPropertySheet* m_pDummySheet; // MFC surrogate property sheet for modal operations CWatermarkInfo* m_pWatermarkInfo; // watermark info for Wiz 97 sheets private: // property sheet only // variables to use across thread boundaries DWORD m_dwLastErr; // generic error code CPropertyPageBase* m_pPropChangePage; // page for which notification is valid public: void SetError(DWORD dwErr) { m_dwLastErr = dwErr;} CPropertyPageBase* GetPropChangePage() { ASSERT(m_pPropChangePage != NULL); return m_pPropChangePage; } friend class CSheetWnd; }; ///////////////////////////////////////////////////////////////////////////// // CPropertyPageBase class CPropertyPageBase : public CPropertyPage { // Construction private: CPropertyPageBase(){} // cannot use this constructor public: CPropertyPageBase(UINT nIDTemplate, UINT nIDCaption = 0); virtual ~CPropertyPageBase(); // Overrides public: virtual BOOL OnInitDialog() { CWinApp* pApp = AfxGetApp(); ASSERT(pApp); return CPropertyPage::OnInitDialog(); } virtual void OnCancel(); virtual BOOL OnApply(); protected: // Generated message map functions //{{AFX_MSG(CGeneralPage) afx_msg int OnCreate(LPCREATESTRUCT lpCreateStruct); afx_msg void OnDestroy(); //}}AFX_MSG afx_msg void OnContextMenu(CWnd* pWnd, CPoint point); afx_msg void OnWhatsThis(); virtual BOOL OnHelp(WPARAM wParam, LPARAM lParam); virtual BOOL OnNotify(WPARAM wParam, LPARAM lParam, LRESULT* pResult); virtual void OnWizardHelp() {} DECLARE_MESSAGE_MAP() // attributes public: // common PROPSHEETPAGE m_psp97; HPROPSHEETPAGE m_hPage; void SetHolder(CPropertyPageHolderBase* pPageHolder) { ASSERT((pPageHolder != NULL) && (m_pPageHolder == NULL)); m_pPageHolder = pPageHolder;} CPropertyPageHolderBase* GetHolder() { return m_pPageHolder;}; // property seet only virtual BOOL OnPropertyChange(BOOL, long*) // execute from main thread { return FALSE; /* do not repaint UI */ } // wizard only UINT m_nPrevPageID; // to be used by OnWizardBack() void InitWiz97( BOOL bHideHeader, UINT nIDHeaderTitle, UINT nIDHeaderSubTitle, bool hasHelp = false); private: CString m_szHeaderTitle; CString m_szHeaderSubTitle; protected: virtual void SetUIData(){} virtual void GetUIData(){} virtual LONG GetUIDataEx() { return 0;} virtual void SetDirty(BOOL bDirty); BOOL IsDirty() { return m_bIsDirty; } private: CPropertyPageHolderBase* m_pPageHolder; // backpointer to holder BOOL m_bIsDirty; // dirty flag HWND m_hWndWhatsThis; // hwnd of right click "What's this" help }; ///////////////////////////////////////////////////////////////////////////// // CPropertyPageHolderTable class CPropertyPageHolderTable { public: CPropertyPageHolderTable(CComponentDataObject* pComponentData); ~CPropertyPageHolderTable(); void Add(CPropertyPageHolderBase* pPPHolder); void AddWindow(CPropertyPageHolderBase* pPPHolder, HWND hWnd); void Remove(CPropertyPageHolderBase* pPPHolder); void DeleteSheetsOfNode(CTreeNode* pNode); void WaitForAllToShutDown(); // sheet notification mechanism void BroadcastMessageToSheets(CTreeNode* pNode, WPARAM wParam, LPARAM lParam); void BroadcastSelectPage(CTreeNode* pNode, long nPageCode); int BroadcastCloseMessageToSheets(CTreeNode* pNode); struct PPAGE_HOLDER_TABLE_ENTRY { CPropertyPageHolderBase* pPPHolder; CTreeNode* pNode; HWND hWnd; }; PPAGE_HOLDER_TABLE_ENTRY* GetPageHolderTableEntry(){return m_pEntries;} int GetPageHolderTableEntrySize(){return m_nSize;} private: CComponentDataObject* m_pComponentData; // back pointer void WaitForSheetShutdown(int nCount, HWND* hWndArr = NULL); PPAGE_HOLDER_TABLE_ENTRY* m_pEntries; int m_nSize; }; //////////////////////////////////////////////////////////// // CHelpDialog class CHelpDialog : public CDialog { // Construction private: CHelpDialog(){} public: CHelpDialog(UINT nIDTemplate, CComponentDataObject* pComponentData); CHelpDialog(UINT nIDTemplate, CWnd* pParentWnd, CComponentDataObject* pComponentData); virtual ~CHelpDialog() {}; virtual void OnOK() { CDialog::OnOK(); } protected: afx_msg void OnContextMenu(CWnd* pWnd, CPoint point); afx_msg void OnWhatsThis(); afx_msg BOOL OnHelp(WPARAM wParam, LPARAM lParam); DECLARE_MESSAGE_MAP() private: HWND m_hWndWhatsThis; // hwnd of right click "What's this" help CComponentDataObject* m_pComponentData; }; #endif // _PROPPAGE_H