1 // Win32++ Version 7.3
\r
2 // Released: 30th November 2011
\r
6 // url: https://sourceforge.net/projects/win32-framework
\r
9 // Copyright (c) 2005-2011 David Nash
\r
11 // Permission is hereby granted, free of charge, to
\r
12 // any person obtaining a copy of this software and
\r
13 // associated documentation files (the "Software"),
\r
14 // to deal in the Software without restriction, including
\r
15 // without limitation the rights to use, copy, modify,
\r
16 // merge, publish, distribute, sublicense, and/or sell
\r
17 // copies of the Software, and to permit persons to whom
\r
18 // the Software is furnished to do so, subject to the
\r
19 // following conditions:
\r
21 // The above copyright notice and this permission notice
\r
22 // shall be included in all copies or substantial portions
\r
25 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF
\r
26 // ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED
\r
27 // TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
\r
28 // PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT
\r
29 // SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR
\r
30 // ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
\r
31 // ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
\r
32 // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE
\r
33 // OR OTHER DEALINGS IN THE SOFTWARE.
\r
35 ////////////////////////////////////////////////////////
\r
38 ///////////////////////////////////////////////////////
\r
40 // Declaration of the following classes:
\r
41 // CPropertyPage and CPropertySheet
\r
43 // These classes add support for property sheets to Win32++. A property sheet
\r
44 // will have one or more property pages. These pages are much like dialogs
\r
45 // which are presented within a tabbed dialog or within a wizard. The data
\r
46 // on a property page can be validated before the next page is presented.
\r
47 // Property sheets have three modes of use: Modal, Modeless, and Wizard.
\r
49 // Refer to the PropertySheet demo program for an example of how propert sheets
\r
53 #ifndef _WIN32XX_PROPERTYSHEET_H_
\r
54 #define _WIN32XX_PROPERTYSHEET_H_
\r
58 #define ID_APPLY_NOW 0x3021
\r
59 #define ID_WIZBACK 0x3023
\r
60 #define ID_WIZNEXT 0x3024
\r
61 #define ID_WIZFINISH 0x3025
\r
62 #define ID_HELP 0xE146
\r
64 #ifndef PROPSHEETHEADER_V1_SIZE
\r
65 #define PROPSHEETHEADER_V1_SIZE 40
\r
70 class CPropertyPage;
\r
71 typedef Shared_Ptr<CPropertyPage> PropertyPagePtr;
\r
73 class CPropertyPage : public CWnd
\r
76 CPropertyPage (UINT nIDTemplate, LPCTSTR szTitle = NULL);
\r
77 virtual ~CPropertyPage() {}
\r
79 virtual INT_PTR DialogProc(UINT uMsg, WPARAM wParam, LPARAM lParam);
\r
80 virtual INT_PTR DialogProcDefault(UINT uMsg, WPARAM wParam, LPARAM lParam);
\r
81 virtual int OnApply();
\r
82 virtual void OnCancel();
\r
83 virtual void OnHelp();
\r
84 virtual BOOL OnInitDialog();
\r
85 virtual BOOL OnKillActive();
\r
86 virtual LRESULT OnNotify(WPARAM wParam, LPARAM lParam);
\r
88 virtual BOOL OnQueryCancel();
\r
89 virtual BOOL OnQuerySiblings(WPARAM wParam, LPARAM lParam);
\r
90 virtual int OnSetActive();
\r
91 virtual int OnWizardBack();
\r
92 virtual INT_PTR OnWizardFinish();
\r
93 virtual int OnWizardNext();
\r
94 virtual BOOL PreTranslateMessage(MSG* pMsg);
\r
96 static UINT CALLBACK StaticPropSheetPageProc(HWND hwnd, UINT uMsg, LPPROPSHEETPAGE ppsp);
\r
97 static INT_PTR CALLBACK StaticDialogProc(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam);
\r
99 void CancelToClose() const;
\r
100 PROPSHEETPAGE GetPSP() const {return m_PSP;}
\r
101 BOOL IsButtonEnabled(int iButton) const;
\r
102 LRESULT QuerySiblings(WPARAM wParam, LPARAM lParam) const;
\r
103 void SetModified(BOOL bChanged) const;
\r
104 void SetTitle(LPCTSTR szTitle);
\r
105 void SetWizardButtons(DWORD dwFlags) const;
\r
108 PROPSHEETPAGE m_PSP;
\r
111 CPropertyPage(const CPropertyPage&); // Disable copy construction
\r
112 CPropertyPage& operator = (const CPropertyPage&); // Disable assignment operator
\r
117 class CPropertySheet : public CWnd
\r
120 CPropertySheet(UINT nIDCaption, CWnd* pParent = NULL);
\r
121 CPropertySheet(LPCTSTR pszCaption = NULL, CWnd* pParent = NULL);
\r
122 virtual ~CPropertySheet() {}
\r
125 virtual CPropertyPage* AddPage(CPropertyPage* pPage);
\r
126 virtual HWND Create(CWnd* pParent = 0);
\r
127 virtual INT_PTR CreatePropertySheet(LPCPROPSHEETHEADER ppsph);
\r
128 virtual void DestroyButton(int iButton);
\r
129 virtual void Destroy();
\r
130 virtual int DoModal();
\r
131 virtual void RemovePage(CPropertyPage* pPage);
\r
134 BOOL IsModeless() const;
\r
135 BOOL IsWizard() const;
\r
138 CPropertyPage* GetActivePage() const;
\r
139 int GetPageCount() const;
\r
140 int GetPageIndex(CPropertyPage* pPage) const;
\r
141 HWND GetTabControl() const;
\r
142 virtual BOOL SetActivePage(int nPage);
\r
143 virtual BOOL SetActivePage(CPropertyPage* pPage);
\r
144 virtual void SetIcon(UINT idIcon);
\r
145 virtual void SetTitle(LPCTSTR szTitle);
\r
146 virtual void SetWizardMode(BOOL bWizard);
\r
149 virtual BOOL PreTranslateMessage(MSG* pMsg);
\r
150 virtual LRESULT WndProcDefault(UINT uMsg, WPARAM wParam, LPARAM lParam);
\r
153 CPropertySheet(const CPropertySheet&); // Disable copy construction
\r
154 CPropertySheet& operator = (const CPropertySheet&); // Disable assignment operator
\r
155 void BuildPageArray();
\r
156 static void CALLBACK Callback(HWND hwnd, UINT uMsg, LPARAM lParam);
\r
159 std::vector<PropertyPagePtr> m_vPages; // vector of CPropertyPage
\r
160 std::vector<PROPSHEETPAGE> m_vPSP; // vector of PROPSHEETPAGE
\r
161 BOOL m_bInitialUpdate;
\r
162 PROPSHEETHEADER m_PSH;
\r
167 //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~//
\r
172 //////////////////////////////////////////
\r
173 // Definitions for the CPropertyPage class
\r
175 inline CPropertyPage::CPropertyPage(UINT nIDTemplate, LPCTSTR szTitle /* = NULL*/)
\r
177 ZeroMemory(&m_PSP, sizeof(PROPSHEETPAGE));
\r
180 m_PSP.dwSize = sizeof(PROPSHEETPAGE);
\r
181 m_PSP.dwFlags |= PSP_USECALLBACK;
\r
182 m_PSP.hInstance = GetApp()->GetResourceHandle();
\r
183 m_PSP.pszTemplate = MAKEINTRESOURCE(nIDTemplate);
\r
184 m_PSP.pszTitle = m_Title;
\r
185 m_PSP.pfnDlgProc = (DLGPROC)CPropertyPage::StaticDialogProc;
\r
186 m_PSP.lParam = (LPARAM)this;
\r
187 m_PSP.pfnCallback = CPropertyPage::StaticPropSheetPageProc;
\r
190 inline void CPropertyPage::CancelToClose() const
\r
191 // Disables the Cancel button and changes the text of the OK button to "Close."
\r
193 assert(::IsWindow(m_hWnd));
\r
194 SendMessage(PSM_CANCELTOCLOSE, 0L, 0L);
\r
198 inline INT_PTR CPropertyPage::DialogProc(UINT uMsg, WPARAM wParam, LPARAM lParam)
\r
200 // Override this function in your class derrived from CPropertyPage if you wish to handle messages
\r
201 // A typical function might look like this:
\r
205 // case MESSAGE1: // Some Win32 API message
\r
206 // OnMessage1(); // A user defined function
\r
207 // break; // Also do default processing
\r
210 // return x; // Don't do default processing, but instead return
\r
211 // // a value recommended by the Win32 API documentation
\r
214 // Always pass unhandled messages on to DialogProcDefault
\r
215 return DialogProcDefault(uMsg, wParam, lParam);
\r
218 inline INT_PTR CPropertyPage::DialogProcDefault(UINT uMsg, WPARAM wParam, LPARAM lParam)
\r
219 // All DialogProc functions should pass unhandled messages to this function
\r
225 case UWM_CLEANUPTEMPS:
\r
227 TLSData* pTLSData = (TLSData*)TlsGetValue(GetApp()->GetTlsIndex());
\r
228 pTLSData->vTmpWnds.clear();
\r
232 case WM_INITDIALOG:
\r
233 return OnInitDialog();
\r
235 case PSM_QUERYSIBLINGS:
\r
236 return (BOOL)OnQuerySiblings(wParam, lParam);
\r
240 // Refelect this message if it's from a control
\r
241 CWnd* pWnd = GetApp()->GetCWndFromMap((HWND)lParam);
\r
243 lr = pWnd->OnCommand(wParam, lParam);
\r
245 // Handle user commands
\r
247 lr = OnCommand(wParam, lParam);
\r
255 // Do Notification reflection if it came from a CWnd object
\r
256 HWND hwndFrom = ((LPNMHDR)lParam)->hwndFrom;
\r
257 CWnd* pWndFrom = GetApp()->GetCWndFromMap(hwndFrom);
\r
259 if (pWndFrom != NULL)
\r
260 lr = pWndFrom->OnNotifyReflect(wParam, lParam);
\r
263 // Some controls (eg ListView) have child windows.
\r
264 // Reflect those notifications too.
\r
265 CWnd* pWndFromParent = GetApp()->GetCWndFromMap(::GetParent(hwndFrom));
\r
266 if (pWndFromParent != NULL)
\r
267 lr = pWndFromParent->OnNotifyReflect(wParam, lParam);
\r
270 // Handle user notifications
\r
271 if (!lr) lr = OnNotify(wParam, lParam);
\r
273 // Set the return code for notifications
\r
275 SetWindowLongPtr(DWLP_MSGRESULT, (LONG_PTR)lr);
\r
282 if (::GetUpdateRect(m_hWnd, NULL, FALSE))
\r
288 // RedrawWindow can require repainting without an update rect
\r
290 CClientDC dc(this);
\r
297 case WM_ERASEBKGND:
\r
299 CDC dc((HDC)wParam);
\r
300 BOOL bResult = OnEraseBkgnd(&dc);
\r
302 if (bResult) return TRUE;
\r
306 // A set of messages to be reflected back to the control that generated them
\r
307 case WM_CTLCOLORBTN:
\r
308 case WM_CTLCOLOREDIT:
\r
309 case WM_CTLCOLORDLG:
\r
310 case WM_CTLCOLORLISTBOX:
\r
311 case WM_CTLCOLORSCROLLBAR:
\r
312 case WM_CTLCOLORSTATIC:
\r
314 case WM_MEASUREITEM:
\r
315 case WM_DELETEITEM:
\r
316 case WM_COMPAREITEM:
\r
317 case WM_CHARTOITEM:
\r
318 case WM_VKEYTOITEM:
\r
321 case WM_PARENTNOTIFY:
\r
322 return MessageReflect(m_hWnd, uMsg, wParam, lParam);
\r
327 } // INT_PTR CALLBACK CPropertyPage::DialogProc(...)
\r
329 inline BOOL CPropertyPage::IsButtonEnabled(int iButton) const
\r
331 assert(::IsWindow(m_hWnd));
\r
332 return GetParent()->GetDlgItem(iButton)->IsWindowEnabled();
\r
335 inline int CPropertyPage::OnApply()
\r
337 // This function is called for each page when the Apply button is pressed
\r
338 // Override this function in your derived class if required.
\r
340 // The possible return values are:
\r
341 // PSNRET_NOERROR. The changes made to this page are valid and have been applied
\r
342 // PSNRET_INVALID. The property sheet will not be destroyed, and focus will be returned to this page.
\r
343 // PSNRET_INVALID_NOCHANGEPAGE. The property sheet will not be destroyed, and focus will be returned;
\r
345 return PSNRET_NOERROR;
\r
348 inline void CPropertyPage::OnCancel()
\r
350 // This function is called for each page when the Cancel button is pressed
\r
351 // Override this function in your derived class if required.
\r
354 inline void CPropertyPage::OnHelp()
\r
356 // This function is called in response to the PSN_HELP notification.
\r
357 SendMessage(m_hWnd, WM_COMMAND, ID_HELP, 0L);
\r
360 inline BOOL CPropertyPage::OnQueryCancel()
\r
362 // Called when the cancel button is pressed, and before the cancel has taken place
\r
363 // Returns TRUE to prevent the cancel operation, or FALSE to allow it.
\r
365 return FALSE; // Allow cancel to proceed
\r
368 inline BOOL CPropertyPage::OnQuerySiblings(WPARAM wParam, LPARAM lParam)
\r
370 UNREFERENCED_PARAMETER(wParam);
\r
371 UNREFERENCED_PARAMETER(lParam);
\r
373 // Responds to a query request from the Property Sheet.
\r
374 // The values for wParam and lParam are the ones set by
\r
375 // the CPropertySheet::QuerySiblings call
\r
377 // return FALSE to allow other siblings to be queried, or
\r
378 // return TRUE to stop query at this page.
\r
383 inline BOOL CPropertyPage::OnInitDialog()
\r
385 // Called when the property page is created
\r
386 // Override this function in your derived class if required.
\r
388 return TRUE; // Pass Keyboard control to handle in WPARAM
\r
391 inline BOOL CPropertyPage::OnKillActive()
\r
393 // This is called in response to a PSN_KILLACTIVE notification, which
\r
394 // is sent whenever the OK or Apply button is pressed.
\r
395 // It provides an opportunity to validate the page contents before it's closed.
\r
396 // Return TRUE to prevent the page from losing the activation, or FALSE to allow it.
\r
401 inline int CPropertyPage::OnOK()
\r
403 // Called for each page when the OK button is pressed
\r
404 // Override this function in your derived class if required.
\r
406 // The possible return values are:
\r
407 // PSNRET_NOERROR. The changes made to this page are valid and have been applied
\r
408 // PSNRET_INVALID. The property sheet will not be destroyed, and focus will be returned to this page.
\r
409 // PSNRET_INVALID_NOCHANGEPAGE. The property sheet will not be destroyed, and focus will be returned;
\r
411 return PSNRET_NOERROR;
\r
414 inline LRESULT CPropertyPage::OnNotify(WPARAM wParam, LPARAM lParam)
\r
416 UNREFERENCED_PARAMETER(wParam);
\r
418 LPPSHNOTIFY pNotify = (LPPSHNOTIFY)lParam;
\r
419 switch(pNotify->hdr.code)
\r
421 case PSN_SETACTIVE:
\r
422 return OnSetActive();
\r
423 case PSN_KILLACTIVE:
\r
424 return OnKillActive();
\r
426 if (pNotify->lParam)
\r
433 case PSN_QUERYCANCEL:
\r
434 return OnQueryCancel();
\r
436 return OnWizardNext();
\r
438 return OnWizardBack();
\r
439 case PSN_WIZFINISH:
\r
440 return OnWizardFinish();
\r
448 inline int CPropertyPage::OnSetActive()
\r
450 // Called when a page becomes active
\r
451 // Override this function in your derived class if required.
\r
453 // Returns zero to accept the activation, or -1 to activate the next or the previous page (depending
\r
454 // on whether the user clicked the Next or Back button). To set the activation to a particular page,
\r
455 // return the resource identifier of the page.
\r
460 inline int CPropertyPage::OnWizardBack()
\r
462 // This function is called when the Back button is pressed on a wizard page
\r
463 // Override this function in your derived class if required.
\r
465 // Returns 0 to allow the wizard to go to the previous page. Returns -1 to prevent the wizard
\r
466 // from changing pages. To display a particular page, return its dialog resource identifier.
\r
471 inline INT_PTR CPropertyPage::OnWizardFinish()
\r
473 // This function is called when the Finish button is pressed on a wizard page
\r
474 // Override this function in your derived class if required.
\r
477 // Return non-zero to prevent the wizard from finishing.
\r
478 // Version 5.80. and later. Return a window handle to prevent the wizard from finishing. The wizard will set the focus to that window. The window must be owned by the wizard page.
\r
479 // Return 0 to allow the wizard to finish.
\r
481 return 0; // Allow wizard to finish
\r
484 inline int CPropertyPage::OnWizardNext()
\r
486 // This function is called when the Next button is pressed on a wizard page
\r
487 // Override this function in your derived class if required.
\r
489 // Return 0 to allow the wizard to go to the next page. Return -1 to prevent the wizard from
\r
490 // changing pages. To display a particular page, return its dialog resource identifier.
\r
495 inline BOOL CPropertyPage::PreTranslateMessage(MSG* pMsg)
\r
497 // allow the tab control to translate keyboard input
\r
498 if (pMsg->message == WM_KEYDOWN && GetAsyncKeyState(VK_CONTROL) < 0 &&
\r
499 (pMsg->wParam == VK_TAB || pMsg->wParam == VK_PRIOR || pMsg->wParam == VK_NEXT))
\r
501 CWnd* pWndParent = GetParent();
\r
502 if (pWndParent->SendMessage(PSM_ISDIALOGMESSAGE, 0L, (LPARAM)pMsg))
\r
506 // allow the dialog to translate keyboard input
\r
507 if ((pMsg->message >= WM_KEYFIRST) && (pMsg->message <= WM_KEYLAST))
\r
509 if (IsDialogMessage(pMsg))
\r
513 return CWnd::PreTranslateMessage(pMsg);
\r
516 inline LRESULT CPropertyPage::QuerySiblings(WPARAM wParam, LPARAM lParam) const
\r
518 // Sent to a property sheet, which then forwards the message to each of its pages.
\r
519 // Set wParam and lParam to values you want passed to the property pages.
\r
520 // Returns the nonzero value from a page in the property sheet, or zero if no page returns a nonzero value.
\r
522 assert(::IsWindow(m_hWnd));
\r
523 return GetParent()->SendMessage(PSM_QUERYSIBLINGS, wParam, lParam);
\r
526 inline void CPropertyPage::SetModified(BOOL bChanged) const
\r
528 // The property sheet will enable the Apply button if bChanged is TRUE.
\r
530 assert(::IsWindow(m_hWnd));
\r
533 GetParent()->SendMessage(PSM_CHANGED, (WPARAM)m_hWnd, 0L);
\r
535 GetParent()->SendMessage(PSM_UNCHANGED, (WPARAM)m_hWnd, 0L);
\r
538 inline void CPropertyPage::SetTitle(LPCTSTR szTitle)
\r
543 m_PSP.dwFlags |= PSP_USETITLE;
\r
548 m_PSP.dwFlags &= ~PSP_USETITLE;
\r
551 m_PSP.pszTitle = m_Title;
\r
554 inline void CPropertyPage::SetWizardButtons(DWORD dwFlags) const
\r
556 // dwFlags: A value that specifies which wizard buttons are enabled. You can combine one or more of the following flags.
\r
557 // PSWIZB_BACK Enable the Back button. If this flag is not set, the Back button is displayed as disabled.
\r
558 // PSWIZB_DISABLEDFINISH Display a disabled Finish button.
\r
559 // PSWIZB_FINISH Display an enabled Finish button.
\r
560 // PSWIZB_NEXT Enable the Next button. If this flag is not set, the Next button is displayed as disabled.
\r
562 assert (::IsWindow(m_hWnd));
\r
563 PropSheet_SetWizButtons(::GetParent(m_hWnd), dwFlags);
\r
566 inline UINT CALLBACK CPropertyPage::StaticPropSheetPageProc(HWND hwnd, UINT uMsg, LPPROPSHEETPAGE ppsp)
\r
568 assert( GetApp() );
\r
569 UNREFERENCED_PARAMETER(hwnd);
\r
571 // Note: the hwnd is always NULL
\r
577 TLSData* pTLSData = (TLSData*)TlsGetValue(GetApp()->GetTlsIndex());
\r
580 // Store the CPropertyPage pointer in Thread Local Storage
\r
581 pTLSData->pCWnd = (CWnd*)ppsp->lParam;
\r
589 inline INT_PTR CALLBACK CPropertyPage::StaticDialogProc(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam)
\r
591 assert( GetApp() );
\r
593 // Find matching CWnd pointer for this HWND
\r
594 CPropertyPage* pPage = (CPropertyPage*)GetApp()->GetCWndFromMap(hwndDlg);
\r
597 // matching CWnd pointer not found, so add it to HWNDMap now
\r
598 TLSData* pTLSData = (TLSData*)TlsGetValue(GetApp()->GetTlsIndex());
\r
599 pPage = (CPropertyPage*)pTLSData->pCWnd;
\r
601 // Set the hWnd members and call DialogProc for this message
\r
602 pPage->m_hWnd = hwndDlg;
\r
606 return pPage->DialogProc(uMsg, wParam, lParam);
\r
610 ///////////////////////////////////////////
\r
611 // Definitions for the CPropertySheet class
\r
613 inline CPropertySheet::CPropertySheet(UINT nIDCaption, CWnd* pParent /* = NULL*/)
\r
615 ZeroMemory(&m_PSH, sizeof (PROPSHEETHEADER));
\r
616 SetTitle(LoadString(nIDCaption));
\r
617 m_bInitialUpdate = FALSE;
\r
620 m_PSH.dwSize = sizeof(PROPSHEETHEADER);
\r
622 if (GetComCtlVersion() >= 471)
\r
623 m_PSH.dwSize = sizeof(PROPSHEETHEADER);
\r
625 m_PSH.dwSize = PROPSHEETHEADER_V1_SIZE;
\r
628 m_PSH.dwFlags = PSH_PROPSHEETPAGE | PSH_USECALLBACK;
\r
629 m_PSH.hwndParent = pParent? pParent->GetHwnd() : 0;
\r
630 m_PSH.hInstance = GetApp()->GetInstanceHandle();
\r
631 m_PSH.pfnCallback = (PFNPROPSHEETCALLBACK)CPropertySheet::Callback;
\r
634 inline CPropertySheet::CPropertySheet(LPCTSTR pszCaption /*= NULL*/, CWnd* pParent /* = NULL*/)
\r
636 ZeroMemory(&m_PSH, sizeof (PROPSHEETHEADER));
\r
637 SetTitle(pszCaption);
\r
638 m_bInitialUpdate = FALSE;
\r
641 m_PSH.dwSize = PROPSHEETHEADER_V1_SIZE;
\r
643 if (GetComCtlVersion() >= 471)
\r
644 m_PSH.dwSize = sizeof(PROPSHEETHEADER);
\r
646 m_PSH.dwSize = PROPSHEETHEADER_V1_SIZE;
\r
649 m_PSH.dwFlags = PSH_PROPSHEETPAGE | PSH_USECALLBACK;
\r
650 m_PSH.hwndParent = pParent? pParent->GetHwnd() : 0;;
\r
651 m_PSH.hInstance = GetApp()->GetInstanceHandle();
\r
652 m_PSH.pfnCallback = (PFNPROPSHEETCALLBACK)CPropertySheet::Callback;
\r
655 inline CPropertyPage* CPropertySheet::AddPage(CPropertyPage* pPage)
\r
656 // Adds a Property Page to the Property Sheet
\r
658 assert(NULL != pPage);
\r
660 m_vPages.push_back(PropertyPagePtr(pPage));
\r
664 // property sheet already exists, so add page to it
\r
665 PROPSHEETPAGE psp = pPage->GetPSP();
\r
666 HPROPSHEETPAGE hpsp = ::CreatePropertySheetPage(&psp);
\r
667 PropSheet_AddPage(m_hWnd, hpsp);
\r
670 m_PSH.nPages = (int)m_vPages.size();
\r
675 inline void CPropertySheet::BuildPageArray()
\r
676 // Builds the PROPSHEETPAGE array
\r
679 std::vector<PropertyPagePtr>::iterator iter;
\r
680 for (iter = m_vPages.begin(); iter < m_vPages.end(); ++iter)
\r
681 m_vPSP.push_back((*iter)->GetPSP());
\r
683 PROPSHEETPAGE* pPSPArray = &m_vPSP.front(); // Array of PROPSHEETPAGE
\r
684 m_PSH.ppsp = pPSPArray;
\r
687 inline void CALLBACK CPropertySheet::Callback(HWND hwnd, UINT uMsg, LPARAM lParam)
\r
689 assert( GetApp() );
\r
693 //called before the dialog is created, hwnd = NULL, lParam points to dialog resource
\r
694 case PSCB_PRECREATE:
\r
696 LPDLGTEMPLATE lpTemplate = (LPDLGTEMPLATE)lParam;
\r
698 if(!(lpTemplate->style & WS_SYSMENU))
\r
700 lpTemplate->style |= WS_SYSMENU;
\r
705 //called after the dialog is created
\r
706 case PSCB_INITIALIZED:
\r
708 // Retrieve pointer to CWnd object from Thread Local Storage
\r
709 TLSData* pTLSData = (TLSData*)TlsGetValue(GetApp()->GetTlsIndex());
\r
712 CPropertySheet* w = (CPropertySheet*)pTLSData->pCWnd;
\r
723 inline HWND CPropertySheet::Create(CWnd* pParent /*= 0*/)
\r
724 // Creates a modeless Property Sheet
\r
726 assert( GetApp() );
\r
730 m_PSH.hwndParent = pParent->GetHwnd();
\r
734 PROPSHEETPAGE* pPSPArray = &m_vPSP.front();
\r
735 m_PSH.ppsp = pPSPArray;
\r
737 // Create a modeless Property Sheet
\r
738 m_PSH.dwFlags &= ~PSH_WIZARD;
\r
739 m_PSH.dwFlags |= PSH_MODELESS;
\r
740 HWND hWnd = (HWND)CreatePropertySheet(&m_PSH);
\r
745 inline INT_PTR CPropertySheet::CreatePropertySheet(LPCPROPSHEETHEADER ppsph)
\r
747 assert( GetApp() );
\r
749 INT_PTR ipResult = 0;
\r
751 // Only one window per CWnd instance allowed
\r
752 assert(!::IsWindow(m_hWnd));
\r
754 // Ensure this thread has the TLS index set
\r
755 TLSData* pTLSData = GetApp()->SetTlsIndex();
\r
757 // Store the 'this' pointer in Thread Local Storage
\r
758 pTLSData->pCWnd = this;
\r
760 // Create the property sheet
\r
761 ipResult = PropertySheet(ppsph);
\r
766 inline void CPropertySheet::DestroyButton(int IDButton)
\r
768 assert(::IsWindow(m_hWnd));
\r
770 HWND hwndButton = ::GetDlgItem(m_hWnd, IDButton);
\r
771 if (hwndButton != NULL)
\r
773 // Hide and disable the button
\r
774 ::ShowWindow(hwndButton, SW_HIDE);
\r
775 ::EnableWindow(hwndButton, FALSE);
\r
779 inline void CPropertySheet::Destroy()
\r
785 inline int CPropertySheet::DoModal()
\r
787 assert( GetApp() );
\r
790 PROPSHEETPAGE* pPSPArray = &m_vPSP.front();
\r
791 m_PSH.ppsp = pPSPArray;
\r
793 // Create the Property Sheet
\r
794 int nResult = (int)CreatePropertySheet(&m_PSH);
\r
801 inline CPropertyPage* CPropertySheet::GetActivePage() const
\r
803 assert(::IsWindow(m_hWnd));
\r
805 CPropertyPage* pPage = NULL;
\r
806 if (m_hWnd != NULL)
\r
808 HWND hPage = (HWND)SendMessage(PSM_GETCURRENTPAGEHWND, 0L, 0L);
\r
809 pPage = (CPropertyPage*)FromHandle(hPage);
\r
815 inline int CPropertySheet::GetPageCount() const
\r
816 // Returns the number of Property Pages in this Property Sheet
\r
818 assert(::IsWindow(m_hWnd));
\r
819 return (int)m_vPages.size();
\r
822 inline int CPropertySheet::GetPageIndex(CPropertyPage* pPage) const
\r
824 assert(::IsWindow(m_hWnd));
\r
826 for (int i = 0; i < GetPageCount(); i++)
\r
828 if (m_vPages[i].get() == pPage)
\r
834 inline HWND CPropertySheet::GetTabControl() const
\r
835 // Returns the handle to the Property Sheet's tab control
\r
837 assert(::IsWindow(m_hWnd));
\r
838 return (HWND)SendMessage(PSM_GETTABCONTROL, 0L, 0L);
\r
841 inline BOOL CPropertySheet::IsModeless() const
\r
843 return (m_PSH.dwFlags & PSH_MODELESS);
\r
846 inline BOOL CPropertySheet::IsWizard() const
\r
848 return (m_PSH.dwFlags & PSH_WIZARD);
\r
851 inline void CPropertySheet::RemovePage(CPropertyPage* pPage)
\r
852 // Removes a Property Page from the Property Sheet
\r
854 assert(::IsWindow(m_hWnd));
\r
856 int nPage = GetPageIndex(pPage);
\r
857 if (m_hWnd != NULL)
\r
858 SendMessage(m_hWnd, PSM_REMOVEPAGE, nPage, 0L);
\r
860 m_vPages.erase(m_vPages.begin() + nPage, m_vPages.begin() + nPage+1);
\r
861 m_PSH.nPages = (int)m_vPages.size();
\r
864 inline BOOL CPropertySheet::PreTranslateMessage(MSG* pMsg)
\r
866 // allow sheet to translate Ctrl+Tab, Shift+Ctrl+Tab, Ctrl+PageUp, and Ctrl+PageDown
\r
867 if (pMsg->message == WM_KEYDOWN && GetAsyncKeyState(VK_CONTROL) < 0 &&
\r
868 (pMsg->wParam == VK_TAB || pMsg->wParam == VK_PRIOR || pMsg->wParam == VK_NEXT))
\r
870 if (SendMessage(PSM_ISDIALOGMESSAGE, 0L, (LPARAM)pMsg))
\r
874 // allow the dialog to translate keyboard input
\r
875 if ((pMsg->message >= WM_KEYFIRST) && (pMsg->message <= WM_KEYLAST))
\r
877 return GetActivePage()->PreTranslateMessage(pMsg);
\r
880 return CWnd::PreTranslateMessage(pMsg);
\r
883 inline BOOL CPropertySheet::SetActivePage(int nPage)
\r
885 assert(::IsWindow(m_hWnd));
\r
886 return (BOOL)SendMessage(m_hWnd, PSM_SETCURSEL, nPage, 0L);
\r
889 inline BOOL CPropertySheet::SetActivePage(CPropertyPage* pPage)
\r
891 assert(::IsWindow(m_hWnd));
\r
892 int nPage = GetPageIndex(pPage);
\r
894 return SetActivePage(nPage);
\r
899 inline void CPropertySheet::SetIcon(UINT idIcon)
\r
901 m_PSH.pszIcon = MAKEINTRESOURCE(idIcon);
\r
902 m_PSH.dwFlags |= PSH_USEICONID;
\r
905 inline void CPropertySheet::SetTitle(LPCTSTR szTitle)
\r
912 m_PSH.pszCaption = m_Title;
\r
915 inline void CPropertySheet::SetWizardMode(BOOL bWizard)
\r
918 m_PSH.dwFlags |= PSH_WIZARD;
\r
920 m_PSH.dwFlags &= ~PSH_WIZARD;
\r
923 inline LRESULT CPropertySheet::WndProcDefault(UINT uMsg, WPARAM wParam, LPARAM lParam)
\r
928 case WM_WINDOWPOSCHANGED:
\r
930 LPWINDOWPOS lpWinPos = (LPWINDOWPOS)lParam;
\r
931 if (lpWinPos->flags & SWP_SHOWWINDOW)
\r
933 if (!m_bInitialUpdate)
\r
934 // The first window positioning with the window visible
\r
936 m_bInitialUpdate = TRUE;
\r
942 m_bInitialUpdate = FALSE;
\r
945 case WM_SYSCOMMAND:
\r
946 if ((SC_CLOSE == wParam) && (m_PSH.dwFlags & PSH_MODELESS))
\r
954 // pass unhandled messages on for default processing
\r
955 return CWnd::WndProcDefault(uMsg, wParam, lParam);
\r
960 #endif // _WIN32XX_PROPERTYSHEET_H_
\r