Leaked source code of windows server 2003
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

2605 lines
69 KiB

  1. // WTL Version 3.1
  2. // Copyright (C) 1997-2000 Microsoft Corporation
  3. // All rights reserved.
  4. //
  5. // This file is a part of Windows Template Library.
  6. // The code and information is provided "as-is" without
  7. // warranty of any kind, either expressed or implied.
  8. #ifndef __ATLDLGS_H__
  9. #define __ATLDLGS_H__
  10. #pragma once
  11. #ifndef __cplusplus
  12. #error ATL requires C++ compilation (use a .cpp suffix)
  13. #endif
  14. #ifndef __ATLAPP_H__
  15. #error atldlgs.h requires atlapp.h to be included first
  16. #endif
  17. #ifndef __ATLWIN_H__
  18. #error atldlgs.h requires atlwin.h to be included first
  19. #endif
  20. #include <commdlg.h>
  21. #include <shlobj.h>
  22. namespace WTL
  23. {
  24. /////////////////////////////////////////////////////////////////////////////
  25. // Forward declarations
  26. template <class T> class CFileDialogImpl;
  27. class CFileDialog;
  28. template <class T> class CFolderDialogImpl;
  29. class CFolderDialog;
  30. template <class T> class CFontDialogImpl;
  31. class CFontDialog;
  32. #ifdef _RICHEDIT_
  33. template <class T> class CRichEditFontDialogImpl;
  34. class CRichEditFontDialog;
  35. #endif //_RICHEDIT_
  36. template <class T> class CColorDialogImpl;
  37. class CColorDialog;
  38. template <class T> class CPrintDialogImpl;
  39. class CPrintDialog;
  40. template <class T> class CPageSetupDialogImpl;
  41. #if (WINVER >= 0x0500)
  42. template <class T> class CPrintDialogExImpl;
  43. class CPrintDialogEx;
  44. #endif //(WINVER >= 0x0500)
  45. class CPageSetupDialog;
  46. template <class T> class CFindReplaceDialogImpl;
  47. class CFindReplaceDialog;
  48. class CPropertySheetWindow;
  49. template <class T, class TBase = CPropertySheetWindow> class CPropertySheetImpl;
  50. class CPropertySheet;
  51. class CPropertyPageWindow;
  52. template <class T, class TBase = CPropertyPageWindow> class CPropertyPageImpl;
  53. template <WORD t_wDlgTemplateID> class CPropertyPage;
  54. /////////////////////////////////////////////////////////////////////////////
  55. // CFileDialogImpl - used for File Open or File Save As
  56. // compatibility with the old (vc6.0) headers
  57. #if (_WIN32_WINNT >= 0x0500) && !defined(OPENFILENAME_SIZE_VERSION_400)
  58. #ifndef CDSIZEOF_STRUCT
  59. #define CDSIZEOF_STRUCT(structname, member) (((int)((LPBYTE)(&((structname*)0)->member) - ((LPBYTE)((structname*)0)))) + sizeof(((structname*)0)->member))
  60. #endif
  61. #define OPENFILENAME_SIZE_VERSION_400A CDSIZEOF_STRUCT(OPENFILENAMEA,lpTemplateName)
  62. #define OPENFILENAME_SIZE_VERSION_400W CDSIZEOF_STRUCT(OPENFILENAMEW,lpTemplateName)
  63. #ifdef UNICODE
  64. #define OPENFILENAME_SIZE_VERSION_400 OPENFILENAME_SIZE_VERSION_400W
  65. #else
  66. #define OPENFILENAME_SIZE_VERSION_400 OPENFILENAME_SIZE_VERSION_400A
  67. #endif // !UNICODE
  68. #endif // (_WIN32_WINNT >= 0x0500) && !defined(OPENFILENAME_SIZE_VERSION_400)
  69. template <class T>
  70. class ATL_NO_VTABLE CFileDialogImpl : public CDialogImplBase
  71. {
  72. public:
  73. OPENFILENAME m_ofn;
  74. BOOL m_bOpenFileDialog; // TRUE for file open, FALSE for file save
  75. TCHAR m_szFileTitle[_MAX_FNAME]; // contains file title after return
  76. TCHAR m_szFileName[_MAX_PATH]; // contains full path name after return
  77. CFileDialogImpl(BOOL bOpenFileDialog, // TRUE for FileOpen, FALSE for FileSaveAs
  78. LPCTSTR lpszDefExt = NULL,
  79. LPCTSTR lpszFileName = NULL,
  80. DWORD dwFlags = OFN_HIDEREADONLY | OFN_OVERWRITEPROMPT,
  81. LPCTSTR lpszFilter = NULL,
  82. HWND hWndParent = NULL)
  83. {
  84. memset(&m_ofn, 0, sizeof(m_ofn)); // initialize structure to 0/NULL
  85. m_szFileName[0] = '\0';
  86. m_szFileTitle[0] = '\0';
  87. m_bOpenFileDialog = bOpenFileDialog;
  88. m_ofn.lStructSize = sizeof(m_ofn);
  89. #if (_WIN32_WINNT >= 0x0500)
  90. // adjust struct size if running on older version of Windows
  91. if(AtlIsOldWindows())
  92. {
  93. ATLASSERT(sizeof(m_ofn) > OPENFILENAME_SIZE_VERSION_400); // must be
  94. m_ofn.lStructSize = OPENFILENAME_SIZE_VERSION_400;
  95. }
  96. #endif //(_WIN32_WINNT >= 0x0500)
  97. m_ofn.lpstrFile = m_szFileName;
  98. m_ofn.nMaxFile = _MAX_PATH;
  99. m_ofn.lpstrDefExt = lpszDefExt;
  100. m_ofn.lpstrFileTitle = (LPTSTR)m_szFileTitle;
  101. m_ofn.nMaxFileTitle = _MAX_FNAME;
  102. m_ofn.Flags |= dwFlags | OFN_EXPLORER | OFN_ENABLEHOOK | OFN_ENABLESIZING;
  103. m_ofn.lpstrFilter = lpszFilter;
  104. m_ofn.hInstance = _Module.GetResourceInstance();
  105. m_ofn.lpfnHook = (LPOFNHOOKPROC)T::StartDialogProc;
  106. m_ofn.hwndOwner = hWndParent;
  107. // setup initial file name
  108. if(lpszFileName != NULL)
  109. lstrcpyn(m_szFileName, lpszFileName, _MAX_PATH);
  110. }
  111. INT_PTR DoModal(HWND hWndParent = ::GetActiveWindow())
  112. {
  113. ATLASSERT(m_ofn.Flags & OFN_ENABLEHOOK);
  114. ATLASSERT(m_ofn.lpfnHook != NULL); // can still be a user hook
  115. ATLASSERT(m_ofn.Flags & OFN_EXPLORER);
  116. if(m_ofn.hwndOwner == NULL) // set only if not specified before
  117. m_ofn.hwndOwner = hWndParent;
  118. ATLASSERT(m_hWnd == NULL);
  119. _Module.AddCreateWndData(&m_thunk.cd, (CDialogImplBase*)this);
  120. BOOL bRet;
  121. if(m_bOpenFileDialog)
  122. bRet = ::GetOpenFileName(&m_ofn);
  123. else
  124. bRet = ::GetSaveFileName(&m_ofn);
  125. m_hWnd = NULL;
  126. return bRet ? IDOK : IDCANCEL;
  127. }
  128. // Attributes
  129. CWindow GetFileDialogWindow() const
  130. {
  131. ATLASSERT(::IsWindow(m_hWnd));
  132. return CWindow(GetParent());
  133. }
  134. int GetFilePath(LPTSTR lpstrFilePath, int nLength) const
  135. {
  136. ATLASSERT(::IsWindow(m_hWnd));
  137. ATLASSERT(m_ofn.Flags & OFN_EXPLORER);
  138. return (int)GetFileDialogWindow().SendMessage(CDM_GETFILEPATH, nLength, (LPARAM)lpstrFilePath);
  139. }
  140. int GetFolderIDList(LPVOID lpBuff, int nLength) const
  141. {
  142. ATLASSERT(::IsWindow(m_hWnd));
  143. ATLASSERT(m_ofn.Flags & OFN_EXPLORER);
  144. return (int)GetFileDialogWindow().SendMessage(CDM_GETFOLDERIDLIST, nLength, (LPARAM)lpBuff);
  145. }
  146. int GetFolderPath(LPTSTR lpstrFolderPath, int nLength) const
  147. {
  148. ATLASSERT(::IsWindow(m_hWnd));
  149. ATLASSERT(m_ofn.Flags & OFN_EXPLORER);
  150. return (int)GetFileDialogWindow().SendMessage(CDM_GETFOLDERPATH, nLength, (LPARAM)lpstrFolderPath);
  151. }
  152. int GetSpec(LPTSTR lpstrSpec, int nLength) const
  153. {
  154. ATLASSERT(::IsWindow(m_hWnd));
  155. ATLASSERT(m_ofn.Flags & OFN_EXPLORER);
  156. return (int)GetFileDialogWindow().SendMessage(CDM_GETSPEC, nLength, (LPARAM)lpstrSpec);
  157. }
  158. void SetControlText(int nCtrlID, LPCTSTR lpstrText)
  159. {
  160. ATLASSERT(::IsWindow(m_hWnd));
  161. ATLASSERT(m_ofn.Flags & OFN_EXPLORER);
  162. GetFileDialogWindow().SendMessage(CDM_SETCONTROLTEXT, nCtrlID, (LPARAM)lpstrText);
  163. }
  164. void SetDefExt(LPCTSTR lpstrExt)
  165. {
  166. ATLASSERT(::IsWindow(m_hWnd));
  167. ATLASSERT(m_ofn.Flags & OFN_EXPLORER);
  168. GetFileDialogWindow().SendMessage(CDM_SETDEFEXT, 0, (LPARAM)lpstrExt);
  169. }
  170. BOOL GetReadOnlyPref() const // return TRUE if readonly checked
  171. {
  172. return m_ofn.Flags & OFN_READONLY ? TRUE : FALSE;
  173. }
  174. // Operations
  175. void HideControl(int nCtrlID)
  176. {
  177. ATLASSERT(::IsWindow(m_hWnd));
  178. ATLASSERT(m_ofn.Flags & OFN_EXPLORER);
  179. GetFileDialogWindow().SendMessage(CDM_HIDECONTROL, nCtrlID);
  180. }
  181. // Special override for common dialogs
  182. BOOL EndDialog(INT_PTR /*nRetCode*/ = 0)
  183. {
  184. ATLASSERT(::IsWindow(m_hWnd));
  185. GetFileDialogWindow().SendMessage(WM_COMMAND, MAKEWPARAM(IDCANCEL, 0));
  186. return TRUE;
  187. }
  188. // Message map and handlers
  189. BEGIN_MSG_MAP(CFileDialogImpl< T >)
  190. NOTIFY_CODE_HANDLER(CDN_FILEOK, _OnFileOK)
  191. NOTIFY_CODE_HANDLER(CDN_FOLDERCHANGE, _OnFolderChange)
  192. NOTIFY_CODE_HANDLER(CDN_HELP, _OnHelp)
  193. NOTIFY_CODE_HANDLER(CDN_INITDONE, _OnInitDone)
  194. NOTIFY_CODE_HANDLER(CDN_SELCHANGE, _OnSelChange)
  195. NOTIFY_CODE_HANDLER(CDN_SHAREVIOLATION, _OnShareViolation)
  196. NOTIFY_CODE_HANDLER(CDN_TYPECHANGE, _OnTypeChange)
  197. END_MSG_MAP()
  198. LRESULT _OnFileOK(int /*idCtrl*/, LPNMHDR pnmh, BOOL& /*bHandled*/)
  199. {
  200. ATLASSERT(::IsWindow(m_hWnd));
  201. T* pT = static_cast<T*>(this);
  202. return !pT->OnFileOK((LPOFNOTIFY)pnmh);
  203. }
  204. LRESULT _OnFolderChange(int /*idCtrl*/, LPNMHDR pnmh, BOOL& /*bHandled*/)
  205. {
  206. ATLASSERT(::IsWindow(m_hWnd));
  207. T* pT = static_cast<T*>(this);
  208. pT->OnFolderChange((LPOFNOTIFY)pnmh);
  209. return 0;
  210. }
  211. LRESULT _OnHelp(int /*idCtrl*/, LPNMHDR pnmh, BOOL& /*bHandled*/)
  212. {
  213. ATLASSERT(::IsWindow(m_hWnd));
  214. T* pT = static_cast<T*>(this);
  215. pT->OnHelp((LPOFNOTIFY)pnmh);
  216. return 0;
  217. }
  218. LRESULT _OnInitDone(int /*idCtrl*/, LPNMHDR pnmh, BOOL& /*bHandled*/)
  219. {
  220. ATLASSERT(::IsWindow(m_hWnd));
  221. T* pT = static_cast<T*>(this);
  222. pT->OnInitDone((LPOFNOTIFY)pnmh);
  223. return 0;
  224. }
  225. LRESULT _OnSelChange(int /*idCtrl*/, LPNMHDR pnmh, BOOL& /*bHandled*/)
  226. {
  227. ATLASSERT(::IsWindow(m_hWnd));
  228. T* pT = static_cast<T*>(this);
  229. pT->OnSelChange((LPOFNOTIFY)pnmh);
  230. return 0;
  231. }
  232. LRESULT _OnShareViolation(int /*idCtrl*/, LPNMHDR pnmh, BOOL& /*bHandled*/)
  233. {
  234. ATLASSERT(::IsWindow(m_hWnd));
  235. T* pT = static_cast<T*>(this);
  236. return pT->OnShareViolation((LPOFNOTIFY)pnmh);
  237. }
  238. LRESULT _OnTypeChange(int /*idCtrl*/, LPNMHDR pnmh, BOOL& /*bHandled*/)
  239. {
  240. ATLASSERT(::IsWindow(m_hWnd));
  241. T* pT = static_cast<T*>(this);
  242. pT->OnTypeChange((LPOFNOTIFY)pnmh);
  243. return 0;
  244. }
  245. // Overrideables
  246. BOOL OnFileOK(LPOFNOTIFY /*lpon*/)
  247. {
  248. return TRUE;
  249. }
  250. void OnFolderChange(LPOFNOTIFY /*lpon*/)
  251. {
  252. }
  253. void OnHelp(LPOFNOTIFY /*lpon*/)
  254. {
  255. }
  256. void OnInitDone(LPOFNOTIFY /*lpon*/)
  257. {
  258. }
  259. void OnSelChange(LPOFNOTIFY /*lpon*/)
  260. {
  261. }
  262. int OnShareViolation(LPOFNOTIFY /*lpon*/)
  263. {
  264. return 0;
  265. }
  266. void OnTypeChange(LPOFNOTIFY /*lpon*/)
  267. {
  268. }
  269. };
  270. class CFileDialog : public CFileDialogImpl<CFileDialog>
  271. {
  272. public:
  273. CFileDialog(BOOL bOpenFileDialog, // TRUE for FileOpen, FALSE for FileSaveAs
  274. LPCTSTR lpszDefExt = NULL,
  275. LPCTSTR lpszFileName = NULL,
  276. DWORD dwFlags = OFN_HIDEREADONLY | OFN_OVERWRITEPROMPT,
  277. LPCTSTR lpszFilter = NULL,
  278. HWND hWndParent = NULL)
  279. : CFileDialogImpl<CFileDialog>(bOpenFileDialog, lpszDefExt, lpszFileName, dwFlags, lpszFilter, hWndParent)
  280. { }
  281. // override base class map and references to handlers
  282. DECLARE_EMPTY_MSG_MAP()
  283. };
  284. /////////////////////////////////////////////////////////////////////////////
  285. // CFolderDialogImpl - used for browsing for a folder
  286. template <class T>
  287. class ATL_NO_VTABLE CFolderDialogImpl
  288. {
  289. public:
  290. BROWSEINFO m_bi;
  291. TCHAR m_szFolderDisplayName[MAX_PATH];
  292. TCHAR m_szFolderPath[MAX_PATH];
  293. HWND m_hWnd; // used only in the callback function
  294. // Constructor
  295. CFolderDialogImpl(HWND hWndParent = NULL, LPCTSTR lpstrTitle = NULL, UINT uFlags = BIF_RETURNONLYFSDIRS)
  296. {
  297. memset(&m_bi, 0, sizeof(m_bi)); // initialize structure to 0/NULL
  298. m_bi.hwndOwner = hWndParent;
  299. m_bi.pidlRoot = NULL;
  300. m_bi.pszDisplayName = m_szFolderDisplayName;
  301. m_bi.lpszTitle = lpstrTitle;
  302. m_bi.ulFlags = uFlags;
  303. m_bi.lpfn = BrowseCallbackProc;
  304. m_bi.lParam = (LPARAM)this;
  305. m_szFolderPath[0] = 0;
  306. m_szFolderDisplayName[0] = 0;
  307. m_hWnd = NULL;
  308. }
  309. // Operations
  310. INT_PTR DoModal(HWND hWndParent = ::GetActiveWindow())
  311. {
  312. if(m_bi.hwndOwner == NULL) // set only if not specified before
  313. m_bi.hwndOwner = hWndParent;
  314. INT_PTR nRet = -1;
  315. LPITEMIDLIST pItemIDList = ::SHBrowseForFolder(&m_bi);
  316. if(pItemIDList != NULL)
  317. {
  318. if(::SHGetPathFromIDList(pItemIDList, m_szFolderPath))
  319. {
  320. IMalloc* pMalloc = NULL;
  321. if(SUCCEEDED(::SHGetMalloc(&pMalloc)))
  322. {
  323. pMalloc->Free(pItemIDList);
  324. pMalloc->Release();
  325. }
  326. nRet = IDOK;
  327. }
  328. else
  329. {
  330. nRet = IDCANCEL;
  331. }
  332. }
  333. return nRet;
  334. }
  335. // filled after a call to DoModal
  336. LPCTSTR GetFolderPath() const
  337. {
  338. return m_szFolderPath;
  339. }
  340. LPCTSTR GetFolderDisplayName() const
  341. {
  342. return m_szFolderDisplayName;
  343. }
  344. int GetFolderImageIndex() const
  345. {
  346. return m_bi.iImage;
  347. }
  348. // Callback function and overrideables
  349. static int CALLBACK BrowseCallbackProc(HWND hWnd, UINT uMsg, LPARAM lParam, LPARAM lpData)
  350. {
  351. #ifndef BFFM_VALIDATEFAILED
  352. #ifdef UNICODE
  353. const int BFFM_VALIDATEFAILED = 4;
  354. #else
  355. const int BFFM_VALIDATEFAILED = 3;
  356. #endif
  357. #endif //!BFFM_VALIDATEFAILED
  358. int nRet = 0;
  359. T* pT = (T*)lpData;
  360. pT->m_hWnd = hWnd;
  361. switch(uMsg)
  362. {
  363. case BFFM_INITIALIZED:
  364. pT->OnInitialized();
  365. break;
  366. case BFFM_SELCHANGED:
  367. pT->OnSelChanged((LPITEMIDLIST)lParam);
  368. break;
  369. case BFFM_VALIDATEFAILED:
  370. nRet = pT->OnValidateFailed((LPCTSTR)lParam);
  371. break;
  372. default:
  373. ATLTRACE2(atlTraceUI, 0, _T("Unknown message received in CFolderDialogImpl::BrowseCallbackProc\n"));
  374. break;
  375. }
  376. pT->m_hWnd = NULL;
  377. return nRet;
  378. }
  379. void OnInitialized()
  380. {
  381. }
  382. void OnSelChanged(LPITEMIDLIST /*pItemIDList*/)
  383. {
  384. }
  385. int OnValidateFailed(LPCTSTR /*lpstrFolderPath*/)
  386. {
  387. return 1; // 1=continue, 0=EndDialog
  388. }
  389. // Commands - valid to call only from handlers
  390. void EnableOK(BOOL bEnable)
  391. {
  392. ATLASSERT(m_hWnd != NULL);
  393. ::SendMessage(m_hWnd, BFFM_ENABLEOK, bEnable, 0L);
  394. }
  395. void SetSelection(LPITEMIDLIST pItemIDList)
  396. {
  397. ATLASSERT(m_hWnd != NULL);
  398. ::SendMessage(m_hWnd, BFFM_SETSELECTION, FALSE, (LPARAM)pItemIDList);
  399. }
  400. void SetSelection(LPCTSTR lpstrFolderPath)
  401. {
  402. ATLASSERT(m_hWnd != NULL);
  403. ::SendMessage(m_hWnd, BFFM_SETSELECTION, TRUE, (LPARAM)lpstrFolderPath);
  404. }
  405. void SetStatusText(LPCTSTR lpstrText)
  406. {
  407. ATLASSERT(m_hWnd != NULL);
  408. ::SendMessage(m_hWnd, BFFM_SETSTATUSTEXT, 0, (LPARAM)lpstrText);
  409. }
  410. };
  411. class CFolderDialog : public CFolderDialogImpl<CFolderDialog>
  412. {
  413. public:
  414. CFolderDialog(HWND hWndParent = NULL, LPCTSTR lpstrTitle = NULL, UINT uFlags = BIF_RETURNONLYFSDIRS)
  415. : CFolderDialogImpl<CFolderDialog>(hWndParent, lpstrTitle, uFlags)
  416. {
  417. m_bi.lpfn = NULL;
  418. }
  419. };
  420. /////////////////////////////////////////////////////////////////////////////
  421. // CCommonDialogImplBase - base class for common dialog classes
  422. class ATL_NO_VTABLE CCommonDialogImplBase : public CWindowImplBase
  423. {
  424. public:
  425. static UINT_PTR APIENTRY HookProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
  426. {
  427. if(uMsg != WM_INITDIALOG)
  428. return 0;
  429. CCommonDialogImplBase* pT = (CCommonDialogImplBase*)_Module.ExtractCreateWndData();
  430. ATLASSERT(pT != NULL);
  431. ATLASSERT(pT->m_hWnd == NULL);
  432. ATLASSERT(::IsWindow(hWnd));
  433. // subclass dialog's window
  434. if(!pT->SubclassWindow(hWnd))
  435. {
  436. ATLTRACE2(atlTraceUI, 0, _T("Subclassing a common dialog failed\n"));
  437. return 0;
  438. }
  439. // check message map for WM_INITDIALOG handler
  440. LRESULT lRes;
  441. if(pT->ProcessWindowMessage(pT->m_hWnd, uMsg, wParam, lParam, lRes, 0) == FALSE)
  442. return 0;
  443. return lRes;
  444. }
  445. // Special override for common dialogs
  446. BOOL EndDialog(INT_PTR /*nRetCode*/ = 0)
  447. {
  448. ATLASSERT(::IsWindow(m_hWnd));
  449. SendMessage(WM_COMMAND, MAKEWPARAM(IDABORT, 0));
  450. return TRUE;
  451. }
  452. // Implementation - try to override these, to prevent errors
  453. HWND Create(HWND, _U_RECT, LPCTSTR, DWORD, DWORD, _U_MENUorID, ATOM, LPVOID)
  454. {
  455. ATLASSERT(FALSE); // should not be called
  456. return NULL;
  457. }
  458. static LRESULT CALLBACK StartWindowProc(HWND /*hWnd*/, UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/)
  459. {
  460. ATLASSERT(FALSE); // should not be called
  461. return 0;
  462. }
  463. };
  464. /////////////////////////////////////////////////////////////////////////////
  465. // CFontDialogImpl - font selection dialog
  466. template <class T>
  467. class ATL_NO_VTABLE CFontDialogImpl : public CCommonDialogImplBase
  468. {
  469. public:
  470. CHOOSEFONT m_cf;
  471. TCHAR m_szStyleName[64]; // contains style name after return
  472. LOGFONT m_lf; // default LOGFONT to store the info
  473. // Constructors
  474. CFontDialogImpl(LPLOGFONT lplfInitial = NULL,
  475. DWORD dwFlags = CF_EFFECTS | CF_SCREENFONTS,
  476. HDC hDCPrinter = NULL,
  477. HWND hWndParent = NULL)
  478. {
  479. memset(&m_cf, 0, sizeof(m_cf));
  480. memset(&m_lf, 0, sizeof(m_lf));
  481. memset(&m_szStyleName, 0, sizeof(m_szStyleName));
  482. m_cf.lStructSize = sizeof(m_cf);
  483. m_cf.hwndOwner = hWndParent;
  484. m_cf.rgbColors = RGB(0, 0, 0);
  485. m_cf.lpszStyle = (LPTSTR)&m_szStyleName;
  486. m_cf.Flags = dwFlags | CF_ENABLEHOOK;
  487. m_cf.lpfnHook = (LPCFHOOKPROC)T::HookProc;
  488. if(lplfInitial != NULL)
  489. {
  490. m_cf.lpLogFont = lplfInitial;
  491. m_cf.Flags |= CF_INITTOLOGFONTSTRUCT;
  492. memcpy(&m_lf, m_cf.lpLogFont, sizeof(m_lf));
  493. }
  494. else
  495. {
  496. m_cf.lpLogFont = &m_lf;
  497. }
  498. if(hDCPrinter != NULL)
  499. {
  500. m_cf.hDC = hDCPrinter;
  501. m_cf.Flags |= CF_PRINTERFONTS;
  502. }
  503. }
  504. // Operations
  505. INT_PTR DoModal(HWND hWndParent = ::GetActiveWindow())
  506. {
  507. ATLASSERT(m_cf.Flags & CF_ENABLEHOOK);
  508. ATLASSERT(m_cf.lpfnHook != NULL); // can still be a user hook
  509. if(m_cf.hwndOwner == NULL) // set only if not specified before
  510. m_cf.hwndOwner = hWndParent;
  511. ATLASSERT(m_hWnd == NULL);
  512. _Module.AddCreateWndData(&m_thunk.cd, (CCommonDialogImplBase*)this);
  513. BOOL bRet = ::ChooseFont(&m_cf);
  514. m_hWnd = NULL;
  515. if(bRet) // copy logical font from user's initialization buffer (if needed)
  516. memcpy(&m_lf, m_cf.lpLogFont, sizeof(m_lf));
  517. return bRet ? IDOK : IDCANCEL;
  518. }
  519. // Get the selected font (works during DoModal displayed or after)
  520. void GetCurrentFont(LPLOGFONT lplf) const
  521. {
  522. ATLASSERT(lplf != NULL);
  523. if(m_hWnd != NULL)
  524. ::SendMessage(m_hWnd, WM_CHOOSEFONT_GETLOGFONT, 0, (LPARAM)lplf);
  525. else
  526. *lplf = m_lf;
  527. }
  528. // Helpers for parsing information after successful return
  529. LPCTSTR GetFaceName() const // return the face name of the font
  530. {
  531. return (LPCTSTR)m_cf.lpLogFont->lfFaceName;
  532. }
  533. LPCTSTR GetStyleName() const // return the style name of the font
  534. {
  535. return m_cf.lpszStyle;
  536. }
  537. int GetSize() const // return the pt size of the font
  538. {
  539. return m_cf.iPointSize;
  540. }
  541. COLORREF GetColor() const // return the color of the font
  542. {
  543. return m_cf.rgbColors;
  544. }
  545. int GetWeight() const // return the chosen font weight
  546. {
  547. return (int)m_cf.lpLogFont->lfWeight;
  548. }
  549. BOOL IsStrikeOut() const // return TRUE if strikeout
  550. {
  551. return m_cf.lpLogFont->lfStrikeOut ? TRUE : FALSE;
  552. }
  553. BOOL IsUnderline() const // return TRUE if underline
  554. {
  555. return m_cf.lpLogFont->lfUnderline ? TRUE : FALSE;
  556. }
  557. BOOL IsBold() const // return TRUE if bold font
  558. {
  559. return m_cf.lpLogFont->lfWeight == FW_BOLD ? TRUE : FALSE;
  560. }
  561. BOOL IsItalic() const // return TRUE if italic font
  562. {
  563. return m_cf.lpLogFont->lfItalic ? TRUE : FALSE;
  564. }
  565. };
  566. class CFontDialog : public CFontDialogImpl<CFontDialog>
  567. {
  568. public:
  569. CFontDialog(LPLOGFONT lplfInitial = NULL,
  570. DWORD dwFlags = CF_EFFECTS | CF_SCREENFONTS,
  571. HDC hDCPrinter = NULL,
  572. HWND hWndParent = NULL)
  573. : CFontDialogImpl<CFontDialog>(lplfInitial, dwFlags, hDCPrinter, hWndParent)
  574. { }
  575. DECLARE_EMPTY_MSG_MAP()
  576. };
  577. /////////////////////////////////////////////////////////////////////////////
  578. // CRichEditFontDialogImpl - font selection for the Rich Edit ctrl
  579. #ifdef _RICHEDIT_
  580. template <class T>
  581. class ATL_NO_VTABLE CRichEditFontDialogImpl : public CFontDialogImpl< T >
  582. {
  583. public:
  584. CRichEditFontDialogImpl(const CHARFORMAT& charformat,
  585. DWORD dwFlags = CF_SCREENFONTS,
  586. HDC hDCPrinter = NULL,
  587. HWND hWndParent = NULL)
  588. : CFontDialogImpl< T >(NULL, dwFlags, hDCPrinter, hWndParent)
  589. {
  590. m_cf.Flags |= CF_INITTOLOGFONTSTRUCT;
  591. m_cf.Flags |= FillInLogFont(charformat);
  592. m_cf.lpLogFont = &m_lf;
  593. if(charformat.dwMask & CFM_COLOR)
  594. m_cf.rgbColors = charformat.crTextColor;
  595. }
  596. void GetCharFormat(CHARFORMAT& cf) const
  597. {
  598. USES_CONVERSION;
  599. cf.dwEffects = 0;
  600. cf.dwMask = 0;
  601. if((m_cf.Flags & CF_NOSTYLESEL) == 0)
  602. {
  603. cf.dwMask |= CFM_BOLD | CFM_ITALIC;
  604. cf.dwEffects |= (IsBold()) ? CFE_BOLD : 0;
  605. cf.dwEffects |= (IsItalic()) ? CFE_ITALIC : 0;
  606. }
  607. if((m_cf.Flags & CF_NOSIZESEL) == 0)
  608. {
  609. cf.dwMask |= CFM_SIZE;
  610. //GetSize() returns in tenths of points so mulitply by 2 to get twips
  611. cf.yHeight = GetSize() * 2;
  612. }
  613. if((m_cf.Flags & CF_NOFACESEL) == 0)
  614. {
  615. cf.dwMask |= CFM_FACE;
  616. cf.bPitchAndFamily = m_cf.lpLogFont->lfPitchAndFamily;
  617. #if (_RICHEDIT_VER >= 0x0200)
  618. lstrcpy(cf.szFaceName, GetFaceName());
  619. #else
  620. lstrcpyA(cf.szFaceName, T2A((LPTSTR)(LPCTSTR)GetFaceName()));
  621. #endif //(_RICHEDIT_VER >= 0x0200)
  622. }
  623. if(m_cf.Flags & CF_EFFECTS)
  624. {
  625. cf.dwMask |= CFM_UNDERLINE | CFM_STRIKEOUT | CFM_COLOR;
  626. cf.dwEffects |= (IsUnderline()) ? CFE_UNDERLINE : 0;
  627. cf.dwEffects |= (IsStrikeOut()) ? CFE_STRIKEOUT : 0;
  628. cf.crTextColor = GetColor();
  629. }
  630. if((m_cf.Flags & CF_NOSCRIPTSEL) == 0)
  631. {
  632. cf.bCharSet = m_cf.lpLogFont->lfCharSet;
  633. cf.dwMask |= CFM_CHARSET;
  634. }
  635. cf.yOffset = 0;
  636. }
  637. DWORD FillInLogFont(const CHARFORMAT& cf)
  638. {
  639. USES_CONVERSION;
  640. DWORD dwFlags = 0;
  641. if(cf.dwMask & CFM_SIZE)
  642. {
  643. HDC hDC = ::CreateDC(_T("DISPLAY"), NULL, NULL, NULL);
  644. LONG yPerInch = ::GetDeviceCaps(hDC, LOGPIXELSY);
  645. m_lf.lfHeight = -(int)((cf.yHeight * yPerInch) / 1440);
  646. }
  647. else
  648. m_lf.lfHeight = 0;
  649. m_lf.lfWidth = 0;
  650. m_lf.lfEscapement = 0;
  651. m_lf.lfOrientation = 0;
  652. if((cf.dwMask & (CFM_ITALIC|CFM_BOLD)) == (CFM_ITALIC|CFM_BOLD))
  653. {
  654. m_lf.lfWeight = (cf.dwEffects & CFE_BOLD) ? FW_BOLD : FW_NORMAL;
  655. m_lf.lfItalic = (BYTE)((cf.dwEffects & CFE_ITALIC) ? TRUE : FALSE);
  656. }
  657. else
  658. {
  659. dwFlags |= CF_NOSTYLESEL;
  660. m_lf.lfWeight = FW_DONTCARE;
  661. m_lf.lfItalic = FALSE;
  662. }
  663. if((cf.dwMask & (CFM_UNDERLINE|CFM_STRIKEOUT|CFM_COLOR)) ==
  664. (CFM_UNDERLINE|CFM_STRIKEOUT|CFM_COLOR))
  665. {
  666. dwFlags |= CF_EFFECTS;
  667. m_lf.lfUnderline = (BYTE)((cf.dwEffects & CFE_UNDERLINE) ? TRUE : FALSE);
  668. m_lf.lfStrikeOut = (BYTE)((cf.dwEffects & CFE_STRIKEOUT) ? TRUE : FALSE);
  669. }
  670. else
  671. {
  672. m_lf.lfUnderline = (BYTE)FALSE;
  673. m_lf.lfStrikeOut = (BYTE)FALSE;
  674. }
  675. if(cf.dwMask & CFM_CHARSET)
  676. m_lf.lfCharSet = cf.bCharSet;
  677. else
  678. dwFlags |= CF_NOSCRIPTSEL;
  679. m_lf.lfOutPrecision = OUT_DEFAULT_PRECIS;
  680. m_lf.lfClipPrecision = CLIP_DEFAULT_PRECIS;
  681. m_lf.lfQuality = DEFAULT_QUALITY;
  682. if(cf.dwMask & CFM_FACE)
  683. {
  684. m_lf.lfPitchAndFamily = cf.bPitchAndFamily;
  685. #if (_RICHEDIT_VER >= 0x0200)
  686. lstrcpy(m_lf.lfFaceName, cf.szFaceName);
  687. #else
  688. lstrcpy(m_lf.lfFaceName, A2T((LPSTR)cf.szFaceName));
  689. #endif //(_RICHEDIT_VER >= 0x0200)
  690. }
  691. else
  692. {
  693. m_lf.lfPitchAndFamily = DEFAULT_PITCH|FF_DONTCARE;
  694. m_lf.lfFaceName[0] = (TCHAR)0;
  695. }
  696. return dwFlags;
  697. }
  698. };
  699. class CRichEditFontDialog : public CRichEditFontDialogImpl<CRichEditFontDialog>
  700. {
  701. public:
  702. CRichEditFontDialog(const CHARFORMAT& charformat,
  703. DWORD dwFlags = CF_SCREENFONTS,
  704. HDC hDCPrinter = NULL,
  705. HWND hWndParent = NULL)
  706. : CRichEditFontDialogImpl<CRichEditFontDialog>(charformat, dwFlags, hDCPrinter, hWndParent)
  707. { }
  708. DECLARE_EMPTY_MSG_MAP()
  709. };
  710. #endif // _RICHEDIT_
  711. /////////////////////////////////////////////////////////////////////////////
  712. // CColorDialogImpl - color selection
  713. static const UINT _nMsgCOLOROK = ::RegisterWindowMessage(COLOROKSTRING);
  714. const UINT _nMsgSETRGB = ::RegisterWindowMessage(SETRGBSTRING);
  715. template <class T>
  716. class ATL_NO_VTABLE CColorDialogImpl : public CCommonDialogImplBase
  717. {
  718. public:
  719. CHOOSECOLOR m_cc;
  720. // Constructors
  721. CColorDialogImpl(COLORREF clrInit = 0, DWORD dwFlags = 0, HWND hWndParent = NULL)
  722. {
  723. memset(&m_cc, 0, sizeof(m_cc));
  724. m_cc.lStructSize = sizeof(m_cc);
  725. m_cc.lpCustColors = GetCustomColors();
  726. m_cc.hwndOwner = hWndParent;
  727. m_cc.Flags = dwFlags | CC_ENABLEHOOK;
  728. m_cc.lpfnHook = (LPCCHOOKPROC)T::HookProc;
  729. if(clrInit != 0)
  730. {
  731. m_cc.rgbResult = clrInit;
  732. m_cc.Flags |= CC_RGBINIT;
  733. }
  734. }
  735. // Operations
  736. INT_PTR DoModal(HWND hWndParent = ::GetActiveWindow())
  737. {
  738. ATLASSERT(m_cc.Flags & CC_ENABLEHOOK);
  739. ATLASSERT(m_cc.lpfnHook != NULL); // can still be a user hook
  740. if(m_cc.hwndOwner == NULL) // set only if not specified before
  741. m_cc.hwndOwner = hWndParent;
  742. ATLASSERT(m_hWnd == NULL);
  743. _Module.AddCreateWndData(&m_thunk.cd, (CCommonDialogImplBase*)this);
  744. BOOL bRet = ::ChooseColor(&m_cc);
  745. m_hWnd = NULL;
  746. return bRet ? IDOK : IDCANCEL;
  747. }
  748. // Set the current color while dialog is displayed
  749. void SetCurrentColor(COLORREF clr)
  750. {
  751. ATLASSERT(::IsWindow(m_hWnd));
  752. SendMessage(_nMsgSETRGB, 0, (LPARAM)clr);
  753. }
  754. // Helpers for parsing information after successful return
  755. COLORREF GetColor() const
  756. {
  757. return m_cc.rgbResult;
  758. }
  759. static COLORREF* GetCustomColors()
  760. {
  761. static COLORREF rgbCustomColors[16] =
  762. {
  763. RGB(255, 255, 255), RGB(255, 255, 255),
  764. RGB(255, 255, 255), RGB(255, 255, 255),
  765. RGB(255, 255, 255), RGB(255, 255, 255),
  766. RGB(255, 255, 255), RGB(255, 255, 255),
  767. RGB(255, 255, 255), RGB(255, 255, 255),
  768. RGB(255, 255, 255), RGB(255, 255, 255),
  769. RGB(255, 255, 255), RGB(255, 255, 255),
  770. RGB(255, 255, 255), RGB(255, 255, 255),
  771. };
  772. return rgbCustomColors;
  773. }
  774. // Overridable callbacks
  775. BEGIN_MSG_MAP(CColorDialogImpl< T >)
  776. MESSAGE_HANDLER(_nMsgCOLOROK, _OnColorOK)
  777. END_MSG_MAP()
  778. LRESULT _OnColorOK(UINT, WPARAM, LPARAM, BOOL&)
  779. {
  780. T* pT = static_cast<T*>(this);
  781. return pT->OnColorOK();
  782. }
  783. BOOL OnColorOK() // validate color
  784. {
  785. return FALSE;
  786. }
  787. };
  788. class CColorDialog : public CColorDialogImpl<CColorDialog>
  789. {
  790. public:
  791. CColorDialog(COLORREF clrInit = 0, DWORD dwFlags = 0, HWND hWndParent = NULL)
  792. : CColorDialogImpl<CColorDialog>(clrInit, dwFlags, hWndParent)
  793. { }
  794. // override base class map and references to handlers
  795. DECLARE_EMPTY_MSG_MAP()
  796. };
  797. /////////////////////////////////////////////////////////////////////////////
  798. // CPrintDialogImpl - used for Print... and PrintSetup...
  799. // global helper
  800. static HDC _AtlCreateDC(HGLOBAL hDevNames, HGLOBAL hDevMode)
  801. {
  802. if(hDevNames == NULL)
  803. return NULL;
  804. LPDEVNAMES lpDevNames = (LPDEVNAMES)::GlobalLock(hDevNames);
  805. LPDEVMODE lpDevMode = (hDevMode != NULL) ? (LPDEVMODE)::GlobalLock(hDevMode) : NULL;
  806. if(lpDevNames == NULL)
  807. return NULL;
  808. HDC hDC = ::CreateDC((LPCTSTR)lpDevNames + lpDevNames->wDriverOffset,
  809. (LPCTSTR)lpDevNames + lpDevNames->wDeviceOffset,
  810. (LPCTSTR)lpDevNames + lpDevNames->wOutputOffset,
  811. lpDevMode);
  812. ::GlobalUnlock(hDevNames);
  813. if(hDevMode != NULL)
  814. ::GlobalUnlock(hDevMode);
  815. return hDC;
  816. }
  817. template <class T>
  818. class ATL_NO_VTABLE CPrintDialogImpl : public CCommonDialogImplBase
  819. {
  820. public:
  821. // print dialog parameter block (note this is a reference)
  822. PRINTDLG& m_pd;
  823. // Constructors
  824. CPrintDialogImpl(BOOL bPrintSetupOnly = FALSE, // TRUE for Print Setup, FALSE for Print Dialog
  825. DWORD dwFlags = PD_ALLPAGES | PD_USEDEVMODECOPIES | PD_NOPAGENUMS | PD_NOSELECTION,
  826. HWND hWndParent = NULL)
  827. : m_pd(m_pdActual)
  828. {
  829. memset(&m_pdActual, 0, sizeof(m_pdActual));
  830. m_pd.lStructSize = sizeof(m_pdActual);
  831. m_pd.hwndOwner = hWndParent;
  832. m_pd.Flags = (dwFlags | PD_ENABLEPRINTHOOK | PD_ENABLESETUPHOOK);
  833. m_pd.lpfnPrintHook = (LPPRINTHOOKPROC)T::HookProc;
  834. m_pd.lpfnSetupHook = (LPSETUPHOOKPROC)T::HookProc;
  835. if(bPrintSetupOnly)
  836. m_pd.Flags |= PD_PRINTSETUP;
  837. else
  838. m_pd.Flags |= PD_RETURNDC;
  839. m_pd.Flags &= ~PD_RETURNIC; // do not support information context
  840. }
  841. // Operations
  842. INT_PTR DoModal(HWND hWndParent = ::GetActiveWindow())
  843. {
  844. ATLASSERT(m_pd.Flags & PD_ENABLEPRINTHOOK);
  845. ATLASSERT(m_pd.Flags & PD_ENABLESETUPHOOK);
  846. ATLASSERT(m_pd.lpfnPrintHook != NULL); // can still be a user hook
  847. ATLASSERT(m_pd.lpfnSetupHook != NULL); // can still be a user hook
  848. ATLASSERT((m_pd.Flags & PD_RETURNDEFAULT) == 0); // use GetDefaults for this
  849. if(m_pd.hwndOwner == NULL) // set only if not specified before
  850. m_pd.hwndOwner = hWndParent;
  851. ATLASSERT(m_hWnd == NULL);
  852. _Module.AddCreateWndData(&m_thunk.cd, (CCommonDialogImplBase*)this);
  853. BOOL bRet = ::PrintDlg(&m_pd);
  854. m_hWnd = NULL;
  855. return bRet ? IDOK : IDCANCEL;
  856. }
  857. // GetDefaults will not display a dialog but will get device defaults
  858. BOOL GetDefaults()
  859. {
  860. m_pd.Flags |= PD_RETURNDEFAULT;
  861. ATLASSERT(m_pd.hDevMode == NULL); // must be NULL
  862. ATLASSERT(m_pd.hDevNames == NULL); // must be NULL
  863. return ::PrintDlg(&m_pd);
  864. }
  865. // Helpers for parsing information after successful return num. copies requested
  866. int GetCopies() const
  867. {
  868. if(m_pd.Flags & PD_USEDEVMODECOPIES)
  869. {
  870. LPDEVMODE lpDevMode = GetDevMode();
  871. return (lpDevMode != NULL) ? lpDevMode->dmCopies : -1;
  872. }
  873. return m_pd.nCopies;
  874. }
  875. BOOL PrintCollate() const // TRUE if collate checked
  876. {
  877. return m_pd.Flags & PD_COLLATE ? TRUE : FALSE;
  878. }
  879. BOOL PrintSelection() const // TRUE if printing selection
  880. {
  881. return m_pd.Flags & PD_SELECTION ? TRUE : FALSE;
  882. }
  883. BOOL PrintAll() const // TRUE if printing all pages
  884. {
  885. return !PrintRange() && !PrintSelection() ? TRUE : FALSE;
  886. }
  887. BOOL PrintRange() const // TRUE if printing page range
  888. {
  889. return m_pd.Flags & PD_PAGENUMS ? TRUE : FALSE;
  890. }
  891. int GetFromPage() const // starting page if valid
  892. {
  893. return (PrintRange() ? m_pd.nFromPage :-1);
  894. }
  895. int GetToPage() const // starting page if valid
  896. {
  897. return (PrintRange() ? m_pd.nToPage :-1);
  898. }
  899. LPDEVMODE GetDevMode() const // return DEVMODE
  900. {
  901. if(m_pd.hDevMode == NULL)
  902. return NULL;
  903. return (LPDEVMODE)::GlobalLock(m_pd.hDevMode);
  904. }
  905. LPCTSTR GetDriverName() const // return driver name
  906. {
  907. if(m_pd.hDevNames == NULL)
  908. return NULL;
  909. LPDEVNAMES lpDev = (LPDEVNAMES)::GlobalLock(m_pd.hDevNames);
  910. if(lpDev == NULL)
  911. return NULL;
  912. return (LPCTSTR)lpDev + lpDev->wDriverOffset;
  913. }
  914. LPCTSTR GetDeviceName() const // return device name
  915. {
  916. if(m_pd.hDevNames == NULL)
  917. return NULL;
  918. LPDEVNAMES lpDev = (LPDEVNAMES)::GlobalLock(m_pd.hDevNames);
  919. if(lpDev == NULL)
  920. return NULL;
  921. return (LPCTSTR)lpDev + lpDev->wDeviceOffset;
  922. }
  923. LPCTSTR GetPortName() const // return output port name
  924. {
  925. if(m_pd.hDevNames == NULL)
  926. return NULL;
  927. LPDEVNAMES lpDev = (LPDEVNAMES)::GlobalLock(m_pd.hDevNames);
  928. if(lpDev == NULL)
  929. return NULL;
  930. return (LPCTSTR)lpDev + lpDev->wOutputOffset;
  931. }
  932. HDC GetPrinterDC() const // return HDC (caller must delete)
  933. {
  934. ATLASSERT(m_pd.Flags & PD_RETURNDC);
  935. return m_pd.hDC;
  936. }
  937. // This helper creates a DC based on the DEVNAMES and DEVMODE structures.
  938. // This DC is returned, but also stored in m_pd.hDC as though it had been
  939. // returned by CommDlg. It is assumed that any previously obtained DC
  940. // has been/will be deleted by the user. This may be
  941. // used without ever invoking the print/print setup dialogs.
  942. HDC CreatePrinterDC()
  943. {
  944. m_pd.hDC = _AtlCreateDC(m_pd.hDevNames, m_pd.hDevMode);
  945. return m_pd.hDC;
  946. }
  947. // Implementation
  948. PRINTDLG m_pdActual; // the Print/Print Setup need to share this
  949. // The following handle the case of print setup... from the print dialog
  950. CPrintDialogImpl(PRINTDLG& pdInit) : m_pd(pdInit)
  951. { }
  952. BEGIN_MSG_MAP(CPrintDialogImpl< T >)
  953. #ifdef psh1
  954. COMMAND_ID_HANDLER(psh1, OnPrintSetup) // print setup button when print is displayed
  955. #else //!psh1
  956. COMMAND_ID_HANDLER(0x0400, OnPrintSetup) // value from dlgs.h
  957. #endif //!psh1
  958. END_MSG_MAP()
  959. LRESULT OnPrintSetup(WORD wNotifyCode, WORD wID, HWND hWndCtl, BOOL& /*bHandled*/)
  960. {
  961. CPrintDialogImpl< T >* pDlgSetup = NULL;
  962. ATLTRY(pDlgSetup = new CPrintDialogImpl< T >(m_pd));
  963. ATLASSERT(pDlgSetup != NULL);
  964. _Module.AddCreateWndData(&m_thunk.cd, (CCommonDialogImplBase*)pDlgSetup);
  965. LRESULT lRet = DefWindowProc(WM_COMMAND, MAKEWPARAM(wID, wNotifyCode), (LPARAM)hWndCtl);
  966. delete pDlgSetup;
  967. return lRet;
  968. }
  969. };
  970. class CPrintDialog : public CPrintDialogImpl<CPrintDialog>
  971. {
  972. public:
  973. CPrintDialog(BOOL bPrintSetupOnly = FALSE,
  974. DWORD dwFlags = PD_ALLPAGES | PD_USEDEVMODECOPIES | PD_NOPAGENUMS | PD_NOSELECTION,
  975. HWND hWndParent = NULL)
  976. : CPrintDialogImpl<CPrintDialog>(bPrintSetupOnly, dwFlags, hWndParent)
  977. { }
  978. CPrintDialog(PRINTDLG& pdInit) : CPrintDialogImpl<CPrintDialog>(pdInit)
  979. { }
  980. };
  981. /////////////////////////////////////////////////////////////////////////////
  982. // CPrintDialogExImpl - new print dialog for Windows 2000
  983. #if (WINVER >= 0x0500)
  984. }; //namespace WTL
  985. #include <atlcom.h>
  986. extern "C" const __declspec(selectany) IID IID_IPrintDialogCallback = {0x5852a2c3, 0x6530, 0x11d1, {0xb6, 0xa3, 0x0, 0x0, 0xf8, 0x75, 0x7b, 0xf9}};
  987. extern "C" const __declspec(selectany) IID IID_IPrintDialogServices = {0x509aaeda, 0x5639, 0x11d1, {0xb6, 0xa1, 0x0, 0x0, 0xf8, 0x75, 0x7b, 0xf9}};
  988. namespace WTL
  989. {
  990. template <class T>
  991. class ATL_NO_VTABLE CPrintDialogExImpl :
  992. public CWindow,
  993. public CMessageMap,
  994. public IPrintDialogCallback,
  995. public IObjectWithSiteImpl< T >
  996. {
  997. public:
  998. PRINTDLGEX m_pdex;
  999. // Constructor
  1000. CPrintDialogExImpl(DWORD dwFlags = PD_ALLPAGES | PD_USEDEVMODECOPIES | PD_NOPAGENUMS | PD_NOSELECTION | PD_NOCURRENTPAGE,
  1001. HWND hWndParent = NULL)
  1002. {
  1003. memset(&m_pdex, 0, sizeof(m_pdex));
  1004. m_pdex.lStructSize = sizeof(PRINTDLGEX);
  1005. m_pdex.hwndOwner = hWndParent;
  1006. m_pdex.Flags = dwFlags;
  1007. m_pdex.nStartPage = START_PAGE_GENERAL;
  1008. // callback object will be set in DoModal
  1009. m_pdex.Flags &= ~PD_RETURNIC; // do not support information context
  1010. }
  1011. // Operations
  1012. HRESULT DoModal(HWND hWndParent = ::GetActiveWindow())
  1013. {
  1014. ATLASSERT(m_hWnd == NULL);
  1015. ATLASSERT((m_pdex.Flags & PD_RETURNDEFAULT) == 0); // use GetDefaults for this
  1016. if(m_pdex.hwndOwner == NULL) // set only if not specified before
  1017. m_pdex.hwndOwner = hWndParent;
  1018. T* pT = static_cast<T*>(this);
  1019. m_pdex.lpCallback = (IUnknown*)(IPrintDialogCallback*)pT;
  1020. HRESULT hResult = ::PrintDlgEx(&m_pdex);
  1021. m_hWnd = NULL;
  1022. return hResult;
  1023. }
  1024. BOOL EndDialog(INT_PTR /*nRetCode*/ = 0)
  1025. {
  1026. ATLASSERT(::IsWindow(m_hWnd));
  1027. SendMessage(WM_COMMAND, MAKEWPARAM(IDABORT, 0));
  1028. return TRUE;
  1029. }
  1030. // GetDefaults will not display a dialog but will get device defaults
  1031. HRESULT GetDefaults()
  1032. {
  1033. m_pdex.Flags |= PD_RETURNDEFAULT;
  1034. ATLASSERT(m_pdex.hDevMode == NULL); // must be NULL
  1035. ATLASSERT(m_pdex.hDevNames == NULL); // must be NULL
  1036. return ::PrintDlgEx(&m_pdex);
  1037. }
  1038. // Helpers for parsing information after successful return num. copies requested
  1039. int GetCopies() const
  1040. {
  1041. if(m_pdex.Flags & PD_USEDEVMODECOPIES)
  1042. {
  1043. LPDEVMODE lpDevMode = GetDevMode();
  1044. return (lpDevMode != NULL) ? lpDevMode->dmCopies : -1;
  1045. }
  1046. return m_pdex.nCopies;
  1047. }
  1048. BOOL PrintCollate() const // TRUE if collate checked
  1049. {
  1050. return m_pdex.Flags & PD_COLLATE ? TRUE : FALSE;
  1051. }
  1052. BOOL PrintSelection() const // TRUE if printing selection
  1053. {
  1054. return m_pdex.Flags & PD_SELECTION ? TRUE : FALSE;
  1055. }
  1056. BOOL PrintAll() const // TRUE if printing all pages
  1057. {
  1058. return !PrintRange() && !PrintSelection() ? TRUE : FALSE;
  1059. }
  1060. BOOL PrintRange() const // TRUE if printing page range
  1061. {
  1062. return m_pdex.Flags & PD_PAGENUMS ? TRUE : FALSE;
  1063. }
  1064. LPDEVMODE GetDevMode() const // return DEVMODE
  1065. {
  1066. if(m_pdex.hDevMode == NULL)
  1067. return NULL;
  1068. return (LPDEVMODE)::GlobalLock(m_pdex.hDevMode);
  1069. }
  1070. LPCTSTR GetDriverName() const // return driver name
  1071. {
  1072. if(m_pdex.hDevNames == NULL)
  1073. return NULL;
  1074. LPDEVNAMES lpDev = (LPDEVNAMES)::GlobalLock(m_pdex.hDevNames);
  1075. if(lpDev == NULL)
  1076. return NULL;
  1077. return (LPCTSTR)lpDev + lpDev->wDriverOffset;
  1078. }
  1079. LPCTSTR GetDeviceName() const // return device name
  1080. {
  1081. if(m_pdex.hDevNames == NULL)
  1082. return NULL;
  1083. LPDEVNAMES lpDev = (LPDEVNAMES)::GlobalLock(m_pdex.hDevNames);
  1084. if(lpDev == NULL)
  1085. return NULL;
  1086. return (LPCTSTR)lpDev + lpDev->wDeviceOffset;
  1087. }
  1088. LPCTSTR GetPortName() const // return output port name
  1089. {
  1090. if(m_pdex.hDevNames == NULL)
  1091. return NULL;
  1092. LPDEVNAMES lpDev = (LPDEVNAMES)::GlobalLock(m_pdex.hDevNames);
  1093. if(lpDev == NULL)
  1094. return NULL;
  1095. return (LPCTSTR)lpDev + lpDev->wOutputOffset;
  1096. }
  1097. HDC GetPrinterDC() const // return HDC (caller must delete)
  1098. {
  1099. ATLASSERT(m_pdex.Flags & PD_RETURNDC);
  1100. return m_pdex.hDC;
  1101. }
  1102. // This helper creates a DC based on the DEVNAMES and DEVMODE structures.
  1103. // This DC is returned, but also stored in m_pdex.hDC as though it had been
  1104. // returned by CommDlg. It is assumed that any previously obtained DC
  1105. // has been/will be deleted by the user. This may be
  1106. // used without ever invoking the print/print setup dialogs.
  1107. HDC CreatePrinterDC()
  1108. {
  1109. m_pdex.hDC = _AtlCreateDC(m_pdex.hDevNames, m_pdex.hDevMode);
  1110. return m_pdex.hDC;
  1111. }
  1112. // Implementation - interfaces
  1113. // IUnknown
  1114. STDMETHOD(QueryInterface)(REFIID riid, void** ppvObject)
  1115. {
  1116. if(ppvObject == NULL)
  1117. return E_POINTER;
  1118. T* pT = static_cast<T*>(this);
  1119. if(IsEqualGUID(riid, IID_IUnknown) || IsEqualGUID(riid, IID_IPrintDialogCallback))
  1120. {
  1121. *ppvObject = (IPrintDialogCallback*)pT;
  1122. // AddRef() not needed
  1123. return S_OK;
  1124. }
  1125. else if(IsEqualGUID(riid, IID_IObjectWithSite))
  1126. {
  1127. *ppvObject = (IObjectWithSite*)pT;
  1128. // AddRef() not needed
  1129. return S_OK;
  1130. }
  1131. return E_NOINTERFACE;
  1132. }
  1133. virtual ULONG STDMETHODCALLTYPE AddRef()
  1134. {
  1135. return 1;
  1136. }
  1137. virtual ULONG STDMETHODCALLTYPE Release()
  1138. {
  1139. return 1;
  1140. }
  1141. // IPrintDialogCallback
  1142. STDMETHOD(InitDone)()
  1143. {
  1144. return S_FALSE;
  1145. }
  1146. STDMETHOD(SelectionChange)()
  1147. {
  1148. return S_FALSE;
  1149. }
  1150. STDMETHOD(HandleMessage)(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam, LRESULT* plResult)
  1151. {
  1152. // set up m_hWnd the first time
  1153. if(m_hWnd == NULL)
  1154. Attach(hWnd);
  1155. // call message map
  1156. HRESULT hRet = ProcessWindowMessage(hWnd, uMsg, wParam, lParam, *plResult, 0) ? S_OK : S_FALSE;
  1157. if(hRet == S_OK && uMsg == WM_NOTIFY) // return in DWLP_MSGRESULT
  1158. ::SetWindowLongPtr(GetParent(), DWLP_MSGRESULT, (LONG_PTR)*plResult);
  1159. if(uMsg == WM_INITDIALOG && hRet == S_OK && (BOOL)*plResult != FALSE)
  1160. hRet = S_FALSE;
  1161. return hRet;
  1162. }
  1163. };
  1164. class CPrintDialogEx : public CPrintDialogExImpl<CPrintDialogEx>
  1165. {
  1166. public:
  1167. CPrintDialogEx(
  1168. DWORD dwFlags = PD_ALLPAGES | PD_USEDEVMODECOPIES | PD_NOPAGENUMS | PD_NOSELECTION | PD_NOCURRENTPAGE,
  1169. HWND hWndParent = NULL)
  1170. : CPrintDialogExImpl<CPrintDialogEx>(dwFlags, hWndParent)
  1171. { }
  1172. DECLARE_EMPTY_MSG_MAP()
  1173. };
  1174. #endif //(WINVER >= 0x0500)
  1175. /////////////////////////////////////////////////////////////////////////////
  1176. // CPageSetupDialogImpl - Page Setup dialog
  1177. template <class T>
  1178. class ATL_NO_VTABLE CPageSetupDialogImpl : public CCommonDialogImplBase
  1179. {
  1180. public:
  1181. PAGESETUPDLG m_psd;
  1182. CWndProcThunk m_thunkPaint;
  1183. // Constructors
  1184. CPageSetupDialogImpl(DWORD dwFlags = PSD_MARGINS | PSD_INWININIINTLMEASURE, HWND hWndParent = NULL)
  1185. {
  1186. memset(&m_psd, 0, sizeof(m_psd));
  1187. m_psd.lStructSize = sizeof(m_psd);
  1188. m_psd.hwndOwner = hWndParent;
  1189. m_psd.Flags = (dwFlags | PSD_ENABLEPAGESETUPHOOK | PSD_ENABLEPAGEPAINTHOOK);
  1190. m_psd.lpfnPageSetupHook = (LPPAGESETUPHOOK)T::HookProc;
  1191. m_thunkPaint.Init((WNDPROC)T::PaintHookProc, this);
  1192. m_psd.lpfnPagePaintHook = (LPPAGEPAINTHOOK)&(m_thunkPaint.thunk);
  1193. }
  1194. DECLARE_EMPTY_MSG_MAP()
  1195. // Attributes
  1196. LPDEVMODE GetDevMode() const // return DEVMODE
  1197. {
  1198. if(m_psd.hDevMode == NULL)
  1199. return NULL;
  1200. return (LPDEVMODE)::GlobalLock(m_psd.hDevMode);
  1201. }
  1202. LPCTSTR GetDriverName() const // return driver name
  1203. {
  1204. if(m_psd.hDevNames == NULL)
  1205. return NULL;
  1206. LPDEVNAMES lpDev = (LPDEVNAMES)::GlobalLock(m_psd.hDevNames);
  1207. return (LPCTSTR)lpDev + lpDev->wDriverOffset;
  1208. }
  1209. LPCTSTR GetDeviceName() const // return device name
  1210. {
  1211. if(m_psd.hDevNames == NULL)
  1212. return NULL;
  1213. LPDEVNAMES lpDev = (LPDEVNAMES)::GlobalLock(m_psd.hDevNames);
  1214. return (LPCTSTR)lpDev + lpDev->wDeviceOffset;
  1215. }
  1216. LPCTSTR GetPortName() const // return output port name
  1217. {
  1218. if(m_psd.hDevNames == NULL)
  1219. return NULL;
  1220. LPDEVNAMES lpDev = (LPDEVNAMES)::GlobalLock(m_psd.hDevNames);
  1221. return (LPCTSTR)lpDev + lpDev->wOutputOffset;
  1222. }
  1223. HDC CreatePrinterDC()
  1224. {
  1225. return _AtlCreateDC(m_psd.hDevNames, m_psd.hDevMode);
  1226. }
  1227. SIZE GetPaperSize() const
  1228. {
  1229. SIZE size;
  1230. size.cx = m_psd.ptPaperSize.x;
  1231. size.cy = m_psd.ptPaperSize.y;
  1232. return size;
  1233. }
  1234. void GetMargins(LPRECT lpRectMargins, LPRECT lpRectMinMargins) const
  1235. {
  1236. if(lpRectMargins != NULL)
  1237. memcpy(lpRectMargins, &m_psd.rtMargin, sizeof(RECT));
  1238. if(lpRectMinMargins != NULL)
  1239. memcpy(lpRectMinMargins, &m_psd.rtMinMargin, sizeof(RECT));
  1240. }
  1241. // Operations
  1242. INT_PTR DoModal(HWND hWndParent = ::GetActiveWindow())
  1243. {
  1244. ATLASSERT(m_psd.Flags & PSD_ENABLEPAGESETUPHOOK);
  1245. ATLASSERT(m_psd.Flags & PSD_ENABLEPAGEPAINTHOOK);
  1246. ATLASSERT(m_psd.lpfnPageSetupHook != NULL); // can still be a user hook
  1247. ATLASSERT(m_psd.lpfnPagePaintHook != NULL); // can still be a user hook
  1248. if(m_psd.hwndOwner == NULL) // set only if not specified before
  1249. m_psd.hwndOwner = hWndParent;
  1250. ATLASSERT(m_hWnd == NULL);
  1251. _Module.AddCreateWndData(&m_thunk.cd, (CCommonDialogImplBase*)this);
  1252. BOOL bRet = ::PageSetupDlg(&m_psd);
  1253. m_hWnd = NULL;
  1254. return bRet ? IDOK : IDCANCEL;
  1255. }
  1256. // Implementation
  1257. static UINT CALLBACK PaintHookProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
  1258. {
  1259. CPageSetupDialogImpl< T >* pDlg = (CPageSetupDialogImpl< T >*)hWnd;
  1260. ATLASSERT(pDlg->m_hWnd == ::GetParent(hWnd));
  1261. UINT uRet = 0;
  1262. switch(uMsg)
  1263. {
  1264. case WM_PSD_PAGESETUPDLG:
  1265. uRet = pDlg->PreDrawPage(LOWORD(wParam), HIWORD(wParam), (LPPAGESETUPDLG)lParam);
  1266. break;
  1267. case WM_PSD_FULLPAGERECT:
  1268. case WM_PSD_MINMARGINRECT:
  1269. case WM_PSD_MARGINRECT:
  1270. case WM_PSD_GREEKTEXTRECT:
  1271. case WM_PSD_ENVSTAMPRECT:
  1272. case WM_PSD_YAFULLPAGERECT:
  1273. uRet = pDlg->OnDrawPage(uMsg, (HDC)wParam, (LPRECT)lParam);
  1274. break;
  1275. default:
  1276. ATLTRACE2(atlTraceUI, 0, _T("CPageSetupDialogImpl::PaintHookProc - unknown message received\n"));
  1277. break;
  1278. }
  1279. return uRet;
  1280. }
  1281. // Overridables
  1282. UINT PreDrawPage(WORD /*wPaper*/, WORD /*wFlags*/, LPPAGESETUPDLG /*pPSD*/)
  1283. {
  1284. // return 1 to prevent any more drawing
  1285. return 0;
  1286. }
  1287. UINT OnDrawPage(UINT /*uMsg*/, HDC /*hDC*/, LPRECT /*lpRect*/)
  1288. {
  1289. return 0; // do the default
  1290. }
  1291. };
  1292. class CPageSetupDialog : public CPageSetupDialogImpl<CPageSetupDialog>
  1293. {
  1294. public:
  1295. CPageSetupDialog(DWORD dwFlags = PSD_MARGINS | PSD_INWININIINTLMEASURE, HWND hWndParent = NULL)
  1296. : CPageSetupDialogImpl<CPageSetupDialog>(dwFlags, hWndParent)
  1297. { }
  1298. // override PaintHookProc and references to handlers
  1299. static UINT CALLBACK PaintHookProc(HWND, UINT, WPARAM, LPARAM)
  1300. {
  1301. return 0;
  1302. }
  1303. };
  1304. /////////////////////////////////////////////////////////////////////////////
  1305. // CFindReplaceDialogImpl - Find/FindReplace modeless dialogs
  1306. template <class T>
  1307. class ATL_NO_VTABLE CFindReplaceDialogImpl : public CCommonDialogImplBase
  1308. {
  1309. public:
  1310. FINDREPLACE m_fr;
  1311. TCHAR m_szFindWhat[128];
  1312. TCHAR m_szReplaceWith[128];
  1313. // Constructors
  1314. CFindReplaceDialogImpl()
  1315. {
  1316. memset(&m_fr, 0, sizeof(m_fr));
  1317. m_szFindWhat[0] = '\0';
  1318. m_szReplaceWith[0] = '\0';
  1319. m_fr.lStructSize = sizeof(m_fr);
  1320. m_fr.Flags = FR_ENABLEHOOK;
  1321. m_fr.lpfnHook = (LPFRHOOKPROC)T::HookProc;
  1322. m_fr.lpstrFindWhat = (LPTSTR)m_szFindWhat;
  1323. }
  1324. // Note: You must allocate the object on the heap.
  1325. // If you do not, you must override OnFinalMessage()
  1326. virtual void OnFinalMessage(HWND /*hWnd*/)
  1327. {
  1328. delete this;
  1329. }
  1330. HWND Create(BOOL bFindDialogOnly, // TRUE for Find, FALSE for FindReplace
  1331. LPCTSTR lpszFindWhat,
  1332. LPCTSTR lpszReplaceWith = NULL,
  1333. DWORD dwFlags = FR_DOWN,
  1334. HWND hWndParent = NULL)
  1335. {
  1336. ATLASSERT(m_fr.Flags & FR_ENABLEHOOK);
  1337. ATLASSERT(m_fr.lpfnHook != NULL);
  1338. m_fr.wFindWhatLen = sizeof(m_szFindWhat)/sizeof(TCHAR);
  1339. m_fr.lpstrReplaceWith = (LPTSTR)m_szReplaceWith;
  1340. m_fr.wReplaceWithLen = sizeof(m_szReplaceWith)/sizeof(TCHAR);
  1341. m_fr.Flags |= dwFlags;
  1342. if(hWndParent == NULL)
  1343. m_fr.hwndOwner = ::GetActiveWindow();
  1344. else
  1345. m_fr.hwndOwner = hWndParent;
  1346. ATLASSERT(m_fr.hwndOwner != NULL); // must have an owner for modeless dialog
  1347. if(lpszFindWhat != NULL)
  1348. lstrcpyn(m_szFindWhat, lpszFindWhat, sizeof(m_szFindWhat)/sizeof(TCHAR));
  1349. if(lpszReplaceWith != NULL)
  1350. lstrcpyn(m_szReplaceWith, lpszReplaceWith, sizeof(m_szReplaceWith)/sizeof(TCHAR));
  1351. ATLASSERT(m_hWnd == NULL);
  1352. _Module.AddCreateWndData(&m_thunk.cd, (CCommonDialogImplBase*)this);
  1353. HWND hWnd;
  1354. if(bFindDialogOnly)
  1355. hWnd = ::FindText(&m_fr);
  1356. else
  1357. hWnd = ::ReplaceText(&m_fr);
  1358. ATLASSERT(m_hWnd == hWnd);
  1359. return hWnd;
  1360. }
  1361. static const UINT GetFindReplaceMsg()
  1362. {
  1363. static const UINT nMsgFindReplace = ::RegisterWindowMessage(FINDMSGSTRING);
  1364. return nMsgFindReplace;
  1365. }
  1366. // call while handling FINDMSGSTRING registered message
  1367. // to retreive the object
  1368. static T* PASCAL GetNotifier(LPARAM lParam)
  1369. {
  1370. ATLASSERT(lParam != NULL);
  1371. T* pDlg = (T*)(lParam - offsetof(T, m_fr));
  1372. return pDlg;
  1373. }
  1374. // Operations
  1375. // Helpers for parsing information after successful return
  1376. LPCTSTR GetFindString() const // get find string
  1377. {
  1378. return (LPCTSTR)m_fr.lpstrFindWhat;
  1379. }
  1380. LPCTSTR GetReplaceString() const // get replacement string
  1381. {
  1382. return (LPCTSTR)m_fr.lpstrReplaceWith;
  1383. }
  1384. BOOL SearchDown() const // TRUE if search down, FALSE is up
  1385. {
  1386. return m_fr.Flags & FR_DOWN ? TRUE : FALSE;
  1387. }
  1388. BOOL FindNext() const // TRUE if command is find next
  1389. {
  1390. return m_fr.Flags & FR_FINDNEXT ? TRUE : FALSE;
  1391. }
  1392. BOOL MatchCase() const // TRUE if matching case
  1393. {
  1394. return m_fr.Flags & FR_MATCHCASE ? TRUE : FALSE;
  1395. }
  1396. BOOL MatchWholeWord() const // TRUE if matching whole words only
  1397. {
  1398. return m_fr.Flags & FR_WHOLEWORD ? TRUE : FALSE;
  1399. }
  1400. BOOL ReplaceCurrent() const // TRUE if replacing current string
  1401. {
  1402. return m_fr. Flags & FR_REPLACE ? TRUE : FALSE;
  1403. }
  1404. BOOL ReplaceAll() const // TRUE if replacing all occurrences
  1405. {
  1406. return m_fr.Flags & FR_REPLACEALL ? TRUE : FALSE;
  1407. }
  1408. BOOL IsTerminating() const // TRUE if terminating dialog
  1409. {
  1410. return m_fr.Flags & FR_DIALOGTERM ? TRUE : FALSE ;
  1411. }
  1412. };
  1413. class CFindReplaceDialog : public CFindReplaceDialogImpl<CFindReplaceDialog>
  1414. {
  1415. public:
  1416. DECLARE_EMPTY_MSG_MAP()
  1417. };
  1418. /////////////////////////////////////////////////////////////////////////////
  1419. // CPropertySheetWindow - client side for a property sheet
  1420. class CPropertySheetWindow : public CWindow
  1421. {
  1422. public:
  1423. // Constructors
  1424. CPropertySheetWindow(HWND hWnd = NULL) : CWindow(hWnd) { }
  1425. CPropertySheetWindow& operator=(HWND hWnd)
  1426. {
  1427. m_hWnd = hWnd;
  1428. return *this;
  1429. }
  1430. // Attributes
  1431. int GetPageCount() const
  1432. {
  1433. ATLASSERT(::IsWindow(m_hWnd));
  1434. HWND hWndTabCtrl = GetTabControl();
  1435. ATLASSERT(hWndTabCtrl != NULL);
  1436. return (int)::SendMessage(hWndTabCtrl, TCM_GETITEMCOUNT, 0, 0L);
  1437. }
  1438. HWND GetActivePage() const
  1439. {
  1440. ATLASSERT(::IsWindow(m_hWnd));
  1441. return (HWND)::SendMessage(m_hWnd, PSM_GETCURRENTPAGEHWND, 0, 0L);
  1442. }
  1443. int GetActiveIndex() const
  1444. {
  1445. ATLASSERT(::IsWindow(m_hWnd));
  1446. HWND hWndTabCtrl = GetTabControl();
  1447. ATLASSERT(hWndTabCtrl != NULL);
  1448. return (int)::SendMessage(hWndTabCtrl, TCM_GETCURSEL, 0, 0L);
  1449. }
  1450. BOOL SetActivePage(int nPageIndex)
  1451. {
  1452. ATLASSERT(::IsWindow(m_hWnd));
  1453. return (BOOL)::SendMessage(m_hWnd, PSM_SETCURSEL, nPageIndex, 0L);
  1454. }
  1455. BOOL SetActivePage(HPROPSHEETPAGE hPage)
  1456. {
  1457. ATLASSERT(::IsWindow(m_hWnd));
  1458. ATLASSERT(hPage != NULL);
  1459. return (BOOL)::SendMessage(m_hWnd, PSM_SETCURSEL, 0, (LPARAM)hPage);
  1460. }
  1461. BOOL SetActivePageByID(int nPageID)
  1462. {
  1463. ATLASSERT(::IsWindow(m_hWnd));
  1464. return (BOOL)::SendMessage(m_hWnd, PSM_SETCURSELID, 0, nPageID);
  1465. }
  1466. void SetTitle(LPCTSTR lpszText, UINT nStyle = 0)
  1467. {
  1468. ATLASSERT(::IsWindow(m_hWnd));
  1469. ATLASSERT((nStyle & ~PSH_PROPTITLE) == 0); // only PSH_PROPTITLE is valid
  1470. ATLASSERT(lpszText != NULL);
  1471. ::SendMessage(m_hWnd, PSM_SETTITLE, nStyle, (LPARAM)lpszText);
  1472. }
  1473. HWND GetTabControl() const
  1474. {
  1475. ATLASSERT(::IsWindow(m_hWnd));
  1476. return (HWND)::SendMessage(m_hWnd, PSM_GETTABCONTROL, 0, 0L);
  1477. }
  1478. void SetFinishText(LPCTSTR lpszText)
  1479. {
  1480. ATLASSERT(::IsWindow(m_hWnd));
  1481. ::SendMessage(m_hWnd, PSM_SETFINISHTEXT, 0, (LPARAM)lpszText);
  1482. }
  1483. void SetWizardButtons(DWORD dwFlags)
  1484. {
  1485. ATLASSERT(::IsWindow(m_hWnd));
  1486. ::PostMessage(m_hWnd, PSM_SETWIZBUTTONS, 0, dwFlags);
  1487. }
  1488. // Operations
  1489. void AddPage(HPROPSHEETPAGE hPage)
  1490. {
  1491. ATLASSERT(::IsWindow(m_hWnd));
  1492. ATLASSERT(hPage != NULL);
  1493. ::SendMessage(m_hWnd, PSM_ADDPAGE, 0, (LPARAM)hPage);
  1494. }
  1495. BOOL AddPage(LPCPROPSHEETPAGE pPage)
  1496. {
  1497. ATLASSERT(::IsWindow(m_hWnd));
  1498. ATLASSERT(pPage != NULL);
  1499. HPROPSHEETPAGE hPage = ::CreatePropertySheetPage(pPage);
  1500. if(hPage == NULL)
  1501. return FALSE;
  1502. ::SendMessage(m_hWnd, PSM_ADDPAGE, 0, (LPARAM)hPage);
  1503. return TRUE;
  1504. }
  1505. void RemovePage(int nPageIndex)
  1506. {
  1507. ATLASSERT(::IsWindow(m_hWnd));
  1508. ::SendMessage(m_hWnd, PSM_REMOVEPAGE, nPageIndex, 0L);
  1509. }
  1510. void RemovePage(HPROPSHEETPAGE hPage)
  1511. {
  1512. ATLASSERT(::IsWindow(m_hWnd));
  1513. ATLASSERT(hPage != NULL);
  1514. ::SendMessage(m_hWnd, PSM_REMOVEPAGE, 0, (LPARAM)hPage);
  1515. }
  1516. BOOL PressButton(int nButton)
  1517. {
  1518. ATLASSERT(::IsWindow(m_hWnd));
  1519. return (BOOL)::SendMessage(m_hWnd, PSM_PRESSBUTTON, nButton, 0L);
  1520. }
  1521. BOOL Apply()
  1522. {
  1523. ATLASSERT(::IsWindow(m_hWnd));
  1524. return (BOOL)::SendMessage(m_hWnd, PSM_APPLY, 0, 0L);
  1525. }
  1526. void CancelToClose()
  1527. {
  1528. ATLASSERT(::IsWindow(m_hWnd));
  1529. ::SendMessage(m_hWnd, PSM_CANCELTOCLOSE, 0, 0L);
  1530. }
  1531. void SetModified(HWND hWndPage, BOOL bChanged = TRUE)
  1532. {
  1533. ATLASSERT(::IsWindow(m_hWnd));
  1534. ATLASSERT(::IsWindow(hWndPage));
  1535. UINT uMsg = bChanged ? PSM_CHANGED : PSM_UNCHANGED;
  1536. ::SendMessage(m_hWnd, uMsg, (WPARAM)hWndPage, 0L);
  1537. }
  1538. LRESULT QuerySiblings(WPARAM wParam, LPARAM lParam)
  1539. {
  1540. ATLASSERT(::IsWindow(m_hWnd));
  1541. return ::SendMessage(m_hWnd, PSM_QUERYSIBLINGS, wParam, lParam);
  1542. }
  1543. void RebootSystem()
  1544. {
  1545. ATLASSERT(::IsWindow(m_hWnd));
  1546. ::SendMessage(m_hWnd, PSM_REBOOTSYSTEM, 0, 0L);
  1547. }
  1548. void RestartWindows()
  1549. {
  1550. ATLASSERT(::IsWindow(m_hWnd));
  1551. ::SendMessage(m_hWnd, PSM_RESTARTWINDOWS, 0, 0L);
  1552. }
  1553. BOOL IsDialogMessage(LPMSG lpMsg)
  1554. {
  1555. ATLASSERT(::IsWindow(m_hWnd));
  1556. return (BOOL)::SendMessage(m_hWnd, PSM_ISDIALOGMESSAGE, 0, (LPARAM)lpMsg);
  1557. }
  1558. #if (_WIN32_IE >= 0x0500)
  1559. int HwndToIndex(HWND hWnd) const
  1560. {
  1561. ATLASSERT(::IsWindow(m_hWnd));
  1562. return (int)::SendMessage(m_hWnd, PSM_HWNDTOINDEX, (WPARAM)hWnd, 0L);
  1563. }
  1564. HWND IndexToHwnd(int nIndex) const
  1565. {
  1566. ATLASSERT(::IsWindow(m_hWnd));
  1567. return (HWND)::SendMessage(m_hWnd, PSM_INDEXTOHWND, nIndex, 0L);
  1568. }
  1569. int PageToIndex(HPROPSHEETPAGE hPage) const
  1570. {
  1571. ATLASSERT(::IsWindow(m_hWnd));
  1572. return (int)::SendMessage(m_hWnd, PSM_PAGETOINDEX, 0, (LPARAM)hPage);
  1573. }
  1574. HPROPSHEETPAGE IndexToPage(int nIndex) const
  1575. {
  1576. ATLASSERT(::IsWindow(m_hWnd));
  1577. return (HPROPSHEETPAGE)::SendMessage(m_hWnd, PSM_INDEXTOPAGE, nIndex, 0L);
  1578. }
  1579. int IdToIndex(int nID) const
  1580. {
  1581. ATLASSERT(::IsWindow(m_hWnd));
  1582. return (int)::SendMessage(m_hWnd, PSM_IDTOINDEX, 0, nID);
  1583. }
  1584. int IndexToId(int nIndex) const
  1585. {
  1586. ATLASSERT(::IsWindow(m_hWnd));
  1587. return (int)::SendMessage(m_hWnd, PSM_INDEXTOID, nIndex, 0L);
  1588. }
  1589. int GetResult() const
  1590. {
  1591. ATLASSERT(::IsWindow(m_hWnd));
  1592. return (int)::SendMessage(m_hWnd, PSM_GETRESULT, 0, 0L);
  1593. }
  1594. BOOL RecalcPageSizes()
  1595. {
  1596. ATLASSERT(::IsWindow(m_hWnd));
  1597. return (BOOL)::SendMessage(m_hWnd, PSM_RECALCPAGESIZES, 0, 0L);
  1598. }
  1599. #endif //(_WIN32_IE >= 0x0500)
  1600. // Implementation - override to prevent usage
  1601. HWND Create(LPCTSTR, HWND, _U_RECT = NULL, LPCTSTR = NULL, DWORD = 0, DWORD = 0, _U_MENUorID = 0U, LPVOID = NULL)
  1602. {
  1603. ATLASSERT(FALSE);
  1604. return NULL;
  1605. }
  1606. };
  1607. /////////////////////////////////////////////////////////////////////////////
  1608. // CPropertySheetImpl - implements a property sheet
  1609. #if (_MSC_VER >= 1200)
  1610. typedef HPROPSHEETPAGE _HPROPSHEETPAGE_TYPE;
  1611. #else
  1612. // we use void* here instead of HPROPSHEETPAGE becuase HPROPSHEETPAGE
  1613. // is a _PSP*, but _PSP is not defined properly
  1614. typedef void* _HPROPSHEETPAGE_TYPE;
  1615. #endif
  1616. template <class T, class TBase /*= CPropertySheetWindow */ >
  1617. class ATL_NO_VTABLE CPropertySheetImpl : public CWindowImplBaseT< TBase >
  1618. {
  1619. public:
  1620. PROPSHEETHEADER m_psh;
  1621. CSimpleArray<_HPROPSHEETPAGE_TYPE> m_arrPages;
  1622. // Construction/Destruction
  1623. CPropertySheetImpl(_U_STRINGorID title = (LPCTSTR)NULL, UINT uStartPage = 0, HWND hWndParent = NULL)
  1624. {
  1625. memset(&m_psh, 0, sizeof(PROPSHEETHEADER));
  1626. m_psh.dwSize = sizeof(PROPSHEETHEADER);
  1627. m_psh.dwFlags = PSH_USECALLBACK;
  1628. m_psh.hInstance = _Module.GetResourceInstance();
  1629. m_psh.phpage = NULL; // will be set later
  1630. m_psh.nPages = 0; // will be set later
  1631. m_psh.pszCaption = title.m_lpstr;
  1632. m_psh.nStartPage = uStartPage;
  1633. m_psh.hwndParent = hWndParent; // if NULL, will be set in DoModal/Create
  1634. m_psh.pfnCallback = T::PropSheetCallback;
  1635. }
  1636. ~CPropertySheetImpl()
  1637. {
  1638. if(m_arrPages.GetSize() > 0) // sheet never created, destroy all pages
  1639. {
  1640. for(int i = 0; i < m_arrPages.GetSize(); i++)
  1641. ::DestroyPropertySheetPage((HPROPSHEETPAGE)m_arrPages[i]);
  1642. }
  1643. }
  1644. static int CALLBACK PropSheetCallback(HWND hWnd, UINT uMsg, LPARAM)
  1645. {
  1646. if(uMsg == PSCB_INITIALIZED)
  1647. {
  1648. ATLASSERT(hWnd != NULL);
  1649. T* pT = (T*)_Module.ExtractCreateWndData();
  1650. // subclass the sheet window
  1651. pT->SubclassWindow(hWnd);
  1652. // remove page handles array
  1653. pT->_CleanUpPages();
  1654. }
  1655. return 0;
  1656. }
  1657. HWND Create(HWND hWndParent = NULL)
  1658. {
  1659. ATLASSERT(m_hWnd == NULL);
  1660. m_psh.dwFlags |= PSH_MODELESS;
  1661. if(m_psh.hwndParent == NULL)
  1662. m_psh.hwndParent = hWndParent;
  1663. m_psh.phpage = (HPROPSHEETPAGE*)m_arrPages.GetData();
  1664. m_psh.nPages = m_arrPages.GetSize();
  1665. T* pT = static_cast<T*>(this);
  1666. _Module.AddCreateWndData(&m_thunk.cd, pT);
  1667. HWND hWnd = (HWND)::PropertySheet(&m_psh);
  1668. _CleanUpPages(); // ensure clean-up, required if call failed
  1669. ATLASSERT(m_hWnd == hWnd);
  1670. return hWnd;
  1671. }
  1672. INT_PTR DoModal(HWND hWndParent = ::GetActiveWindow())
  1673. {
  1674. ATLASSERT(m_hWnd == NULL);
  1675. m_psh.dwFlags &= ~PSH_MODELESS;
  1676. if(m_psh.hwndParent == NULL)
  1677. m_psh.hwndParent = hWndParent;
  1678. m_psh.phpage = (HPROPSHEETPAGE*)m_arrPages.GetData();
  1679. m_psh.nPages = m_arrPages.GetSize();
  1680. T* pT = static_cast<T*>(this);
  1681. _Module.AddCreateWndData(&m_thunk.cd, pT);
  1682. INT_PTR nRet = ::PropertySheet(&m_psh);
  1683. _CleanUpPages(); // ensure clean-up, required if call failed
  1684. return nRet;
  1685. }
  1686. // implementation helper - clean up pages array
  1687. void _CleanUpPages()
  1688. {
  1689. m_psh.nPages = 0;
  1690. m_psh.phpage = NULL;
  1691. m_arrPages.RemoveAll();
  1692. }
  1693. // Attributes (extended overrides of client class methods)
  1694. // These now can be called before the sheet is created
  1695. // Note: Calling these after the sheet is created gives unpredictable results
  1696. int GetPageCount() const
  1697. {
  1698. if(m_hWnd == NULL) // not created yet
  1699. return m_arrPages.GetSize();
  1700. return TBase::GetPageCount();
  1701. }
  1702. int GetActiveIndex() const
  1703. {
  1704. if(m_hWnd == NULL) // not created yet
  1705. return m_psh.nStartPage;
  1706. return TBase::GetActiveIndex();
  1707. }
  1708. HPROPSHEETPAGE GetPage(int nPageIndex) const
  1709. {
  1710. ATLASSERT(m_hWnd == NULL); // can't do this after it's created
  1711. return (HPROPSHEETPAGE)m_arrPages[nPageIndex];
  1712. }
  1713. int GetPageIndex(HPROPSHEETPAGE hPage) const
  1714. {
  1715. ATLASSERT(m_hWnd == NULL); // can't do this after it's created
  1716. return m_arrPages.Find((_HPROPSHEETPAGE_TYPE&)hPage);
  1717. }
  1718. BOOL SetActivePage(int nPageIndex)
  1719. {
  1720. if(m_hWnd == NULL) // not created yet
  1721. {
  1722. ATLASSERT(nPageIndex >= 0 && nPageIndex < m_arrPages.GetSize());
  1723. m_psh.nStartPage = nPageIndex;
  1724. return TRUE;
  1725. }
  1726. return TBase::SetActivePage(nPageIndex);
  1727. }
  1728. BOOL SetActivePage(HPROPSHEETPAGE hPage)
  1729. {
  1730. ATLASSERT(hPage != NULL);
  1731. if (m_hWnd == NULL) // not created yet
  1732. {
  1733. int nPageIndex = GetPageIndex(hPage);
  1734. if(nPageIndex == -1)
  1735. return FALSE;
  1736. return SetActivePage(nPageIndex);
  1737. }
  1738. return TBase::SetActivePage(hPage);
  1739. }
  1740. void SetTitle(LPCTSTR lpszText, UINT nStyle = 0)
  1741. {
  1742. ATLASSERT((nStyle & ~PSH_PROPTITLE) == 0); // only PSH_PROPTITLE is valid
  1743. ATLASSERT(lpszText != NULL);
  1744. if(m_hWnd == NULL)
  1745. {
  1746. // set internal state
  1747. m_psh.pszCaption = lpszText; // must exist until sheet is created
  1748. m_psh.dwFlags &= ~PSH_PROPTITLE;
  1749. m_psh.dwFlags |= nStyle;
  1750. }
  1751. else
  1752. {
  1753. // set external state
  1754. TBase::SetTitle(lpszText, nStyle);
  1755. }
  1756. }
  1757. void SetWizardMode()
  1758. {
  1759. m_psh.dwFlags |= PSH_WIZARD;
  1760. }
  1761. void EnableHelp()
  1762. {
  1763. m_psh.dwFlags |= PSH_HASHELP;
  1764. }
  1765. // Operations
  1766. BOOL AddPage(HPROPSHEETPAGE hPage)
  1767. {
  1768. ATLASSERT(hPage != NULL);
  1769. BOOL bRet = TRUE;
  1770. if(m_hWnd != NULL)
  1771. TBase::AddPage(hPage);
  1772. else // sheet not created yet, use internal data
  1773. bRet = m_arrPages.Add((_HPROPSHEETPAGE_TYPE&)hPage);
  1774. return bRet;
  1775. }
  1776. BOOL AddPage(LPCPROPSHEETPAGE pPage)
  1777. {
  1778. ATLASSERT(pPage != NULL);
  1779. HPROPSHEETPAGE hPage = ::CreatePropertySheetPage(pPage);
  1780. if(hPage == NULL)
  1781. return FALSE;
  1782. BOOL bRet = AddPage(hPage);
  1783. if(!bRet)
  1784. ::DestroyPropertySheetPage(hPage);
  1785. return bRet;
  1786. }
  1787. BOOL RemovePage(HPROPSHEETPAGE hPage)
  1788. {
  1789. ATLASSERT(hPage != NULL);
  1790. if (m_hWnd == NULL) // not created yet
  1791. {
  1792. int nPage = GetPageIndex(hPage);
  1793. if(nPage == -1)
  1794. return FALSE;
  1795. return RemovePage(nPage);
  1796. }
  1797. TBase::RemovePage(hPage);
  1798. return TRUE;
  1799. }
  1800. BOOL RemovePage(int nPageIndex)
  1801. {
  1802. BOOL bRet = TRUE;
  1803. if(m_hWnd != NULL)
  1804. TBase::RemovePage(nPageIndex);
  1805. else // sheet not created yet, use internal data
  1806. bRet = m_arrPages.RemoveAt(nPageIndex);
  1807. return bRet;
  1808. }
  1809. #if (_WIN32_IE >= 0x0400)
  1810. void SetHeader(LPCTSTR szbmHeader)
  1811. {
  1812. ATLASSERT(m_hWnd == NULL); // can't do this after it's created
  1813. m_psh.dwFlags &= ~PSH_WIZARD;
  1814. m_psh.dwFlags |= (PSH_HEADER | PSH_WIZARD97);
  1815. m_psh.pszbmHeader = szbmHeader;
  1816. }
  1817. void SetHeader(HBITMAP hbmHeader)
  1818. {
  1819. ATLASSERT(m_hWnd == NULL); // can't do this after it's created
  1820. m_psh.dwFlags &= ~PSH_WIZARD;
  1821. m_psh.dwFlags |= (PSH_HEADER | PSH_USEHBMHEADER | PSH_WIZARD97);
  1822. m_psh.hbmHeader = hbmHeader;
  1823. }
  1824. void SetWatermark(LPCTSTR szbmWatermark, HPALETTE hplWatermark = NULL)
  1825. {
  1826. ATLASSERT(m_hWnd == NULL); // can't do this after it's created
  1827. m_psh.dwFlags &= ~PSH_WIZARD;
  1828. m_psh.dwFlags |= PSH_WATERMARK | PSH_WIZARD97;
  1829. m_psh.pszbmWatermark = szbmWatermark;
  1830. if (hplWatermark != NULL)
  1831. {
  1832. m_psh.dwFlags |= PSH_USEHPLWATERMARK;
  1833. m_psh.hplWatermark = hplWatermark;
  1834. }
  1835. }
  1836. void SetWatermark(HBITMAP hbmWatermark, HPALETTE hplWatermark = NULL)
  1837. {
  1838. ATLASSERT(m_hWnd == NULL); // can't do this after it's created
  1839. m_psh.dwFlags &= ~PSH_WIZARD;
  1840. m_psh.dwFlags |= (PSH_WATERMARK | PSH_USEHBMWATERMARK | PSH_WIZARD97);
  1841. m_psh.hbmWatermark = hbmWatermark;
  1842. if (hplWatermark != NULL)
  1843. {
  1844. m_psh.dwFlags |= PSH_USEHPLWATERMARK;
  1845. m_psh.hplWatermark = hplWatermark;
  1846. }
  1847. }
  1848. void StretchWatermark(bool bStretchWatermark)
  1849. {
  1850. ATLASSERT(m_hWnd == NULL); // can't do this after it's created
  1851. if (bStretchWatermark)
  1852. m_psh.dwFlags |= PSH_STRETCHWATERMARK;
  1853. else
  1854. m_psh.dwFlags &= ~PSH_STRETCHWATERMARK;
  1855. }
  1856. #endif
  1857. // Message map and handlers handlers
  1858. typedef CPropertySheetImpl< T, TBase > thisClass;
  1859. BEGIN_MSG_MAP(thisClass)
  1860. MESSAGE_HANDLER(WM_COMMAND, OnCommand)
  1861. END_MSG_MAP()
  1862. LRESULT OnCommand(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& /*bHandled*/)
  1863. {
  1864. LRESULT lRet = DefWindowProc(uMsg, wParam, lParam);
  1865. if(HIWORD(wParam) == BN_CLICKED && (LOWORD(wParam) == IDOK || LOWORD(wParam) == IDCANCEL) &&
  1866. ((m_psh.dwFlags & PSH_MODELESS) != 0) && (GetActivePage() == NULL))
  1867. DestroyWindow();
  1868. return lRet;
  1869. }
  1870. };
  1871. // for non-customized sheets
  1872. class CPropertySheet : public CPropertySheetImpl<CPropertySheet>
  1873. {
  1874. public:
  1875. CPropertySheet(_U_STRINGorID title = (LPCTSTR)NULL, UINT uStartPage = 0, HWND hWndParent = NULL)
  1876. : CPropertySheetImpl<CPropertySheet>(title, uStartPage, hWndParent)
  1877. { }
  1878. BEGIN_MSG_MAP(thisClass)
  1879. MESSAGE_HANDLER(WM_COMMAND, CPropertySheetImpl<CPropertySheet>::OnCommand)
  1880. END_MSG_MAP()
  1881. };
  1882. /////////////////////////////////////////////////////////////////////////////
  1883. // CPropertyPageWindow - client side for a property page
  1884. class CPropertyPageWindow : public CWindow
  1885. {
  1886. public:
  1887. // Constructors
  1888. CPropertyPageWindow(HWND hWnd = NULL) : CWindow(hWnd) { }
  1889. CPropertyPageWindow& operator=(HWND hWnd)
  1890. {
  1891. m_hWnd = hWnd;
  1892. return *this;
  1893. }
  1894. // Attributes
  1895. CPropertySheetWindow GetPropertySheet() const
  1896. {
  1897. ATLASSERT(::IsWindow(m_hWnd));
  1898. return CPropertySheetWindow(GetParent());
  1899. }
  1900. // Operations
  1901. BOOL Apply()
  1902. {
  1903. ATLASSERT(::IsWindow(m_hWnd));
  1904. ATLASSERT(GetParent() != NULL);
  1905. return GetPropertySheet().Apply();
  1906. }
  1907. void CancelToClose()
  1908. {
  1909. ATLASSERT(::IsWindow(m_hWnd));
  1910. ATLASSERT(GetParent() != NULL);
  1911. GetPropertySheet().CancelToClose();
  1912. }
  1913. void SetModified(BOOL bChanged = TRUE)
  1914. {
  1915. ATLASSERT(::IsWindow(m_hWnd));
  1916. ATLASSERT(GetParent() != NULL);
  1917. GetPropertySheet().SetModified(m_hWnd, bChanged);
  1918. }
  1919. LRESULT QuerySiblings(WPARAM wParam, LPARAM lParam)
  1920. {
  1921. ATLASSERT(::IsWindow(m_hWnd));
  1922. ATLASSERT(GetParent() != NULL);
  1923. return GetPropertySheet().QuerySiblings(wParam, lParam);
  1924. }
  1925. void RebootSystem()
  1926. {
  1927. ATLASSERT(::IsWindow(m_hWnd));
  1928. ATLASSERT(GetParent() != NULL);
  1929. GetPropertySheet().RebootSystem();
  1930. }
  1931. void RestartWindows()
  1932. {
  1933. ATLASSERT(::IsWindow(m_hWnd));
  1934. ATLASSERT(GetParent() != NULL);
  1935. GetPropertySheet().RestartWindows();
  1936. }
  1937. void SetWizardButtons(DWORD dwFlags)
  1938. {
  1939. ATLASSERT(::IsWindow(m_hWnd));
  1940. ATLASSERT(GetParent() != NULL);
  1941. GetPropertySheet().SetWizardButtons(dwFlags);
  1942. }
  1943. // Implementation - overrides to prevent usage
  1944. HWND Create(LPCTSTR, HWND, _U_RECT = NULL, LPCTSTR = NULL, DWORD = 0, DWORD = 0, _U_MENUorID = 0U, LPVOID = NULL)
  1945. {
  1946. ATLASSERT(FALSE);
  1947. return NULL;
  1948. }
  1949. };
  1950. /////////////////////////////////////////////////////////////////////////////
  1951. // CPropertyPageImpl - implements a property page
  1952. template <class T, class TBase /*= CPropertyPageWindow */ >
  1953. class ATL_NO_VTABLE CPropertyPageImpl : public CDialogImplBaseT< TBase >
  1954. {
  1955. public:
  1956. PROPSHEETPAGE m_psp;
  1957. operator PROPSHEETPAGE*() { return &m_psp; }
  1958. // Construction
  1959. CPropertyPageImpl(_U_STRINGorID title = (LPCTSTR)NULL)
  1960. {
  1961. // initialize PROPSHEETPAGE struct
  1962. memset(&m_psp, 0, sizeof(PROPSHEETPAGE));
  1963. m_psp.dwSize = sizeof(PROPSHEETPAGE);
  1964. m_psp.dwFlags = PSP_USECALLBACK;
  1965. m_psp.hInstance = _Module.GetResourceInstance();
  1966. T* pT = static_cast<T*>(this);
  1967. m_psp.pszTemplate = MAKEINTRESOURCE(pT->IDD);
  1968. m_psp.pfnDlgProc = T::StartDialogProc;
  1969. m_psp.pfnCallback = T::PropPageCallback;
  1970. m_psp.lParam = (LPARAM)pT;
  1971. if(title.m_lpstr != NULL)
  1972. SetTitle(title);
  1973. }
  1974. static UINT CALLBACK PropPageCallback(HWND hWnd, UINT uMsg, LPPROPSHEETPAGE ppsp)
  1975. {
  1976. hWnd; // avoid level 4 warning
  1977. if(uMsg == PSPCB_CREATE)
  1978. {
  1979. ATLASSERT(hWnd == NULL);
  1980. CDialogImplBaseT< TBase >* pPage = (CDialogImplBaseT< TBase >*)(T*)ppsp->lParam;
  1981. _Module.AddCreateWndData(&pPage->m_thunk.cd, pPage);
  1982. }
  1983. return 1;
  1984. }
  1985. HPROPSHEETPAGE Create()
  1986. {
  1987. return ::CreatePropertySheetPage(&m_psp);
  1988. }
  1989. // Attributes
  1990. void SetTitle(_U_STRINGorID title)
  1991. {
  1992. m_psp.pszTitle = title.m_lpstr;
  1993. m_psp.dwFlags |= PSP_USETITLE;
  1994. }
  1995. #if (_WIN32_IE >= 0x0500)
  1996. void SetHeaderTitle(LPCTSTR lpstrHeaderTitle)
  1997. {
  1998. ATLASSERT(m_hWnd == NULL); // can't do this after it's created
  1999. m_psp.dwFlags |= PSP_USEHEADERTITLE;
  2000. m_psp.pszHeaderTitle = lpstrHeaderTitle;
  2001. }
  2002. void SetHeaderSubTitle(LPCTSTR lpstrHeaderSubTitle)
  2003. {
  2004. ATLASSERT(m_hWnd == NULL); // can't do this after it's created
  2005. m_psp.dwFlags |= PSP_USEHEADERSUBTITLE;
  2006. m_psp.pszHeaderSubTitle = lpstrHeaderSubTitle;
  2007. }
  2008. #endif //(_WIN32_IE >= 0x0500)
  2009. // Operations
  2010. void EnableHelp()
  2011. {
  2012. m_psp.dwFlags |= PSP_HASHELP;
  2013. }
  2014. // Message map and handlers
  2015. typedef CPropertyPageImpl< T, TBase > thisClass;
  2016. BEGIN_MSG_MAP(thisClass)
  2017. MESSAGE_HANDLER(WM_NOTIFY, OnNotify)
  2018. END_MSG_MAP()
  2019. LRESULT OnNotify(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM lParam, BOOL& bHandled)
  2020. {
  2021. ATLASSERT(::IsWindow(m_hWnd));
  2022. NMHDR* pNMHDR = (NMHDR*)lParam;
  2023. // don't handle messages not from the page/sheet itself
  2024. if(pNMHDR->hwndFrom != m_hWnd && pNMHDR->hwndFrom != ::GetParent(m_hWnd))
  2025. {
  2026. bHandled = FALSE;
  2027. return 1;
  2028. }
  2029. T* pT = static_cast<T*>(this);
  2030. LRESULT lResult = 0;
  2031. switch(pNMHDR->code)
  2032. {
  2033. case PSN_SETACTIVE:
  2034. lResult = pT->OnSetActive() ? 0 : -1;
  2035. break;
  2036. case PSN_KILLACTIVE:
  2037. lResult = !pT->OnKillActive();
  2038. break;
  2039. case PSN_APPLY:
  2040. lResult = pT->OnApply() ? PSNRET_NOERROR : PSNRET_INVALID_NOCHANGEPAGE;
  2041. break;
  2042. case PSN_RESET:
  2043. pT->OnReset();
  2044. break;
  2045. case PSN_QUERYCANCEL:
  2046. lResult = !pT->OnQueryCancel();
  2047. break;
  2048. case PSN_WIZNEXT:
  2049. lResult = pT->OnWizardNext();
  2050. break;
  2051. case PSN_WIZBACK:
  2052. lResult = pT->OnWizardBack();
  2053. break;
  2054. case PSN_WIZFINISH:
  2055. lResult = !pT->OnWizardFinish();
  2056. break;
  2057. case PSN_HELP:
  2058. pT->OnHelp();
  2059. break;
  2060. #if (_WIN32_IE >= 0x0400)
  2061. case PSN_GETOBJECT:
  2062. if(!pT->OnGetObject((LPNMOBJECTNOTIFY)lParam))
  2063. bHandled = FALSE;
  2064. break;
  2065. #endif //(_WIN32_IE >= 0x0400)
  2066. #if (_WIN32_IE >= 0x0500)
  2067. case PSN_TRANSLATEACCELERATOR:
  2068. {
  2069. LPPSHNOTIFY lpPSHNotify = (LPPSHNOTIFY)lParam;
  2070. lResult = pT->OnTranslateAccelerator((LPMSG)lpPSHNotify->lParam) ? PSNRET_MESSAGEHANDLED : PSNRET_NOERROR;
  2071. }
  2072. break;
  2073. case PSN_QUERYINITIALFOCUS:
  2074. {
  2075. LPPSHNOTIFY lpPSHNotify = (LPPSHNOTIFY)lParam;
  2076. lResult = (LRESULT)pT->OnQueryInitialFocus((HWND)lpPSHNotify->lParam);
  2077. }
  2078. break;
  2079. #endif //(_WIN32_IE >= 0x0500)
  2080. default:
  2081. bHandled = FALSE; // not handled
  2082. }
  2083. return lResult;
  2084. }
  2085. // Overridables
  2086. BOOL OnSetActive()
  2087. {
  2088. return TRUE;
  2089. }
  2090. BOOL OnKillActive()
  2091. {
  2092. return TRUE;
  2093. }
  2094. BOOL OnApply()
  2095. {
  2096. return TRUE;
  2097. }
  2098. void OnReset()
  2099. {
  2100. }
  2101. BOOL OnQueryCancel()
  2102. {
  2103. return TRUE; // ok to cancel
  2104. }
  2105. int OnWizardBack()
  2106. {
  2107. // 0 = goto next page
  2108. // -1 = prevent page change
  2109. // >0 = jump to page by dlg ID
  2110. return 0;
  2111. }
  2112. int OnWizardNext()
  2113. {
  2114. // 0 = goto next page
  2115. // -1 = prevent page change
  2116. // >0 = jump to page by dlg ID
  2117. return 0;
  2118. }
  2119. BOOL OnWizardFinish()
  2120. {
  2121. return TRUE;
  2122. }
  2123. void OnHelp()
  2124. {
  2125. }
  2126. #if (_WIN32_IE >= 0x0400)
  2127. BOOL OnGetObject(LPNMOBJECTNOTIFY /*lpObjectNotify*/)
  2128. {
  2129. return FALSE; // not processed
  2130. }
  2131. #endif //(_WIN32_IE >= 0x0400)
  2132. #if (_WIN32_IE >= 0x0500)
  2133. BOOL OnTranslateAccelerator(LPMSG /*lpMsg*/)
  2134. {
  2135. return FALSE; // not translated
  2136. }
  2137. HWND OnQueryInitialFocus(HWND /*hWndFocus*/)
  2138. {
  2139. return NULL; // default
  2140. }
  2141. #endif //(_WIN32_IE >= 0x0500)
  2142. };
  2143. // for non-customized pages
  2144. template <WORD t_wDlgTemplateID>
  2145. class CPropertyPage : public CPropertyPageImpl<CPropertyPage<t_wDlgTemplateID> >
  2146. {
  2147. public:
  2148. enum { IDD = t_wDlgTemplateID };
  2149. CPropertyPage(_U_STRINGorID title = (LPCTSTR)NULL) : CPropertyPageImpl<CPropertyPage>(title)
  2150. { }
  2151. DECLARE_EMPTY_MSG_MAP()
  2152. };
  2153. /////////////////////////////////////////////////////////////////////////////
  2154. // CAxPropertyPageImpl - property page that hosts ActiveX controls
  2155. #ifndef _ATL_NO_HOSTING
  2156. // Note: You must #include <atlhost.h> to use these classes
  2157. template <class T, class TBase = CPropertyPageWindow>
  2158. class ATL_NO_VTABLE CAxPropertyPageImpl : public CPropertyPageImpl< T, TBase >
  2159. {
  2160. public:
  2161. // Data members
  2162. HGLOBAL m_hInitData;
  2163. HGLOBAL m_hDlgRes;
  2164. HGLOBAL m_hDlgResSplit;
  2165. // Constructor/destructor
  2166. CAxPropertyPageImpl(_U_STRINGorID title = (LPCTSTR)NULL) :
  2167. CPropertyPageImpl< T, TBase >(title),
  2168. m_hInitData(NULL), m_hDlgRes(NULL), m_hDlgResSplit(NULL)
  2169. {
  2170. T* pT = static_cast<T*>(this);
  2171. pT; // avoid level 4 warning
  2172. // initialize ActiveX hosting and modify dialog template
  2173. AtlAxWinInit();
  2174. HINSTANCE hInstance = _Module.GetResourceInstance();
  2175. LPCTSTR lpTemplateName = MAKEINTRESOURCE(pT->IDD);
  2176. HRSRC hDlg = ::FindResource(hInstance, lpTemplateName, (LPTSTR)RT_DIALOG);
  2177. if(hDlg != NULL)
  2178. {
  2179. HRSRC hDlgInit = ::FindResource(hInstance, lpTemplateName, (LPTSTR)_ATL_RT_DLGINIT);
  2180. BYTE* pInitData = NULL;
  2181. if(hDlgInit != NULL)
  2182. {
  2183. m_hInitData = ::LoadResource(hInstance, hDlgInit);
  2184. pInitData = (BYTE*)::LockResource(m_hInitData);
  2185. }
  2186. m_hDlgRes = ::LoadResource(hInstance, hDlg);
  2187. DLGTEMPLATE* pDlg = (DLGTEMPLATE*)::LockResource(m_hDlgRes);
  2188. LPCDLGTEMPLATE lpDialogTemplate = _DialogSplitHelper::SplitDialogTemplate(pDlg, pInitData);
  2189. if(lpDialogTemplate != pDlg)
  2190. m_hDlgResSplit = ::GlobalHandle(lpDialogTemplate);
  2191. // set up property page to use in-memory dialog template
  2192. if(lpDialogTemplate != NULL)
  2193. {
  2194. m_psp.dwFlags |= PSP_DLGINDIRECT;
  2195. m_psp.pResource = lpDialogTemplate;
  2196. }
  2197. else
  2198. {
  2199. ATLASSERT(FALSE && _T("CAxPropertyPageImpl - ActiveX initializtion failed!"));
  2200. }
  2201. }
  2202. else
  2203. {
  2204. ATLASSERT(FALSE && _T("CAxPropertyPageImpl - Cannot find dialog template!"));
  2205. }
  2206. }
  2207. ~CAxPropertyPageImpl()
  2208. {
  2209. if(m_hInitData != NULL)
  2210. {
  2211. UnlockResource(m_hInitData);
  2212. ::FreeResource(m_hInitData);
  2213. }
  2214. if(m_hDlgRes != NULL)
  2215. {
  2216. UnlockResource(m_hDlgRes);
  2217. ::FreeResource(m_hDlgRes);
  2218. }
  2219. if(m_hDlgResSplit != NULL)
  2220. {
  2221. ::GlobalFree(m_hDlgResSplit);
  2222. }
  2223. }
  2224. // Methods
  2225. // call this one to handle keyboard message for ActiveX controls
  2226. BOOL PreTranslateMessage(LPMSG pMsg)
  2227. {
  2228. if ((pMsg->message < WM_KEYFIRST || pMsg->message > WM_KEYLAST) &&
  2229. (pMsg->message < WM_MOUSEFIRST || pMsg->message > WM_MOUSELAST))
  2230. return FALSE;
  2231. // find a direct child of the dialog from the window that has focus
  2232. HWND hWndCtl = ::GetFocus();
  2233. if (IsChild(hWndCtl) && ::GetParent(hWndCtl) != m_hWnd)
  2234. {
  2235. do
  2236. {
  2237. hWndCtl = ::GetParent(hWndCtl);
  2238. }
  2239. while (::GetParent(hWndCtl) != m_hWnd);
  2240. }
  2241. // give controls a chance to translate this message
  2242. return (BOOL)::SendMessage(hWndCtl, WM_FORWARDMSG, 0, (LPARAM)pMsg);
  2243. }
  2244. // Overridables
  2245. #if (_WIN32_IE >= 0x0500)
  2246. // new default implementation for ActiveX hosting pages
  2247. BOOL OnTranslateAccelerator(LPMSG lpMsg)
  2248. {
  2249. T* pT = static_cast<T*>(this);
  2250. return pT->PreTranslateMessage(lpMsg);
  2251. }
  2252. #endif //(_WIN32_IE >= 0x0500)
  2253. };
  2254. // for non-customized pages
  2255. template <WORD t_wDlgTemplateID>
  2256. class CAxPropertyPage : public CAxPropertyPageImpl<CAxPropertyPage<t_wDlgTemplateID> >
  2257. {
  2258. public:
  2259. enum { IDD = t_wDlgTemplateID };
  2260. CAxPropertyPage(_U_STRINGorID title = (LPCTSTR)NULL) : CAxPropertyPageImpl<CAxPropertyPage>(title)
  2261. { }
  2262. #if (_WIN32_IE >= 0x0500)
  2263. // not empty so we handle accelerators
  2264. BEGIN_MSG_MAP(CAxPropertyPage)
  2265. CHAIN_MSG_MAP(CAxPropertyPageImpl<CAxPropertyPage<t_wDlgTemplateID> >)
  2266. END_MSG_MAP()
  2267. #else //!(_WIN32_IE >= 0x0500)
  2268. DECLARE_EMPTY_MSG_MAP()
  2269. #endif //!(_WIN32_IE >= 0x0500)
  2270. };
  2271. #endif //_ATL_NO_HOSTING
  2272. }; //namespace WTL
  2273. #endif // __ATLDLGS_H__