PageRenderTime 72ms CodeModel.GetById 9ms RepoModel.GetById 1ms app.codeStats 0ms

/winx/include/winx/PropertySheet.h

http://winx.googlecode.com/
C Header | 581 lines | 433 code | 78 blank | 70 comment | 25 complexity | dd957a719d42dc02bd3d67dd2f23d4b4 MD5 | raw file
  1. /* -------------------------------------------------------------------------
  2. // WINX: a C++ template GUI library - MOST SIMPLE BUT EFFECTIVE
  3. //
  4. // This file is a part of the WINX Library.
  5. // The use and distribution terms for this software are covered by the
  6. // Common Public License 1.0 (http://opensource.org/licenses/cpl.php)
  7. // which can be found in the file CPL.txt at this distribution. By using
  8. // this software in any fashion, you are agreeing to be bound by the terms
  9. // of this license. You must not remove this notice, or any other, from
  10. // this software.
  11. //
  12. // Module: winx/PropertySheet.h
  13. // Creator: xushiwei
  14. // Email: xushiweizh@gmail.com
  15. // Date: 2006-9-2 21:26:41
  16. //
  17. // $Id: PropertySheet.h,v 1.3 2006/09/13 17:05:11 xushiwei Exp $
  18. // -----------------------------------------------------------------------*/
  19. #ifndef WINX_WIN_PROPERTYSHEET_H
  20. #define WINX_WIN_PROPERTYSHEET_H
  21. #ifndef WINX_WIN_DIALOG_H
  22. #include "win/Dialog.h"
  23. #endif
  24. // -------------------------------------------------------------------------
  25. // Reference Win32 SDK
  26. #if defined(WINX_USE_WINSDK)
  27. #ifndef _INC_COMMDLG
  28. #include "../../../winsdk/include/commdlg.h"
  29. #endif
  30. #ifndef _SHLOBJ_H_
  31. #include "../../../winsdk/include/shlobj.h"
  32. #endif
  33. #else // defined(WINX_USE_DEFSDK)
  34. #ifndef _INC_COMMDLG
  35. #include <commdlg.h>
  36. #endif
  37. #ifndef _SHLOBJ_H_
  38. #include <shlobj.h>
  39. #endif
  40. #endif
  41. // -------------------------------------------------------------------------
  42. // Reference WTL
  43. #ifndef __ATLDLGS_H__
  44. #include "../../../wtl/include/atldlgs.h"
  45. #endif
  46. NS_WINX_BEGIN
  47. // =========================================================================
  48. // class PropertySheetHandle
  49. class PropertySheetHandle : public HandleT<WTL::CPropertySheetWindow>
  50. {
  51. WINX_HANDLE_CLASS(PropertySheetHandle);
  52. };
  53. // -------------------------------------------------------------------------
  54. // class PropertyPageHandle
  55. class PropertyPageHandle : public HandleT<WTL::CPropertyPageWindow>
  56. {
  57. WINX_HANDLE_CLASS(PropertyPageHandle);
  58. };
  59. // =========================================================================
  60. // class StaticPageContainer
  61. template <UINT nPages>
  62. class StaticPageContainer
  63. {
  64. private:
  65. HPROPSHEETPAGE m_hPages[nPages];
  66. UINT m_nPages;
  67. public:
  68. StaticPageContainer() : m_nPages(0) {}
  69. BOOL winx_call AddPage(HPROPSHEETPAGE hPage)
  70. {
  71. WINX_ASSERT(m_nPages < nPages);
  72. if (m_nPages < nPages)
  73. {
  74. m_hPages[m_nPages++] = hPage;
  75. return TRUE;
  76. }
  77. return FALSE;
  78. }
  79. BOOL winx_call AddPage(LPCPROPSHEETPAGE pPage)
  80. {
  81. WINX_ASSERT(pPage != NULL);
  82. HPROPSHEETPAGE hPage = ::CreatePropertySheetPage(pPage);
  83. if (hPage == NULL)
  84. return FALSE;
  85. return AddPage(hPage);
  86. }
  87. VOID winx_call ClearPages(BOOL fDestroy)
  88. {
  89. if (fDestroy)
  90. {
  91. for (UINT i = 0; i < m_nPages; ++i)
  92. ::DestroyPropertySheetPage(m_hPages[i]);
  93. }
  94. m_nPages = 0;
  95. }
  96. HPROPSHEETPAGE* winx_call GetPages(UINT* pnPages)
  97. {
  98. *pnPages = m_nPages;
  99. return m_hPages;
  100. }
  101. BOOL winx_call IsEmpty() const
  102. {
  103. return m_nPages == 0;
  104. }
  105. };
  106. // -------------------------------------------------------------------------
  107. // class DynamicPageContainer
  108. class DynamicPageContainer
  109. {
  110. private:
  111. std::TypedPtrArray<HPROPSHEETPAGE> m_pages;
  112. public:
  113. BOOL winx_call AddPage(HPROPSHEETPAGE hPage)
  114. {
  115. m_pages.push_back(hPage);
  116. return TRUE;
  117. }
  118. BOOL winx_call AddPage(LPCPROPSHEETPAGE pPage)
  119. {
  120. WINX_ASSERT(pPage != NULL);
  121. HPROPSHEETPAGE hPage = ::CreatePropertySheetPage(pPage);
  122. if (hPage == NULL)
  123. return FALSE;
  124. return AddPage(hPage);
  125. }
  126. VOID winx_call ClearPages(BOOL fDestroy)
  127. {
  128. if (fDestroy)
  129. {
  130. UINT nPages = m_pages.size();
  131. for (UINT i = 0; i < nPages; ++i)
  132. ::DestroyPropertySheetPage(m_pages.at(i));
  133. }
  134. m_pages.clear();
  135. }
  136. HPROPSHEETPAGE* winx_call GetPages(UINT* pnPages)
  137. {
  138. *pnPages = m_pages.size();
  139. return &m_pages.at(0);
  140. }
  141. BOOL winx_call IsEmpty() const
  142. {
  143. return m_pages.empty();
  144. }
  145. };
  146. // =========================================================================
  147. // class PropertySheetT
  148. template <UINT nPages = 0, class PageContainer = StaticPageContainer<nPages> >
  149. class PropertySheetT : public PageContainer
  150. {
  151. public:
  152. PROPSHEETHEADER m_psh;
  153. public:
  154. PropertySheetT(
  155. RESID title = (LPCTSTR)NULL, UINT uStartPage = 0,
  156. HINSTANCE hInst = GetThisModule())
  157. {
  158. ZeroMemory(&m_psh, sizeof(PROPSHEETHEADER));
  159. m_psh.dwSize = sizeof(PROPSHEETHEADER);
  160. m_psh.hInstance = hInst;
  161. m_psh.pszCaption = title.m_lpstr;
  162. m_psh.nStartPage = uStartPage;
  163. }
  164. #if defined(_DEBUG)
  165. ~PropertySheetT()
  166. {
  167. WINX_ASSERT(IsEmpty());
  168. }
  169. #endif
  170. int winx_call DoModal(HWND hWndParent = NULL)
  171. {
  172. m_psh.hwndParent = hWndParent;
  173. m_psh.phpage = GetPages(&m_psh.nPages);
  174. int result = ::PropertySheet(&m_psh);
  175. ClearPages(FALSE);
  176. return result;
  177. }
  178. };
  179. typedef PropertySheetT<0, DynamicPageContainer> DynamicPropertySheet;
  180. // =========================================================================
  181. // class PropertyPageInit
  182. class PropertyPageInit : public PROPSHEETPAGE
  183. {
  184. public:
  185. void SetTitle(RESID title)
  186. {
  187. pszTitle = title.m_lpstr;
  188. dwFlags |= PSP_USETITLE;
  189. }
  190. #if (_WIN32_IE >= 0x0500) && !defined(_WIN32_WCE)
  191. void SetHeaderTitle(LPCTSTR lpstrHeaderTitle)
  192. {
  193. dwFlags |= PSP_USEHEADERTITLE;
  194. pszHeaderTitle = lpstrHeaderTitle;
  195. }
  196. void SetHeaderSubTitle(LPCTSTR lpstrHeaderSubTitle)
  197. {
  198. dwFlags |= PSP_USEHEADERSUBTITLE;
  199. pszHeaderSubTitle = lpstrHeaderSubTitle;
  200. }
  201. #endif // (_WIN32_IE >= 0x0500) && !defined(_WIN32_WCE)
  202. void EnableHelp()
  203. {
  204. dwFlags |= PSP_HASHELP;
  205. }
  206. };
  207. // -------------------------------------------------------------------------
  208. // class PropertySheetNotify
  209. template <class WindowImplClass>
  210. class PropertySheetNotify
  211. {
  212. public:
  213. BOOL winx_msg ProcessNotifyMessage(HWND hWnd, int idCtrl, LPNMHDR pnmh, LRESULT* pResult)
  214. {
  215. const UINT message = pnmh->code;
  216. WINX_MSG_CASE(PSN_SETACTIVE, PSN_OnSetActive)
  217. {
  218. *pResult = _WINX_PWND->PSN_OnSetActive(hWnd);
  219. return TRUE;
  220. }
  221. WINX_MSG_CASE(PSN_KILLACTIVE, PSN_OnKillActive)
  222. {
  223. *pResult = _WINX_PWND->PSN_OnKillActive(hWnd);
  224. return TRUE;
  225. }
  226. WINX_MSG_CASE(PSN_APPLY, PSN_OnApply)
  227. {
  228. *pResult = _WINX_PWND->PSN_OnApply(hWnd);
  229. return TRUE;
  230. }
  231. WINX_MSG_CASE(PSN_RESET, PSN_OnReset)
  232. {
  233. _WINX_PWND->PSN_OnReset(hWnd);
  234. return TRUE;
  235. }
  236. WINX_MSG_CASE(PSN_QUERYCANCEL, PSN_OnQueryCancel)
  237. {
  238. *pResult = _WINX_PWND->PSN_OnQueryCancel(hWnd);
  239. return TRUE;
  240. }
  241. WINX_MSG_CASE(PSN_WIZNEXT, PSN_OnWizardNext)
  242. {
  243. *pResult = _WINX_PWND->PSN_OnWizardNext(hWnd);
  244. return TRUE;
  245. }
  246. WINX_MSG_CASE(PSN_WIZBACK, PSN_OnWizardBack)
  247. {
  248. *pResult = _WINX_PWND->PSN_OnWizardBack(hWnd);
  249. return TRUE;
  250. }
  251. WINX_MSG_CASE(PSN_WIZFINISH, PSN_OnWizardFinish)
  252. {
  253. *pResult = _WINX_PWND->PSN_OnWizardFinish(hWnd);
  254. return TRUE;
  255. }
  256. WINX_MSG_CASE(PSN_HELP, PSN_OnHelp)
  257. {
  258. _WINX_PWND->PSN_OnHelp(hWnd);
  259. return TRUE;
  260. }
  261. #ifndef _WIN32_WCE
  262. #if (_WIN32_IE >= 0x0400)
  263. WINX_MSG_CASE(PSN_GETOBJECT, PSN_OnGetObject)
  264. {
  265. return _WINX_PWND->PSN_OnGetObject(hWnd, (LPNMOBJECTNOTIFY)pnmh);
  266. }
  267. #endif // (_WIN32_IE >= 0x0400)
  268. #if (_WIN32_IE >= 0x0500)
  269. WINX_MSG_CASE(PSN_TRANSLATEACCELERATOR, PSN_OnTranslateAccelerator)
  270. {
  271. LPPSHNOTIFY lpPSHNotify = (LPPSHNOTIFY)pnmh;
  272. *pResult = _WINX_PWND->PSN_OnTranslateAccelerator(hWnd, (LPMSG)lpPSHNotify->lParam);
  273. return TRUE;
  274. }
  275. WINX_MSG_CASE(PSN_QUERYINITIALFOCUS, PSN_OnQueryInitialFocus)
  276. {
  277. LPPSHNOTIFY lpPSHNotify = (LPPSHNOTIFY)pnmh;
  278. *pResult = (LRESULT)_WINX_PWND->PSN_OnQueryInitialFocus(hWnd, (HWND)lpPSHNotify->lParam);
  279. return TRUE;
  280. }
  281. #endif // (_WIN32_IE >= 0x0500)
  282. #endif // !_WIN32_WCE
  283. return FALSE;
  284. }
  285. public:
  286. WINX_MSG_NULL_HANDLER(PSN_OnSetActive);
  287. WINX_MSG_NULL_HANDLER(PSN_OnKillActive);
  288. WINX_MSG_NULL_HANDLER(PSN_OnApply);
  289. WINX_MSG_NULL_HANDLER(PSN_OnReset);
  290. WINX_MSG_NULL_HANDLER(PSN_OnQueryCancel);
  291. WINX_MSG_NULL_HANDLER(PSN_OnWizardBack);
  292. WINX_MSG_NULL_HANDLER(PSN_OnWizardNext);
  293. WINX_MSG_NULL_HANDLER(PSN_OnWizardFinish);
  294. WINX_MSG_NULL_HANDLER(PSN_OnHelp);
  295. WINX_MSG_NULL_HANDLER(PSN_OnGetObject);
  296. WINX_MSG_NULL_HANDLER(PSN_OnTranslateAccelerator);
  297. WINX_MSG_NULL_HANDLER(PSN_OnQueryInitialFocus);
  298. #if (0)
  299. int winx_msg PSN_OnSetActive(HWND hWnd)
  300. {
  301. // 0 = allow activate
  302. // -1 = go back that was active
  303. // page ID = jump to page
  304. return 0;
  305. }
  306. BOOL winx_msg PSN_OnKillActive(HWND hWnd)
  307. {
  308. // FALSE = allow deactivate
  309. // TRUE = prevent deactivation
  310. return FALSE;
  311. }
  312. int winx_msg PSN_OnApply(HWND hWnd)
  313. {
  314. // PSNRET_NOERROR = apply OK
  315. // PSNRET_INVALID = apply not OK, return to this page
  316. // PSNRET_INVALID_NOCHANGEPAGE = apply not OK, don't change focus
  317. return PSNRET_NOERROR;
  318. }
  319. void winx_msg PSN_OnReset(HWND hWnd)
  320. {
  321. }
  322. BOOL winx_msg PSN_OnQueryCancel(HWND hWnd)
  323. {
  324. // FALSE = allow cancel
  325. // TRUE = prevent cancel
  326. return FALSE;
  327. }
  328. int winx_msg PSN_OnWizardBack(HWND hWnd)
  329. {
  330. // 0 = goto previous page
  331. // -1 = prevent page change
  332. // >0 = jump to page by dlg ID
  333. return 0;
  334. }
  335. int winx_msg PSN_OnWizardNext(HWND hWnd)
  336. {
  337. // 0 = goto next page
  338. // -1 = prevent page change
  339. // >0 = jump to page by dlg ID
  340. return 0;
  341. }
  342. INT_PTR winx_msg PSN_OnWizardFinish(HWND hWnd)
  343. {
  344. // FALSE = allow finish
  345. // TRUE = prevent finish
  346. // HWND = prevent finish and set focus to HWND (CommCtrl 5.80 only)
  347. return FALSE;
  348. }
  349. void winx_msg PSN_OnHelp(HWND hWnd)
  350. {
  351. }
  352. BOOL winx_msg PSN_OnGetObject(HWND hWnd, LPNMOBJECTNOTIFY lpObjectNotify)
  353. {
  354. return FALSE; // not processed
  355. }
  356. int winx_msg PSN_OnTranslateAccelerator(HWND hWnd, LPMSG lpMsg)
  357. {
  358. // PSNRET_NOERROR - message not handled
  359. // PSNRET_MESSAGEHANDLED - message handled
  360. return PSNRET_NOERROR;
  361. }
  362. HWND winx_msg PSN_OnQueryInitialFocus(HWND hWnd, HWND hWndFocus)
  363. {
  364. // NULL = set focus to default control
  365. // HWND = set focus to HWND
  366. return NULL;
  367. }
  368. #endif
  369. };
  370. // -------------------------------------------------------------------------
  371. // class PropertyPage
  372. template <class WindowClass, int nDlgId = 0, class HandleClass = DefaultWindowHandle>
  373. class PropertyPage :
  374. public ModelessDialog<WindowClass, nDlgId, HandleClass>,
  375. public PropertySheetNotify<WindowClass>
  376. {
  377. public:
  378. static BOOL CALLBACK DialogProc(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam)
  379. {
  380. WindowClass* pWnd = (WindowClass*)WindowMap::GetWindow(hDlg);
  381. if (pWnd == NULL)
  382. {
  383. if (message != WM_INITDIALOG)
  384. return FALSE;
  385. if (lParam) {
  386. LPPROPSHEETPAGE ppsp = (LPPROPSHEETPAGE)lParam;
  387. pWnd = (WindowClass*)ppsp->lParam;
  388. lParam = 0;
  389. }
  390. else {
  391. WINX_ASSERT(!WindowClass::StackWindowObject);
  392. if (!WindowClass::StackWindowObject)
  393. pWnd = WINX_NEW(WindowClass);
  394. }
  395. WindowMap::SetWindow(hDlg, pWnd);
  396. }
  397. return pWnd->ProcessMessage(hDlg, message, wParam, lParam);
  398. }
  399. static UINT CALLBACK PropertyPageProc(HWND hWnd, UINT uMsg, LPPROPSHEETPAGE ppsp)
  400. {
  401. WindowClass* pWnd = (WindowClass*)ppsp->lParam;
  402. switch(uMsg)
  403. {
  404. case PSPCB_CREATE:
  405. return pWnd->OnPageCreate(hWnd);
  406. #if (_WIN32_IE >= 0x0500)
  407. case PSPCB_ADDREF:
  408. pWnd->OnPageAddRef(hWnd);
  409. break;
  410. #endif // (_WIN32_IE >= 0x0500)
  411. case PSPCB_RELEASE:
  412. pWnd->OnPageRelease(hWnd);
  413. break;
  414. }
  415. return 0;
  416. }
  417. BOOL winx_msg OnNotify(HWND hWnd, int idCtrl, LPNMHDR pnmh, LRESULT* pResult)
  418. {
  419. return ProcessNotifyMessage(hWnd, idCtrl, pnmh, pResult);
  420. }
  421. public:
  422. WINX_MSG_NULL_HANDLER(OnPagePreCreate);
  423. WINX_MSG_SIMPLE_HANDLER(OnPageCreate, TRUE);
  424. WINX_MSG_SIMPLE_HANDLER(OnPageAddRef, 0);
  425. WINX_MSG_SIMPLE_HANDLER(OnPageRelease, 0);
  426. #if (0)
  427. BOOL winx_msg OnPagePreCreate(PropertyPageInit* pPsp, LPVOID pInitParam)
  428. {
  429. return TRUE;
  430. }
  431. BOOL winx_msg OnPageCreate(HWND hWndZero) { return TRUE; }
  432. void winx_msg OnPageAddRef(HWND hWndZero) {}
  433. void winx_msg OnPageRelease(HWND hWndZero) {}
  434. #endif
  435. public:
  436. HPROPSHEETPAGE winx_call Create(
  437. RESID title = (LPCTSTR)NULL, LPVOID pInitParam = NULL,
  438. HINSTANCE hInst = GetThisModule())
  439. {
  440. PropertyPageInit psp;
  441. ZeroMemory(&psp, sizeof(PropertyPageInit));
  442. psp.dwSize = sizeof(PROPSHEETPAGE);
  443. psp.hInstance = hInst;
  444. psp.pszTemplate = MAKEINTRESOURCE(IDD);
  445. psp.pfnDlgProc = (DLGPROC)WindowClass::DialogProc;
  446. psp.lParam = (LPARAM)_WINX_PWND;
  447. WINX_MSG_HAS3(OnPageCreate, OnPageAddRef, OnPageRelease)
  448. {
  449. WINX_MSG_HAS(PropertyPageProc)
  450. {
  451. psp.dwFlags = PSP_USECALLBACK;
  452. psp.pfnCallback = WindowClass::PropertyPageProc;
  453. }
  454. }
  455. if (title.m_lpstr != NULL)
  456. {
  457. psp.dwFlags |= PSP_USETITLE;
  458. psp.pszTitle = title.m_lpstr;
  459. }
  460. WINX_MSG_HAS(OnPagePreCreate)
  461. _WINX_PWND->OnPagePreCreate(&psp, pInitParam);
  462. return ::CreatePropertySheetPage(&psp);
  463. }
  464. public:
  465. template <class SheetClass>
  466. BOOL winx_call AddTo(
  467. SheetClass& sheet,
  468. RESID title = (LPCTSTR)NULL, LPVOID pInitParam = NULL,
  469. HINSTANCE hInst = GetThisModule())
  470. {
  471. HPROPSHEETPAGE hPage = Create(title, pInitParam, hInst);
  472. if (hPage == NULL)
  473. {
  474. WINX_DELETE_THIS_PWND();
  475. return FALSE;
  476. }
  477. return sheet.AddPage(hPage);
  478. }
  479. public:
  480. int winx_call DoModal(
  481. HWND hWndParent = NULL,
  482. RESID titleSheet = (LPCTSTR)NULL,
  483. RESID titlePage = (LPCTSTR)NULL, LPVOID pInitParam = NULL,
  484. HINSTANCE hInst = GetThisModule())
  485. {
  486. PropertySheetT<1> sheet(titleSheet, 0, hInst);
  487. BOOL fRet = AddTo(sheet, titlePage, pInitParam, hInst);
  488. if (fRet)
  489. return sheet.DoModal(hWndParent);
  490. return -1;
  491. }
  492. };
  493. // =========================================================================
  494. // $Log: PropertySheet.h,v $
  495. // Revision 1.3 2006/09/13 17:05:11 xushiwei
  496. // WINX-Basic: DefaultWindowHandle(see macro WINX_NULL_WINDOW_HANDLE)
  497. // WINX-Core: AxModelDialog/AxModelessDialog
  498. //
  499. // Revision 1.2 2006/09/03 06:32:12 xushiwei
  500. // WINX-Extension: PropertySheet, PropertyPage
  501. //
  502. NS_WINX_END
  503. #endif /* WINX_WIN_PROPERTYSHEET_H */