Add policy_templates target for GN.
[chromium-blink-merge.git] / third_party / wtl / include / atldlgs.h
blob62db9178013cd6e61cf763e11c079f388e20f144
1 // Windows Template Library - WTL version 8.0
2 // Copyright (C) Microsoft Corporation. All rights reserved.
3 //
4 // This file is a part of the Windows Template Library.
5 // The use and distribution terms for this software are covered by the
6 // Microsoft Permissive License (Ms-PL) which can be found in the file
7 // Ms-PL.txt at the root of this distribution.
9 #ifndef __ATLDLGS_H__
10 #define __ATLDLGS_H__
12 #pragma once
14 #ifndef __cplusplus
15 #error ATL requires C++ compilation (use a .cpp suffix)
16 #endif
18 #ifndef __ATLAPP_H__
19 #error atldlgs.h requires atlapp.h to be included first
20 #endif
22 #ifndef __ATLWIN_H__
23 #error atldlgs.h requires atlwin.h to be included first
24 #endif
26 #include <commdlg.h>
27 #include <shlobj.h>
29 #if (_WIN32_WINNT >= 0x0600) && !defined(_WIN32_WCE)
30 #include <shobjidl.h>
31 #endif // (_WIN32_WINNT >= 0x0600) && !defined(_WIN32_WCE)
34 ///////////////////////////////////////////////////////////////////////////////
35 // Classes in this file:
37 // CFileDialogImpl<T>
38 // CFileDialog
39 // CFileDialogEx
40 // CMultiFileDialogImpl<T>
41 // CMultiFileDialog
42 // CShellFileDialogImpl<T>
43 // CShellFileOpenDialogImpl<T>
44 // CShellFileOpenDialog
45 // CShellFileSaveDialogImpl<T>
46 // CShellFileSaveDialog
47 // CFolderDialogImpl<T>
48 // CFolderDialog
49 // CFontDialogImpl<T>
50 // CFontDialog
51 // CRichEditFontDialogImpl<T>
52 // CRichEditFontDialog
53 // CColorDialogImpl<T>
54 // CColorDialog
55 // CPrintDialogImpl<T>
56 // CPrintDialog
57 // CPrintDialogExImpl<T>
58 // CPrintDialogEx
59 // CPageSetupDialogImpl<T>
60 // CPageSetupDialog
61 // CFindReplaceDialogImpl<T>
62 // CFindReplaceDialog
64 // CMemDlgTemplate
65 // CIndirectDialogImpl<T, TDlgTemplate, TBase>
67 // CPropertySheetWindow
68 // CPropertySheetImpl<T, TBase>
69 // CPropertySheet
70 // CPropertyPageWindow
71 // CPropertyPageImpl<T, TBase>
72 // CPropertyPage<t_wDlgTemplateID>
73 // CAxPropertyPageImpl<T, TBase>
74 // CAxPropertyPage<t_wDlgTemplateID>
76 // CWizard97SheetWindow
77 // CWizard97SheetImpl<T, TBase>
78 // CWizard97Sheet
79 // CWizard97PageWindow
80 // CWizard97PageImpl<T, TBase>
81 // CWizard97ExteriorPageImpl<T, TBase>
82 // CWizard97InteriorPageImpl<T, TBase>
84 // CAeroWizardFrameWindow
85 // CAeroWizardFrameImpl<T, TBase>
86 // CAeroWizardFrame
87 // CAeroWizardPageWindow
88 // CAeroWizardPageImpl<T, TBase>
89 // CAeroWizardPage<t_wDlgTemplateID>
90 // CAeroWizardAxPageImpl<T, TBase>
91 // CAeroWizardAxPage<t_wDlgTemplateID>
93 // CTaskDialogConfig
94 // CTaskDialogImpl<T>
95 // CTaskDialog
97 // Global functions:
98 // AtlTaskDialog()
101 namespace WTL
104 ///////////////////////////////////////////////////////////////////////////////
105 // CFileDialogImpl - used for File Open or File Save As
107 // compatibility with the old (vc6.0) headers
108 #if (_WIN32_WINNT >= 0x0500) && !defined(OPENFILENAME_SIZE_VERSION_400)
109 #ifndef CDSIZEOF_STRUCT
110 #define CDSIZEOF_STRUCT(structname, member) (((int)((LPBYTE)(&((structname*)0)->member) - ((LPBYTE)((structname*)0)))) + sizeof(((structname*)0)->member))
111 #endif
112 #define OPENFILENAME_SIZE_VERSION_400A CDSIZEOF_STRUCT(OPENFILENAMEA,lpTemplateName)
113 #define OPENFILENAME_SIZE_VERSION_400W CDSIZEOF_STRUCT(OPENFILENAMEW,lpTemplateName)
114 #ifdef UNICODE
115 #define OPENFILENAME_SIZE_VERSION_400 OPENFILENAME_SIZE_VERSION_400W
116 #else
117 #define OPENFILENAME_SIZE_VERSION_400 OPENFILENAME_SIZE_VERSION_400A
118 #endif // !UNICODE
119 #endif // (_WIN32_WINNT >= 0x0500) && !defined(OPENFILENAME_SIZE_VERSION_400)
121 #if !defined(_WIN32_WCE) && !defined(CDN_INCLUDEITEM)
122 #define CDN_INCLUDEITEM (CDN_FIRST - 0x0007)
123 #endif
125 template <class T>
126 class ATL_NO_VTABLE CFileDialogImpl : public ATL::CDialogImplBase
128 public:
129 #if defined(__AYGSHELL_H__) && (_WIN32_WCE >= 0x0501)
130 OPENFILENAMEEX m_ofn;
131 #else
132 OPENFILENAME m_ofn;
133 #endif
134 BOOL m_bOpenFileDialog; // TRUE for file open, FALSE for file save
135 TCHAR m_szFileTitle[_MAX_FNAME]; // contains file title after return
136 TCHAR m_szFileName[_MAX_PATH]; // contains full path name after return
138 CFileDialogImpl(BOOL bOpenFileDialog, // TRUE for FileOpen, FALSE for FileSaveAs
139 LPCTSTR lpszDefExt = NULL,
140 LPCTSTR lpszFileName = NULL,
141 DWORD dwFlags = OFN_HIDEREADONLY | OFN_OVERWRITEPROMPT,
142 LPCTSTR lpszFilter = NULL,
143 HWND hWndParent = NULL)
145 memset(&m_ofn, 0, sizeof(m_ofn)); // initialize structure to 0/NULL
146 m_szFileName[0] = _T('\0');
147 m_szFileTitle[0] = _T('\0');
149 m_bOpenFileDialog = bOpenFileDialog;
151 m_ofn.lStructSize = sizeof(m_ofn);
152 #if (_WIN32_WINNT >= 0x0500)
153 // adjust struct size if running on older version of Windows
154 if(AtlIsOldWindows())
156 ATLASSERT(sizeof(m_ofn) > OPENFILENAME_SIZE_VERSION_400); // must be
157 m_ofn.lStructSize = OPENFILENAME_SIZE_VERSION_400;
159 #endif // (_WIN32_WINNT >= 0x0500)
160 m_ofn.lpstrFile = m_szFileName;
161 m_ofn.nMaxFile = _MAX_PATH;
162 m_ofn.lpstrDefExt = lpszDefExt;
163 m_ofn.lpstrFileTitle = (LPTSTR)m_szFileTitle;
164 m_ofn.nMaxFileTitle = _MAX_FNAME;
165 #ifndef _WIN32_WCE
166 m_ofn.Flags = dwFlags | OFN_EXPLORER | OFN_ENABLEHOOK | OFN_ENABLESIZING;
167 #else // CE specific
168 m_ofn.Flags = dwFlags | OFN_EXPLORER | OFN_ENABLEHOOK;
169 #endif // !_WIN32_WCE
170 m_ofn.lpstrFilter = lpszFilter;
171 m_ofn.hInstance = ModuleHelper::GetResourceInstance();
172 m_ofn.lpfnHook = (LPOFNHOOKPROC)T::StartDialogProc;
173 m_ofn.hwndOwner = hWndParent;
175 // setup initial file name
176 if(lpszFileName != NULL)
177 SecureHelper::strncpy_x(m_szFileName, _countof(m_szFileName), lpszFileName, _TRUNCATE);
180 INT_PTR DoModal(HWND hWndParent = ::GetActiveWindow())
182 ATLASSERT((m_ofn.Flags & OFN_ENABLEHOOK) != 0);
183 ATLASSERT(m_ofn.lpfnHook != NULL); // can still be a user hook
185 ATLASSERT((m_ofn.Flags & OFN_EXPLORER) != 0);
187 if(m_ofn.hwndOwner == NULL) // set only if not specified before
188 m_ofn.hwndOwner = hWndParent;
190 ATLASSERT(m_hWnd == NULL);
191 ModuleHelper::AddCreateWndData(&m_thunk.cd, (ATL::CDialogImplBase*)this);
193 BOOL bRet;
194 if(m_bOpenFileDialog)
195 #if defined(__AYGSHELL_H__) && (_WIN32_WCE >= 0x0501)
196 bRet = ::GetOpenFileNameEx(&m_ofn);
197 else
198 bRet = ::GetSaveFileName((LPOPENFILENAME)&m_ofn);
199 #else
200 bRet = ::GetOpenFileName(&m_ofn);
201 else
202 bRet = ::GetSaveFileName(&m_ofn);
203 #endif
205 m_hWnd = NULL;
207 return bRet ? IDOK : IDCANCEL;
210 // Attributes
211 ATL::CWindow GetFileDialogWindow() const
213 ATLASSERT(::IsWindow(m_hWnd));
214 return ATL::CWindow(GetParent());
217 int GetFilePath(LPTSTR lpstrFilePath, int nLength) const
219 ATLASSERT(::IsWindow(m_hWnd));
220 ATLASSERT((m_ofn.Flags & OFN_EXPLORER) != 0);
222 return (int)GetFileDialogWindow().SendMessage(CDM_GETFILEPATH, nLength, (LPARAM)lpstrFilePath);
225 int GetFolderIDList(LPVOID lpBuff, int nLength) const
227 ATLASSERT(::IsWindow(m_hWnd));
228 ATLASSERT((m_ofn.Flags & OFN_EXPLORER) != 0);
230 return (int)GetFileDialogWindow().SendMessage(CDM_GETFOLDERIDLIST, nLength, (LPARAM)lpBuff);
233 int GetFolderPath(LPTSTR lpstrFolderPath, int nLength) const
235 ATLASSERT(::IsWindow(m_hWnd));
236 ATLASSERT((m_ofn.Flags & OFN_EXPLORER) != 0);
238 return (int)GetFileDialogWindow().SendMessage(CDM_GETFOLDERPATH, nLength, (LPARAM)lpstrFolderPath);
241 int GetSpec(LPTSTR lpstrSpec, int nLength) const
243 ATLASSERT(::IsWindow(m_hWnd));
244 ATLASSERT((m_ofn.Flags & OFN_EXPLORER) != 0);
246 return (int)GetFileDialogWindow().SendMessage(CDM_GETSPEC, nLength, (LPARAM)lpstrSpec);
249 void SetControlText(int nCtrlID, LPCTSTR lpstrText)
251 ATLASSERT(::IsWindow(m_hWnd));
252 ATLASSERT((m_ofn.Flags & OFN_EXPLORER) != 0);
254 GetFileDialogWindow().SendMessage(CDM_SETCONTROLTEXT, nCtrlID, (LPARAM)lpstrText);
257 void SetDefExt(LPCTSTR lpstrExt)
259 ATLASSERT(::IsWindow(m_hWnd));
260 ATLASSERT((m_ofn.Flags & OFN_EXPLORER) != 0);
262 GetFileDialogWindow().SendMessage(CDM_SETDEFEXT, 0, (LPARAM)lpstrExt);
265 BOOL GetReadOnlyPref() const // return TRUE if readonly checked
267 return ((m_ofn.Flags & OFN_READONLY) != 0) ? TRUE : FALSE;
270 // Operations
271 void HideControl(int nCtrlID)
273 ATLASSERT(::IsWindow(m_hWnd));
274 ATLASSERT((m_ofn.Flags & OFN_EXPLORER) != 0);
276 GetFileDialogWindow().SendMessage(CDM_HIDECONTROL, nCtrlID);
279 // Special override for common dialogs
280 BOOL EndDialog(INT_PTR /*nRetCode*/ = 0)
282 ATLASSERT(::IsWindow(m_hWnd));
283 GetFileDialogWindow().SendMessage(WM_COMMAND, MAKEWPARAM(IDCANCEL, 0));
284 return TRUE;
287 // Message map and handlers
288 BEGIN_MSG_MAP(CFileDialogImpl)
289 NOTIFY_CODE_HANDLER(CDN_FILEOK, _OnFileOK)
290 NOTIFY_CODE_HANDLER(CDN_FOLDERCHANGE, _OnFolderChange)
291 NOTIFY_CODE_HANDLER(CDN_HELP, _OnHelp)
292 NOTIFY_CODE_HANDLER(CDN_INITDONE, _OnInitDone)
293 NOTIFY_CODE_HANDLER(CDN_SELCHANGE, _OnSelChange)
294 NOTIFY_CODE_HANDLER(CDN_SHAREVIOLATION, _OnShareViolation)
295 NOTIFY_CODE_HANDLER(CDN_TYPECHANGE, _OnTypeChange)
296 #ifndef _WIN32_WCE
297 NOTIFY_CODE_HANDLER(CDN_INCLUDEITEM, _OnIncludeItem)
298 #endif // !_WIN32_WCE
299 END_MSG_MAP()
301 LRESULT _OnFileOK(int /*idCtrl*/, LPNMHDR pnmh, BOOL& /*bHandled*/)
303 ATLASSERT(::IsWindow(m_hWnd));
304 T* pT = static_cast<T*>(this);
305 return !pT->OnFileOK((LPOFNOTIFY)pnmh);
308 LRESULT _OnFolderChange(int /*idCtrl*/, LPNMHDR pnmh, BOOL& /*bHandled*/)
310 ATLASSERT(::IsWindow(m_hWnd));
311 T* pT = static_cast<T*>(this);
312 pT->OnFolderChange((LPOFNOTIFY)pnmh);
313 return 0;
316 LRESULT _OnHelp(int /*idCtrl*/, LPNMHDR pnmh, BOOL& /*bHandled*/)
318 ATLASSERT(::IsWindow(m_hWnd));
319 T* pT = static_cast<T*>(this);
320 pT->OnHelp((LPOFNOTIFY)pnmh);
321 return 0;
324 LRESULT _OnInitDone(int /*idCtrl*/, LPNMHDR pnmh, BOOL& /*bHandled*/)
326 ATLASSERT(::IsWindow(m_hWnd));
327 T* pT = static_cast<T*>(this);
328 pT->OnInitDone((LPOFNOTIFY)pnmh);
329 return 0;
332 LRESULT _OnSelChange(int /*idCtrl*/, LPNMHDR pnmh, BOOL& /*bHandled*/)
334 ATLASSERT(::IsWindow(m_hWnd));
335 T* pT = static_cast<T*>(this);
336 pT->OnSelChange((LPOFNOTIFY)pnmh);
337 return 0;
340 LRESULT _OnShareViolation(int /*idCtrl*/, LPNMHDR pnmh, BOOL& /*bHandled*/)
342 ATLASSERT(::IsWindow(m_hWnd));
343 T* pT = static_cast<T*>(this);
344 return pT->OnShareViolation((LPOFNOTIFY)pnmh);
347 LRESULT _OnTypeChange(int /*idCtrl*/, LPNMHDR pnmh, BOOL& /*bHandled*/)
349 ATLASSERT(::IsWindow(m_hWnd));
350 T* pT = static_cast<T*>(this);
351 pT->OnTypeChange((LPOFNOTIFY)pnmh);
352 return 0;
355 #ifndef _WIN32_WCE
356 LRESULT _OnIncludeItem(int /*idCtrl*/, LPNMHDR pnmh, BOOL& /*bHandled*/)
358 ATLASSERT(::IsWindow(m_hWnd));
359 T* pT = static_cast<T*>(this);
360 return pT->OnIncludeItem((LPOFNOTIFYEX)pnmh);
362 #endif // !_WIN32_WCE
364 // Overrideables
365 BOOL OnFileOK(LPOFNOTIFY /*lpon*/)
367 return TRUE;
370 void OnFolderChange(LPOFNOTIFY /*lpon*/)
374 void OnHelp(LPOFNOTIFY /*lpon*/)
378 void OnInitDone(LPOFNOTIFY /*lpon*/)
382 void OnSelChange(LPOFNOTIFY /*lpon*/)
386 int OnShareViolation(LPOFNOTIFY /*lpon*/)
388 return 0;
391 void OnTypeChange(LPOFNOTIFY /*lpon*/)
395 #ifndef _WIN32_WCE
396 BOOL OnIncludeItem(LPOFNOTIFYEX /*lponex*/)
398 return TRUE; // include item
400 #endif // !_WIN32_WCE
403 class CFileDialog : public CFileDialogImpl<CFileDialog>
405 public:
406 CFileDialog(BOOL bOpenFileDialog, // TRUE for FileOpen, FALSE for FileSaveAs
407 LPCTSTR lpszDefExt = NULL,
408 LPCTSTR lpszFileName = NULL,
409 DWORD dwFlags = OFN_HIDEREADONLY | OFN_OVERWRITEPROMPT,
410 LPCTSTR lpszFilter = NULL,
411 HWND hWndParent = NULL)
412 : CFileDialogImpl<CFileDialog>(bOpenFileDialog, lpszDefExt, lpszFileName, dwFlags, lpszFilter, hWndParent)
415 // override base class map and references to handlers
416 DECLARE_EMPTY_MSG_MAP()
419 #if defined(__AYGSHELL_H__) && (_WIN32_WCE >= 0x0501)
420 class CFileDialogEx : public CFileDialogImpl<CFileDialogEx>
422 public:
423 CFileDialogEx( // Supports only FileOpen
424 LPCTSTR lpszDefExt = NULL,
425 LPCTSTR lpszFileName = NULL,
426 DWORD dwFlags = OFN_HIDEREADONLY | OFN_OVERWRITEPROMPT,
427 OFN_EXFLAG ExFlags = OFN_EXFLAG_THUMBNAILVIEW,
428 OFN_SORTORDER dwSortOrder = OFN_SORTORDER_AUTO,
429 LPCTSTR lpszFilter = NULL,
430 HWND hWndParent = NULL)
431 : CFileDialogImpl<CFileDialogEx>(TRUE, lpszDefExt, lpszFileName, dwFlags, lpszFilter, hWndParent)
433 m_ofn.ExFlags = ExFlags;
434 m_ofn.dwSortOrder = dwSortOrder;
437 // override base class map and references to handlers
438 DECLARE_EMPTY_MSG_MAP()
440 #endif // defined(__AYGSHELL_H__) && (_WIN32_WCE >= 0x0501)
443 ///////////////////////////////////////////////////////////////////////////////
444 // Multi File Dialog - Multi-select File Open dialog
446 #ifndef _WIN32_WCE
448 // The class dynamically resizes the buffer as the file selection changes
449 // (as described in Knowledge Base article 131462). It also expands selected
450 // shortcut files to take into account the full path of the target file.
451 // Note that this doesn't work on Win9x for the old style dialogs, as well as
452 // on NT for non-Unicode builds.
454 #ifndef _WTL_FIXED_OFN_BUFFER_LENGTH
455 #define _WTL_FIXED_OFN_BUFFER_LENGTH 0x10000
456 #endif
458 template <class T>
459 class ATL_NO_VTABLE CMultiFileDialogImpl : public CFileDialogImpl< T >
461 public:
462 mutable LPCTSTR m_pNextFile;
463 #ifndef _UNICODE
464 bool m_bIsNT;
465 #endif
467 CMultiFileDialogImpl(
468 LPCTSTR lpszDefExt = NULL,
469 LPCTSTR lpszFileName = NULL,
470 DWORD dwFlags = OFN_HIDEREADONLY,
471 LPCTSTR lpszFilter = NULL,
472 HWND hWndParent = NULL)
473 : CFileDialogImpl<T>(TRUE, lpszDefExt, lpszFileName, dwFlags, lpszFilter, hWndParent),
474 m_pNextFile(NULL)
476 m_ofn.Flags |= OFN_ALLOWMULTISELECT; // Force multiple selection mode
478 #ifndef _UNICODE
479 OSVERSIONINFO ovi = { sizeof(ovi) };
480 ::GetVersionEx(&ovi);
481 m_bIsNT = (ovi.dwPlatformId == VER_PLATFORM_WIN32_NT);
482 if (m_bIsNT)
484 // On NT platforms, GetOpenFileNameA thunks to GetOpenFileNameW and there
485 // is absolutely nothing we can do except to start off with a large buffer.
486 ATLVERIFY(ResizeFilenameBuffer(_WTL_FIXED_OFN_BUFFER_LENGTH));
488 #endif
491 ~CMultiFileDialogImpl()
493 if (m_ofn.lpstrFile != m_szFileName) // Free the buffer if we allocated it
494 delete[] m_ofn.lpstrFile;
497 // Operations
498 // Get the directory that the files were chosen from.
499 // The function returns the number of characters copied, not including the terminating zero.
500 // If the buffer is NULL, the function returns the required size, in characters, including the terminating zero.
501 // If the function fails, the return value is zero.
502 int GetDirectory(LPTSTR pBuffer, int nBufLen) const
504 if (m_ofn.lpstrFile == NULL)
505 return 0;
507 LPCTSTR pStr = m_ofn.lpstrFile;
508 int nLength = lstrlen(pStr);
509 if (pStr[nLength + 1] == 0)
511 // The OFN buffer contains a single item so extract its path.
512 LPCTSTR pSep = _strrchr(pStr, _T('\\'));
513 if (pSep != NULL)
514 nLength = (int)(DWORD_PTR)(pSep - pStr);
517 int nRet = 0;
518 if (pBuffer == NULL) // If the buffer is NULL, return the required length
520 nRet = nLength + 1;
522 else if (nBufLen > nLength)
524 SecureHelper::strncpy_x(pBuffer, nBufLen, pStr, nLength);
525 nRet = nLength;
528 return nRet;
531 #if defined(_WTL_USE_CSTRING) || defined(__ATLSTR_H__)
532 bool GetDirectory(_CSTRING_NS::CString& strDir) const
534 bool bRet = false;
536 int nLength = GetDirectory(NULL, 0);
537 if (nLength > 0)
539 bRet = (GetDirectory(strDir.GetBuffer(nLength), nLength) > 0);
540 strDir.ReleaseBuffer(nLength - 1);
543 return bRet;
545 #endif // defined(_WTL_USE_CSTRING) || defined(__ATLSTR_H__)
547 // Get the first filename as a pointer into the buffer.
548 LPCTSTR GetFirstFileName() const
550 if (m_ofn.lpstrFile == NULL)
551 return NULL;
553 m_pNextFile = NULL; // Reset internal buffer pointer
555 LPCTSTR pStr = m_ofn.lpstrFile;
556 int nLength = lstrlen(pStr);
557 if (pStr[nLength + 1] != 0)
559 // Multiple items were selected. The first string is the directory,
560 // so skip forwards to the second string.
561 pStr += nLength + 1;
563 // Set up m_pNext so it points to the second item (or null).
564 m_pNextFile = pStr;
565 GetNextFileName();
567 else
569 // A single item was selected. Skip forward past the path.
570 LPCTSTR pSep = _strrchr(pStr, _T('\\'));
571 if (pSep != NULL)
572 pStr = pSep + 1;
575 return pStr;
578 // Get the next filename as a pointer into the buffer.
579 LPCTSTR GetNextFileName() const
581 if (m_pNextFile == NULL)
582 return NULL;
584 LPCTSTR pStr = m_pNextFile;
585 // Set "m_pNextFile" to point to the next file name, or null if we
586 // have reached the last file in the list.
587 int nLength = lstrlen(pStr);
588 m_pNextFile = (pStr[nLength + 1] != 0) ? &pStr[nLength + 1] : NULL;
590 return pStr;
593 // Get the first filename as a full path.
594 // The function returns the number of characters copied, not including the terminating zero.
595 // If the buffer is NULL, the function returns the required size, in characters, including the terminating zero.
596 // If the function fails, the return value is zero.
597 int GetFirstPathName(LPTSTR pBuffer, int nBufLen) const
599 LPCTSTR pStr = GetFirstFileName();
600 int nLengthDir = GetDirectory(NULL, 0);
601 if((pStr == NULL) || (nLengthDir == 0))
602 return 0;
604 // Figure out the required length.
605 int nLengthTotal = nLengthDir + lstrlen(pStr);
607 int nRet = 0;
608 if(pBuffer == NULL) // If the buffer is NULL, return the required length
610 nRet = nLengthTotal + 1;
612 else if (nBufLen > nLengthTotal) // If the buffer is big enough, go ahead and construct the path
614 GetDirectory(pBuffer, nBufLen);
615 SecureHelper::strcat_x(pBuffer, nBufLen, _T("\\"));
616 SecureHelper::strcat_x(pBuffer, nBufLen, pStr);
617 nRet = nLengthTotal;
620 return nRet;
623 #if defined(_WTL_USE_CSTRING) || defined(__ATLSTR_H__)
624 bool GetFirstPathName(_CSTRING_NS::CString& strPath) const
626 bool bRet = false;
628 int nLength = GetFirstPathName(NULL, 0);
629 if (nLength > 0)
631 bRet = (GetFirstPathName(strPath.GetBuffer(nLength), nLength) > 0);
632 strPath.ReleaseBuffer(nLength - 1);
635 return bRet;
637 #endif // defined(_WTL_USE_CSTRING) || defined(__ATLSTR_H__)
639 // Get the next filename as a full path.
640 // The function returns the number of characters copied, not including the terminating zero.
641 // If the buffer is NULL, the function returns the required size, in characters, including the terminating zero.
642 // If the function fails, the return value is zero.
643 // The internal position marker is moved forward only if the function succeeds and the buffer was large enough.
644 int GetNextPathName(LPTSTR pBuffer, int nBufLen) const
646 if (m_pNextFile == NULL)
647 return 0;
649 int nRet = 0;
650 LPCTSTR pStr = m_pNextFile;
651 // Does the filename contain a backslash?
652 if (_strrchr(pStr, _T('\\')) != NULL)
654 // Yes, so we'll assume it's a full path.
655 int nLength = lstrlen(pStr);
657 if (pBuffer == NULL) // If the buffer is NULL, return the required length
659 nRet = nLength + 1;
661 else if (nBufLen > nLength) // The buffer is big enough, so go ahead and copy the filename
663 SecureHelper::strcpy_x(pBuffer, nBufLen, GetNextFileName());
664 nRet = nBufLen;
667 else
669 // The filename is relative, so construct the full path.
670 int nLengthDir = GetDirectory(NULL, 0);
671 if (nLengthDir > 0)
673 // Calculate the required space.
674 int nLengthTotal = nLengthDir + lstrlen(pStr);
676 if(pBuffer == NULL) // If the buffer is NULL, return the required length
678 nRet = nLengthTotal + 1;
680 else if (nBufLen > nLengthTotal) // If the buffer is big enough, go ahead and construct the path
682 GetDirectory(pBuffer, nBufLen);
683 SecureHelper::strcat_x(pBuffer, nBufLen, _T("\\"));
684 SecureHelper::strcat_x(pBuffer, nBufLen, GetNextFileName());
685 nRet = nLengthTotal;
690 return nRet;
693 #if defined(_WTL_USE_CSTRING) || defined(__ATLSTR_H__)
694 bool GetNextPathName(_CSTRING_NS::CString& strPath) const
696 bool bRet = false;
698 int nLength = GetNextPathName(NULL, 0);
699 if (nLength > 0)
701 bRet = (GetNextPathName(strPath.GetBuffer(nLength), nLength) > 0);
702 strPath.ReleaseBuffer(nLength - 1);
705 return bRet;
707 #endif // defined(_WTL_USE_CSTRING) || defined(__ATLSTR_H__)
709 // Implementation
710 bool ResizeFilenameBuffer(DWORD dwLength)
712 if (dwLength > m_ofn.nMaxFile)
714 // Free the old buffer.
715 if (m_ofn.lpstrFile != m_szFileName)
717 delete[] m_ofn.lpstrFile;
718 m_ofn.lpstrFile = NULL;
719 m_ofn.nMaxFile = 0;
722 // Allocate the new buffer.
723 LPTSTR lpstrBuff = NULL;
724 ATLTRY(lpstrBuff = new TCHAR[dwLength]);
725 if (lpstrBuff != NULL)
727 m_ofn.lpstrFile = lpstrBuff;
728 m_ofn.lpstrFile[0] = 0;
729 m_ofn.nMaxFile = dwLength;
733 return (m_ofn.lpstrFile != NULL);
736 void OnSelChange(LPOFNOTIFY /*lpon*/)
738 #ifndef _UNICODE
739 // There is no point resizing the buffer in ANSI builds running on NT.
740 if (m_bIsNT)
741 return;
742 #endif
744 // Get the buffer length required to hold the spec.
745 int nLength = GetSpec(NULL, 0);
746 if (nLength <= 1)
747 return; // no files are selected, presumably
749 // Add room for the directory, and an extra terminating zero.
750 nLength += GetFolderPath(NULL, 0) + 1;
752 if (!ResizeFilenameBuffer(nLength))
754 ATLASSERT(FALSE);
755 return;
758 // If we are not following links then our work is done.
759 if ((m_ofn.Flags & OFN_NODEREFERENCELINKS) != 0)
760 return;
762 // Get the file spec, which is the text in the edit control.
763 if (GetSpec(m_ofn.lpstrFile, m_ofn.nMaxFile) <= 0)
764 return;
766 // Get the ID-list of the current folder.
767 int nBytes = GetFolderIDList(NULL, 0);
768 CTempBuffer<ITEMIDLIST> idlist;
769 idlist.AllocateBytes(nBytes);
770 if ((nBytes <= 0) || (GetFolderIDList(idlist, nBytes) <= 0))
771 return;
773 // First bind to the desktop folder, then to the current folder.
774 ATL::CComPtr<IShellFolder> pDesktop, pFolder;
775 if (FAILED(::SHGetDesktopFolder(&pDesktop)))
776 return;
777 if (FAILED(pDesktop->BindToObject(idlist, NULL, IID_IShellFolder, (void**)&pFolder)))
778 return;
780 // Work through the file spec, looking for quoted filenames. If we find a shortcut file, then
781 // we need to add enough extra buffer space to hold its target path.
782 DWORD nExtraChars = 0;
783 bool bInsideQuotes = false;
784 LPCTSTR pAnchor = m_ofn.lpstrFile;
785 LPCTSTR pChar = m_ofn.lpstrFile;
786 for ( ; *pChar; ++pChar)
788 // Look for quotation marks.
789 if (*pChar == _T('\"'))
791 // We are either entering or leaving a passage of quoted text.
792 bInsideQuotes = !bInsideQuotes;
794 // Is it an opening or closing quote?
795 if (bInsideQuotes)
797 // We found an opening quote, so set "pAnchor" to the following character.
798 pAnchor = pChar + 1;
800 else // closing quote
802 // Each quoted entity should be shorter than MAX_PATH.
803 if (pChar - pAnchor >= MAX_PATH)
804 return;
806 // Get the ID-list and attributes of the file.
807 USES_CONVERSION;
808 int nFileNameLength = (int)(DWORD_PTR)(pChar - pAnchor);
809 TCHAR szFileName[MAX_PATH];
810 SecureHelper::strncpy_x(szFileName, MAX_PATH, pAnchor, nFileNameLength);
811 LPITEMIDLIST pidl = NULL;
812 DWORD dwAttrib = SFGAO_LINK;
813 if (SUCCEEDED(pFolder->ParseDisplayName(NULL, NULL, T2W(szFileName), NULL, &pidl, &dwAttrib)))
815 // Is it a shortcut file?
816 if (dwAttrib & SFGAO_LINK)
818 // Bind to its IShellLink interface.
819 ATL::CComPtr<IShellLink> pLink;
820 if (SUCCEEDED(pFolder->BindToObject(pidl, NULL, IID_IShellLink, (void**)&pLink)))
822 // Get the shortcut's target path.
823 TCHAR szPath[MAX_PATH];
824 if (SUCCEEDED(pLink->GetPath(szPath, MAX_PATH, NULL, 0)))
826 // If the target path is longer than the shortcut name, then add on the number
827 // of extra characters that are required.
828 int nNewLength = lstrlen(szPath);
829 if (nNewLength > nFileNameLength)
830 nExtraChars += nNewLength - nFileNameLength;
835 // Free the ID-list returned by ParseDisplayName.
836 ::CoTaskMemFree(pidl);
842 // If we need more space for shortcut targets, then reallocate.
843 if (nExtraChars > 0)
844 ATLVERIFY(ResizeFilenameBuffer(m_ofn.nMaxFile + nExtraChars));
847 // Helper for _ATM_MIN_CRT
848 static const TCHAR* _strrchr(const TCHAR* p, TCHAR ch)
850 #ifndef _ATL_MIN_CRT
851 return _tcsrchr(p, ch);
852 #else // _ATL_MIN_CRT
853 const TCHAR* lpsz = NULL;
854 while (*p != 0)
856 if (*p == ch)
857 lpsz = p;
858 p = ::CharNext(p);
860 return lpsz;
861 #endif // _ATL_MIN_CRT
865 class CMultiFileDialog : public CMultiFileDialogImpl<CMultiFileDialog>
867 public:
868 CMultiFileDialog(
869 LPCTSTR lpszDefExt = NULL,
870 LPCTSTR lpszFileName = NULL,
871 DWORD dwFlags = OFN_HIDEREADONLY,
872 LPCTSTR lpszFilter = NULL,
873 HWND hWndParent = NULL)
874 : CMultiFileDialogImpl<CMultiFileDialog>(lpszDefExt, lpszFileName, dwFlags, lpszFilter, hWndParent)
877 BEGIN_MSG_MAP(CMultiFileDialog)
878 CHAIN_MSG_MAP(CMultiFileDialogImpl<CMultiFileDialog>)
879 END_MSG_MAP()
882 #endif // !_WIN32_WCE
885 ///////////////////////////////////////////////////////////////////////////////
886 // Shell File Dialog - new Shell File Open and Save dialogs in Vista
888 // Note: Use GetPtr() to access dialog interface methods.
889 // Example:
890 // CShellFileOpenDialog dlg;
891 // dlg.GetPtr()->SetTitle(L"MyFileOpenDialog");
893 #if (_WIN32_WINNT >= 0x0600) && !defined(_WIN32_WCE)
895 ///////////////////////////////////////////////////////////////////////////////
896 // CShellFileDialogImpl - base class for CShellFileOpenDialogImpl and CShellFileSaveDialogImpl
898 template <class T>
899 class ATL_NO_VTABLE CShellFileDialogImpl : public IFileDialogEvents
901 public:
902 // Operations
903 INT_PTR DoModal(HWND hWndParent = ::GetActiveWindow())
905 INT_PTR nRet = -1;
907 T* pT = static_cast<T*>(this);
908 if(pT->m_spFileDlg == NULL)
910 ATLASSERT(FALSE);
911 return nRet;
914 DWORD dwCookie = 0;
915 pT->_Advise(dwCookie);
917 HRESULT hRet = pT->m_spFileDlg->Show(hWndParent);
918 if(SUCCEEDED(hRet))
919 nRet = IDOK;
920 else if(hRet == HRESULT_FROM_WIN32(ERROR_CANCELLED))
921 nRet = IDCANCEL;
922 else
923 ATLASSERT(FALSE); // error
925 pT->_Unadvise(dwCookie);
927 return nRet;
930 bool IsNull() const
932 const T* pT = static_cast<const T*>(this);
933 return (pT->m_spFileDlg == NULL);
936 // Operations - get file path after dialog returns
937 HRESULT GetFilePath(LPWSTR lpstrFilePath, int cchLength)
939 T* pT = static_cast<T*>(this);
940 ATLASSERT(pT->m_spFileDlg != NULL);
942 ATL::CComPtr<IShellItem> spItem;
943 HRESULT hRet = pT->m_spFileDlg->GetResult(&spItem);
945 if(SUCCEEDED(hRet))
946 hRet = GetFileNameFromShellItem(spItem, SIGDN_FILESYSPATH, lpstrFilePath, cchLength);
948 return hRet;
951 HRESULT GetFileTitle(LPWSTR lpstrFileTitle, int cchLength)
953 T* pT = static_cast<T*>(this);
954 ATLASSERT(pT->m_spFileDlg != NULL);
956 ATL::CComPtr<IShellItem> spItem;
957 HRESULT hRet = pT->m_spFileDlg->GetResult(&spItem);
959 if(SUCCEEDED(hRet))
960 hRet = GetFileNameFromShellItem(spItem, SIGDN_NORMALDISPLAY, lpstrFileTitle, cchLength);
962 return hRet;
965 #if defined(_WTL_USE_CSTRING) || defined(__ATLSTR_H__)
966 HRESULT GetFilePath(_CSTRING_NS::CString& strFilePath)
968 T* pT = static_cast<T*>(this);
969 ATLASSERT(pT->m_spFileDlg != NULL);
971 ATL::CComPtr<IShellItem> spItem;
972 HRESULT hRet = pT->m_spFileDlg->GetResult(&spItem);
974 if(SUCCEEDED(hRet))
975 hRet = GetFileNameFromShellItem(spItem, SIGDN_FILESYSPATH, strFilePath);
977 return hRet;
980 HRESULT GetFileTitle(_CSTRING_NS::CString& strFileTitle)
982 T* pT = static_cast<T*>(this);
983 ATLASSERT(pT->m_spFileDlg != NULL);
985 ATL::CComPtr<IShellItem> spItem;
986 HRESULT hRet = pT->m_spFileDlg->GetResult(&spItem);
988 if(SUCCEEDED(hRet))
989 hRet = GetFileNameFromShellItem(spItem, SIGDN_NORMALDISPLAY, strFileTitle);
991 return hRet;
993 #endif // defined(_WTL_USE_CSTRING) || defined(__ATLSTR_H__)
995 // Helpers for IShellItem
996 static HRESULT GetFileNameFromShellItem(IShellItem* pShellItem, SIGDN type, LPWSTR lpstr, int cchLength)
998 ATLASSERT(pShellItem != NULL);
1000 LPWSTR lpstrName = NULL;
1001 HRESULT hRet = pShellItem->GetDisplayName(type, &lpstrName);
1003 if(SUCCEEDED(hRet))
1005 if(lstrlenW(lpstrName) < cchLength)
1007 SecureHelper::strcpyW_x(lpstr, cchLength, lpstrName);
1009 else
1011 ATLASSERT(FALSE);
1012 hRet = DISP_E_BUFFERTOOSMALL;
1015 ::CoTaskMemFree(lpstrName);
1018 return hRet;
1021 #if defined(_WTL_USE_CSTRING) || defined(__ATLSTR_H__)
1022 static HRESULT GetFileNameFromShellItem(IShellItem* pShellItem, SIGDN type, _CSTRING_NS::CString& str)
1024 ATLASSERT(pShellItem != NULL);
1026 LPWSTR lpstrName = NULL;
1027 HRESULT hRet = pShellItem->GetDisplayName(type, &lpstrName);
1029 if(SUCCEEDED(hRet))
1031 str = lpstrName;
1032 ::CoTaskMemFree(lpstrName);
1035 return hRet;
1037 #endif // defined(_WTL_USE_CSTRING) || defined(__ATLSTR_H__)
1039 // Implementation
1040 void _Advise(DWORD& dwCookie)
1042 T* pT = static_cast<T*>(this);
1043 ATLASSERT(pT->m_spFileDlg != NULL);
1044 HRESULT hRet = pT->m_spFileDlg->Advise((IFileDialogEvents*)this, &dwCookie);
1045 ATLVERIFY(SUCCEEDED(hRet));
1048 void _Unadvise(DWORD dwCookie)
1050 T* pT = static_cast<T*>(this);
1051 ATLASSERT(pT->m_spFileDlg != NULL);
1052 HRESULT hRet = pT->m_spFileDlg->Unadvise(dwCookie);
1053 ATLVERIFY(SUCCEEDED(hRet));
1056 void _Init(LPCWSTR lpszFileName, DWORD dwOptions, LPCWSTR lpszDefExt, const COMDLG_FILTERSPEC* arrFilterSpec, UINT uFilterSpecCount)
1058 T* pT = static_cast<T*>(this);
1059 ATLASSERT(pT->m_spFileDlg != NULL);
1061 HRESULT hRet = E_FAIL;
1063 if(lpszFileName != NULL)
1065 hRet = pT->m_spFileDlg->SetFileName(lpszFileName);
1066 ATLASSERT(SUCCEEDED(hRet));
1069 hRet = pT->m_spFileDlg->SetOptions(dwOptions);
1070 ATLASSERT(SUCCEEDED(hRet));
1072 if(lpszDefExt != NULL)
1074 hRet = pT->m_spFileDlg->SetDefaultExtension(lpszDefExt);
1075 ATLASSERT(SUCCEEDED(hRet));
1078 if(arrFilterSpec != NULL && uFilterSpecCount != 0U)
1080 hRet = pT->m_spFileDlg->SetFileTypes(uFilterSpecCount, arrFilterSpec);
1081 ATLASSERT(SUCCEEDED(hRet));
1085 // Implementation - IUnknown interface
1086 STDMETHOD(QueryInterface)(REFIID riid, void** ppvObject)
1088 if(ppvObject == NULL)
1089 return E_POINTER;
1091 T* pT = static_cast<T*>(this);
1092 if(IsEqualGUID(riid, IID_IUnknown) || IsEqualGUID(riid, IID_IFileDialogEvents))
1094 *ppvObject = (IFileDialogEvents*)pT;
1095 // AddRef() not needed
1096 return S_OK;
1099 return E_NOINTERFACE;
1102 virtual ULONG STDMETHODCALLTYPE AddRef()
1104 return 1;
1107 virtual ULONG STDMETHODCALLTYPE Release()
1109 return 1;
1112 // Implementation - IFileDialogEvents interface
1113 virtual HRESULT STDMETHODCALLTYPE IFileDialogEvents::OnFileOk(IFileDialog* pfd)
1115 T* pT = static_cast<T*>(this);
1116 ATLASSERT(pT->m_spFileDlg.IsEqualObject(pfd));
1117 pfd; // avoid level 4 warning
1118 return pT->OnFileOk();
1121 virtual HRESULT STDMETHODCALLTYPE IFileDialogEvents::OnFolderChanging(IFileDialog* pfd, IShellItem* psiFolder)
1123 T* pT = static_cast<T*>(this);
1124 ATLASSERT(pT->m_spFileDlg.IsEqualObject(pfd));
1125 pfd; // avoid level 4 warning
1126 return pT->OnFolderChanging(psiFolder);
1129 virtual HRESULT STDMETHODCALLTYPE IFileDialogEvents::OnFolderChange(IFileDialog* pfd)
1131 T* pT = static_cast<T*>(this);
1132 ATLASSERT(pT->m_spFileDlg.IsEqualObject(pfd));
1133 pfd; // avoid level 4 warning
1134 return pT->OnFolderChange();
1137 virtual HRESULT STDMETHODCALLTYPE IFileDialogEvents::OnSelectionChange(IFileDialog* pfd)
1139 T* pT = static_cast<T*>(this);
1140 ATLASSERT(pT->m_spFileDlg.IsEqualObject(pfd));
1141 pfd; // avoid level 4 warning
1142 return pT->OnSelectionChange();
1145 virtual HRESULT STDMETHODCALLTYPE IFileDialogEvents::OnShareViolation(IFileDialog* pfd, IShellItem* psi, FDE_SHAREVIOLATION_RESPONSE* pResponse)
1147 T* pT = static_cast<T*>(this);
1148 ATLASSERT(pT->m_spFileDlg.IsEqualObject(pfd));
1149 pfd; // avoid level 4 warning
1150 return pT->OnShareViolation(psi, pResponse);
1153 virtual HRESULT STDMETHODCALLTYPE IFileDialogEvents::OnTypeChange(IFileDialog* pfd)
1155 T* pT = static_cast<T*>(this);
1156 ATLASSERT(pT->m_spFileDlg.IsEqualObject(pfd));
1157 pfd; // avoid level 4 warning
1158 return pT->OnTypeChange();
1161 virtual HRESULT STDMETHODCALLTYPE IFileDialogEvents::OnOverwrite(IFileDialog* pfd, IShellItem* psi, FDE_OVERWRITE_RESPONSE* pResponse)
1163 T* pT = static_cast<T*>(this);
1164 ATLASSERT(pT->m_spFileDlg.IsEqualObject(pfd));
1165 pfd; // avoid level 4 warning
1166 return pT->OnOverwrite(psi, pResponse);
1169 // Overrideables - Event handlers
1170 HRESULT OnFileOk()
1172 return E_NOTIMPL;
1175 HRESULT OnFolderChanging(IShellItem* /*psiFolder*/)
1177 return E_NOTIMPL;
1180 HRESULT OnFolderChange()
1182 return E_NOTIMPL;
1185 HRESULT OnSelectionChange()
1187 return E_NOTIMPL;
1190 HRESULT OnShareViolation(IShellItem* /*psi*/, FDE_SHAREVIOLATION_RESPONSE* /*pResponse*/)
1192 return E_NOTIMPL;
1195 HRESULT OnTypeChange()
1197 return E_NOTIMPL;
1200 HRESULT OnOverwrite(IShellItem* /*psi*/, FDE_OVERWRITE_RESPONSE* /*pResponse*/)
1202 return E_NOTIMPL;
1207 ///////////////////////////////////////////////////////////////////////////////
1208 // CShellFileOpenDialogImpl - implements new Shell File Open dialog
1210 template <class T>
1211 class ATL_NO_VTABLE CShellFileOpenDialogImpl : public CShellFileDialogImpl< T >
1213 public:
1214 ATL::CComPtr<IFileOpenDialog> m_spFileDlg;
1216 CShellFileOpenDialogImpl(LPCWSTR lpszFileName = NULL,
1217 DWORD dwOptions = FOS_FORCEFILESYSTEM | FOS_PATHMUSTEXIST | FOS_FILEMUSTEXIST,
1218 LPCWSTR lpszDefExt = NULL,
1219 const COMDLG_FILTERSPEC* arrFilterSpec = NULL,
1220 UINT uFilterSpecCount = 0U)
1222 HRESULT hRet = m_spFileDlg.CoCreateInstance(CLSID_FileOpenDialog);
1224 if(SUCCEEDED(hRet))
1225 _Init(lpszFileName, dwOptions, lpszDefExt, arrFilterSpec, uFilterSpecCount);
1228 IFileOpenDialog* GetPtr()
1230 return m_spFileDlg;
1235 ///////////////////////////////////////////////////////////////////////////////
1236 // CShellFileOpenDialog - new Shell File Open dialog without events
1238 class CShellFileOpenDialog : public CShellFileOpenDialogImpl<CShellFileOpenDialog>
1240 public:
1241 CShellFileOpenDialog(LPCWSTR lpszFileName = NULL,
1242 DWORD dwOptions = FOS_FORCEFILESYSTEM | FOS_PATHMUSTEXIST | FOS_FILEMUSTEXIST,
1243 LPCWSTR lpszDefExt = NULL,
1244 const COMDLG_FILTERSPEC* arrFilterSpec = NULL,
1245 UINT uFilterSpecCount = 0U) : CShellFileOpenDialogImpl<CShellFileOpenDialog>(lpszFileName, dwOptions, lpszDefExt, arrFilterSpec, uFilterSpecCount)
1248 // Implementation (remove _Advise/_Unadvise code using template magic)
1249 void _Advise(DWORD& /*dwCookie*/)
1252 void _Unadvise(DWORD /*dwCookie*/)
1257 ///////////////////////////////////////////////////////////////////////////////
1258 // CShellFileSaveDialogImpl - implements new Shell File Save dialog
1260 template <class T>
1261 class ATL_NO_VTABLE CShellFileSaveDialogImpl : public CShellFileDialogImpl< T >
1263 public:
1264 ATL::CComPtr<IFileSaveDialog> m_spFileDlg;
1266 CShellFileSaveDialogImpl(LPCWSTR lpszFileName = NULL,
1267 DWORD dwOptions = FOS_FORCEFILESYSTEM | FOS_PATHMUSTEXIST | FOS_OVERWRITEPROMPT,
1268 LPCWSTR lpszDefExt = NULL,
1269 const COMDLG_FILTERSPEC* arrFilterSpec = NULL,
1270 UINT uFilterSpecCount = 0U)
1272 HRESULT hRet = m_spFileDlg.CoCreateInstance(CLSID_FileSaveDialog);
1274 if(SUCCEEDED(hRet))
1275 _Init(lpszFileName, dwOptions, lpszDefExt, arrFilterSpec, uFilterSpecCount);
1278 IFileSaveDialog* GetPtr()
1280 return m_spFileDlg;
1285 ///////////////////////////////////////////////////////////////////////////////
1286 // CShellFileSaveDialog - new Shell File Save dialog without events
1288 class CShellFileSaveDialog : public CShellFileSaveDialogImpl<CShellFileSaveDialog>
1290 public:
1291 CShellFileSaveDialog(LPCWSTR lpszFileName = NULL,
1292 DWORD dwOptions = FOS_FORCEFILESYSTEM | FOS_PATHMUSTEXIST | FOS_OVERWRITEPROMPT,
1293 LPCWSTR lpszDefExt = NULL,
1294 const COMDLG_FILTERSPEC* arrFilterSpec = NULL,
1295 UINT uFilterSpecCount = 0U) : CShellFileSaveDialogImpl<CShellFileSaveDialog>(lpszFileName, dwOptions, lpszDefExt, arrFilterSpec, uFilterSpecCount)
1298 // Implementation (remove _Advise/_Unadvise code using template magic)
1299 void _Advise(DWORD& /*dwCookie*/)
1302 void _Unadvise(DWORD /*dwCookie*/)
1306 #endif // (_WIN32_WINNT >= 0x0600) && !defined(_WIN32_WCE)
1309 ///////////////////////////////////////////////////////////////////////////////
1310 // CFolderDialogImpl - used for browsing for a folder
1312 #ifndef _WIN32_WCE
1314 template <class T>
1315 class ATL_NO_VTABLE CFolderDialogImpl
1317 public:
1318 BROWSEINFO m_bi;
1319 LPCTSTR m_lpstrInitialFolder;
1320 LPCITEMIDLIST m_pidlInitialSelection;
1321 bool m_bExpandInitialSelection;
1322 TCHAR m_szFolderDisplayName[MAX_PATH];
1323 TCHAR m_szFolderPath[MAX_PATH];
1324 LPITEMIDLIST m_pidlSelected;
1325 HWND m_hWnd; // used only in the callback function
1327 // Constructor
1328 CFolderDialogImpl(HWND hWndParent = NULL, LPCTSTR lpstrTitle = NULL, UINT uFlags = BIF_RETURNONLYFSDIRS) :
1329 m_lpstrInitialFolder(NULL), m_pidlInitialSelection(NULL), m_bExpandInitialSelection(false), m_pidlSelected(NULL), m_hWnd(NULL)
1331 memset(&m_bi, 0, sizeof(m_bi)); // initialize structure to 0/NULL
1333 m_bi.hwndOwner = hWndParent;
1334 m_bi.pidlRoot = NULL;
1335 m_bi.pszDisplayName = m_szFolderDisplayName;
1336 m_bi.lpszTitle = lpstrTitle;
1337 m_bi.ulFlags = uFlags;
1338 m_bi.lpfn = BrowseCallbackProc;
1339 m_bi.lParam = (LPARAM)static_cast<T*>(this);
1341 m_szFolderPath[0] = 0;
1342 m_szFolderDisplayName[0] = 0;
1345 ~CFolderDialogImpl()
1347 ::CoTaskMemFree(m_pidlSelected);
1350 // Operations
1351 INT_PTR DoModal(HWND hWndParent = ::GetActiveWindow())
1353 if(m_bi.hwndOwner == NULL) // set only if not specified before
1354 m_bi.hwndOwner = hWndParent;
1356 // Clear out any previous results
1357 m_szFolderPath[0] = 0;
1358 m_szFolderDisplayName[0] = 0;
1359 ::CoTaskMemFree(m_pidlSelected);
1361 INT_PTR nRet = IDCANCEL;
1362 m_pidlSelected = ::SHBrowseForFolder(&m_bi);
1364 if(m_pidlSelected != NULL)
1366 nRet = IDOK;
1368 // If BIF_RETURNONLYFSDIRS is set, we try to get the filesystem path.
1369 // Otherwise, the caller must handle the ID-list directly.
1370 if((m_bi.ulFlags & BIF_RETURNONLYFSDIRS) != 0)
1372 if(::SHGetPathFromIDList(m_pidlSelected, m_szFolderPath) == FALSE)
1373 nRet = IDCANCEL;
1377 return nRet;
1380 // Methods to call before DoModal
1381 void SetInitialFolder(LPCTSTR lpstrInitialFolder, bool bExpand = true)
1383 // lpstrInitialFolder may be a file if BIF_BROWSEINCLUDEFILES is specified
1384 m_lpstrInitialFolder = lpstrInitialFolder;
1385 m_bExpandInitialSelection = bExpand;
1388 void SetInitialSelection(LPCITEMIDLIST pidl, bool bExpand = true)
1390 m_pidlInitialSelection = pidl;
1391 m_bExpandInitialSelection = bExpand;
1394 // Methods to call after DoModal
1395 LPITEMIDLIST GetSelectedItem(bool bDetach = false)
1397 LPITEMIDLIST pidl = m_pidlSelected;
1398 if(bDetach)
1399 m_pidlSelected = NULL;
1401 return pidl;
1404 LPCTSTR GetFolderPath() const
1406 return m_szFolderPath;
1409 LPCTSTR GetFolderDisplayName() const
1411 return m_szFolderDisplayName;
1414 int GetFolderImageIndex() const
1416 return m_bi.iImage;
1419 // Callback function and overrideables
1420 static int CALLBACK BrowseCallbackProc(HWND hWnd, UINT uMsg, LPARAM lParam, LPARAM lpData)
1422 #ifndef BFFM_VALIDATEFAILED
1423 #ifdef UNICODE
1424 const int BFFM_VALIDATEFAILED = 4;
1425 #else
1426 const int BFFM_VALIDATEFAILED = 3;
1427 #endif
1428 #endif // !BFFM_VALIDATEFAILED
1429 #ifndef BFFM_IUNKNOWN
1430 const int BFFM_IUNKNOWN = 5;
1431 #endif // !BFFM_IUNKNOWN
1432 #ifndef BIF_NEWDIALOGSTYLE
1433 const UINT BIF_NEWDIALOGSTYLE = 0x0040;
1434 #endif // !BIF_NEWDIALOGSTYLE
1436 int nRet = 0;
1437 T* pT = (T*)lpData;
1438 bool bClear = false;
1439 if(pT->m_hWnd == NULL)
1441 pT->m_hWnd = hWnd;
1442 bClear = true;
1444 else
1446 ATLASSERT(pT->m_hWnd == hWnd);
1449 switch(uMsg)
1451 case BFFM_INITIALIZED:
1452 // Set initial selection
1453 // Note that m_pidlInitialSelection, if set, takes precedence over m_lpstrInitialFolder
1454 if(pT->m_pidlInitialSelection != NULL)
1455 pT->SetSelection(pT->m_pidlInitialSelection);
1456 else if(pT->m_lpstrInitialFolder != NULL)
1457 pT->SetSelection(pT->m_lpstrInitialFolder);
1459 // Expand initial selection if appropriate
1460 if(pT->m_bExpandInitialSelection && ((pT->m_bi.ulFlags & BIF_NEWDIALOGSTYLE) != 0))
1462 if(pT->m_pidlInitialSelection != NULL)
1463 pT->SetExpanded(pT->m_pidlInitialSelection);
1464 else if(pT->m_lpstrInitialFolder != NULL)
1465 pT->SetExpanded(pT->m_lpstrInitialFolder);
1467 pT->OnInitialized();
1468 break;
1469 case BFFM_SELCHANGED:
1470 pT->OnSelChanged((LPITEMIDLIST)lParam);
1471 break;
1472 case BFFM_VALIDATEFAILED:
1473 nRet = pT->OnValidateFailed((LPCTSTR)lParam);
1474 break;
1475 case BFFM_IUNKNOWN:
1476 pT->OnIUnknown((IUnknown*)lParam);
1477 break;
1478 default:
1479 ATLTRACE2(atlTraceUI, 0, _T("Unknown message received in CFolderDialogImpl::BrowseCallbackProc\n"));
1480 break;
1483 if(bClear)
1484 pT->m_hWnd = NULL;
1485 return nRet;
1488 void OnInitialized()
1492 void OnSelChanged(LPITEMIDLIST /*pItemIDList*/)
1496 int OnValidateFailed(LPCTSTR /*lpstrFolderPath*/)
1498 return 1; // 1=continue, 0=EndDialog
1501 void OnIUnknown(IUnknown* /*pUnknown*/)
1505 // Commands - valid to call only from handlers
1506 void EnableOK(BOOL bEnable)
1508 ATLASSERT(m_hWnd != NULL);
1509 ::SendMessage(m_hWnd, BFFM_ENABLEOK, 0, bEnable);
1512 void SetSelection(LPCITEMIDLIST pItemIDList)
1514 ATLASSERT(m_hWnd != NULL);
1515 ::SendMessage(m_hWnd, BFFM_SETSELECTION, FALSE, (LPARAM)pItemIDList);
1518 void SetSelection(LPCTSTR lpstrFolderPath)
1520 ATLASSERT(m_hWnd != NULL);
1521 ::SendMessage(m_hWnd, BFFM_SETSELECTION, TRUE, (LPARAM)lpstrFolderPath);
1524 void SetStatusText(LPCTSTR lpstrText)
1526 ATLASSERT(m_hWnd != NULL);
1527 ::SendMessage(m_hWnd, BFFM_SETSTATUSTEXT, 0, (LPARAM)lpstrText);
1530 void SetOKText(LPCTSTR lpstrOKText)
1532 #ifndef BFFM_SETOKTEXT
1533 const UINT BFFM_SETOKTEXT = WM_USER + 105;
1534 #endif
1535 ATLASSERT(m_hWnd != NULL);
1536 USES_CONVERSION;
1537 LPCWSTR lpstr = T2CW(lpstrOKText);
1538 ::SendMessage(m_hWnd, BFFM_SETOKTEXT, (WPARAM)lpstr, 0L);
1541 void SetExpanded(LPCITEMIDLIST pItemIDList)
1543 #ifndef BFFM_SETEXPANDED
1544 const UINT BFFM_SETEXPANDED = WM_USER + 106;
1545 #endif
1546 ATLASSERT(m_hWnd != NULL);
1547 ::SendMessage(m_hWnd, BFFM_SETEXPANDED, FALSE, (LPARAM)pItemIDList);
1550 void SetExpanded(LPCTSTR lpstrFolderPath)
1552 #ifndef BFFM_SETEXPANDED
1553 const UINT BFFM_SETEXPANDED = WM_USER + 106;
1554 #endif
1555 ATLASSERT(m_hWnd != NULL);
1556 USES_CONVERSION;
1557 LPCWSTR lpstr = T2CW(lpstrFolderPath);
1558 ::SendMessage(m_hWnd, BFFM_SETEXPANDED, TRUE, (LPARAM)lpstr);
1562 class CFolderDialog : public CFolderDialogImpl<CFolderDialog>
1564 public:
1565 CFolderDialog(HWND hWndParent = NULL, LPCTSTR lpstrTitle = NULL, UINT uFlags = BIF_RETURNONLYFSDIRS)
1566 : CFolderDialogImpl<CFolderDialog>(hWndParent, lpstrTitle, uFlags)
1570 #endif // !_WIN32_WCE
1573 ///////////////////////////////////////////////////////////////////////////////
1574 // CCommonDialogImplBase - base class for common dialog classes
1576 class ATL_NO_VTABLE CCommonDialogImplBase : public ATL::CWindowImplBase
1578 public:
1579 static UINT_PTR APIENTRY HookProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
1581 if(uMsg != WM_INITDIALOG)
1582 return 0;
1583 CCommonDialogImplBase* pT = (CCommonDialogImplBase*)ModuleHelper::ExtractCreateWndData();
1584 ATLASSERT(pT != NULL);
1585 ATLASSERT(pT->m_hWnd == NULL);
1586 ATLASSERT(::IsWindow(hWnd));
1587 // subclass dialog's window
1588 if(!pT->SubclassWindow(hWnd))
1590 ATLTRACE2(atlTraceUI, 0, _T("Subclassing a common dialog failed\n"));
1591 return 0;
1593 // check message map for WM_INITDIALOG handler
1594 LRESULT lRes = 0;
1595 if(pT->ProcessWindowMessage(pT->m_hWnd, uMsg, wParam, lParam, lRes, 0) == FALSE)
1596 return 0;
1597 return lRes;
1600 // Special override for common dialogs
1601 BOOL EndDialog(INT_PTR /*nRetCode*/ = 0)
1603 ATLASSERT(::IsWindow(m_hWnd));
1604 SendMessage(WM_COMMAND, MAKEWPARAM(IDABORT, 0));
1605 return TRUE;
1608 // Implementation - try to override these, to prevent errors
1609 HWND Create(HWND, ATL::_U_RECT, LPCTSTR, DWORD, DWORD, ATL::_U_MENUorID, ATOM, LPVOID)
1611 ATLASSERT(FALSE); // should not be called
1612 return NULL;
1615 static LRESULT CALLBACK StartWindowProc(HWND /*hWnd*/, UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/)
1617 ATLASSERT(FALSE); // should not be called
1618 return 0;
1623 ///////////////////////////////////////////////////////////////////////////////
1624 // CFontDialogImpl - font selection dialog
1626 #ifndef _WIN32_WCE
1628 template <class T>
1629 class ATL_NO_VTABLE CFontDialogImpl : public CCommonDialogImplBase
1631 public:
1632 enum { _cchStyleName = 64 };
1634 CHOOSEFONT m_cf;
1635 TCHAR m_szStyleName[_cchStyleName]; // contains style name after return
1636 LOGFONT m_lf; // default LOGFONT to store the info
1638 // Constructors
1639 CFontDialogImpl(LPLOGFONT lplfInitial = NULL,
1640 DWORD dwFlags = CF_EFFECTS | CF_SCREENFONTS,
1641 HDC hDCPrinter = NULL,
1642 HWND hWndParent = NULL)
1644 memset(&m_cf, 0, sizeof(m_cf));
1645 memset(&m_lf, 0, sizeof(m_lf));
1646 memset(&m_szStyleName, 0, sizeof(m_szStyleName));
1648 m_cf.lStructSize = sizeof(m_cf);
1649 m_cf.hwndOwner = hWndParent;
1650 m_cf.rgbColors = RGB(0, 0, 0);
1651 m_cf.lpszStyle = (LPTSTR)&m_szStyleName;
1652 m_cf.Flags = dwFlags | CF_ENABLEHOOK;
1653 m_cf.lpfnHook = (LPCFHOOKPROC)T::HookProc;
1655 if(lplfInitial != NULL)
1657 m_cf.lpLogFont = lplfInitial;
1658 m_cf.Flags |= CF_INITTOLOGFONTSTRUCT;
1659 m_lf = *lplfInitial;
1661 else
1663 m_cf.lpLogFont = &m_lf;
1666 if(hDCPrinter != NULL)
1668 m_cf.hDC = hDCPrinter;
1669 m_cf.Flags |= CF_PRINTERFONTS;
1673 // Operations
1674 INT_PTR DoModal(HWND hWndParent = ::GetActiveWindow())
1676 ATLASSERT((m_cf.Flags & CF_ENABLEHOOK) != 0);
1677 ATLASSERT(m_cf.lpfnHook != NULL); // can still be a user hook
1679 if(m_cf.hwndOwner == NULL) // set only if not specified before
1680 m_cf.hwndOwner = hWndParent;
1682 ATLASSERT(m_hWnd == NULL);
1683 ModuleHelper::AddCreateWndData(&m_thunk.cd, (CCommonDialogImplBase*)this);
1685 BOOL bRet = ::ChooseFont(&m_cf);
1687 m_hWnd = NULL;
1689 if(bRet) // copy logical font from user's initialization buffer (if needed)
1690 SecureHelper::memcpy_x(&m_lf, sizeof(m_lf), m_cf.lpLogFont, sizeof(m_lf));
1692 return bRet ? IDOK : IDCANCEL;
1695 // works only when the dialog is dislayed or after
1696 void GetCurrentFont(LPLOGFONT lplf) const
1698 ATLASSERT(lplf != NULL);
1700 if(m_hWnd != NULL)
1701 ::SendMessage(m_hWnd, WM_CHOOSEFONT_GETLOGFONT, 0, (LPARAM)lplf);
1702 else
1703 *lplf = m_lf;
1706 // works only when the dialog is dislayed or before
1707 #ifndef _WIN32_WCE
1708 void SetLogFont(LPLOGFONT lplf)
1710 ATLASSERT(lplf != NULL);
1711 #ifndef WM_CHOOSEFONT_SETLOGFONT
1712 const UINT WM_CHOOSEFONT_SETLOGFONT = (WM_USER + 101);
1713 #endif
1714 if(m_hWnd != NULL)
1716 ::SendMessage(m_hWnd, WM_CHOOSEFONT_SETLOGFONT, 0, (LPARAM)lplf);
1718 else
1720 m_lf = *lplf;
1721 m_cf.Flags |= CF_INITTOLOGFONTSTRUCT;
1725 void SetFlags(DWORD dwFlags)
1727 #ifndef WM_CHOOSEFONT_SETFLAGS
1728 const UINT WM_CHOOSEFONT_SETFLAGS = (WM_USER + 102);
1729 #endif
1730 if(m_hWnd != NULL)
1732 CHOOSEFONT cf = { sizeof(CHOOSEFONT) };
1733 cf.Flags = dwFlags;
1734 ::SendMessage(m_hWnd, WM_CHOOSEFONT_SETFLAGS, 0, (LPARAM)&cf);
1736 else
1738 m_cf.Flags = dwFlags;
1741 #endif // !_WIN32_WCE
1743 // Helpers for parsing information after successful return
1744 LPCTSTR GetFaceName() const // return the face name of the font
1746 return (LPCTSTR)m_cf.lpLogFont->lfFaceName;
1749 LPCTSTR GetStyleName() const // return the style name of the font
1751 return m_cf.lpszStyle;
1754 int GetSize() const // return the pt size of the font
1756 return m_cf.iPointSize;
1759 COLORREF GetColor() const // return the color of the font
1761 return m_cf.rgbColors;
1764 int GetWeight() const // return the chosen font weight
1766 return (int)m_cf.lpLogFont->lfWeight;
1769 BOOL IsStrikeOut() const // return TRUE if strikeout
1771 return (m_cf.lpLogFont->lfStrikeOut) ? TRUE : FALSE;
1774 BOOL IsUnderline() const // return TRUE if underline
1776 return (m_cf.lpLogFont->lfUnderline) ? TRUE : FALSE;
1779 BOOL IsBold() const // return TRUE if bold font
1781 return (m_cf.lpLogFont->lfWeight == FW_BOLD) ? TRUE : FALSE;
1784 BOOL IsItalic() const // return TRUE if italic font
1786 return m_cf.lpLogFont->lfItalic ? TRUE : FALSE;
1790 class CFontDialog : public CFontDialogImpl<CFontDialog>
1792 public:
1793 CFontDialog(LPLOGFONT lplfInitial = NULL,
1794 DWORD dwFlags = CF_EFFECTS | CF_SCREENFONTS,
1795 HDC hDCPrinter = NULL,
1796 HWND hWndParent = NULL)
1797 : CFontDialogImpl<CFontDialog>(lplfInitial, dwFlags, hDCPrinter, hWndParent)
1800 DECLARE_EMPTY_MSG_MAP()
1803 #endif // _WIN32_WCE
1806 ///////////////////////////////////////////////////////////////////////////////
1807 // CRichEditFontDialogImpl - font selection for the Rich Edit ctrl
1809 #if defined(_RICHEDIT_) && !defined(_WIN32_WCE)
1811 template <class T>
1812 class ATL_NO_VTABLE CRichEditFontDialogImpl : public CFontDialogImpl< T >
1814 public:
1815 CRichEditFontDialogImpl(const CHARFORMAT& charformat,
1816 DWORD dwFlags = CF_SCREENFONTS,
1817 HDC hDCPrinter = NULL,
1818 HWND hWndParent = NULL)
1819 : CFontDialogImpl< T >(NULL, dwFlags, hDCPrinter, hWndParent)
1821 m_cf.Flags |= CF_INITTOLOGFONTSTRUCT;
1822 m_cf.Flags |= FillInLogFont(charformat);
1823 m_cf.lpLogFont = &m_lf;
1825 if((charformat.dwMask & CFM_COLOR) != 0)
1826 m_cf.rgbColors = charformat.crTextColor;
1829 void GetCharFormat(CHARFORMAT& cf) const
1831 USES_CONVERSION;
1832 cf.dwEffects = 0;
1833 cf.dwMask = 0;
1834 if((m_cf.Flags & CF_NOSTYLESEL) == 0)
1836 cf.dwMask |= CFM_BOLD | CFM_ITALIC;
1837 cf.dwEffects |= IsBold() ? CFE_BOLD : 0;
1838 cf.dwEffects |= IsItalic() ? CFE_ITALIC : 0;
1840 if((m_cf.Flags & CF_NOSIZESEL) == 0)
1842 cf.dwMask |= CFM_SIZE;
1843 // GetSize() returns in tenths of points so mulitply by 2 to get twips
1844 cf.yHeight = GetSize() * 2;
1847 if((m_cf.Flags & CF_NOFACESEL) == 0)
1849 cf.dwMask |= CFM_FACE;
1850 cf.bPitchAndFamily = m_cf.lpLogFont->lfPitchAndFamily;
1851 #if (_RICHEDIT_VER >= 0x0200)
1852 SecureHelper::strcpy_x(cf.szFaceName, _countof(cf.szFaceName), GetFaceName());
1853 #else // !(_RICHEDIT_VER >= 0x0200)
1854 SecureHelper::strcpyA_x(cf.szFaceName, _countof(cf.szFaceName), T2A((LPTSTR)(LPCTSTR)GetFaceName()));
1855 #endif // !(_RICHEDIT_VER >= 0x0200)
1858 if((m_cf.Flags & CF_EFFECTS) != 0)
1860 cf.dwMask |= CFM_UNDERLINE | CFM_STRIKEOUT | CFM_COLOR;
1861 cf.dwEffects |= IsUnderline() ? CFE_UNDERLINE : 0;
1862 cf.dwEffects |= IsStrikeOut() ? CFE_STRIKEOUT : 0;
1863 cf.crTextColor = GetColor();
1865 if((m_cf.Flags & CF_NOSCRIPTSEL) == 0)
1867 cf.bCharSet = m_cf.lpLogFont->lfCharSet;
1868 cf.dwMask |= CFM_CHARSET;
1870 cf.yOffset = 0;
1873 DWORD FillInLogFont(const CHARFORMAT& cf)
1875 USES_CONVERSION;
1876 DWORD dwFlags = 0;
1877 if((cf.dwMask & CFM_SIZE) != 0)
1879 HDC hDC = ::CreateDC(_T("DISPLAY"), NULL, NULL, NULL);
1880 LONG yPerInch = ::GetDeviceCaps(hDC, LOGPIXELSY);
1881 m_lf.lfHeight = -(int)((cf.yHeight * yPerInch) / 1440);
1883 else
1884 m_lf.lfHeight = 0;
1886 m_lf.lfWidth = 0;
1887 m_lf.lfEscapement = 0;
1888 m_lf.lfOrientation = 0;
1890 if((cf.dwMask & (CFM_ITALIC | CFM_BOLD)) == (CFM_ITALIC | CFM_BOLD))
1892 m_lf.lfWeight = ((cf.dwEffects & CFE_BOLD) != 0) ? FW_BOLD : FW_NORMAL;
1893 m_lf.lfItalic = (BYTE)(((cf.dwEffects & CFE_ITALIC) != 0) ? TRUE : FALSE);
1895 else
1897 dwFlags |= CF_NOSTYLESEL;
1898 m_lf.lfWeight = FW_DONTCARE;
1899 m_lf.lfItalic = FALSE;
1902 if((cf.dwMask & (CFM_UNDERLINE | CFM_STRIKEOUT | CFM_COLOR)) == (CFM_UNDERLINE|CFM_STRIKEOUT|CFM_COLOR))
1904 dwFlags |= CF_EFFECTS;
1905 m_lf.lfUnderline = (BYTE)(((cf.dwEffects & CFE_UNDERLINE) != 0) ? TRUE : FALSE);
1906 m_lf.lfStrikeOut = (BYTE)(((cf.dwEffects & CFE_STRIKEOUT) != 0) ? TRUE : FALSE);
1908 else
1910 m_lf.lfUnderline = (BYTE)FALSE;
1911 m_lf.lfStrikeOut = (BYTE)FALSE;
1914 if((cf.dwMask & CFM_CHARSET) != 0)
1915 m_lf.lfCharSet = cf.bCharSet;
1916 else
1917 dwFlags |= CF_NOSCRIPTSEL;
1918 m_lf.lfOutPrecision = OUT_DEFAULT_PRECIS;
1919 m_lf.lfClipPrecision = CLIP_DEFAULT_PRECIS;
1920 m_lf.lfQuality = DEFAULT_QUALITY;
1921 if((cf.dwMask & CFM_FACE) != 0)
1923 m_lf.lfPitchAndFamily = cf.bPitchAndFamily;
1924 #if (_RICHEDIT_VER >= 0x0200)
1925 SecureHelper::strcpy_x(m_lf.lfFaceName, _countof(m_lf.lfFaceName), cf.szFaceName);
1926 #else // !(_RICHEDIT_VER >= 0x0200)
1927 SecureHelper::strcpy_x(m_lf.lfFaceName, _countof(m_lf.lfFaceName), A2T((LPSTR)cf.szFaceName));
1928 #endif // !(_RICHEDIT_VER >= 0x0200)
1930 else
1932 m_lf.lfPitchAndFamily = DEFAULT_PITCH|FF_DONTCARE;
1933 m_lf.lfFaceName[0] = (TCHAR)0;
1935 return dwFlags;
1939 class CRichEditFontDialog : public CRichEditFontDialogImpl<CRichEditFontDialog>
1941 public:
1942 CRichEditFontDialog(const CHARFORMAT& charformat,
1943 DWORD dwFlags = CF_SCREENFONTS,
1944 HDC hDCPrinter = NULL,
1945 HWND hWndParent = NULL)
1946 : CRichEditFontDialogImpl<CRichEditFontDialog>(charformat, dwFlags, hDCPrinter, hWndParent)
1949 DECLARE_EMPTY_MSG_MAP()
1952 #endif // defined(_RICHEDIT_) && !defined(_WIN32_WCE)
1955 ///////////////////////////////////////////////////////////////////////////////
1956 // CColorDialogImpl - color selection
1958 #if !defined(_WIN32_WCE) || ((_WIN32_WCE > 420) && !(defined(WIN32_PLATFORM_WFSP) && (_WIN32_WCE > 0x0500)))
1960 #ifdef _WIN32_WCE
1961 #pragma comment(lib, "commdlg.lib")
1963 #ifndef SETRGBSTRING
1964 #define SETRGBSTRING _T("commdlg_SetRGBColor")
1965 #endif
1967 #ifndef COLOROKSTRING
1968 #define COLOROKSTRING _T("commdlg_ColorOK")
1969 #endif
1970 #endif
1972 template <class T>
1973 class ATL_NO_VTABLE CColorDialogImpl : public CCommonDialogImplBase
1975 public:
1976 CHOOSECOLOR m_cc;
1978 // Constructor
1979 CColorDialogImpl(COLORREF clrInit = 0, DWORD dwFlags = 0, HWND hWndParent = NULL)
1981 memset(&m_cc, 0, sizeof(m_cc));
1983 m_cc.lStructSize = sizeof(m_cc);
1984 m_cc.lpCustColors = GetCustomColors();
1985 m_cc.hwndOwner = hWndParent;
1986 m_cc.Flags = dwFlags | CC_ENABLEHOOK;
1987 m_cc.lpfnHook = (LPCCHOOKPROC)T::HookProc;
1989 if(clrInit != 0)
1991 m_cc.rgbResult = clrInit;
1992 m_cc.Flags |= CC_RGBINIT;
1996 // Operations
1997 INT_PTR DoModal(HWND hWndParent = ::GetActiveWindow())
1999 ATLASSERT((m_cc.Flags & CC_ENABLEHOOK) != 0);
2000 ATLASSERT(m_cc.lpfnHook != NULL); // can still be a user hook
2002 if(m_cc.hwndOwner == NULL) // set only if not specified before
2003 m_cc.hwndOwner = hWndParent;
2005 ATLASSERT(m_hWnd == NULL);
2006 ModuleHelper::AddCreateWndData(&m_thunk.cd, (CCommonDialogImplBase*)this);
2008 BOOL bRet = ::ChooseColor(&m_cc);
2010 m_hWnd = NULL;
2012 return bRet ? IDOK : IDCANCEL;
2015 // Set the current color while dialog is displayed
2016 void SetCurrentColor(COLORREF clr)
2018 ATLASSERT(::IsWindow(m_hWnd));
2019 SendMessage(_GetSetRGBMessage(), 0, (LPARAM)clr);
2022 // Get the selected color after DoModal returns, or in OnColorOK
2023 COLORREF GetColor() const
2025 return m_cc.rgbResult;
2028 // Special override for the color dialog
2029 static UINT_PTR APIENTRY HookProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
2031 if(uMsg != WM_INITDIALOG && uMsg != _GetColorOKMessage())
2032 return 0;
2034 LPCHOOSECOLOR lpCC = (LPCHOOSECOLOR)lParam;
2035 CCommonDialogImplBase* pT = NULL;
2037 if(uMsg == WM_INITDIALOG)
2039 pT = (CCommonDialogImplBase*)ModuleHelper::ExtractCreateWndData();
2040 lpCC->lCustData = (LPARAM)pT;
2041 ATLASSERT(pT != NULL);
2042 ATLASSERT(pT->m_hWnd == NULL);
2043 ATLASSERT(::IsWindow(hWnd));
2044 // subclass dialog's window
2045 if(!pT->SubclassWindow(hWnd))
2047 ATLTRACE2(atlTraceUI, 0, _T("Subclassing a Color common dialog failed\n"));
2048 return 0;
2051 else if(uMsg == _GetColorOKMessage())
2053 pT = (CCommonDialogImplBase*)lpCC->lCustData;
2054 ATLASSERT(pT != NULL);
2055 ATLASSERT(::IsWindow(pT->m_hWnd));
2058 // pass to the message map
2059 LRESULT lRes;
2060 if(pT->ProcessWindowMessage(pT->m_hWnd, uMsg, wParam, lParam, lRes, 0) == FALSE)
2061 return 0;
2062 return lRes;
2065 // Helpers
2066 static COLORREF* GetCustomColors()
2068 static COLORREF rgbCustomColors[16] =
2070 RGB(255, 255, 255), RGB(255, 255, 255),
2071 RGB(255, 255, 255), RGB(255, 255, 255),
2072 RGB(255, 255, 255), RGB(255, 255, 255),
2073 RGB(255, 255, 255), RGB(255, 255, 255),
2074 RGB(255, 255, 255), RGB(255, 255, 255),
2075 RGB(255, 255, 255), RGB(255, 255, 255),
2076 RGB(255, 255, 255), RGB(255, 255, 255),
2077 RGB(255, 255, 255), RGB(255, 255, 255),
2080 return rgbCustomColors;
2083 static UINT _GetSetRGBMessage()
2085 static UINT uSetRGBMessage = 0;
2086 if(uSetRGBMessage == 0)
2088 CStaticDataInitCriticalSectionLock lock;
2089 if(FAILED(lock.Lock()))
2091 ATLTRACE2(atlTraceUI, 0, _T("ERROR : Unable to lock critical section in CColorDialogImpl::_GetSetRGBMessage.\n"));
2092 ATLASSERT(FALSE);
2093 return 0;
2096 if(uSetRGBMessage == 0)
2097 uSetRGBMessage = ::RegisterWindowMessage(SETRGBSTRING);
2099 lock.Unlock();
2101 ATLASSERT(uSetRGBMessage != 0);
2102 return uSetRGBMessage;
2105 static UINT _GetColorOKMessage()
2107 static UINT uColorOKMessage = 0;
2108 if(uColorOKMessage == 0)
2110 CStaticDataInitCriticalSectionLock lock;
2111 if(FAILED(lock.Lock()))
2113 ATLTRACE2(atlTraceUI, 0, _T("ERROR : Unable to lock critical section in CColorDialogImpl::_GetColorOKMessage.\n"));
2114 ATLASSERT(FALSE);
2115 return 0;
2118 if(uColorOKMessage == 0)
2119 uColorOKMessage = ::RegisterWindowMessage(COLOROKSTRING);
2121 lock.Unlock();
2123 ATLASSERT(uColorOKMessage != 0);
2124 return uColorOKMessage;
2127 // Message map and handlers
2128 BEGIN_MSG_MAP(CColorDialogImpl)
2129 MESSAGE_HANDLER(_GetColorOKMessage(), _OnColorOK)
2130 END_MSG_MAP()
2132 LRESULT _OnColorOK(UINT, WPARAM, LPARAM, BOOL&)
2134 T* pT = static_cast<T*>(this);
2135 return pT->OnColorOK();
2138 // Overrideable
2139 BOOL OnColorOK() // validate color
2141 return FALSE;
2145 class CColorDialog : public CColorDialogImpl<CColorDialog>
2147 public:
2148 CColorDialog(COLORREF clrInit = 0, DWORD dwFlags = 0, HWND hWndParent = NULL)
2149 : CColorDialogImpl<CColorDialog>(clrInit, dwFlags, hWndParent)
2152 // override base class map and references to handlers
2153 DECLARE_EMPTY_MSG_MAP()
2156 #endif // !defined(_WIN32_WCE) || ((_WIN32_WCE > 420) && !(defined(WIN32_PLATFORM_WFSP) && (_WIN32_WCE > 0x0500)))
2159 ///////////////////////////////////////////////////////////////////////////////
2160 // CPrintDialogImpl - used for Print... and PrintSetup...
2162 #ifndef _WIN32_WCE
2164 // global helper
2165 static HDC _AtlCreateDC(HGLOBAL hDevNames, HGLOBAL hDevMode)
2167 if(hDevNames == NULL)
2168 return NULL;
2170 LPDEVNAMES lpDevNames = (LPDEVNAMES)::GlobalLock(hDevNames);
2171 LPDEVMODE lpDevMode = (hDevMode != NULL) ? (LPDEVMODE)::GlobalLock(hDevMode) : NULL;
2173 if(lpDevNames == NULL)
2174 return NULL;
2176 HDC hDC = ::CreateDC((LPCTSTR)lpDevNames + lpDevNames->wDriverOffset,
2177 (LPCTSTR)lpDevNames + lpDevNames->wDeviceOffset,
2178 (LPCTSTR)lpDevNames + lpDevNames->wOutputOffset,
2179 lpDevMode);
2181 ::GlobalUnlock(hDevNames);
2182 if(hDevMode != NULL)
2183 ::GlobalUnlock(hDevMode);
2184 return hDC;
2187 template <class T>
2188 class ATL_NO_VTABLE CPrintDialogImpl : public CCommonDialogImplBase
2190 public:
2191 // print dialog parameter block (note this is a reference)
2192 PRINTDLG& m_pd;
2194 // Constructors
2195 CPrintDialogImpl(BOOL bPrintSetupOnly = FALSE, // TRUE for Print Setup, FALSE for Print Dialog
2196 DWORD dwFlags = PD_ALLPAGES | PD_USEDEVMODECOPIES | PD_NOPAGENUMS | PD_NOSELECTION,
2197 HWND hWndParent = NULL)
2198 : m_pd(m_pdActual)
2200 memset(&m_pdActual, 0, sizeof(m_pdActual));
2202 m_pd.lStructSize = sizeof(m_pdActual);
2203 m_pd.hwndOwner = hWndParent;
2204 m_pd.Flags = (dwFlags | PD_ENABLEPRINTHOOK | PD_ENABLESETUPHOOK);
2205 m_pd.lpfnPrintHook = (LPPRINTHOOKPROC)T::HookProc;
2206 m_pd.lpfnSetupHook = (LPSETUPHOOKPROC)T::HookProc;
2208 if(bPrintSetupOnly)
2209 m_pd.Flags |= PD_PRINTSETUP;
2210 else
2211 m_pd.Flags |= PD_RETURNDC;
2213 m_pd.Flags &= ~PD_RETURNIC; // do not support information context
2216 // Operations
2217 INT_PTR DoModal(HWND hWndParent = ::GetActiveWindow())
2219 ATLASSERT((m_pd.Flags & PD_ENABLEPRINTHOOK) != 0);
2220 ATLASSERT((m_pd.Flags & PD_ENABLESETUPHOOK) != 0);
2221 ATLASSERT(m_pd.lpfnPrintHook != NULL); // can still be a user hook
2222 ATLASSERT(m_pd.lpfnSetupHook != NULL); // can still be a user hook
2223 ATLASSERT((m_pd.Flags & PD_RETURNDEFAULT) == 0); // use GetDefaults for this
2225 if(m_pd.hwndOwner == NULL) // set only if not specified before
2226 m_pd.hwndOwner = hWndParent;
2228 ATLASSERT(m_hWnd == NULL);
2229 ModuleHelper::AddCreateWndData(&m_thunk.cd, (CCommonDialogImplBase*)this);
2231 BOOL bRet = ::PrintDlg(&m_pd);
2233 m_hWnd = NULL;
2235 return bRet ? IDOK : IDCANCEL;
2238 // GetDefaults will not display a dialog but will get device defaults
2239 BOOL GetDefaults()
2241 m_pd.Flags |= PD_RETURNDEFAULT;
2242 ATLASSERT(m_pd.hDevMode == NULL); // must be NULL
2243 ATLASSERT(m_pd.hDevNames == NULL); // must be NULL
2245 return ::PrintDlg(&m_pd);
2248 // Helpers for parsing information after successful return num. copies requested
2249 int GetCopies() const
2251 if((m_pd.Flags & PD_USEDEVMODECOPIES) != 0)
2253 LPDEVMODE lpDevMode = GetDevMode();
2254 return (lpDevMode != NULL) ? lpDevMode->dmCopies : -1;
2257 return m_pd.nCopies;
2260 BOOL PrintCollate() const // TRUE if collate checked
2262 return ((m_pd.Flags & PD_COLLATE) != 0) ? TRUE : FALSE;
2265 BOOL PrintSelection() const // TRUE if printing selection
2267 return ((m_pd.Flags & PD_SELECTION) != 0) ? TRUE : FALSE;
2270 BOOL PrintAll() const // TRUE if printing all pages
2272 return (!PrintRange() && !PrintSelection()) ? TRUE : FALSE;
2275 BOOL PrintRange() const // TRUE if printing page range
2277 return ((m_pd.Flags & PD_PAGENUMS) != 0) ? TRUE : FALSE;
2280 BOOL PrintToFile() const // TRUE if printing to a file
2282 return ((m_pd.Flags & PD_PRINTTOFILE) != 0) ? TRUE : FALSE;
2285 int GetFromPage() const // starting page if valid
2287 return PrintRange() ? m_pd.nFromPage : -1;
2290 int GetToPage() const // ending page if valid
2292 return PrintRange() ? m_pd.nToPage : -1;
2295 LPDEVMODE GetDevMode() const // return DEVMODE
2297 if(m_pd.hDevMode == NULL)
2298 return NULL;
2300 return (LPDEVMODE)::GlobalLock(m_pd.hDevMode);
2303 LPCTSTR GetDriverName() const // return driver name
2305 if(m_pd.hDevNames == NULL)
2306 return NULL;
2308 LPDEVNAMES lpDev = (LPDEVNAMES)::GlobalLock(m_pd.hDevNames);
2309 if(lpDev == NULL)
2310 return NULL;
2312 return (LPCTSTR)lpDev + lpDev->wDriverOffset;
2315 LPCTSTR GetDeviceName() const // return device name
2317 if(m_pd.hDevNames == NULL)
2318 return NULL;
2320 LPDEVNAMES lpDev = (LPDEVNAMES)::GlobalLock(m_pd.hDevNames);
2321 if(lpDev == NULL)
2322 return NULL;
2324 return (LPCTSTR)lpDev + lpDev->wDeviceOffset;
2327 LPCTSTR GetPortName() const // return output port name
2329 if(m_pd.hDevNames == NULL)
2330 return NULL;
2332 LPDEVNAMES lpDev = (LPDEVNAMES)::GlobalLock(m_pd.hDevNames);
2333 if(lpDev == NULL)
2334 return NULL;
2336 return (LPCTSTR)lpDev + lpDev->wOutputOffset;
2339 HDC GetPrinterDC() const // return HDC (caller must delete)
2341 ATLASSERT((m_pd.Flags & PD_RETURNDC) != 0);
2342 return m_pd.hDC;
2345 // This helper creates a DC based on the DEVNAMES and DEVMODE structures.
2346 // This DC is returned, but also stored in m_pd.hDC as though it had been
2347 // returned by CommDlg. It is assumed that any previously obtained DC
2348 // has been/will be deleted by the user. This may be
2349 // used without ever invoking the print/print setup dialogs.
2350 HDC CreatePrinterDC()
2352 m_pd.hDC = _AtlCreateDC(m_pd.hDevNames, m_pd.hDevMode);
2353 return m_pd.hDC;
2356 // Implementation
2357 PRINTDLG m_pdActual; // the Print/Print Setup need to share this
2359 // The following handle the case of print setup... from the print dialog
2360 CPrintDialogImpl(PRINTDLG& pdInit) : m_pd(pdInit)
2363 BEGIN_MSG_MAP(CPrintDialogImpl)
2364 #ifdef psh1
2365 COMMAND_ID_HANDLER(psh1, OnPrintSetup) // print setup button when print is displayed
2366 #else // !psh1
2367 COMMAND_ID_HANDLER(0x0400, OnPrintSetup) // value from dlgs.h
2368 #endif // !psh1
2369 END_MSG_MAP()
2371 LRESULT OnPrintSetup(WORD wNotifyCode, WORD wID, HWND hWndCtl, BOOL& /*bHandled*/)
2373 T dlgSetup(m_pd);
2374 ModuleHelper::AddCreateWndData(&dlgSetup.m_thunk.cd, (CCommonDialogImplBase*)&dlgSetup);
2375 return DefWindowProc(WM_COMMAND, MAKEWPARAM(wID, wNotifyCode), (LPARAM)hWndCtl);
2379 class CPrintDialog : public CPrintDialogImpl<CPrintDialog>
2381 public:
2382 CPrintDialog(BOOL bPrintSetupOnly = FALSE,
2383 DWORD dwFlags = PD_ALLPAGES | PD_USEDEVMODECOPIES | PD_NOPAGENUMS | PD_NOSELECTION,
2384 HWND hWndParent = NULL)
2385 : CPrintDialogImpl<CPrintDialog>(bPrintSetupOnly, dwFlags, hWndParent)
2388 CPrintDialog(PRINTDLG& pdInit) : CPrintDialogImpl<CPrintDialog>(pdInit)
2392 #endif // _WIN32_WCE
2395 ///////////////////////////////////////////////////////////////////////////////
2396 // CPrintDialogExImpl - new print dialog for Windows 2000
2398 #if (WINVER >= 0x0500) && !defined(_WIN32_WCE)
2400 }; // namespace WTL
2402 #include <atlcom.h>
2404 extern "C" const __declspec(selectany) IID IID_IPrintDialogCallback = {0x5852a2c3, 0x6530, 0x11d1, {0xb6, 0xa3, 0x0, 0x0, 0xf8, 0x75, 0x7b, 0xf9}};
2405 extern "C" const __declspec(selectany) IID IID_IPrintDialogServices = {0x509aaeda, 0x5639, 0x11d1, {0xb6, 0xa1, 0x0, 0x0, 0xf8, 0x75, 0x7b, 0xf9}};
2407 namespace WTL
2410 template <class T>
2411 class ATL_NO_VTABLE CPrintDialogExImpl :
2412 public ATL::CWindow,
2413 public ATL::CMessageMap,
2414 public IPrintDialogCallback,
2415 public ATL::IObjectWithSiteImpl< T >
2417 public:
2418 PRINTDLGEX m_pdex;
2420 // Constructor
2421 CPrintDialogExImpl(DWORD dwFlags = PD_ALLPAGES | PD_USEDEVMODECOPIES | PD_NOPAGENUMS | PD_NOSELECTION | PD_NOCURRENTPAGE,
2422 HWND hWndParent = NULL)
2424 memset(&m_pdex, 0, sizeof(m_pdex));
2426 m_pdex.lStructSize = sizeof(PRINTDLGEX);
2427 m_pdex.hwndOwner = hWndParent;
2428 m_pdex.Flags = dwFlags;
2429 m_pdex.nStartPage = START_PAGE_GENERAL;
2430 // callback object will be set in DoModal
2432 m_pdex.Flags &= ~PD_RETURNIC; // do not support information context
2435 // Operations
2436 HRESULT DoModal(HWND hWndParent = ::GetActiveWindow())
2438 ATLASSERT(m_hWnd == NULL);
2439 ATLASSERT((m_pdex.Flags & PD_RETURNDEFAULT) == 0); // use GetDefaults for this
2441 if(m_pdex.hwndOwner == NULL) // set only if not specified before
2442 m_pdex.hwndOwner = hWndParent;
2444 T* pT = static_cast<T*>(this);
2445 m_pdex.lpCallback = (IUnknown*)(IPrintDialogCallback*)pT;
2447 HRESULT hResult = ::PrintDlgEx(&m_pdex);
2449 m_hWnd = NULL;
2451 return hResult;
2454 BOOL EndDialog(INT_PTR /*nRetCode*/ = 0)
2456 ATLASSERT(::IsWindow(m_hWnd));
2457 SendMessage(WM_COMMAND, MAKEWPARAM(IDABORT, 0));
2458 return TRUE;
2461 // GetDefaults will not display a dialog but will get device defaults
2462 HRESULT GetDefaults()
2464 m_pdex.Flags |= PD_RETURNDEFAULT;
2465 ATLASSERT(m_pdex.hDevMode == NULL); // must be NULL
2466 ATLASSERT(m_pdex.hDevNames == NULL); // must be NULL
2468 return ::PrintDlgEx(&m_pdex);
2471 // Helpers for parsing information after successful return num. copies requested
2472 int GetCopies() const
2474 if((m_pdex.Flags & PD_USEDEVMODECOPIES) != 0)
2476 LPDEVMODE lpDevMode = GetDevMode();
2477 return (lpDevMode != NULL) ? lpDevMode->dmCopies : -1;
2480 return m_pdex.nCopies;
2483 BOOL PrintCollate() const // TRUE if collate checked
2485 return ((m_pdex.Flags & PD_COLLATE) != 0) ? TRUE : FALSE;
2488 BOOL PrintSelection() const // TRUE if printing selection
2490 return ((m_pdex.Flags & PD_SELECTION) != 0) ? TRUE : FALSE;
2493 BOOL PrintAll() const // TRUE if printing all pages
2495 return (!PrintRange() && !PrintSelection()) ? TRUE : FALSE;
2498 BOOL PrintRange() const // TRUE if printing page range
2500 return ((m_pdex.Flags & PD_PAGENUMS) != 0) ? TRUE : FALSE;
2503 BOOL PrintToFile() const // TRUE if printing to a file
2505 return ((m_pdex.Flags & PD_PRINTTOFILE) != 0) ? TRUE : FALSE;
2508 LPDEVMODE GetDevMode() const // return DEVMODE
2510 if(m_pdex.hDevMode == NULL)
2511 return NULL;
2513 return (LPDEVMODE)::GlobalLock(m_pdex.hDevMode);
2516 LPCTSTR GetDriverName() const // return driver name
2518 if(m_pdex.hDevNames == NULL)
2519 return NULL;
2521 LPDEVNAMES lpDev = (LPDEVNAMES)::GlobalLock(m_pdex.hDevNames);
2522 if(lpDev == NULL)
2523 return NULL;
2525 return (LPCTSTR)lpDev + lpDev->wDriverOffset;
2528 LPCTSTR GetDeviceName() const // return device name
2530 if(m_pdex.hDevNames == NULL)
2531 return NULL;
2533 LPDEVNAMES lpDev = (LPDEVNAMES)::GlobalLock(m_pdex.hDevNames);
2534 if(lpDev == NULL)
2535 return NULL;
2537 return (LPCTSTR)lpDev + lpDev->wDeviceOffset;
2540 LPCTSTR GetPortName() const // return output port name
2542 if(m_pdex.hDevNames == NULL)
2543 return NULL;
2545 LPDEVNAMES lpDev = (LPDEVNAMES)::GlobalLock(m_pdex.hDevNames);
2546 if(lpDev == NULL)
2547 return NULL;
2549 return (LPCTSTR)lpDev + lpDev->wOutputOffset;
2552 HDC GetPrinterDC() const // return HDC (caller must delete)
2554 ATLASSERT((m_pdex.Flags & PD_RETURNDC) != 0);
2555 return m_pdex.hDC;
2558 // This helper creates a DC based on the DEVNAMES and DEVMODE structures.
2559 // This DC is returned, but also stored in m_pdex.hDC as though it had been
2560 // returned by CommDlg. It is assumed that any previously obtained DC
2561 // has been/will be deleted by the user. This may be
2562 // used without ever invoking the print/print setup dialogs.
2563 HDC CreatePrinterDC()
2565 m_pdex.hDC = _AtlCreateDC(m_pdex.hDevNames, m_pdex.hDevMode);
2566 return m_pdex.hDC;
2569 // Implementation - interfaces
2571 // IUnknown
2572 STDMETHOD(QueryInterface)(REFIID riid, void** ppvObject)
2574 if(ppvObject == NULL)
2575 return E_POINTER;
2577 T* pT = static_cast<T*>(this);
2578 if(IsEqualGUID(riid, IID_IUnknown) || IsEqualGUID(riid, IID_IPrintDialogCallback))
2580 *ppvObject = (IPrintDialogCallback*)pT;
2581 // AddRef() not needed
2582 return S_OK;
2584 else if(IsEqualGUID(riid, IID_IObjectWithSite))
2586 *ppvObject = (IObjectWithSite*)pT;
2587 // AddRef() not needed
2588 return S_OK;
2591 return E_NOINTERFACE;
2594 virtual ULONG STDMETHODCALLTYPE AddRef()
2596 return 1;
2599 virtual ULONG STDMETHODCALLTYPE Release()
2601 return 1;
2604 // IPrintDialogCallback
2605 STDMETHOD(InitDone)()
2607 return S_FALSE;
2610 STDMETHOD(SelectionChange)()
2612 return S_FALSE;
2615 STDMETHOD(HandleMessage)(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam, LRESULT* plResult)
2617 // set up m_hWnd the first time
2618 if(m_hWnd == NULL)
2619 Attach(hWnd);
2621 // call message map
2622 HRESULT hRet = ProcessWindowMessage(hWnd, uMsg, wParam, lParam, *plResult, 0) ? S_OK : S_FALSE;
2623 if(hRet == S_OK && uMsg == WM_NOTIFY) // return in DWLP_MSGRESULT
2624 ::SetWindowLongPtr(GetParent(), DWLP_MSGRESULT, (LONG_PTR)*plResult);
2626 if(uMsg == WM_INITDIALOG && hRet == S_OK && (BOOL)*plResult != FALSE)
2627 hRet = S_FALSE;
2629 return hRet;
2633 class CPrintDialogEx : public CPrintDialogExImpl<CPrintDialogEx>
2635 public:
2636 CPrintDialogEx(
2637 DWORD dwFlags = PD_ALLPAGES | PD_USEDEVMODECOPIES | PD_NOPAGENUMS | PD_NOSELECTION | PD_NOCURRENTPAGE,
2638 HWND hWndParent = NULL)
2639 : CPrintDialogExImpl<CPrintDialogEx>(dwFlags, hWndParent)
2642 DECLARE_EMPTY_MSG_MAP()
2645 #endif // (WINVER >= 0x0500) && !defined(_WIN32_WCE)
2648 ///////////////////////////////////////////////////////////////////////////////
2649 // CPageSetupDialogImpl - Page Setup dialog
2651 #ifndef _WIN32_WCE
2653 template <class T>
2654 class ATL_NO_VTABLE CPageSetupDialogImpl : public CCommonDialogImplBase
2656 public:
2657 PAGESETUPDLG m_psd;
2658 ATL::CWndProcThunk m_thunkPaint;
2660 // Constructors
2661 CPageSetupDialogImpl(DWORD dwFlags = PSD_MARGINS | PSD_INWININIINTLMEASURE, HWND hWndParent = NULL)
2663 memset(&m_psd, 0, sizeof(m_psd));
2665 m_psd.lStructSize = sizeof(m_psd);
2666 m_psd.hwndOwner = hWndParent;
2667 m_psd.Flags = (dwFlags | PSD_ENABLEPAGESETUPHOOK | PSD_ENABLEPAGEPAINTHOOK);
2668 m_psd.lpfnPageSetupHook = (LPPAGESETUPHOOK)T::HookProc;
2669 m_thunkPaint.Init((WNDPROC)T::PaintHookProc, this);
2670 #if (_ATL_VER >= 0x0700)
2671 m_psd.lpfnPagePaintHook = (LPPAGEPAINTHOOK)m_thunkPaint.GetWNDPROC();
2672 #else
2673 m_psd.lpfnPagePaintHook = (LPPAGEPAINTHOOK)&(m_thunkPaint.thunk);
2674 #endif
2677 DECLARE_EMPTY_MSG_MAP()
2679 // Attributes
2680 LPDEVMODE GetDevMode() const // return DEVMODE
2682 if(m_psd.hDevMode == NULL)
2683 return NULL;
2685 return (LPDEVMODE)::GlobalLock(m_psd.hDevMode);
2688 LPCTSTR GetDriverName() const // return driver name
2690 if(m_psd.hDevNames == NULL)
2691 return NULL;
2693 LPDEVNAMES lpDev = (LPDEVNAMES)::GlobalLock(m_psd.hDevNames);
2694 return (LPCTSTR)lpDev + lpDev->wDriverOffset;
2697 LPCTSTR GetDeviceName() const // return device name
2699 if(m_psd.hDevNames == NULL)
2700 return NULL;
2702 LPDEVNAMES lpDev = (LPDEVNAMES)::GlobalLock(m_psd.hDevNames);
2703 return (LPCTSTR)lpDev + lpDev->wDeviceOffset;
2706 LPCTSTR GetPortName() const // return output port name
2708 if(m_psd.hDevNames == NULL)
2709 return NULL;
2711 LPDEVNAMES lpDev = (LPDEVNAMES)::GlobalLock(m_psd.hDevNames);
2712 return (LPCTSTR)lpDev + lpDev->wOutputOffset;
2715 HDC CreatePrinterDC()
2717 return _AtlCreateDC(m_psd.hDevNames, m_psd.hDevMode);
2720 SIZE GetPaperSize() const
2722 SIZE size;
2723 size.cx = m_psd.ptPaperSize.x;
2724 size.cy = m_psd.ptPaperSize.y;
2725 return size;
2728 void GetMargins(LPRECT lpRectMargins, LPRECT lpRectMinMargins) const
2730 if(lpRectMargins != NULL)
2731 *lpRectMargins = m_psd.rtMargin;
2732 if(lpRectMinMargins != NULL)
2733 *lpRectMinMargins = m_psd.rtMinMargin;
2736 // Operations
2737 INT_PTR DoModal(HWND hWndParent = ::GetActiveWindow())
2739 ATLASSERT((m_psd.Flags & PSD_ENABLEPAGESETUPHOOK) != 0);
2740 ATLASSERT((m_psd.Flags & PSD_ENABLEPAGEPAINTHOOK) != 0);
2741 ATLASSERT(m_psd.lpfnPageSetupHook != NULL); // can still be a user hook
2742 ATLASSERT(m_psd.lpfnPagePaintHook != NULL); // can still be a user hook
2744 if(m_psd.hwndOwner == NULL) // set only if not specified before
2745 m_psd.hwndOwner = hWndParent;
2747 ATLASSERT(m_hWnd == NULL);
2748 ModuleHelper::AddCreateWndData(&m_thunk.cd, (CCommonDialogImplBase*)this);
2750 BOOL bRet = ::PageSetupDlg(&m_psd);
2752 m_hWnd = NULL;
2754 return bRet ? IDOK : IDCANCEL;
2757 // Implementation
2758 static UINT_PTR CALLBACK PaintHookProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
2760 T* pT = (T*)hWnd;
2761 UINT_PTR uRet = 0;
2762 switch(uMsg)
2764 case WM_PSD_PAGESETUPDLG:
2765 uRet = pT->PreDrawPage(LOWORD(wParam), HIWORD(wParam), (LPPAGESETUPDLG)lParam);
2766 break;
2767 case WM_PSD_FULLPAGERECT:
2768 case WM_PSD_MINMARGINRECT:
2769 case WM_PSD_MARGINRECT:
2770 case WM_PSD_GREEKTEXTRECT:
2771 case WM_PSD_ENVSTAMPRECT:
2772 case WM_PSD_YAFULLPAGERECT:
2773 uRet = pT->OnDrawPage(uMsg, (HDC)wParam, (LPRECT)lParam);
2774 break;
2775 default:
2776 ATLTRACE2(atlTraceUI, 0, _T("CPageSetupDialogImpl::PaintHookProc - unknown message received\n"));
2777 break;
2779 return uRet;
2782 // Overridables
2783 UINT_PTR PreDrawPage(WORD /*wPaper*/, WORD /*wFlags*/, LPPAGESETUPDLG /*pPSD*/)
2785 // return 1 to prevent any more drawing
2786 return 0;
2789 UINT_PTR OnDrawPage(UINT /*uMsg*/, HDC /*hDC*/, LPRECT /*lpRect*/)
2791 return 0; // do the default
2795 class CPageSetupDialog : public CPageSetupDialogImpl<CPageSetupDialog>
2797 public:
2798 CPageSetupDialog(DWORD dwFlags = PSD_MARGINS | PSD_INWININIINTLMEASURE, HWND hWndParent = NULL)
2799 : CPageSetupDialogImpl<CPageSetupDialog>(dwFlags, hWndParent)
2802 // override PaintHookProc and references to handlers
2803 static UINT_PTR CALLBACK PaintHookProc(HWND, UINT, WPARAM, LPARAM)
2805 return 0;
2809 #endif // _WIN32_WCE
2812 ///////////////////////////////////////////////////////////////////////////////
2813 // CFindReplaceDialogImpl - Find/FindReplace modeless dialogs
2815 #ifndef _WIN32_WCE
2817 template <class T>
2818 class ATL_NO_VTABLE CFindReplaceDialogImpl : public CCommonDialogImplBase
2820 public:
2821 enum { _cchFindReplaceBuffer = 128 };
2823 FINDREPLACE m_fr;
2824 TCHAR m_szFindWhat[_cchFindReplaceBuffer];
2825 TCHAR m_szReplaceWith[_cchFindReplaceBuffer];
2827 // Constructors
2828 CFindReplaceDialogImpl()
2830 memset(&m_fr, 0, sizeof(m_fr));
2831 m_szFindWhat[0] = _T('\0');
2832 m_szReplaceWith[0] = _T('\0');
2834 m_fr.lStructSize = sizeof(m_fr);
2835 m_fr.Flags = FR_ENABLEHOOK;
2836 m_fr.lpfnHook = (LPFRHOOKPROC)T::HookProc;
2837 m_fr.lpstrFindWhat = (LPTSTR)m_szFindWhat;
2838 m_fr.wFindWhatLen = _cchFindReplaceBuffer;
2839 m_fr.lpstrReplaceWith = (LPTSTR)m_szReplaceWith;
2840 m_fr.wReplaceWithLen = _cchFindReplaceBuffer;
2843 // Note: You must allocate the object on the heap.
2844 // If you do not, you must override OnFinalMessage()
2845 virtual void OnFinalMessage(HWND /*hWnd*/)
2847 delete this;
2850 HWND Create(BOOL bFindDialogOnly, // TRUE for Find, FALSE for FindReplace
2851 LPCTSTR lpszFindWhat,
2852 LPCTSTR lpszReplaceWith = NULL,
2853 DWORD dwFlags = FR_DOWN,
2854 HWND hWndParent = NULL)
2856 ATLASSERT((m_fr.Flags & FR_ENABLEHOOK) != 0);
2857 ATLASSERT(m_fr.lpfnHook != NULL);
2859 m_fr.Flags |= dwFlags;
2861 if(hWndParent == NULL)
2862 m_fr.hwndOwner = ::GetActiveWindow();
2863 else
2864 m_fr.hwndOwner = hWndParent;
2865 ATLASSERT(m_fr.hwndOwner != NULL); // must have an owner for modeless dialog
2867 if(lpszFindWhat != NULL)
2868 SecureHelper::strncpy_x(m_szFindWhat, _countof(m_szFindWhat), lpszFindWhat, _TRUNCATE);
2870 if(lpszReplaceWith != NULL)
2871 SecureHelper::strncpy_x(m_szReplaceWith, _countof(m_szReplaceWith), lpszReplaceWith, _TRUNCATE);
2873 ATLASSERT(m_hWnd == NULL);
2874 ModuleHelper::AddCreateWndData(&m_thunk.cd, (CCommonDialogImplBase*)this);
2876 HWND hWnd = NULL;
2877 if(bFindDialogOnly)
2878 hWnd = ::FindText(&m_fr);
2879 else
2880 hWnd = ::ReplaceText(&m_fr);
2882 ATLASSERT(m_hWnd == hWnd);
2883 return hWnd;
2886 static const UINT GetFindReplaceMsg()
2888 static const UINT nMsgFindReplace = ::RegisterWindowMessage(FINDMSGSTRING);
2889 return nMsgFindReplace;
2891 // call while handling FINDMSGSTRING registered message
2892 // to retreive the object
2893 static T* PASCAL GetNotifier(LPARAM lParam)
2895 ATLASSERT(lParam != NULL);
2896 T* pDlg = (T*)(lParam - offsetof(T, m_fr));
2897 return pDlg;
2900 // Operations
2901 // Helpers for parsing information after successful return
2902 LPCTSTR GetFindString() const // get find string
2904 return (LPCTSTR)m_fr.lpstrFindWhat;
2907 LPCTSTR GetReplaceString() const // get replacement string
2909 return (LPCTSTR)m_fr.lpstrReplaceWith;
2912 BOOL SearchDown() const // TRUE if search down, FALSE is up
2914 return ((m_fr.Flags & FR_DOWN) != 0) ? TRUE : FALSE;
2917 BOOL FindNext() const // TRUE if command is find next
2919 return ((m_fr.Flags & FR_FINDNEXT) != 0) ? TRUE : FALSE;
2922 BOOL MatchCase() const // TRUE if matching case
2924 return ((m_fr.Flags & FR_MATCHCASE) != 0) ? TRUE : FALSE;
2927 BOOL MatchWholeWord() const // TRUE if matching whole words only
2929 return ((m_fr.Flags & FR_WHOLEWORD) != 0) ? TRUE : FALSE;
2932 BOOL ReplaceCurrent() const // TRUE if replacing current string
2934 return ((m_fr. Flags & FR_REPLACE) != 0) ? TRUE : FALSE;
2937 BOOL ReplaceAll() const // TRUE if replacing all occurrences
2939 return ((m_fr.Flags & FR_REPLACEALL) != 0) ? TRUE : FALSE;
2942 BOOL IsTerminating() const // TRUE if terminating dialog
2944 return ((m_fr.Flags & FR_DIALOGTERM) != 0) ? TRUE : FALSE ;
2948 class CFindReplaceDialog : public CFindReplaceDialogImpl<CFindReplaceDialog>
2950 public:
2951 DECLARE_EMPTY_MSG_MAP()
2954 #endif // !_WIN32_WCE
2957 #if (_ATL_VER >= 0x800)
2958 typedef ATL::_DialogSplitHelper::DLGTEMPLATEEX DLGTEMPLATEEX;
2959 typedef ATL::_DialogSplitHelper::DLGITEMTEMPLATEEX DLGITEMTEMPLATEEX;
2960 #else // (_ATL_VER >= 0x800)
2961 typedef ATL::_DialogSizeHelper::_ATL_DLGTEMPLATEEX DLGTEMPLATEEX;
2962 #pragma pack(push, 4)
2963 struct DLGITEMTEMPLATEEX
2965 DWORD helpID;
2966 DWORD exStyle;
2967 DWORD style;
2968 short x;
2969 short y;
2970 short cx;
2971 short cy;
2972 WORD id;
2974 #pragma pack(pop)
2975 #endif // (_ATL_VER >= 0x800)
2978 ///////////////////////////////////////////////////////////////////////////////
2979 // CMemDlgTemplate - in-memory dialog template - DLGTEMPLATE or DLGTEMPLATEEX
2981 class CMemDlgTemplate
2983 public:
2984 enum StdCtrlType
2986 CTRL_BUTTON = 0x0080,
2987 CTRL_EDIT = 0x0081,
2988 CTRL_STATIC = 0x0082,
2989 CTRL_LISTBOX = 0x0083,
2990 CTRL_SCROLLBAR = 0x0084,
2991 CTRL_COMBOBOX = 0x0085
2994 CMemDlgTemplate() : m_pData(NULL), m_pPtr(NULL), m_cAllocated(0)
2997 ~CMemDlgTemplate()
2999 Reset();
3002 bool IsValid() const
3004 return (m_pData != NULL);
3007 bool IsTemplateEx() const
3009 return (IsValid() && ((DLGTEMPLATEEX*)m_pData)->signature == 0xFFFF);
3012 LPDLGTEMPLATE GetTemplatePtr()
3014 return reinterpret_cast<LPDLGTEMPLATE>(m_pData);
3017 DLGTEMPLATEEX* GetTemplateExPtr()
3019 return reinterpret_cast<DLGTEMPLATEEX*>(m_pData);
3022 void Reset()
3024 if (IsValid())
3025 ATLVERIFY(::GlobalFree(m_pData) == NULL);
3027 m_pData = NULL;
3028 m_pPtr = NULL;
3029 m_cAllocated = 0;
3032 void Create(bool bDlgEx, LPCTSTR lpszCaption, short nX, short nY, short nWidth, short nHeight, DWORD dwStyle = 0, DWORD dwExStyle = 0,
3033 LPCTSTR lpstrFontName = NULL, WORD wFontSize = 0, WORD wWeight = 0, BYTE bItalic = 0, BYTE bCharset = 0, DWORD dwHelpID = 0,
3034 ATL::_U_STRINGorID ClassName = 0U, ATL::_U_STRINGorID Menu = 0U)
3036 // Should have DS_SETFONT style to set the dialog font name and size
3037 if (lpstrFontName != NULL)
3039 dwStyle |= DS_SETFONT;
3041 else
3043 dwStyle &= ~DS_SETFONT;
3046 if (bDlgEx)
3048 DLGTEMPLATEEX dlg = {1, 0xFFFF, dwHelpID, dwExStyle, dwStyle, 0, nX, nY, nWidth, nHeight};
3049 AddData(&dlg, sizeof(dlg));
3051 else
3053 DLGTEMPLATE dlg = {dwStyle, dwExStyle, 0, nX, nY, nWidth, nHeight};
3054 AddData(&dlg, sizeof(dlg));
3057 #ifndef _WIN32_WCE
3058 if (Menu.m_lpstr == NULL)
3060 WORD menuData = 0;
3061 AddData(&menuData, sizeof(WORD));
3063 else if (IS_INTRESOURCE(Menu.m_lpstr))
3065 WORD menuData[] = {0xFFFF, (WORD)Menu.m_lpstr};
3066 AddData(menuData, sizeof(menuData));
3068 else
3070 AddString(Menu.m_lpstr);
3072 #else // _WIN32_WCE
3073 // Windows CE doesn't support the addition of menus to a dialog box
3074 ATLASSERT(Menu.m_lpstr == NULL);
3075 Menu.m_lpstr; // avoid level 4 warning
3076 WORD menuData = 0;
3077 AddData(&menuData, sizeof(WORD));
3078 #endif // _WIN32_WCE
3080 if (ClassName.m_lpstr == NULL)
3082 WORD classData = 0;
3083 AddData(&classData, sizeof(WORD));
3085 else if (IS_INTRESOURCE(ClassName.m_lpstr))
3087 WORD classData[] = {0xFFFF, (WORD)ClassName.m_lpstr};
3088 AddData(classData, sizeof(classData));
3090 else
3092 AddString(ClassName.m_lpstr);
3095 // Set dialog caption
3096 AddString(lpszCaption);
3098 if (lpstrFontName != NULL)
3100 AddData(&wFontSize, sizeof(wFontSize));
3102 if (bDlgEx)
3104 AddData(&wWeight, sizeof(wWeight));
3105 AddData(&bItalic, sizeof(bItalic));
3106 AddData(&bCharset, sizeof(bCharset));
3109 AddString(lpstrFontName);
3113 void AddControl(ATL::_U_STRINGorID ClassName, WORD wId, short nX, short nY, short nWidth, short nHeight, DWORD dwStyle, DWORD dwExStyle,
3114 ATL::_U_STRINGorID Text, const WORD* pCreationData = NULL, WORD nCreationData = 0, DWORD dwHelpID = 0)
3116 ATLASSERT(IsValid());
3118 // DWORD align data
3119 m_pPtr = (LPBYTE)(DWORD_PTR)((DWORD)(DWORD_PTR)(m_pPtr + 3) & (~3));
3121 if (IsTemplateEx())
3123 DLGTEMPLATEEX* dlg = (DLGTEMPLATEEX*)m_pData;
3124 dlg->cDlgItems++;
3126 DLGITEMTEMPLATEEX item = {dwHelpID, ATL::CControlWinTraits::GetWndExStyle(0) | dwExStyle, ATL::CControlWinTraits::GetWndStyle(0) | dwStyle, nX, nY, nWidth, nHeight, wId};
3127 AddData(&item, sizeof(item));
3129 else
3131 LPDLGTEMPLATE dlg = (LPDLGTEMPLATE)m_pData;
3132 dlg->cdit++;
3134 DLGITEMTEMPLATE item = {ATL::CControlWinTraits::GetWndStyle(0) | dwStyle, ATL::CControlWinTraits::GetWndExStyle(0) | dwExStyle, nX, nY, nWidth, nHeight, wId};
3135 AddData(&item, sizeof(item));
3138 ATLASSERT(ClassName.m_lpstr != NULL);
3139 if (IS_INTRESOURCE(ClassName.m_lpstr))
3141 WORD wData[] = {0xFFFF, (WORD)ClassName.m_lpstr};
3142 AddData(wData, sizeof(wData));
3144 else
3146 AddString(ClassName.m_lpstr);
3149 if (Text.m_lpstr == NULL)
3151 WORD classData = 0;
3152 AddData(&classData, sizeof(WORD));
3154 else if (IS_INTRESOURCE(Text.m_lpstr))
3156 WORD wData[] = {0xFFFF, (WORD)Text.m_lpstr};
3157 AddData(wData, sizeof(wData));
3159 else
3161 AddString(Text.m_lpstr);
3164 AddData(&nCreationData, sizeof(nCreationData));
3166 if ((nCreationData != 0))
3168 ATLASSERT(pCreationData != NULL);
3169 AddData(pCreationData, nCreationData * sizeof(WORD));
3173 void AddStdControl(StdCtrlType CtrlType, WORD wId, short nX, short nY, short nWidth, short nHeight,
3174 DWORD dwStyle, DWORD dwExStyle, ATL::_U_STRINGorID Text, const WORD* pCreationData = NULL, WORD nCreationData = 0, DWORD dwHelpID = 0)
3176 AddControl(CtrlType, wId, nX, nY, nWidth, nHeight, dwStyle, dwExStyle, Text, pCreationData, nCreationData, dwHelpID);
3179 protected:
3180 void AddData(LPCVOID pData, size_t nData)
3182 ATLASSERT(pData != NULL);
3184 const size_t ALLOCATION_INCREMENT = 1024;
3186 if (m_pData == NULL)
3188 m_cAllocated = ((nData / ALLOCATION_INCREMENT) + 1) * ALLOCATION_INCREMENT;
3189 m_pPtr = m_pData = static_cast<LPBYTE>(::GlobalAlloc(GPTR, m_cAllocated));
3190 ATLASSERT(m_pData != NULL);
3192 else if (((m_pPtr - m_pData) + nData) > m_cAllocated)
3194 size_t ptrPos = (m_pPtr - m_pData);
3195 m_cAllocated += ((nData / ALLOCATION_INCREMENT) + 1) * ALLOCATION_INCREMENT;
3196 m_pData = static_cast<LPBYTE>(::GlobalReAlloc(m_pData, m_cAllocated, 0));
3197 ATLASSERT(m_pData != NULL);
3198 m_pPtr = m_pData + ptrPos;
3201 SecureHelper::memcpy_x(m_pPtr, m_cAllocated - (m_pPtr - m_pData), pData, nData);
3203 m_pPtr += nData;
3206 void AddString(LPCTSTR lpszStr)
3208 if (lpszStr == NULL)
3210 WCHAR szEmpty = 0;
3211 AddData(&szEmpty, sizeof(szEmpty));
3213 else
3215 USES_CONVERSION;
3216 LPCWSTR lpstr = T2CW(lpszStr);
3217 int nSize = lstrlenW(lpstr) + 1;
3218 AddData(lpstr, nSize * sizeof(WCHAR));
3222 LPBYTE m_pData;
3223 LPBYTE m_pPtr;
3224 SIZE_T m_cAllocated;
3228 ///////////////////////////////////////////////////////////////////////////////
3229 // Dialog and control macros for indirect dialogs
3231 // for DLGTEMPLATE
3232 #define BEGIN_DIALOG(x, y, width, height) \
3233 void DoInitTemplate() \
3235 bool bExTemplate = false; \
3236 short nX = x, nY = y, nWidth = width, nHeight = height; \
3237 LPCTSTR szCaption = NULL; \
3238 DWORD dwStyle = WS_POPUP | WS_BORDER | WS_SYSMENU; \
3239 DWORD dwExStyle = 0; \
3240 LPCTSTR szFontName = NULL; \
3241 WORD wFontSize = 0; \
3242 WORD wWeight = 0; \
3243 BYTE bItalic = 0; \
3244 BYTE bCharset = 0; \
3245 DWORD dwHelpID = 0; \
3246 ATL::_U_STRINGorID Menu = 0U; \
3247 ATL::_U_STRINGorID ClassName = 0U;
3249 // for DLGTEMPLATEEX
3250 #define BEGIN_DIALOG_EX(x, y, width, height, helpID) \
3251 void DoInitTemplate() \
3253 bool bExTemplate = true; \
3254 short nX = x, nY = y, nWidth = width, nHeight = height; \
3255 LPCTSTR szCaption = NULL; \
3256 DWORD dwStyle = WS_POPUP | WS_BORDER | WS_SYSMENU; \
3257 DWORD dwExStyle = 0; \
3258 LPCTSTR szFontName = NULL; \
3259 WORD wFontSize = 0; \
3260 WORD wWeight = 0; \
3261 BYTE bItalic = 0; \
3262 BYTE bCharset = 0; \
3263 DWORD dwHelpID = helpID; \
3264 ATL::_U_STRINGorID Menu = 0U; \
3265 ATL::_U_STRINGorID ClassName = 0U;
3267 #define END_DIALOG() \
3268 m_Template.Create(bExTemplate, szCaption, nX, nY, nWidth, nHeight, dwStyle, dwExStyle, szFontName, wFontSize, wWeight, bItalic, bCharset, dwHelpID, ClassName, Menu); \
3271 #define DIALOG_CAPTION(caption) \
3272 szCaption = caption;
3273 #define DIALOG_STYLE(style) \
3274 dwStyle = style;
3275 #define DIALOG_EXSTYLE(exStyle) \
3276 dwExStyle = exStyle;
3277 #define DIALOG_FONT(pointSize, typeFace) \
3278 wFontSize = pointSize; \
3279 szFontName = typeFace;
3280 #define DIALOG_FONT_EX(pointsize, typeface, weight, italic, charset) \
3281 ATLASSERT(bExTemplate); \
3282 wFontSize = pointsize; \
3283 szFontName = typeface; \
3284 wWeight = weight; \
3285 bItalic = italic; \
3286 bCharset = charset;
3287 #define DIALOG_MENU(menuName) \
3288 Menu = menuName;
3289 #define DIALOG_CLASS(className) \
3290 ClassName = className;
3292 #define BEGIN_CONTROLS_MAP() \
3293 void DoInitControls() \
3296 #define END_CONTROLS_MAP() \
3300 #define CONTROL_LTEXT(text, id, x, y, width, height, style, exStyle) \
3301 m_Template.AddStdControl(WTL::CMemDlgTemplate::CTRL_STATIC, (WORD)id, x, y, width, height, style | SS_LEFT | WS_GROUP, exStyle, text, NULL, 0);
3302 #define CONTROL_CTEXT(text, id, x, y, width, height, style, exStyle) \
3303 m_Template.AddStdControl(WTL::CMemDlgTemplate::CTRL_STATIC, (WORD)id, x, y, width, height, style | SS_CENTER | WS_GROUP, exStyle, text, NULL, 0);
3304 #define CONTROL_RTEXT(text, id, x, y, width, height, style, exStyle) \
3305 m_Template.AddStdControl(WTL::CMemDlgTemplate::CTRL_STATIC, (WORD)id, x, y, width, height, style | SS_RIGHT | WS_GROUP, exStyle, text, NULL, 0);
3306 #define CONTROL_PUSHBUTTON(text, id, x, y, width, height, style, exStyle) \
3307 m_Template.AddStdControl(WTL::CMemDlgTemplate::CTRL_BUTTON, (WORD)id, x, y, width, height, style | BS_PUSHBUTTON | WS_TABSTOP, exStyle, text, NULL, 0);
3308 #define CONTROL_DEFPUSHBUTTON(text, id, x, y, width, height, style, exStyle) \
3309 m_Template.AddStdControl(WTL::CMemDlgTemplate::CTRL_BUTTON, (WORD)id, x, y, width, height, style | BS_DEFPUSHBUTTON | WS_TABSTOP, exStyle, text, NULL, 0);
3310 #ifndef _WIN32_WCE
3311 #define CONTROL_PUSHBOX(text, id, x, y, width, height, style, exStyle) \
3312 m_Template.AddStdControl(WTL::CMemDlgTemplate::CTRL_BUTTON, (WORD)id, x, y, width, height, style | BS_PUSHBOX | WS_TABSTOP, exStyle, text, NULL, 0);
3313 #endif // !_WIN32_WCE
3314 #define CONTROL_STATE3(text, id, x, y, width, height, style, exStyle) \
3315 m_Template.AddStdControl(WTL::CMemDlgTemplate::CTRL_BUTTON, (WORD)id, x, y, width, height, style | BS_3STATE | WS_TABSTOP, exStyle, text, NULL, 0);
3316 #define CONTROL_AUTO3STATE(text, id, x, y, width, height, style, exStyle) \
3317 m_Template.AddStdControl(WTL::CMemDlgTemplate::CTRL_BUTTON, (WORD)id, x, y, width, height, style | BS_AUTO3STATE | WS_TABSTOP, exStyle, text, NULL, 0);
3318 #define CONTROL_CHECKBOX(text, id, x, y, width, height, style, exStyle) \
3319 m_Template.AddStdControl(WTL::CMemDlgTemplate::CTRL_BUTTON, (WORD)id, x, y, width, height, style | BS_CHECKBOX | WS_TABSTOP, exStyle, text, NULL, 0);
3320 #define CONTROL_AUTOCHECKBOX(text, id, x, y, width, height, style, exStyle) \
3321 m_Template.AddStdControl(WTL::CMemDlgTemplate::CTRL_BUTTON, (WORD)id, x, y, width, height, style | BS_AUTOCHECKBOX | WS_TABSTOP, exStyle, text, NULL, 0);
3322 #define CONTROL_RADIOBUTTON(text, id, x, y, width, height, style, exStyle) \
3323 m_Template.AddStdControl(WTL::CMemDlgTemplate::CTRL_BUTTON, (WORD)id, x, y, width, height, style | BS_RADIOBUTTON | WS_TABSTOP, exStyle, text, NULL, 0);
3324 #define CONTROL_AUTORADIOBUTTON(text, id, x, y, width, height, style, exStyle) \
3325 m_Template.AddStdControl(WTL::CMemDlgTemplate::CTRL_BUTTON, (WORD)id, x, y, width, height, style | BS_AUTORADIOBUTTON | WS_TABSTOP, exStyle, text, NULL, 0);
3326 #define CONTROL_COMBOBOX(id, x, y, width, height, style, exStyle) \
3327 m_Template.AddStdControl(WTL::CMemDlgTemplate::CTRL_COMBOBOX, (WORD)id, x, y, width, height, style | CBS_DROPDOWN | WS_TABSTOP, exStyle, (LPCTSTR)NULL, NULL, 0);
3328 #define CONTROL_EDITTEXT(id, x, y, width, height, style, exStyle) \
3329 m_Template.AddStdControl(WTL::CMemDlgTemplate::CTRL_EDIT, (WORD)id, x, y, width, height, style | ES_LEFT | WS_BORDER | WS_TABSTOP, exStyle, (LPCTSTR)NULL, NULL, 0);
3330 #define CONTROL_GROUPBOX(text, id, x, y, width, height, style, exStyle) \
3331 m_Template.AddStdControl(WTL::CMemDlgTemplate::CTRL_BUTTON, (WORD)id, x, y, width, height, style | BS_GROUPBOX, exStyle, text, NULL, 0);
3332 #define CONTROL_LISTBOX(id, x, y, width, height, style, exStyle) \
3333 m_Template.AddStdControl(WTL::CMemDlgTemplate::CTRL_LISTBOX, (WORD)id, x, y, width, height, style | LBS_NOTIFY | WS_BORDER, exStyle, (LPCTSTR)NULL, NULL, 0);
3334 #define CONTROL_SCROLLBAR(id, x, y, width, height, style, exStyle) \
3335 m_Template.AddStdControl(WTL::CMemDlgTemplate::CTRL_SCROLLBAR, (WORD)id, x, y, width, height, style | SBS_HORZ, exStyle, (LPCTSTR)NULL, NULL, 0);
3336 #define CONTROL_ICON(text, id, x, y, width, height, style, exStyle) \
3337 m_Template.AddStdControl(WTL::CMemDlgTemplate::CTRL_STATIC, (WORD)id, x, y, width, height, style | SS_ICON, exStyle, text, NULL, 0);
3338 #define CONTROL_CONTROL(text, id, className, style, x, y, width, height, exStyle) \
3339 m_Template.AddControl(className, (WORD)id, x, y, width, height, style, exStyle, text, NULL, 0);
3342 ///////////////////////////////////////////////////////////////////////////////
3343 // CIndirectDialogImpl - dialogs with template in memory
3345 template <class T, class TDlgTemplate = CMemDlgTemplate, class TBase = ATL::CDialogImpl<T, ATL::CWindow> >
3346 class ATL_NO_VTABLE CIndirectDialogImpl : public TBase
3348 public:
3349 enum { IDD = 0 }; // no dialog template resource
3351 TDlgTemplate m_Template;
3353 void CreateTemplate()
3355 T* pT = static_cast<T*>(this);
3356 pT->DoInitTemplate();
3357 pT->DoInitControls();
3360 INT_PTR DoModal(HWND hWndParent = ::GetActiveWindow(), LPARAM dwInitParam = NULL)
3362 T* pT = static_cast<T*>(this);
3363 ATLASSERT(pT->m_hWnd == NULL);
3365 if (!m_Template.IsValid())
3366 CreateTemplate();
3368 #if (_ATL_VER >= 0x0800)
3369 // Allocate the thunk structure here, where we can fail gracefully.
3370 BOOL result = m_thunk.Init(NULL, NULL);
3371 if (result == FALSE)
3373 SetLastError(ERROR_OUTOFMEMORY);
3374 return -1;
3376 #endif // (_ATL_VER >= 0x0800)
3378 ModuleHelper::AddCreateWndData(&m_thunk.cd, pT);
3380 #ifdef _DEBUG
3381 m_bModal = true;
3382 #endif // _DEBUG
3384 return ::DialogBoxIndirectParam(ModuleHelper::GetResourceInstance(), m_Template.GetTemplatePtr(), hWndParent, (DLGPROC)T::StartDialogProc, dwInitParam);
3387 HWND Create(HWND hWndParent, LPARAM dwInitParam = NULL)
3389 T* pT = static_cast<T*>(this);
3390 ATLASSERT(pT->m_hWnd == NULL);
3392 if (!m_Template.IsValid())
3393 CreateTemplate();
3395 #if (_ATL_VER >= 0x0800)
3396 // Allocate the thunk structure here, where we can fail gracefully.
3397 BOOL result = m_thunk.Init(NULL, NULL);
3398 if (result == FALSE)
3400 SetLastError(ERROR_OUTOFMEMORY);
3401 return NULL;
3403 #endif // (_ATL_VER >= 0x0800)
3405 ModuleHelper::AddCreateWndData(&m_thunk.cd, pT);
3407 #ifdef _DEBUG
3408 m_bModal = false;
3409 #endif // _DEBUG
3411 HWND hWnd = ::CreateDialogIndirectParam(ModuleHelper::GetResourceInstance(), (LPCDLGTEMPLATE)m_Template.GetTemplatePtr(), hWndParent, (DLGPROC)T::StartDialogProc, dwInitParam);
3412 ATLASSERT(m_hWnd == hWnd);
3414 return hWnd;
3417 // for CComControl
3418 HWND Create(HWND hWndParent, RECT&, LPARAM dwInitParam = NULL)
3420 return Create(hWndParent, dwInitParam);
3423 void DoInitTemplate()
3425 ATLASSERT(FALSE); // MUST be defined in derived class
3428 void DoInitControls()
3430 ATLASSERT(FALSE); // MUST be defined in derived class
3434 ///////////////////////////////////////////////////////////////////////////////
3435 // CPropertySheetWindow - client side for a property sheet
3437 class CPropertySheetWindow : public ATL::CWindow
3439 public:
3440 // Constructors
3441 CPropertySheetWindow(HWND hWnd = NULL) : ATL::CWindow(hWnd)
3444 CPropertySheetWindow& operator =(HWND hWnd)
3446 m_hWnd = hWnd;
3447 return *this;
3450 // Attributes
3451 int GetPageCount() const
3453 ATLASSERT(::IsWindow(m_hWnd));
3454 HWND hWndTabCtrl = GetTabControl();
3455 ATLASSERT(hWndTabCtrl != NULL);
3456 return (int)::SendMessage(hWndTabCtrl, TCM_GETITEMCOUNT, 0, 0L);
3459 HWND GetActivePage() const
3461 ATLASSERT(::IsWindow(m_hWnd));
3462 return (HWND)::SendMessage(m_hWnd, PSM_GETCURRENTPAGEHWND, 0, 0L);
3465 int GetActiveIndex() const
3467 ATLASSERT(::IsWindow(m_hWnd));
3468 HWND hWndTabCtrl = GetTabControl();
3469 ATLASSERT(hWndTabCtrl != NULL);
3470 return (int)::SendMessage(hWndTabCtrl, TCM_GETCURSEL, 0, 0L);
3473 BOOL SetActivePage(int nPageIndex)
3475 ATLASSERT(::IsWindow(m_hWnd));
3476 return (BOOL)::SendMessage(m_hWnd, PSM_SETCURSEL, nPageIndex, 0L);
3479 BOOL SetActivePage(HPROPSHEETPAGE hPage)
3481 ATLASSERT(::IsWindow(m_hWnd));
3482 ATLASSERT(hPage != NULL);
3483 return (BOOL)::SendMessage(m_hWnd, PSM_SETCURSEL, 0, (LPARAM)hPage);
3486 BOOL SetActivePageByID(int nPageID)
3488 ATLASSERT(::IsWindow(m_hWnd));
3489 return (BOOL)::SendMessage(m_hWnd, PSM_SETCURSELID, 0, nPageID);
3492 void SetTitle(LPCTSTR lpszText, UINT nStyle = 0)
3494 ATLASSERT(::IsWindow(m_hWnd));
3495 ATLASSERT((nStyle & ~PSH_PROPTITLE) == 0); // only PSH_PROPTITLE is valid
3496 ATLASSERT(lpszText != NULL);
3497 ::SendMessage(m_hWnd, PSM_SETTITLE, nStyle, (LPARAM)lpszText);
3500 HWND GetTabControl() const
3502 ATLASSERT(::IsWindow(m_hWnd));
3503 return (HWND)::SendMessage(m_hWnd, PSM_GETTABCONTROL, 0, 0L);
3506 void SetFinishText(LPCTSTR lpszText)
3508 ATLASSERT(::IsWindow(m_hWnd));
3509 ::SendMessage(m_hWnd, PSM_SETFINISHTEXT, 0, (LPARAM)lpszText);
3512 void SetWizardButtons(DWORD dwFlags)
3514 ATLASSERT(::IsWindow(m_hWnd));
3515 ::PostMessage(m_hWnd, PSM_SETWIZBUTTONS, 0, dwFlags);
3518 // Operations
3519 BOOL AddPage(HPROPSHEETPAGE hPage)
3521 ATLASSERT(::IsWindow(m_hWnd));
3522 ATLASSERT(hPage != NULL);
3523 return (BOOL)::SendMessage(m_hWnd, PSM_ADDPAGE, 0, (LPARAM)hPage);
3526 BOOL AddPage(LPCPROPSHEETPAGE pPage)
3528 ATLASSERT(::IsWindow(m_hWnd));
3529 ATLASSERT(pPage != NULL);
3530 HPROPSHEETPAGE hPage = ::CreatePropertySheetPage(pPage);
3531 if(hPage == NULL)
3532 return FALSE;
3533 return (BOOL)::SendMessage(m_hWnd, PSM_ADDPAGE, 0, (LPARAM)hPage);
3536 #ifndef _WIN32_WCE
3537 BOOL InsertPage(int nNewPageIndex, HPROPSHEETPAGE hPage)
3539 ATLASSERT(::IsWindow(m_hWnd));
3540 ATLASSERT(hPage != NULL);
3541 return (BOOL)::SendMessage(m_hWnd, PSM_INSERTPAGE, nNewPageIndex, (LPARAM)hPage);
3544 BOOL InsertPage(int nNewPageIndex, LPCPROPSHEETPAGE pPage)
3546 ATLASSERT(::IsWindow(m_hWnd));
3547 ATLASSERT(pPage != NULL);
3548 HPROPSHEETPAGE hPage = ::CreatePropertySheetPage(pPage);
3549 if(hPage == NULL)
3550 return FALSE;
3551 return (BOOL)::SendMessage(m_hWnd, PSM_INSERTPAGE, nNewPageIndex, (LPARAM)hPage);
3554 BOOL InsertPage(HPROPSHEETPAGE hPageInsertAfter, HPROPSHEETPAGE hPage)
3556 ATLASSERT(::IsWindow(m_hWnd));
3557 ATLASSERT(hPage != NULL);
3558 return (BOOL)::SendMessage(m_hWnd, PSM_INSERTPAGE, (WPARAM)hPageInsertAfter, (LPARAM)hPage);
3561 BOOL InsertPage(HPROPSHEETPAGE hPageInsertAfter, LPCPROPSHEETPAGE pPage)
3563 ATLASSERT(::IsWindow(m_hWnd));
3564 ATLASSERT(pPage != NULL);
3565 HPROPSHEETPAGE hPage = ::CreatePropertySheetPage(pPage);
3566 if(hPage == NULL)
3567 return FALSE;
3568 return (BOOL)::SendMessage(m_hWnd, PSM_INSERTPAGE, (WPARAM)hPageInsertAfter, (LPARAM)hPage);
3570 #endif // !_WIN32_WCE
3572 void RemovePage(int nPageIndex)
3574 ATLASSERT(::IsWindow(m_hWnd));
3575 ::SendMessage(m_hWnd, PSM_REMOVEPAGE, nPageIndex, 0L);
3578 void RemovePage(HPROPSHEETPAGE hPage)
3580 ATLASSERT(::IsWindow(m_hWnd));
3581 ATLASSERT(hPage != NULL);
3582 ::SendMessage(m_hWnd, PSM_REMOVEPAGE, 0, (LPARAM)hPage);
3585 BOOL PressButton(int nButton)
3587 ATLASSERT(::IsWindow(m_hWnd));
3588 return (BOOL)::SendMessage(m_hWnd, PSM_PRESSBUTTON, nButton, 0L);
3591 BOOL Apply()
3593 ATLASSERT(::IsWindow(m_hWnd));
3594 return (BOOL)::SendMessage(m_hWnd, PSM_APPLY, 0, 0L);
3597 void CancelToClose()
3599 ATLASSERT(::IsWindow(m_hWnd));
3600 ::SendMessage(m_hWnd, PSM_CANCELTOCLOSE, 0, 0L);
3603 void SetModified(HWND hWndPage, BOOL bChanged = TRUE)
3605 ATLASSERT(::IsWindow(m_hWnd));
3606 ATLASSERT(::IsWindow(hWndPage));
3607 UINT uMsg = bChanged ? PSM_CHANGED : PSM_UNCHANGED;
3608 ::SendMessage(m_hWnd, uMsg, (WPARAM)hWndPage, 0L);
3611 LRESULT QuerySiblings(WPARAM wParam, LPARAM lParam)
3613 ATLASSERT(::IsWindow(m_hWnd));
3614 return ::SendMessage(m_hWnd, PSM_QUERYSIBLINGS, wParam, lParam);
3617 void RebootSystem()
3619 ATLASSERT(::IsWindow(m_hWnd));
3620 ::SendMessage(m_hWnd, PSM_REBOOTSYSTEM, 0, 0L);
3623 void RestartWindows()
3625 ATLASSERT(::IsWindow(m_hWnd));
3626 ::SendMessage(m_hWnd, PSM_RESTARTWINDOWS, 0, 0L);
3629 BOOL IsDialogMessage(LPMSG lpMsg)
3631 ATLASSERT(::IsWindow(m_hWnd));
3632 return (BOOL)::SendMessage(m_hWnd, PSM_ISDIALOGMESSAGE, 0, (LPARAM)lpMsg);
3635 #if (_WIN32_IE >= 0x0500) && !defined(_WIN32_WCE)
3636 int HwndToIndex(HWND hWnd) const
3638 ATLASSERT(::IsWindow(m_hWnd));
3639 return (int)::SendMessage(m_hWnd, PSM_HWNDTOINDEX, (WPARAM)hWnd, 0L);
3642 HWND IndexToHwnd(int nIndex) const
3644 ATLASSERT(::IsWindow(m_hWnd));
3645 return (HWND)::SendMessage(m_hWnd, PSM_INDEXTOHWND, nIndex, 0L);
3648 int PageToIndex(HPROPSHEETPAGE hPage) const
3650 ATLASSERT(::IsWindow(m_hWnd));
3651 return (int)::SendMessage(m_hWnd, PSM_PAGETOINDEX, 0, (LPARAM)hPage);
3654 HPROPSHEETPAGE IndexToPage(int nIndex) const
3656 ATLASSERT(::IsWindow(m_hWnd));
3657 return (HPROPSHEETPAGE)::SendMessage(m_hWnd, PSM_INDEXTOPAGE, nIndex, 0L);
3660 int IdToIndex(int nID) const
3662 ATLASSERT(::IsWindow(m_hWnd));
3663 return (int)::SendMessage(m_hWnd, PSM_IDTOINDEX, 0, nID);
3666 int IndexToId(int nIndex) const
3668 ATLASSERT(::IsWindow(m_hWnd));
3669 return (int)::SendMessage(m_hWnd, PSM_INDEXTOID, nIndex, 0L);
3672 int GetResult() const
3674 ATLASSERT(::IsWindow(m_hWnd));
3675 return (int)::SendMessage(m_hWnd, PSM_GETRESULT, 0, 0L);
3678 BOOL RecalcPageSizes()
3680 ATLASSERT(::IsWindow(m_hWnd));
3681 return (BOOL)::SendMessage(m_hWnd, PSM_RECALCPAGESIZES, 0, 0L);
3684 void SetHeaderTitle(int nIndex, LPCTSTR lpstrHeaderTitle)
3686 ATLASSERT(::IsWindow(m_hWnd));
3687 ::SendMessage(m_hWnd, PSM_SETHEADERTITLE, nIndex, (LPARAM)lpstrHeaderTitle);
3690 void SetHeaderSubTitle(int nIndex, LPCTSTR lpstrHeaderSubTitle)
3692 ATLASSERT(::IsWindow(m_hWnd));
3693 ::SendMessage(m_hWnd, PSM_SETHEADERSUBTITLE, nIndex, (LPARAM)lpstrHeaderSubTitle);
3695 #endif // (_WIN32_IE >= 0x0500) && !defined(_WIN32_WCE)
3697 // Implementation - override to prevent usage
3698 HWND Create(LPCTSTR, HWND, ATL::_U_RECT = NULL, LPCTSTR = NULL, DWORD = 0, DWORD = 0, ATL::_U_MENUorID = 0U, LPVOID = NULL)
3700 ATLASSERT(FALSE);
3701 return NULL;
3705 ///////////////////////////////////////////////////////////////////////////////
3706 // CPropertySheetImpl - implements a property sheet
3708 template <class T, class TBase = CPropertySheetWindow>
3709 class ATL_NO_VTABLE CPropertySheetImpl : public ATL::CWindowImplBaseT< TBase >
3711 public:
3712 PROPSHEETHEADER m_psh;
3713 ATL::CSimpleArray<HPROPSHEETPAGE> m_arrPages;
3715 #if defined(_AYGSHELL_H_) || defined(__AYGSHELL_H__) // PPC specific
3716 #ifndef PROPSHEET_LINK_SIZE
3717 #define PROPSHEET_LINK_SIZE 128
3718 #endif // PROPSHEET_LINK_SIZE
3719 TCHAR m_szLink[PROPSHEET_LINK_SIZE];
3720 static LPCTSTR m_pszTitle;
3721 static LPCTSTR m_pszLink;
3722 #endif // defined(_AYGSHELL_H_) || defined(__AYGSHELL_H__)
3724 // Construction/Destruction
3725 CPropertySheetImpl(ATL::_U_STRINGorID title = (LPCTSTR)NULL, UINT uStartPage = 0, HWND hWndParent = NULL)
3727 memset(&m_psh, 0, sizeof(PROPSHEETHEADER));
3728 m_psh.dwSize = sizeof(PROPSHEETHEADER);
3729 m_psh.dwFlags = PSH_USECALLBACK;
3730 m_psh.hInstance = ModuleHelper::GetResourceInstance();
3731 m_psh.phpage = NULL; // will be set later
3732 m_psh.nPages = 0; // will be set later
3733 m_psh.pszCaption = title.m_lpstr;
3734 m_psh.nStartPage = uStartPage;
3735 m_psh.hwndParent = hWndParent; // if NULL, will be set in DoModal/Create
3736 m_psh.pfnCallback = T::PropSheetCallback;
3738 #if defined(_AYGSHELL_H_) || defined(__AYGSHELL_H__) // PPC specific
3739 m_psh.dwFlags |= PSH_MAXIMIZE;
3740 m_szLink[0] = 0;
3741 #endif // defined(_AYGSHELL_H_) || defined(__AYGSHELL_H__)
3744 ~CPropertySheetImpl()
3746 if(m_arrPages.GetSize() > 0) // sheet never created, destroy all pages
3748 for(int i = 0; i < m_arrPages.GetSize(); i++)
3749 ::DestroyPropertySheetPage((HPROPSHEETPAGE)m_arrPages[i]);
3753 // Callback function and overrideables
3754 static int CALLBACK PropSheetCallback(HWND hWnd, UINT uMsg, LPARAM lParam)
3756 lParam; // avoid level 4 warning
3757 int nRet = 0;
3759 if(uMsg == PSCB_INITIALIZED)
3761 ATLASSERT(hWnd != NULL);
3762 T* pT = (T*)ModuleHelper::ExtractCreateWndData();
3763 // subclass the sheet window
3764 pT->SubclassWindow(hWnd);
3765 // remove page handles array
3766 pT->_CleanUpPages();
3768 #if defined(_AYGSHELL_H_) || defined(__AYGSHELL_H__) // PPC specific
3769 m_pszTitle = pT->m_psh.pszCaption;
3770 if(*pT->m_szLink != 0)
3771 m_pszLink = pT->m_szLink;
3772 #endif // defined(_AYGSHELL_H_) || defined(__AYGSHELL_H__) // PPC specific
3774 pT->OnSheetInitialized();
3776 #if defined(_AYGSHELL_H_) || defined(__AYGSHELL_H__) // PPC specific uMsg
3777 else
3779 switch(uMsg)
3781 case PSCB_GETVERSION :
3782 nRet = COMCTL32_VERSION;
3783 break;
3784 case PSCB_GETTITLE :
3785 if(m_pszTitle != NULL)
3787 lstrcpy((LPTSTR)lParam, m_pszTitle);
3788 m_pszTitle = NULL;
3790 break;
3791 case PSCB_GETLINKTEXT:
3792 if(m_pszLink != NULL)
3794 lstrcpy((LPTSTR)lParam, m_pszLink);
3795 m_pszLink = NULL;
3797 break;
3798 default:
3799 break;
3802 #endif // defined(_AYGSHELL_H_) || defined(__AYGSHELL_H__)
3804 return nRet;
3807 void OnSheetInitialized()
3811 // Create method
3812 HWND Create(HWND hWndParent = NULL)
3814 ATLASSERT(m_hWnd == NULL);
3816 m_psh.dwFlags |= PSH_MODELESS;
3817 if(m_psh.hwndParent == NULL)
3818 m_psh.hwndParent = hWndParent;
3819 m_psh.phpage = (HPROPSHEETPAGE*)m_arrPages.GetData();
3820 m_psh.nPages = m_arrPages.GetSize();
3822 T* pT = static_cast<T*>(this);
3823 ModuleHelper::AddCreateWndData(&pT->m_thunk.cd, pT);
3825 HWND hWnd = (HWND)::PropertySheet(&m_psh);
3826 _CleanUpPages(); // ensure clean-up, required if call failed
3828 ATLASSERT(m_hWnd == hWnd);
3830 return hWnd;
3833 INT_PTR DoModal(HWND hWndParent = ::GetActiveWindow())
3835 ATLASSERT(m_hWnd == NULL);
3837 m_psh.dwFlags &= ~PSH_MODELESS;
3838 if(m_psh.hwndParent == NULL)
3839 m_psh.hwndParent = hWndParent;
3840 m_psh.phpage = (HPROPSHEETPAGE*)m_arrPages.GetData();
3841 m_psh.nPages = m_arrPages.GetSize();
3843 T* pT = static_cast<T*>(this);
3844 ModuleHelper::AddCreateWndData(&pT->m_thunk.cd, pT);
3846 INT_PTR nRet = ::PropertySheet(&m_psh);
3847 _CleanUpPages(); // ensure clean-up, required if call failed
3849 return nRet;
3852 // implementation helper - clean up pages array
3853 void _CleanUpPages()
3855 m_psh.nPages = 0;
3856 m_psh.phpage = NULL;
3857 m_arrPages.RemoveAll();
3860 // Attributes (extended overrides of client class methods)
3861 // These now can be called before the sheet is created
3862 // Note: Calling these after the sheet is created gives unpredictable results
3863 int GetPageCount() const
3865 if(m_hWnd == NULL) // not created yet
3866 return m_arrPages.GetSize();
3867 return TBase::GetPageCount();
3870 int GetActiveIndex() const
3872 if(m_hWnd == NULL) // not created yet
3873 return m_psh.nStartPage;
3874 return TBase::GetActiveIndex();
3877 HPROPSHEETPAGE GetPage(int nPageIndex) const
3879 ATLASSERT(m_hWnd == NULL); // can't do this after it's created
3880 return (HPROPSHEETPAGE)m_arrPages[nPageIndex];
3883 int GetPageIndex(HPROPSHEETPAGE hPage) const
3885 ATLASSERT(m_hWnd == NULL); // can't do this after it's created
3886 return m_arrPages.Find((HPROPSHEETPAGE&)hPage);
3889 BOOL SetActivePage(int nPageIndex)
3891 if(m_hWnd == NULL) // not created yet
3893 ATLASSERT(nPageIndex >= 0 && nPageIndex < m_arrPages.GetSize());
3894 m_psh.nStartPage = nPageIndex;
3895 return TRUE;
3897 return TBase::SetActivePage(nPageIndex);
3900 BOOL SetActivePage(HPROPSHEETPAGE hPage)
3902 ATLASSERT(hPage != NULL);
3903 if (m_hWnd == NULL) // not created yet
3905 int nPageIndex = GetPageIndex(hPage);
3906 if(nPageIndex == -1)
3907 return FALSE;
3909 return SetActivePage(nPageIndex);
3911 return TBase::SetActivePage(hPage);
3915 void SetTitle(LPCTSTR lpszText, UINT nStyle = 0)
3917 ATLASSERT((nStyle & ~PSH_PROPTITLE) == 0); // only PSH_PROPTITLE is valid
3918 ATLASSERT(lpszText != NULL);
3920 if(m_hWnd == NULL)
3922 // set internal state
3923 m_psh.pszCaption = lpszText; // must exist until sheet is created
3924 m_psh.dwFlags &= ~PSH_PROPTITLE;
3925 m_psh.dwFlags |= nStyle;
3927 else
3929 // set external state
3930 TBase::SetTitle(lpszText, nStyle);
3934 #if defined(_AYGSHELL_H_) || defined(__AYGSHELL_H__) // PPC specific Link field
3935 void SetLinkText(LPCTSTR lpszText)
3937 ATLASSERT(lpszText != NULL);
3938 ATLASSERT(lstrlen(lpszText) < PROPSHEET_LINK_SIZE);
3939 lstrcpy(m_szLink, lpszText);
3941 #endif // defined(_AYGSHELL_H_) || defined(__AYGSHELL_H__)
3943 void SetWizardMode()
3945 m_psh.dwFlags |= PSH_WIZARD;
3948 void EnableHelp()
3950 m_psh.dwFlags |= PSH_HASHELP;
3953 // Operations
3954 BOOL AddPage(HPROPSHEETPAGE hPage)
3956 ATLASSERT(hPage != NULL);
3957 BOOL bRet = FALSE;
3958 if(m_hWnd != NULL)
3959 bRet = TBase::AddPage(hPage);
3960 else // sheet not created yet, use internal data
3961 bRet = m_arrPages.Add((HPROPSHEETPAGE&)hPage);
3962 return bRet;
3965 BOOL AddPage(LPCPROPSHEETPAGE pPage)
3967 ATLASSERT(pPage != NULL);
3968 HPROPSHEETPAGE hPage = ::CreatePropertySheetPage(pPage);
3969 if(hPage == NULL)
3970 return FALSE;
3971 BOOL bRet = AddPage(hPage);
3972 if(!bRet)
3973 ::DestroyPropertySheetPage(hPage);
3974 return bRet;
3977 BOOL RemovePage(HPROPSHEETPAGE hPage)
3979 ATLASSERT(hPage != NULL);
3980 if (m_hWnd == NULL) // not created yet
3982 int nPage = GetPageIndex(hPage);
3983 if(nPage == -1)
3984 return FALSE;
3985 return RemovePage(nPage);
3987 TBase::RemovePage(hPage);
3988 return TRUE;
3992 BOOL RemovePage(int nPageIndex)
3994 BOOL bRet = TRUE;
3995 if(m_hWnd != NULL)
3996 TBase::RemovePage(nPageIndex);
3997 else // sheet not created yet, use internal data
3998 bRet = m_arrPages.RemoveAt(nPageIndex);
3999 return bRet;
4002 #if (_WIN32_IE >= 0x0400) && !defined(_WIN32_WCE)
4003 void SetHeader(LPCTSTR szbmHeader)
4005 ATLASSERT(m_hWnd == NULL); // can't do this after it's created
4007 m_psh.dwFlags &= ~PSH_WIZARD;
4008 m_psh.dwFlags |= (PSH_HEADER | PSH_WIZARD97);
4009 m_psh.pszbmHeader = szbmHeader;
4012 void SetHeader(HBITMAP hbmHeader)
4014 ATLASSERT(m_hWnd == NULL); // can't do this after it's created
4016 m_psh.dwFlags &= ~PSH_WIZARD;
4017 m_psh.dwFlags |= (PSH_HEADER | PSH_USEHBMHEADER | PSH_WIZARD97);
4018 m_psh.hbmHeader = hbmHeader;
4021 void SetWatermark(LPCTSTR szbmWatermark, HPALETTE hplWatermark = NULL)
4023 ATLASSERT(m_hWnd == NULL); // can't do this after it's created
4025 m_psh.dwFlags &= ~PSH_WIZARD;
4026 m_psh.dwFlags |= PSH_WATERMARK | PSH_WIZARD97;
4027 m_psh.pszbmWatermark = szbmWatermark;
4029 if (hplWatermark != NULL)
4031 m_psh.dwFlags |= PSH_USEHPLWATERMARK;
4032 m_psh.hplWatermark = hplWatermark;
4036 void SetWatermark(HBITMAP hbmWatermark, HPALETTE hplWatermark = NULL)
4038 ATLASSERT(m_hWnd == NULL); // can't do this after it's created
4040 m_psh.dwFlags &= ~PSH_WIZARD;
4041 m_psh.dwFlags |= (PSH_WATERMARK | PSH_USEHBMWATERMARK | PSH_WIZARD97);
4042 m_psh.hbmWatermark = hbmWatermark;
4044 if (hplWatermark != NULL)
4046 m_psh.dwFlags |= PSH_USEHPLWATERMARK;
4047 m_psh.hplWatermark = hplWatermark;
4051 void StretchWatermark(bool bStretchWatermark)
4053 ATLASSERT(m_hWnd == NULL); // can't do this after it's created
4054 if (bStretchWatermark)
4055 m_psh.dwFlags |= PSH_STRETCHWATERMARK;
4056 else
4057 m_psh.dwFlags &= ~PSH_STRETCHWATERMARK;
4059 #endif // (_WIN32_IE >= 0x0400) && !defined(_WIN32_WCE)
4061 // Message map and handlers
4062 BEGIN_MSG_MAP(CPropertySheetImpl)
4063 MESSAGE_HANDLER(WM_COMMAND, OnCommand)
4064 MESSAGE_HANDLER(WM_SYSCOMMAND, OnSysCommand)
4065 END_MSG_MAP()
4067 LRESULT OnCommand(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& /*bHandled*/)
4069 LRESULT lRet = DefWindowProc(uMsg, wParam, lParam);
4070 if(HIWORD(wParam) == BN_CLICKED && (LOWORD(wParam) == IDOK || LOWORD(wParam) == IDCANCEL) &&
4071 ((m_psh.dwFlags & PSH_MODELESS) != 0) && (GetActivePage() == NULL))
4072 DestroyWindow();
4073 return lRet;
4076 LRESULT OnSysCommand(UINT /*uMsg*/, WPARAM wParam, LPARAM /*lParam*/, BOOL& bHandled)
4078 if(((m_psh.dwFlags & PSH_MODELESS) == PSH_MODELESS) && ((wParam & 0xFFF0) == SC_CLOSE))
4079 SendMessage(WM_CLOSE);
4080 else
4081 bHandled = FALSE;
4082 return 0;
4086 #if defined(_AYGSHELL_H_) || defined(__AYGSHELL_H__) // PPC static pointers
4087 template < class T, class TBase >
4088 LPCWSTR CPropertySheetImpl<T,TBase>::m_pszTitle = NULL;
4089 template < class T, class TBase>
4090 LPCWSTR CPropertySheetImpl<T,TBase>::m_pszLink = NULL;
4091 #endif // defined(_AYGSHELL_H_) || defined(__AYGSHELL_H__)
4093 // for non-customized sheets
4094 class CPropertySheet : public CPropertySheetImpl<CPropertySheet>
4096 public:
4097 CPropertySheet(ATL::_U_STRINGorID title = (LPCTSTR)NULL, UINT uStartPage = 0, HWND hWndParent = NULL)
4098 : CPropertySheetImpl<CPropertySheet>(title, uStartPage, hWndParent)
4103 ///////////////////////////////////////////////////////////////////////////////
4104 // CPropertyPageWindow - client side for a property page
4106 class CPropertyPageWindow : public ATL::CWindow
4108 public:
4109 // Constructors
4110 CPropertyPageWindow(HWND hWnd = NULL) : ATL::CWindow(hWnd)
4113 CPropertyPageWindow& operator =(HWND hWnd)
4115 m_hWnd = hWnd;
4116 return *this;
4119 // Attributes
4120 CPropertySheetWindow GetPropertySheet() const
4122 ATLASSERT(::IsWindow(m_hWnd));
4123 return CPropertySheetWindow(GetParent());
4126 // Operations
4127 BOOL Apply()
4129 ATLASSERT(::IsWindow(m_hWnd));
4130 ATLASSERT(GetParent() != NULL);
4131 return GetPropertySheet().Apply();
4134 void CancelToClose()
4136 ATLASSERT(::IsWindow(m_hWnd));
4137 ATLASSERT(GetParent() != NULL);
4138 GetPropertySheet().CancelToClose();
4141 void SetModified(BOOL bChanged = TRUE)
4143 ATLASSERT(::IsWindow(m_hWnd));
4144 ATLASSERT(GetParent() != NULL);
4145 GetPropertySheet().SetModified(m_hWnd, bChanged);
4148 LRESULT QuerySiblings(WPARAM wParam, LPARAM lParam)
4150 ATLASSERT(::IsWindow(m_hWnd));
4151 ATLASSERT(GetParent() != NULL);
4152 return GetPropertySheet().QuerySiblings(wParam, lParam);
4155 void RebootSystem()
4157 ATLASSERT(::IsWindow(m_hWnd));
4158 ATLASSERT(GetParent() != NULL);
4159 GetPropertySheet().RebootSystem();
4162 void RestartWindows()
4164 ATLASSERT(::IsWindow(m_hWnd));
4165 ATLASSERT(GetParent() != NULL);
4166 GetPropertySheet().RestartWindows();
4169 void SetWizardButtons(DWORD dwFlags)
4171 ATLASSERT(::IsWindow(m_hWnd));
4172 ATLASSERT(GetParent() != NULL);
4173 GetPropertySheet().SetWizardButtons(dwFlags);
4176 // Implementation - overrides to prevent usage
4177 HWND Create(LPCTSTR, HWND, ATL::_U_RECT = NULL, LPCTSTR = NULL, DWORD = 0, DWORD = 0, ATL::_U_MENUorID = 0U, LPVOID = NULL)
4179 ATLASSERT(FALSE);
4180 return NULL;
4184 ///////////////////////////////////////////////////////////////////////////////
4185 // CPropertyPageImpl - implements a property page
4187 template <class T, class TBase = CPropertyPageWindow>
4188 class ATL_NO_VTABLE CPropertyPageImpl : public ATL::CDialogImplBaseT< TBase >
4190 public:
4191 PROPSHEETPAGE m_psp;
4193 operator PROPSHEETPAGE*() { return &m_psp; }
4195 // Construction
4196 CPropertyPageImpl(ATL::_U_STRINGorID title = (LPCTSTR)NULL)
4198 // initialize PROPSHEETPAGE struct
4199 memset(&m_psp, 0, sizeof(PROPSHEETPAGE));
4200 m_psp.dwSize = sizeof(PROPSHEETPAGE);
4201 m_psp.dwFlags = PSP_USECALLBACK;
4202 m_psp.hInstance = ModuleHelper::GetResourceInstance();
4203 T* pT = static_cast<T*>(this);
4204 m_psp.pszTemplate = MAKEINTRESOURCE(pT->IDD);
4205 m_psp.pfnDlgProc = (DLGPROC)T::StartDialogProc;
4206 m_psp.pfnCallback = T::PropPageCallback;
4207 m_psp.lParam = (LPARAM)pT;
4209 if(title.m_lpstr != NULL)
4210 SetTitle(title);
4213 // Callback function and overrideables
4214 static UINT CALLBACK PropPageCallback(HWND hWnd, UINT uMsg, LPPROPSHEETPAGE ppsp)
4216 hWnd; // avoid level 4 warning
4217 ATLASSERT(hWnd == NULL);
4218 T* pT = (T*)ppsp->lParam;
4219 UINT uRet = 0;
4221 switch(uMsg)
4223 case PSPCB_CREATE:
4225 ATL::CDialogImplBaseT< TBase >* pPage = (ATL::CDialogImplBaseT< TBase >*)pT;
4226 ModuleHelper::AddCreateWndData(&pPage->m_thunk.cd, pPage);
4227 uRet = pT->OnPageCreate() ? 1 : 0;
4229 break;
4230 #if (_WIN32_IE >= 0x0500)
4231 case PSPCB_ADDREF:
4232 pT->OnPageAddRef();
4233 break;
4234 #endif // (_WIN32_IE >= 0x0500)
4235 case PSPCB_RELEASE:
4236 pT->OnPageRelease();
4237 break;
4238 default:
4239 break;
4242 return uRet;
4245 bool OnPageCreate()
4247 return true; // true - allow page to be created, false - prevent creation
4250 #if (_WIN32_IE >= 0x0500)
4251 void OnPageAddRef()
4254 #endif // (_WIN32_IE >= 0x0500)
4256 void OnPageRelease()
4260 // Create method
4261 HPROPSHEETPAGE Create()
4263 return ::CreatePropertySheetPage(&m_psp);
4266 // Attributes
4267 void SetTitle(ATL::_U_STRINGorID title)
4269 m_psp.pszTitle = title.m_lpstr;
4270 m_psp.dwFlags |= PSP_USETITLE;
4273 #if (_WIN32_IE >= 0x0500) && !defined(_WIN32_WCE)
4274 void SetHeaderTitle(LPCTSTR lpstrHeaderTitle)
4276 ATLASSERT(m_hWnd == NULL); // can't do this after it's created
4277 m_psp.dwFlags |= PSP_USEHEADERTITLE;
4278 m_psp.pszHeaderTitle = lpstrHeaderTitle;
4281 void SetHeaderSubTitle(LPCTSTR lpstrHeaderSubTitle)
4283 ATLASSERT(m_hWnd == NULL); // can't do this after it's created
4284 m_psp.dwFlags |= PSP_USEHEADERSUBTITLE;
4285 m_psp.pszHeaderSubTitle = lpstrHeaderSubTitle;
4287 #endif // (_WIN32_IE >= 0x0500) && !defined(_WIN32_WCE)
4289 // Operations
4290 void EnableHelp()
4292 m_psp.dwFlags |= PSP_HASHELP;
4295 // Message map and handlers
4296 BEGIN_MSG_MAP(CPropertyPageImpl)
4297 MESSAGE_HANDLER(WM_NOTIFY, OnNotify)
4298 END_MSG_MAP()
4300 // NOTE: Define _WTL_NEW_PAGE_NOTIFY_HANDLERS to use new notification
4301 // handlers that return direct values without any restrictions
4302 LRESULT OnNotify(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM lParam, BOOL& bHandled)
4304 #ifndef _WIN32_WCE
4305 // This notification is sometimes received on Windows CE after the window is already destroyed
4306 ATLASSERT(::IsWindow(m_hWnd));
4307 #endif
4308 NMHDR* pNMHDR = (NMHDR*)lParam;
4310 // don't handle messages not from the page/sheet itself
4311 if(pNMHDR->hwndFrom != m_hWnd && pNMHDR->hwndFrom != ::GetParent(m_hWnd))
4313 bHandled = FALSE;
4314 return 1;
4316 #ifdef _WIN32_WCE
4317 ATLASSERT(::IsWindow(m_hWnd));
4318 #endif
4320 T* pT = static_cast<T*>(this);
4321 LRESULT lResult = 0;
4322 switch(pNMHDR->code)
4324 #ifdef _WTL_NEW_PAGE_NOTIFY_HANDLERS
4325 case PSN_SETACTIVE:
4326 lResult = pT->OnSetActive();
4327 break;
4328 case PSN_KILLACTIVE:
4329 lResult = pT->OnKillActive();
4330 break;
4331 case PSN_APPLY:
4332 lResult = pT->OnApply();
4333 break;
4334 case PSN_RESET:
4335 pT->OnReset();
4336 break;
4337 case PSN_QUERYCANCEL:
4338 lResult = pT->OnQueryCancel();
4339 break;
4340 case PSN_WIZNEXT:
4341 lResult = pT->OnWizardNext();
4342 break;
4343 case PSN_WIZBACK:
4344 lResult = pT->OnWizardBack();
4345 break;
4346 case PSN_WIZFINISH:
4347 lResult = pT->OnWizardFinish();
4348 break;
4349 case PSN_HELP:
4350 pT->OnHelp();
4351 break;
4352 #ifndef _WIN32_WCE
4353 #if (_WIN32_IE >= 0x0400)
4354 case PSN_GETOBJECT:
4355 if(!pT->OnGetObject((LPNMOBJECTNOTIFY)lParam))
4356 bHandled = FALSE;
4357 break;
4358 #endif // (_WIN32_IE >= 0x0400)
4359 #if (_WIN32_IE >= 0x0500)
4360 case PSN_TRANSLATEACCELERATOR:
4362 LPPSHNOTIFY lpPSHNotify = (LPPSHNOTIFY)lParam;
4363 lResult = pT->OnTranslateAccelerator((LPMSG)lpPSHNotify->lParam);
4365 break;
4366 case PSN_QUERYINITIALFOCUS:
4368 LPPSHNOTIFY lpPSHNotify = (LPPSHNOTIFY)lParam;
4369 lResult = (LRESULT)pT->OnQueryInitialFocus((HWND)lpPSHNotify->lParam);
4371 break;
4372 #endif // (_WIN32_IE >= 0x0500)
4373 #endif // !_WIN32_WCE
4375 #else // !_WTL_NEW_PAGE_NOTIFY_HANDLERS
4376 case PSN_SETACTIVE:
4377 lResult = pT->OnSetActive() ? 0 : -1;
4378 break;
4379 case PSN_KILLACTIVE:
4380 lResult = !pT->OnKillActive();
4381 break;
4382 case PSN_APPLY:
4383 lResult = pT->OnApply() ? PSNRET_NOERROR : PSNRET_INVALID_NOCHANGEPAGE;
4384 break;
4385 case PSN_RESET:
4386 pT->OnReset();
4387 break;
4388 case PSN_QUERYCANCEL:
4389 lResult = !pT->OnQueryCancel();
4390 break;
4391 case PSN_WIZNEXT:
4392 lResult = pT->OnWizardNext();
4393 break;
4394 case PSN_WIZBACK:
4395 lResult = pT->OnWizardBack();
4396 break;
4397 case PSN_WIZFINISH:
4398 lResult = !pT->OnWizardFinish();
4399 break;
4400 case PSN_HELP:
4401 pT->OnHelp();
4402 break;
4403 #ifndef _WIN32_WCE
4404 #if (_WIN32_IE >= 0x0400)
4405 case PSN_GETOBJECT:
4406 if(!pT->OnGetObject((LPNMOBJECTNOTIFY)lParam))
4407 bHandled = FALSE;
4408 break;
4409 #endif // (_WIN32_IE >= 0x0400)
4410 #if (_WIN32_IE >= 0x0500)
4411 case PSN_TRANSLATEACCELERATOR:
4413 LPPSHNOTIFY lpPSHNotify = (LPPSHNOTIFY)lParam;
4414 lResult = pT->OnTranslateAccelerator((LPMSG)lpPSHNotify->lParam) ? PSNRET_MESSAGEHANDLED : PSNRET_NOERROR;
4416 break;
4417 case PSN_QUERYINITIALFOCUS:
4419 LPPSHNOTIFY lpPSHNotify = (LPPSHNOTIFY)lParam;
4420 lResult = (LRESULT)pT->OnQueryInitialFocus((HWND)lpPSHNotify->lParam);
4422 break;
4423 #endif // (_WIN32_IE >= 0x0500)
4424 #endif // !_WIN32_WCE
4426 #endif // !_WTL_NEW_PAGE_NOTIFY_HANDLERS
4427 default:
4428 bHandled = FALSE; // not handled
4431 return lResult;
4434 // Overridables
4435 // NOTE: Define _WTL_NEW_PAGE_NOTIFY_HANDLERS to use new notification
4436 // handlers that return direct values without any restrictions
4437 #ifdef _WTL_NEW_PAGE_NOTIFY_HANDLERS
4438 int OnSetActive()
4440 // 0 = allow activate
4441 // -1 = go back that was active
4442 // page ID = jump to page
4443 return 0;
4446 BOOL OnKillActive()
4448 // FALSE = allow deactivate
4449 // TRUE = prevent deactivation
4450 return FALSE;
4453 int OnApply()
4455 // PSNRET_NOERROR = apply OK
4456 // PSNRET_INVALID = apply not OK, return to this page
4457 // PSNRET_INVALID_NOCHANGEPAGE = apply not OK, don't change focus
4458 return PSNRET_NOERROR;
4461 void OnReset()
4465 BOOL OnQueryCancel()
4467 // FALSE = allow cancel
4468 // TRUE = prevent cancel
4469 return FALSE;
4472 int OnWizardBack()
4474 // 0 = goto previous page
4475 // -1 = prevent page change
4476 // >0 = jump to page by dlg ID
4477 return 0;
4480 int OnWizardNext()
4482 // 0 = goto next page
4483 // -1 = prevent page change
4484 // >0 = jump to page by dlg ID
4485 return 0;
4488 INT_PTR OnWizardFinish()
4490 // FALSE = allow finish
4491 // TRUE = prevent finish
4492 // HWND = prevent finish and set focus to HWND (CommCtrl 5.80 only)
4493 return FALSE;
4496 void OnHelp()
4500 #ifndef _WIN32_WCE
4501 #if (_WIN32_IE >= 0x0400)
4502 BOOL OnGetObject(LPNMOBJECTNOTIFY /*lpObjectNotify*/)
4504 return FALSE; // not processed
4506 #endif // (_WIN32_IE >= 0x0400)
4508 #if (_WIN32_IE >= 0x0500)
4509 int OnTranslateAccelerator(LPMSG /*lpMsg*/)
4511 // PSNRET_NOERROR - message not handled
4512 // PSNRET_MESSAGEHANDLED - message handled
4513 return PSNRET_NOERROR;
4516 HWND OnQueryInitialFocus(HWND /*hWndFocus*/)
4518 // NULL = set focus to default control
4519 // HWND = set focus to HWND
4520 return NULL;
4522 #endif // (_WIN32_IE >= 0x0500)
4523 #endif // !_WIN32_WCE
4525 #else // !_WTL_NEW_PAGE_NOTIFY_HANDLERS
4526 BOOL OnSetActive()
4528 return TRUE;
4531 BOOL OnKillActive()
4533 return TRUE;
4536 BOOL OnApply()
4538 return TRUE;
4541 void OnReset()
4545 BOOL OnQueryCancel()
4547 return TRUE; // ok to cancel
4550 int OnWizardBack()
4552 // 0 = goto previous page
4553 // -1 = prevent page change
4554 // >0 = jump to page by dlg ID
4555 return 0;
4558 int OnWizardNext()
4560 // 0 = goto next page
4561 // -1 = prevent page change
4562 // >0 = jump to page by dlg ID
4563 return 0;
4566 BOOL OnWizardFinish()
4568 return TRUE;
4571 void OnHelp()
4575 #ifndef _WIN32_WCE
4576 #if (_WIN32_IE >= 0x0400)
4577 BOOL OnGetObject(LPNMOBJECTNOTIFY /*lpObjectNotify*/)
4579 return FALSE; // not processed
4581 #endif // (_WIN32_IE >= 0x0400)
4583 #if (_WIN32_IE >= 0x0500)
4584 BOOL OnTranslateAccelerator(LPMSG /*lpMsg*/)
4586 return FALSE; // not translated
4589 HWND OnQueryInitialFocus(HWND /*hWndFocus*/)
4591 return NULL; // default
4593 #endif // (_WIN32_IE >= 0x0500)
4594 #endif // !_WIN32_WCE
4596 #endif // !_WTL_NEW_PAGE_NOTIFY_HANDLERS
4599 // for non-customized pages
4600 template <WORD t_wDlgTemplateID>
4601 class CPropertyPage : public CPropertyPageImpl<CPropertyPage<t_wDlgTemplateID> >
4603 public:
4604 enum { IDD = t_wDlgTemplateID };
4606 CPropertyPage(ATL::_U_STRINGorID title = (LPCTSTR)NULL) : CPropertyPageImpl<CPropertyPage>(title)
4609 DECLARE_EMPTY_MSG_MAP()
4612 ///////////////////////////////////////////////////////////////////////////////
4613 // CAxPropertyPageImpl - property page that hosts ActiveX controls
4615 #ifndef _ATL_NO_HOSTING
4617 // Note: You must #include <atlhost.h> to use these classes
4619 template <class T, class TBase = CPropertyPageWindow>
4620 class ATL_NO_VTABLE CAxPropertyPageImpl : public CPropertyPageImpl< T, TBase >
4622 public:
4623 // Data members
4624 HGLOBAL m_hInitData;
4625 HGLOBAL m_hDlgRes;
4626 HGLOBAL m_hDlgResSplit;
4628 // Constructor/destructor
4629 CAxPropertyPageImpl(ATL::_U_STRINGorID title = (LPCTSTR)NULL) :
4630 CPropertyPageImpl< T, TBase >(title),
4631 m_hInitData(NULL), m_hDlgRes(NULL), m_hDlgResSplit(NULL)
4633 T* pT = static_cast<T*>(this);
4634 pT; // avoid level 4 warning
4636 // initialize ActiveX hosting and modify dialog template
4637 ATL::AtlAxWinInit();
4639 HINSTANCE hInstance = ModuleHelper::GetResourceInstance();
4640 LPCTSTR lpTemplateName = MAKEINTRESOURCE(pT->IDD);
4641 HRSRC hDlg = ::FindResource(hInstance, lpTemplateName, (LPTSTR)RT_DIALOG);
4642 if(hDlg != NULL)
4644 HRSRC hDlgInit = ::FindResource(hInstance, lpTemplateName, (LPTSTR)_ATL_RT_DLGINIT);
4646 BYTE* pInitData = NULL;
4647 if(hDlgInit != NULL)
4649 m_hInitData = ::LoadResource(hInstance, hDlgInit);
4650 pInitData = (BYTE*)::LockResource(m_hInitData);
4653 m_hDlgRes = ::LoadResource(hInstance, hDlg);
4654 DLGTEMPLATE* pDlg = (DLGTEMPLATE*)::LockResource(m_hDlgRes);
4655 LPCDLGTEMPLATE lpDialogTemplate = ATL::_DialogSplitHelper::SplitDialogTemplate(pDlg, pInitData);
4656 if(lpDialogTemplate != pDlg)
4657 m_hDlgResSplit = GlobalHandle(lpDialogTemplate);
4659 // set up property page to use in-memory dialog template
4660 if(lpDialogTemplate != NULL)
4662 m_psp.dwFlags |= PSP_DLGINDIRECT;
4663 m_psp.pResource = lpDialogTemplate;
4665 else
4667 ATLASSERT(FALSE && _T("CAxPropertyPageImpl - ActiveX initializtion failed!"));
4670 else
4672 ATLASSERT(FALSE && _T("CAxPropertyPageImpl - Cannot find dialog template!"));
4676 ~CAxPropertyPageImpl()
4678 if(m_hInitData != NULL)
4680 UnlockResource(m_hInitData);
4681 FreeResource(m_hInitData);
4683 if(m_hDlgRes != NULL)
4685 UnlockResource(m_hDlgRes);
4686 FreeResource(m_hDlgRes);
4688 if(m_hDlgResSplit != NULL)
4690 ::GlobalFree(m_hDlgResSplit);
4694 // Methods
4695 // call this one to handle keyboard message for ActiveX controls
4696 BOOL PreTranslateMessage(LPMSG pMsg)
4698 if ((pMsg->message < WM_KEYFIRST || pMsg->message > WM_KEYLAST) &&
4699 (pMsg->message < WM_MOUSEFIRST || pMsg->message > WM_MOUSELAST))
4700 return FALSE;
4701 // find a direct child of the dialog from the window that has focus
4702 HWND hWndCtl = ::GetFocus();
4703 if (IsChild(hWndCtl) && ::GetParent(hWndCtl) != m_hWnd)
4707 hWndCtl = ::GetParent(hWndCtl);
4709 while (::GetParent(hWndCtl) != m_hWnd);
4711 // give controls a chance to translate this message
4712 return (BOOL)::SendMessage(hWndCtl, WM_FORWARDMSG, 0, (LPARAM)pMsg);
4715 // Overridables
4716 #if (_WIN32_IE >= 0x0500)
4717 // new default implementation for ActiveX hosting pages
4718 #ifdef _WTL_NEW_PAGE_NOTIFY_HANDLERS
4719 int OnTranslateAccelerator(LPMSG lpMsg)
4721 T* pT = static_cast<T*>(this);
4722 return (pT->PreTranslateMessage(lpMsg) != FALSE) ? PSNRET_MESSAGEHANDLED : PSNRET_NOERROR;
4724 #else // !_WTL_NEW_PAGE_NOTIFY_HANDLERS
4725 BOOL OnTranslateAccelerator(LPMSG lpMsg)
4727 T* pT = static_cast<T*>(this);
4728 return pT->PreTranslateMessage(lpMsg);
4730 #endif // !_WTL_NEW_PAGE_NOTIFY_HANDLERS
4731 #endif // (_WIN32_IE >= 0x0500)
4733 // Support for new stuff in ATL7
4734 #if (_ATL_VER >= 0x0700)
4735 int GetIDD()
4737 return( static_cast<T*>(this)->IDD );
4740 virtual DLGPROC GetDialogProc()
4742 return DialogProc;
4745 static INT_PTR CALLBACK DialogProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
4747 CAxPropertyPageImpl< T, TBase >* pThis = (CAxPropertyPageImpl< T, TBase >*)hWnd;
4748 if (uMsg == WM_INITDIALOG)
4750 HRESULT hr;
4751 if (FAILED(hr = pThis->CreateActiveXControls(pThis->GetIDD())))
4753 ATLASSERT(FALSE);
4754 return FALSE;
4757 return CPropertyPageImpl< T, TBase >::DialogProc(hWnd, uMsg, wParam, lParam);
4760 // ActiveX controls creation
4761 virtual HRESULT CreateActiveXControls(UINT nID)
4763 // Load dialog template and InitData
4764 HRSRC hDlgInit = ::FindResource(ATL::_AtlBaseModule.GetResourceInstance(), MAKEINTRESOURCE(nID), (LPTSTR)_ATL_RT_DLGINIT);
4765 BYTE* pInitData = NULL;
4766 HGLOBAL hData = NULL;
4767 HRESULT hr = S_OK;
4768 if (hDlgInit != NULL)
4770 hData = ::LoadResource(ATL::_AtlBaseModule.GetResourceInstance(), hDlgInit);
4771 if (hData != NULL)
4772 pInitData = (BYTE*) ::LockResource(hData);
4775 HRSRC hDlg = ::FindResource(ATL::_AtlBaseModule.GetResourceInstance(), MAKEINTRESOURCE(nID), (LPTSTR)RT_DIALOG);
4776 if (hDlg != NULL)
4778 HGLOBAL hResource = ::LoadResource(ATL::_AtlBaseModule.GetResourceInstance(), hDlg);
4779 DLGTEMPLATE* pDlg = NULL;
4780 if (hResource != NULL)
4782 pDlg = (DLGTEMPLATE*) ::LockResource(hResource);
4783 if (pDlg != NULL)
4785 // Get first control on the template
4786 BOOL bDialogEx = ATL::_DialogSplitHelper::IsDialogEx(pDlg);
4787 WORD nItems = ATL::_DialogSplitHelper::DlgTemplateItemCount(pDlg);
4789 // Get first control on the dialog
4790 DLGITEMTEMPLATE* pItem = ATL::_DialogSplitHelper::FindFirstDlgItem(pDlg);
4791 HWND hWndPrev = GetWindow(GW_CHILD);
4793 // Create all ActiveX cotnrols in the dialog template and place them in the correct tab order (z-order)
4794 for (WORD nItem = 0; nItem < nItems; nItem++)
4796 DWORD wID = bDialogEx ? ((ATL::_DialogSplitHelper::DLGITEMTEMPLATEEX*)pItem)->id : pItem->id;
4797 if (ATL::_DialogSplitHelper::IsActiveXControl(pItem, bDialogEx))
4799 BYTE* pData = NULL;
4800 DWORD dwLen = ATL::_DialogSplitHelper::FindCreateData(wID, pInitData, &pData);
4801 ATL::CComPtr<IStream> spStream;
4802 if (dwLen != 0)
4804 HGLOBAL h = GlobalAlloc(GHND, dwLen);
4805 if (h != NULL)
4807 BYTE* pBytes = (BYTE*) GlobalLock(h);
4808 BYTE* pSource = pData;
4809 SecureHelper::memcpy_x(pBytes, dwLen, pSource, dwLen);
4810 GlobalUnlock(h);
4811 CreateStreamOnHGlobal(h, TRUE, &spStream);
4813 else
4815 hr = E_OUTOFMEMORY;
4816 break;
4820 ATL::CComBSTR bstrLicKey;
4821 hr = ATL::_DialogSplitHelper::ParseInitData(spStream, &bstrLicKey.m_str);
4822 if (SUCCEEDED(hr))
4824 ATL::CAxWindow2 wnd;
4825 // Get control caption.
4826 LPWSTR pszClassName =
4827 bDialogEx ?
4828 (LPWSTR)(((ATL::_DialogSplitHelper::DLGITEMTEMPLATEEX*)pItem) + 1) :
4829 (LPWSTR)(pItem + 1);
4830 // Get control rect.
4831 RECT rect;
4832 rect.left =
4833 bDialogEx ?
4834 ((ATL::_DialogSplitHelper::DLGITEMTEMPLATEEX*)pItem)->x :
4835 pItem->x;
4836 rect.top =
4837 bDialogEx ?
4838 ((ATL::_DialogSplitHelper::DLGITEMTEMPLATEEX*)pItem)->y :
4839 pItem->y;
4840 rect.right = rect.left +
4841 (bDialogEx ?
4842 ((ATL::_DialogSplitHelper::DLGITEMTEMPLATEEX*)pItem)->cx :
4843 pItem->cx);
4844 rect.bottom = rect.top +
4845 (bDialogEx ?
4846 ((ATL::_DialogSplitHelper::DLGITEMTEMPLATEEX*)pItem)->cy :
4847 pItem->cy);
4849 // Convert from dialog units to screen units
4850 MapDialogRect(&rect);
4852 // Create AxWindow with a NULL caption.
4853 wnd.Create(m_hWnd,
4854 &rect,
4855 NULL,
4856 (bDialogEx ?
4857 ((ATL::_DialogSplitHelper::DLGITEMTEMPLATEEX*)pItem)->style :
4858 pItem->style) | WS_TABSTOP,
4859 bDialogEx ?
4860 ((ATL::_DialogSplitHelper::DLGITEMTEMPLATEEX*)pItem)->exStyle :
4862 bDialogEx ?
4863 ((ATL::_DialogSplitHelper::DLGITEMTEMPLATEEX*)pItem)->id :
4864 pItem->id,
4865 NULL);
4867 if (wnd != NULL)
4869 #ifndef _WIN32_WCE
4870 // Set the Help ID
4871 if (bDialogEx && ((ATL::_DialogSplitHelper::DLGITEMTEMPLATEEX*)pItem)->helpID != 0)
4872 wnd.SetWindowContextHelpId(((ATL::_DialogSplitHelper::DLGITEMTEMPLATEEX*)pItem)->helpID);
4873 #endif // !_WIN32_WCE
4874 // Try to create the ActiveX control.
4875 hr = wnd.CreateControlLic(pszClassName, spStream, NULL, bstrLicKey);
4876 if (FAILED(hr))
4877 break;
4878 // Set the correct tab position.
4879 if (nItem == 0)
4880 hWndPrev = HWND_TOP;
4881 wnd.SetWindowPos(hWndPrev, 0,0,0,0,SWP_NOACTIVATE | SWP_NOMOVE | SWP_NOSIZE);
4882 hWndPrev = wnd;
4884 else
4886 hr = ATL::AtlHresultFromLastError();
4890 else
4892 if (nItem != 0)
4893 hWndPrev = ::GetWindow(hWndPrev, GW_HWNDNEXT);
4895 pItem = ATL::_DialogSplitHelper::FindNextDlgItem(pItem, bDialogEx);
4898 else
4899 hr = ATL::AtlHresultFromLastError();
4901 else
4902 hr = ATL::AtlHresultFromLastError();
4904 return hr;
4907 // Event handling support
4908 HRESULT AdviseSinkMap(bool bAdvise)
4910 if(!bAdvise && m_hWnd == NULL)
4912 // window is gone, controls are already unadvised
4913 ATLTRACE2(atlTraceUI, 0, _T("CAxPropertyPageImpl::AdviseSinkMap called after the window was destroyed\n"));
4914 return S_OK;
4916 HRESULT hRet = E_NOTIMPL;
4917 __if_exists(T::_GetSinkMapFinder)
4919 T* pT = static_cast<T*>(this);
4920 hRet = AtlAdviseSinkMap(pT, bAdvise);
4922 return hRet;
4925 // Message map and handlers
4926 typedef CPropertyPageImpl< T, TBase> _baseClass;
4927 BEGIN_MSG_MAP(CAxPropertyPageImpl)
4928 MESSAGE_HANDLER(WM_INITDIALOG, OnInitDialog)
4929 MESSAGE_HANDLER(WM_DESTROY, OnDestroy)
4930 CHAIN_MSG_MAP(_baseClass)
4931 END_MSG_MAP()
4933 LRESULT OnInitDialog(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& bHandled)
4935 // initialize controls in dialog with DLGINIT resource section
4936 ExecuteDlgInit(static_cast<T*>(this)->IDD);
4937 AdviseSinkMap(true);
4938 bHandled = FALSE;
4939 return 1;
4942 LRESULT OnDestroy(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& bHandled)
4944 AdviseSinkMap(false);
4945 bHandled = FALSE;
4946 return 1;
4948 #endif // (_ATL_VER >= 0x0700)
4951 // for non-customized pages
4952 template <WORD t_wDlgTemplateID>
4953 class CAxPropertyPage : public CAxPropertyPageImpl<CAxPropertyPage<t_wDlgTemplateID> >
4955 public:
4956 enum { IDD = t_wDlgTemplateID };
4958 CAxPropertyPage(ATL::_U_STRINGorID title = (LPCTSTR)NULL) : CAxPropertyPageImpl<CAxPropertyPage>(title)
4961 #if (_WIN32_IE >= 0x0500) || (_ATL_VER >= 0x0700)
4962 // not empty so we handle accelerators/create controls
4963 BEGIN_MSG_MAP(CAxPropertyPage)
4964 CHAIN_MSG_MAP(CAxPropertyPageImpl<CAxPropertyPage<t_wDlgTemplateID> >)
4965 END_MSG_MAP()
4966 #else // !((_WIN32_IE >= 0x0500) || (_ATL_VER >= 0x0700))
4967 DECLARE_EMPTY_MSG_MAP()
4968 #endif // !((_WIN32_IE >= 0x0500) || (_ATL_VER >= 0x0700))
4971 #endif // _ATL_NO_HOSTING
4974 ///////////////////////////////////////////////////////////////////////////////
4975 // Wizard97 Support
4977 #if (_WIN32_IE >= 0x0500) && !defined(_WIN32_WCE)
4979 // Sample wizard dialog resources:
4981 // IDD_WIZ97_INTERIOR_BLANK DIALOG 0, 0, 317, 143
4982 // STYLE DS_SETFONT | WS_CHILD | WS_DISABLED | WS_CAPTION
4983 // CAPTION "Wizard97 Property Page - Interior"
4984 // FONT 8, "MS Shell Dlg"
4985 // BEGIN
4986 // END
4988 // IDD_WIZ97_EXTERIOR_BLANK DIALOGEX 0, 0, 317, 193
4989 // STYLE DS_SETFONT | DS_FIXEDSYS | WS_CHILD | WS_DISABLED | WS_CAPTION
4990 // CAPTION "Wizard97 Property Page - Welcome/Complete"
4991 // FONT 8, "MS Shell Dlg", 0, 0, 0x0
4992 // BEGIN
4993 // LTEXT "Welcome to the X Wizard",IDC_WIZ97_EXTERIOR_TITLE,115,8,
4994 // 195,24
4995 // LTEXT "Wizard Explanation\r\n(The height of the static text should be in multiples of 8 dlus)",
4996 // IDC_STATIC,115,40,195,16
4997 // LTEXT "h",IDC_WIZ97_BULLET1,118,64,8,8
4998 // LTEXT "List Item 1 (the h is turned into a bullet)",IDC_STATIC,
4999 // 127,63,122,8
5000 // LTEXT "h",IDC_WIZ97_BULLET2,118,79,8,8
5001 // LTEXT "List Item 2. Keep 7 dlus between paragraphs",IDC_STATIC,
5002 // 127,78,33,8
5003 // CONTROL "&Do not show this Welcome page again",
5004 // IDC_WIZ97_WELCOME_NOTAGAIN,"Button",BS_AUTOCHECKBOX |
5005 // WS_TABSTOP,115,169,138,10
5006 // END
5008 // GUIDELINES DESIGNINFO
5009 // BEGIN
5010 // IDD_WIZ97_INTERIOR_BLANK, DIALOG
5011 // BEGIN
5012 // LEFTMARGIN, 7
5013 // RIGHTMARGIN, 310
5014 // VERTGUIDE, 21
5015 // VERTGUIDE, 31
5016 // VERTGUIDE, 286
5017 // VERTGUIDE, 296
5018 // TOPMARGIN, 7
5019 // BOTTOMMARGIN, 136
5020 // HORZGUIDE, 8
5021 // END
5023 // IDD_WIZ97_EXTERIOR_BLANK, DIALOG
5024 // BEGIN
5025 // RIGHTMARGIN, 310
5026 // VERTGUIDE, 115
5027 // VERTGUIDE, 118
5028 // VERTGUIDE, 127
5029 // TOPMARGIN, 7
5030 // BOTTOMMARGIN, 186
5031 // HORZGUIDE, 8
5032 // HORZGUIDE, 32
5033 // HORZGUIDE, 40
5034 // HORZGUIDE, 169
5035 // END
5036 // END
5038 ///////////////////////////////////////////////////////////////////////////////
5039 // CWizard97SheetWindow - client side for a Wizard 97 style wizard sheet
5041 class CWizard97SheetWindow : public CPropertySheetWindow
5043 public:
5044 // Constructors
5045 CWizard97SheetWindow(HWND hWnd = NULL) : CPropertySheetWindow(hWnd)
5048 CWizard97SheetWindow& operator =(HWND hWnd)
5050 m_hWnd = hWnd;
5051 return *this;
5054 // Operations
5055 HFONT GetExteriorPageTitleFont(void)
5057 ATLASSERT(::IsWindow(m_hWnd));
5058 return (HFONT)::SendMessage(m_hWnd, GetMessage_GetExteriorPageTitleFont(), 0, 0L);
5061 HFONT GetBulletFont(void)
5063 ATLASSERT(::IsWindow(m_hWnd));
5064 return (HFONT)::SendMessage(m_hWnd, GetMessage_GetBulletFont(), 0, 0L);
5067 // Helpers
5068 static UINT GetMessage_GetExteriorPageTitleFont()
5070 static UINT uGetExteriorPageTitleFont = 0;
5071 if(uGetExteriorPageTitleFont == 0)
5073 CStaticDataInitCriticalSectionLock lock;
5074 if(FAILED(lock.Lock()))
5076 ATLTRACE2(atlTraceUI, 0, _T("ERROR : Unable to lock critical section in CWizard97SheetWindow::GetMessage_GetExteriorPageTitleFont().\n"));
5077 ATLASSERT(FALSE);
5078 return 0;
5081 if(uGetExteriorPageTitleFont == 0)
5082 uGetExteriorPageTitleFont = ::RegisterWindowMessage(_T("GetExteriorPageTitleFont_531AF056-B8BE-4c4c-B786-AC608DF0DF12"));
5084 lock.Unlock();
5086 ATLASSERT(uGetExteriorPageTitleFont != 0);
5087 return uGetExteriorPageTitleFont;
5090 static UINT GetMessage_GetBulletFont()
5092 static UINT uGetBulletFont = 0;
5093 if(uGetBulletFont == 0)
5095 CStaticDataInitCriticalSectionLock lock;
5096 if(FAILED(lock.Lock()))
5098 ATLTRACE2(atlTraceUI, 0, _T("ERROR : Unable to lock critical section in CWizard97SheetWindow::GetMessage_GetBulletFont().\n"));
5099 ATLASSERT(FALSE);
5100 return 0;
5103 if(uGetBulletFont == 0)
5104 uGetBulletFont = ::RegisterWindowMessage(_T("GetBulletFont_AD347D08-8F65-45ef-982E-6352E8218AD5"));
5106 lock.Unlock();
5108 ATLASSERT(uGetBulletFont != 0);
5109 return uGetBulletFont;
5112 // Implementation - override to prevent usage
5113 HWND Create(LPCTSTR, HWND, ATL::_U_RECT = NULL, LPCTSTR = NULL, DWORD = 0, DWORD = 0, ATL::_U_MENUorID = 0U, LPVOID = NULL)
5115 ATLASSERT(FALSE);
5116 return NULL;
5121 ///////////////////////////////////////////////////////////////////////////////
5122 // CWizard97SheetImpl - implements a Wizard 97 style wizard sheet
5124 template <class T, class TBase = CWizard97SheetWindow>
5125 class ATL_NO_VTABLE CWizard97SheetImpl : public CPropertySheetImpl< T, TBase >
5127 protected:
5128 // Typedefs
5129 typedef CWizard97SheetImpl< T, TBase > thisClass;
5130 typedef CPropertySheetImpl< T, TBase > baseClass;
5132 // Member variables
5133 CFont m_fontExteriorPageTitle; // Welcome and Completion page title font
5134 CFont m_fontBullet; // Bullet font (used on static text 'h' to produce a small bullet)
5135 bool m_bReceivedFirstSizeMessage;
5137 public:
5138 CWizard97SheetImpl(ATL::_U_STRINGorID title, ATL::_U_STRINGorID headerBitmap, ATL::_U_STRINGorID watermarkBitmap, UINT uStartPage = 0, HWND hWndParent = NULL) :
5139 baseClass(title, uStartPage, hWndParent),
5140 m_bReceivedFirstSizeMessage(false)
5142 m_psh.dwFlags &= ~(PSH_NOCONTEXTHELP);
5143 m_psh.dwFlags &= ~(PSH_WIZARD | PSH_WIZARD_LITE);
5145 m_psh.dwFlags |= (PSH_HASHELP | PSH_WIZARDCONTEXTHELP);
5146 m_psh.dwFlags |= PSH_WIZARD97;
5148 baseClass::SetHeader(headerBitmap.m_lpstr);
5149 baseClass::SetWatermark(watermarkBitmap.m_lpstr);
5152 // Overrides from base class
5153 void OnSheetInitialized()
5155 T* pT = static_cast<T*>(this);
5156 pT->_InitializeFonts();
5158 // We'd like to center the wizard here, but its too early.
5159 // Instead, we'll do CenterWindow upon our first WM_SIZE message
5162 // Initialization
5163 void _InitializeFonts()
5165 // Setup the Title and Bullet Font
5166 // (Property pages can send the "get external page title font" and "get bullet font" messages)
5167 // The derived class needs to do the actual SetFont for the dialog items)
5169 CFontHandle fontThisDialog = this->GetFont();
5170 CClientDC dcScreen(NULL);
5172 LOGFONT titleLogFont = {0};
5173 LOGFONT bulletLogFont = {0};
5174 fontThisDialog.GetLogFont(&titleLogFont);
5175 fontThisDialog.GetLogFont(&bulletLogFont);
5177 // The Wizard 97 Spec recommends to do the Title Font
5178 // as Verdana Bold, 12pt.
5179 titleLogFont.lfCharSet = DEFAULT_CHARSET;
5180 titleLogFont.lfWeight = FW_BOLD;
5181 SecureHelper::strcpy_x(titleLogFont.lfFaceName, _countof(titleLogFont.lfFaceName), _T("Verdana Bold"));
5182 INT titleFontPointSize = 12;
5183 titleLogFont.lfHeight = -::MulDiv(titleFontPointSize, dcScreen.GetDeviceCaps(LOGPIXELSY), 72);
5184 m_fontExteriorPageTitle.CreateFontIndirect(&titleLogFont);
5186 // The Wizard 97 Spec recommends to do Bullets by having
5187 // static text of "h" in the Marlett font.
5188 bulletLogFont.lfCharSet = DEFAULT_CHARSET;
5189 bulletLogFont.lfWeight = FW_NORMAL;
5190 SecureHelper::strcpy_x(bulletLogFont.lfFaceName, _countof(bulletLogFont.lfFaceName), _T("Marlett"));
5191 INT bulletFontSize = 8;
5192 bulletLogFont.lfHeight = -::MulDiv(bulletFontSize, dcScreen.GetDeviceCaps(LOGPIXELSY), 72);
5193 m_fontBullet.CreateFontIndirect(&bulletLogFont);
5196 // Message Handling
5197 BEGIN_MSG_MAP(thisClass)
5198 MESSAGE_HANDLER(CWizard97SheetWindow::GetMessage_GetExteriorPageTitleFont(), OnGetExteriorPageTitleFont)
5199 MESSAGE_HANDLER(CWizard97SheetWindow::GetMessage_GetBulletFont(), OnGetBulletFont)
5200 MESSAGE_HANDLER(WM_SIZE, OnSize)
5201 CHAIN_MSG_MAP(baseClass)
5202 END_MSG_MAP()
5204 LRESULT OnGetExteriorPageTitleFont(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& /*bHandled*/)
5206 return (LRESULT)(HFONT)m_fontExteriorPageTitle;
5209 LRESULT OnGetBulletFont(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& /*bHandled*/)
5211 return (LRESULT)(HFONT)m_fontBullet;
5214 LRESULT OnSize(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& bHandled)
5216 if(!m_bReceivedFirstSizeMessage)
5218 m_bReceivedFirstSizeMessage = true;
5219 this->CenterWindow();
5222 bHandled = FALSE;
5223 return 0;
5227 // for non-customized sheets
5228 class CWizard97Sheet : public CWizard97SheetImpl<CWizard97Sheet>
5230 protected:
5231 // Typedefs
5232 typedef CWizard97Sheet thisClass;
5233 typedef CWizard97SheetImpl<CWizard97Sheet> baseClass;
5235 public:
5236 CWizard97Sheet(ATL::_U_STRINGorID title, ATL::_U_STRINGorID headerBitmap, ATL::_U_STRINGorID watermarkBitmap, UINT uStartPage = 0, HWND hWndParent = NULL) :
5237 baseClass(title, headerBitmap, watermarkBitmap, uStartPage, hWndParent)
5240 BEGIN_MSG_MAP(thisClass)
5241 CHAIN_MSG_MAP(baseClass)
5242 END_MSG_MAP()
5246 ///////////////////////////////////////////////////////////////////////////////
5247 // CWizard97PageWindow - client side for a Wizard 97 style wizard page
5249 #define WIZARD97_EXTERIOR_CXDLG 317
5250 #define WIZARD97_EXTERIOR_CYDLG 193
5252 #define WIZARD97_INTERIOR_CXDLG 317
5253 #define WIZARD97_INTERIOR_CYDLG 143
5255 class CWizard97PageWindow : public CPropertyPageWindow
5257 public:
5258 // Constructors
5259 CWizard97PageWindow(HWND hWnd = NULL) : CPropertyPageWindow(hWnd)
5262 CWizard97PageWindow& operator =(HWND hWnd)
5264 m_hWnd = hWnd;
5265 return *this;
5268 // Attributes
5269 CWizard97SheetWindow GetPropertySheet() const
5271 ATLASSERT(::IsWindow(m_hWnd));
5272 return CWizard97SheetWindow(GetParent());
5275 // Operations
5276 HFONT GetExteriorPageTitleFont(void)
5278 ATLASSERT(::IsWindow(m_hWnd));
5279 return GetPropertySheet().GetExteriorPageTitleFont();
5282 HFONT GetBulletFont(void)
5284 ATLASSERT(::IsWindow(m_hWnd));
5285 return GetPropertySheet().GetBulletFont();
5288 // Implementation - overrides to prevent usage
5289 HWND Create(LPCTSTR, HWND, ATL::_U_RECT = NULL, LPCTSTR = NULL, DWORD = 0, DWORD = 0, ATL::_U_MENUorID = 0U, LPVOID = NULL)
5291 ATLASSERT(FALSE);
5292 return NULL;
5298 ///////////////////////////////////////////////////////////////////////////////
5299 // CWizard97PageImpl - implements a Wizard 97 style wizard page
5301 template <class T, class TBase = CWizard97PageWindow>
5302 class ATL_NO_VTABLE CWizard97PageImpl : public CPropertyPageImpl< T, TBase >
5304 protected:
5305 // Typedefs
5306 typedef CWizard97PageImpl< T, TBase > thisClass;
5307 typedef CPropertyPageImpl< T, TBase > baseClass;
5309 public:
5310 CWizard97PageImpl(ATL::_U_STRINGorID title = (LPCTSTR)NULL) : baseClass(title)
5313 // Message Handling
5314 BEGIN_MSG_MAP(thisClass)
5315 CHAIN_MSG_MAP(baseClass)
5316 END_MSG_MAP()
5320 ///////////////////////////////////////////////////////////////////////////////
5321 // CWizard97ExteriorPageImpl - implements a Wizard 97 style exterior wizard page
5323 template <class T, class TBase = CWizard97PageWindow>
5324 class ATL_NO_VTABLE CWizard97ExteriorPageImpl : public CPropertyPageImpl< T, TBase >
5326 protected:
5327 // Typedefs
5328 typedef CWizard97ExteriorPageImpl< T, TBase > thisClass;
5329 typedef CPropertyPageImpl< T, TBase > baseClass;
5331 public:
5332 // Constructors
5333 CWizard97ExteriorPageImpl(ATL::_U_STRINGorID title = (LPCTSTR)NULL) : baseClass(title)
5335 m_psp.dwFlags |= PSP_HASHELP;
5336 m_psp.dwFlags |= PSP_HIDEHEADER;
5339 // Message Handling
5340 BEGIN_MSG_MAP(thisClass)
5341 CHAIN_MSG_MAP(baseClass)
5342 END_MSG_MAP()
5346 ///////////////////////////////////////////////////////////////////////////////
5347 // CWizard97InteriorPageImpl - implements a Wizard 97 style interior wizard page
5349 template <class T, class TBase = CWizard97PageWindow>
5350 class ATL_NO_VTABLE CWizard97InteriorPageImpl : public CPropertyPageImpl< T, TBase >
5352 protected:
5353 // Typedefs
5354 typedef CWizard97InteriorPageImpl< T, TBase > thisClass;
5355 typedef CPropertyPageImpl< T, TBase > baseClass;
5357 public:
5358 // Constructors
5359 CWizard97InteriorPageImpl(ATL::_U_STRINGorID title = (LPCTSTR)NULL) : baseClass(title)
5361 m_psp.dwFlags |= PSP_HASHELP;
5362 m_psp.dwFlags &= ~PSP_HIDEHEADER;
5363 m_psp.dwFlags |= PSP_USEHEADERTITLE | PSP_USEHEADERSUBTITLE;
5365 // Be sure to have the derived class define this in the constructor.
5366 // We'll default it to something obvious in case its forgotten.
5367 baseClass::SetHeaderTitle(_T("Call SetHeaderTitle in Derived Class"));
5368 baseClass::SetHeaderSubTitle(_T("Call SetHeaderSubTitle in the constructor of the Derived Class."));
5371 // Message Handling
5372 BEGIN_MSG_MAP(thisClass)
5373 CHAIN_MSG_MAP(baseClass)
5374 END_MSG_MAP()
5377 #endif // (_WIN32_IE >= 0x0500) && !defined(_WIN32_WCE)
5380 ///////////////////////////////////////////////////////////////////////////////
5381 // Aero Wizard support
5383 #if (_WIN32_WINNT >= 0x0600) && !defined(_WIN32_WCE)
5385 ///////////////////////////////////////////////////////////////////////////////
5386 // CAeroWizardFrameWindow - client side for an Aero Wizard frame window
5388 class CAeroWizardFrameWindow : public CPropertySheetWindow
5390 public:
5391 // Constructors
5392 CAeroWizardFrameWindow(HWND hWnd = NULL) : CPropertySheetWindow(hWnd)
5395 CAeroWizardFrameWindow& operator =(HWND hWnd)
5397 m_hWnd = hWnd;
5398 return *this;
5401 // Operations - new, Aero Wizard only
5402 void SetNextText(LPCWSTR lpszText)
5404 ATLASSERT(::IsWindow(m_hWnd));
5405 ::SendMessage(m_hWnd, PSM_SETNEXTTEXT, 0, (LPARAM)lpszText);
5408 void ShowWizardButtons(DWORD dwButtons, DWORD dwStates)
5410 ATLASSERT(::IsWindow(m_hWnd));
5411 ::PostMessage(m_hWnd, PSM_SHOWWIZBUTTONS, (WPARAM)dwStates, (LPARAM)dwButtons);
5414 void EnableWizardButtons(DWORD dwButtons, DWORD dwStates)
5416 ATLASSERT(::IsWindow(m_hWnd));
5417 ::PostMessage(m_hWnd, PSM_ENABLEWIZBUTTONS, (WPARAM)dwStates, (LPARAM)dwButtons);
5420 void SetButtonText(DWORD dwButton, LPCWSTR lpszText)
5422 ATLASSERT(::IsWindow(m_hWnd));
5423 ::SendMessage(m_hWnd, PSM_SETBUTTONTEXT, (WPARAM)dwButton, (LPARAM)lpszText);
5428 ///////////////////////////////////////////////////////////////////////////////
5429 // CAeroWizardFrameImpl - implements an Aero Wizard frame
5431 template <class T, class TBase = CAeroWizardFrameWindow>
5432 class ATL_NO_VTABLE CAeroWizardFrameImpl : public CPropertySheetImpl<T, TBase >
5434 public:
5435 // Constructor
5436 CAeroWizardFrameImpl(ATL::_U_STRINGorID title = (LPCTSTR)NULL, UINT uStartPage = 0, HWND hWndParent = NULL) :
5437 CPropertySheetImpl<T, TBase >(title, uStartPage, hWndParent)
5439 m_psh.dwFlags |= PSH_WIZARD | PSH_AEROWIZARD;
5442 // Operations
5443 void EnableResizing()
5445 ATLASSERT(m_hWnd == NULL); // can't do this after it's created
5446 m_psh.dwFlags |= PSH_RESIZABLE;
5449 void UseHeaderBitmap()
5451 ATLASSERT(m_hWnd == NULL); // can't do this after it's created
5452 m_psh.dwFlags |= PSH_HEADERBITMAP;
5455 void SetNoMargin()
5457 ATLASSERT(m_hWnd == NULL); // can't do this after it's created
5458 m_psh.dwFlags |= PSH_NOMARGIN;
5461 // Override to prevent use
5462 HWND Create(HWND /*hWndParent*/ = NULL)
5464 ATLASSERT(FALSE); // not supported for Aero Wizard
5465 return NULL;
5470 ///////////////////////////////////////////////////////////////////////////////
5471 // CAeroWizardFrame - for non-customized frames
5473 class CAeroWizardFrame : public CAeroWizardFrameImpl<CAeroWizardFrame>
5475 public:
5476 CAeroWizardFrame(ATL::_U_STRINGorID title = (LPCTSTR)NULL, UINT uStartPage = 0, HWND hWndParent = NULL)
5477 : CAeroWizardFrameImpl<CAeroWizardFrame>(title, uStartPage, hWndParent)
5480 BEGIN_MSG_MAP(CAeroWizardFrame)
5481 MESSAGE_HANDLER(WM_COMMAND, CAeroWizardFrameImpl<CAeroWizardFrame>::OnCommand)
5482 END_MSG_MAP()
5486 ///////////////////////////////////////////////////////////////////////////////
5487 // CAeroWizardPageWindow - client side for an Aero Wizard page
5489 class CAeroWizardPageWindow : public CPropertyPageWindow
5491 public:
5492 // Constructors
5493 CAeroWizardPageWindow(HWND hWnd = NULL) : CPropertyPageWindow(hWnd)
5496 CAeroWizardPageWindow& operator =(HWND hWnd)
5498 m_hWnd = hWnd;
5499 return *this;
5502 // Attributes
5503 CAeroWizardFrameWindow GetAeroWizardFrame() const
5505 ATLASSERT(::IsWindow(m_hWnd));
5506 // This is not really top-level frame window, but it processes all frame messages
5507 return CAeroWizardFrameWindow(GetParent());
5510 // Operations - new, Aero Wizard only
5511 void SetNextText(LPCWSTR lpszText)
5513 ATLASSERT(::IsWindow(m_hWnd));
5514 ATLASSERT(GetParent() != NULL);
5515 GetAeroWizardFrame().SetNextText(lpszText);
5518 void ShowWizardButtons(DWORD dwButtons, DWORD dwStates)
5520 ATLASSERT(::IsWindow(m_hWnd));
5521 ATLASSERT(GetParent() != NULL);
5522 GetAeroWizardFrame().ShowWizardButtons(dwButtons, dwStates);
5525 void EnableWizardButtons(DWORD dwButtons, DWORD dwStates)
5527 ATLASSERT(::IsWindow(m_hWnd));
5528 ATLASSERT(GetParent() != NULL);
5529 GetAeroWizardFrame().EnableWizardButtons(dwButtons, dwStates);
5532 void SetButtonText(DWORD dwButton, LPCWSTR lpszText)
5534 ATLASSERT(::IsWindow(m_hWnd));
5535 ATLASSERT(GetParent() != NULL);
5536 GetAeroWizardFrame().SetButtonText(dwButton, lpszText);
5541 ///////////////////////////////////////////////////////////////////////////////
5542 // CAeroWizardPageImpl - implements an Aero Wizard page
5544 template <class T, class TBase = CAeroWizardPageWindow>
5545 class ATL_NO_VTABLE CAeroWizardPageImpl : public CPropertyPageImpl<T, TBase >
5547 public:
5548 CAeroWizardPageImpl(ATL::_U_STRINGorID title = (LPCTSTR)NULL) : CPropertyPageImpl<T, TBase >(title)
5553 ///////////////////////////////////////////////////////////////////////////////
5554 // CAeroWizardPage - for non-customized pages
5556 template <WORD t_wDlgTemplateID>
5557 class CAeroWizardPage : public CAeroWizardPageImpl<CAeroWizardPage<t_wDlgTemplateID> >
5559 public:
5560 enum { IDD = t_wDlgTemplateID };
5562 CAeroWizardPage(ATL::_U_STRINGorID title = (LPCTSTR)NULL) : CAeroWizardPageImpl<CAeroWizardPage>(title)
5565 DECLARE_EMPTY_MSG_MAP()
5569 #ifndef _ATL_NO_HOSTING
5571 // Note: You must #include <atlhost.h> to use these classes
5573 ///////////////////////////////////////////////////////////////////////////////
5574 // CAeroWizardAxPageImpl - Aero Wizard page that hosts ActiveX controls
5576 template <class T, class TBase = CAeroWizardPageWindow>
5577 class ATL_NO_VTABLE CAeroWizardAxPageImpl : public CAxPropertyPageImpl< T, TBase >
5579 public:
5580 CAeroWizardAxPageImpl(ATL::_U_STRINGorID title = (LPCTSTR)NULL) : CAxPropertyPageImpl< T, TBase >(title)
5585 ///////////////////////////////////////////////////////////////////////////////
5586 // CAeroWizardAxPage - for non-customized pages
5588 template <WORD t_wDlgTemplateID>
5589 class CAeroWizardAxPage : public CAeroWizardAxPageImpl<CAeroWizardAxPage<t_wDlgTemplateID> >
5591 public:
5592 enum { IDD = t_wDlgTemplateID };
5594 CAeroWizardAxPage(ATL::_U_STRINGorID title = (LPCTSTR)NULL) : CAeroWizardAxPageImpl<CAeroWizardAxPage>(title)
5597 #if (_WIN32_IE >= 0x0500) || (_ATL_VER >= 0x0700)
5598 // not empty so we handle accelerators/create controls
5599 BEGIN_MSG_MAP(CAeroWizardAxPage)
5600 CHAIN_MSG_MAP(CAeroWizardAxPageImpl<CAeroWizardAxPage<t_wDlgTemplateID> >)
5601 END_MSG_MAP()
5602 #else // !((_WIN32_IE >= 0x0500) || (_ATL_VER >= 0x0700))
5603 DECLARE_EMPTY_MSG_MAP()
5604 #endif // !((_WIN32_IE >= 0x0500) || (_ATL_VER >= 0x0700))
5607 #endif // _ATL_NO_HOSTING
5609 #endif // (_WIN32_WINNT >= 0x0600) && !defined(_WIN32_WCE)
5612 ///////////////////////////////////////////////////////////////////////////////
5613 // TaskDialog support
5615 #if ((_WIN32_WINNT >= 0x0600) || defined(_WTL_TASKDIALOG)) && !defined(_WIN32_WCE)
5617 ///////////////////////////////////////////////////////////////////////////////
5618 // AtlTaskDialog - support for TaskDialog() function
5620 inline int AtlTaskDialog(HWND hWndParent,
5621 ATL::_U_STRINGorID WindowTitle, ATL::_U_STRINGorID MainInstructionText, ATL::_U_STRINGorID ContentText,
5622 TASKDIALOG_COMMON_BUTTON_FLAGS dwCommonButtons = 0U, ATL::_U_STRINGorID Icon = (LPCTSTR)NULL)
5624 int nRet = -1;
5626 #ifdef _WTL_TASKDIALOG_DIRECT
5627 USES_CONVERSION;
5628 HRESULT hRet = ::TaskDialog(hWndParent, ModuleHelper::GetResourceInstance(), T2CW(WindowTitle.m_lpstr), T2CW(MainInstructionText.m_lpstr), T2CW(ContentText.m_lpstr), dwCommonButtons, T2CW(Icon.m_lpstr), &nRet);
5629 ATLVERIFY(SUCCEEDED(hRet));
5630 #else
5631 // This allows apps to run on older versions of Windows
5632 typedef HRESULT (STDAPICALLTYPE *PFN_TaskDialog)(HWND hwndParent, HINSTANCE hInstance, PCWSTR pszWindowTitle, PCWSTR pszMainInstruction, PCWSTR pszContent, TASKDIALOG_COMMON_BUTTON_FLAGS dwCommonButtons, PCWSTR pszIcon, int* pnButton);
5634 HMODULE m_hCommCtrlDLL = ::LoadLibrary(_T("comctl32.dll"));
5635 if(m_hCommCtrlDLL != NULL)
5637 PFN_TaskDialog pfnTaskDialog = (PFN_TaskDialog)::GetProcAddress(m_hCommCtrlDLL, "TaskDialog");
5638 if(pfnTaskDialog != NULL)
5640 USES_CONVERSION;
5641 HRESULT hRet = pfnTaskDialog(hWndParent, ModuleHelper::GetResourceInstance(), T2CW(WindowTitle.m_lpstr), T2CW(MainInstructionText.m_lpstr), T2CW(ContentText.m_lpstr), dwCommonButtons, T2CW(Icon.m_lpstr), &nRet);
5642 ATLVERIFY(SUCCEEDED(hRet));
5645 ::FreeLibrary(m_hCommCtrlDLL);
5647 #endif
5649 return nRet;
5653 ///////////////////////////////////////////////////////////////////////////////
5654 // CTaskDialogConfig - TASKDIALOGCONFIG wrapper
5656 class CTaskDialogConfig : public TASKDIALOGCONFIG
5658 public:
5659 // Constructor
5660 CTaskDialogConfig()
5662 Init();
5665 void Init()
5667 memset(this, 0, sizeof(TASKDIALOGCONFIG)); // initialize structure to 0/NULL
5668 this->cbSize = sizeof(TASKDIALOGCONFIG);
5669 this->hInstance = ModuleHelper::GetResourceInstance();
5672 // Operations - setting values
5673 // common buttons
5674 void SetCommonButtons(TASKDIALOG_COMMON_BUTTON_FLAGS dwCommonButtons)
5676 this->dwCommonButtons = dwCommonButtons;
5679 // window title text
5680 void SetWindowTitle(UINT nID)
5682 this->pszWindowTitle = MAKEINTRESOURCEW(nID);
5685 void SetWindowTitle(LPCWSTR lpstrWindowTitle)
5687 this->pszWindowTitle = lpstrWindowTitle;
5690 // main icon
5691 void SetMainIcon(HICON hIcon)
5693 this->dwFlags |= TDF_USE_HICON_MAIN;
5694 this->hMainIcon = hIcon;
5697 void SetMainIcon(UINT nID)
5699 this->dwFlags &= ~TDF_USE_HICON_MAIN;
5700 this->pszMainIcon = MAKEINTRESOURCEW(nID);
5703 void SetMainIcon(LPCWSTR lpstrMainIcon)
5705 this->dwFlags &= ~TDF_USE_HICON_MAIN;
5706 this->pszMainIcon = lpstrMainIcon;
5709 // main instruction text
5710 void SetMainInstructionText(UINT nID)
5712 this->pszMainInstruction = MAKEINTRESOURCEW(nID);
5715 void SetMainInstructionText(LPCWSTR lpstrMainInstruction)
5717 this->pszMainInstruction = lpstrMainInstruction;
5720 // content text
5721 void SetContentText(UINT nID)
5723 this->pszContent = MAKEINTRESOURCEW(nID);
5726 void SetContentText(LPCWSTR lpstrContent)
5728 this->pszContent = lpstrContent;
5731 // buttons
5732 void SetButtons(const TASKDIALOG_BUTTON* pButtons, UINT cButtons, int nDefaultButton = 0)
5734 this->pButtons = pButtons;
5735 this->cButtons = cButtons;
5736 if(nDefaultButton != 0)
5737 this->nDefaultButton = nDefaultButton;
5740 void SetDefaultButton(int nDefaultButton)
5742 this->nDefaultButton = nDefaultButton;
5745 // radio buttons
5746 void SetRadioButtons(const TASKDIALOG_BUTTON* pRadioButtons, UINT cRadioButtons, int nDefaultRadioButton = 0)
5748 this->pRadioButtons = pRadioButtons;
5749 this->cRadioButtons = cRadioButtons;
5750 if(nDefaultRadioButton != 0)
5751 this->nDefaultRadioButton = nDefaultRadioButton;
5754 void SetDefaultRadioButton(int nDefaultRadioButton)
5756 this->nDefaultRadioButton = nDefaultRadioButton;
5759 // verification text
5760 void SetVerificationText(UINT nID)
5762 this->pszVerificationText = MAKEINTRESOURCEW(nID);
5765 void SetVerificationText(LPCWSTR lpstrVerificationText)
5767 this->pszVerificationText = lpstrVerificationText;
5770 // expanded information text
5771 void SetExpandedInformationText(UINT nID)
5773 this->pszExpandedInformation = MAKEINTRESOURCEW(nID);
5776 void SetExpandedInformationText(LPCWSTR lpstrExpandedInformation)
5778 this->pszExpandedInformation = lpstrExpandedInformation;
5781 // expanded control text
5782 void SetExpandedControlText(UINT nID)
5784 this->pszExpandedControlText = MAKEINTRESOURCEW(nID);
5787 void SetExpandedControlText(LPCWSTR lpstrExpandedControlText)
5789 this->pszExpandedControlText = lpstrExpandedControlText;
5792 // collapsed control text
5793 void SetCollapsedControlText(UINT nID)
5795 this->pszCollapsedControlText = MAKEINTRESOURCEW(nID);
5798 void SetCollapsedControlText(LPCWSTR lpstrCollapsedControlText)
5800 this->pszCollapsedControlText = lpstrCollapsedControlText;
5803 // footer icon
5804 void SetFooterIcon(HICON hIcon)
5806 this->dwFlags |= TDF_USE_HICON_FOOTER;
5807 this->hFooterIcon = hIcon;
5810 void SetFooterIcon(UINT nID)
5812 this->dwFlags &= ~TDF_USE_HICON_FOOTER;
5813 this->pszFooterIcon = MAKEINTRESOURCEW(nID);
5816 void SetFooterIcon(LPCWSTR lpstrFooterIcon)
5818 this->dwFlags &= ~TDF_USE_HICON_FOOTER;
5819 this->pszFooterIcon = lpstrFooterIcon;
5822 // footer text
5823 void SetFooterText(UINT nID)
5825 this->pszFooter = MAKEINTRESOURCEW(nID);
5828 void SetFooterText(LPCWSTR lpstrFooterText)
5830 this->pszFooter = lpstrFooterText;
5833 // width (in DLUs)
5834 void SetWidth(UINT cxWidth)
5836 this->cxWidth = cxWidth;
5839 // modify flags
5840 void ModifyFlags(DWORD dwRemove, DWORD dwAdd)
5842 this->dwFlags = (this->dwFlags & ~dwRemove) | dwAdd;
5847 ///////////////////////////////////////////////////////////////////////////////
5848 // CTaskDialogImpl - implements a Task Dialog
5850 template <class T>
5851 class ATL_NO_VTABLE CTaskDialogImpl
5853 public:
5854 CTaskDialogConfig m_tdc;
5855 HWND m_hWnd; // used only in callback functions
5857 // Constructor
5858 CTaskDialogImpl(HWND hWndParent = NULL) : m_hWnd(NULL)
5860 m_tdc.hwndParent = hWndParent;
5861 m_tdc.pfCallback = T::TaskDialogCallback;
5862 m_tdc.lpCallbackData = (LONG_PTR)static_cast<T*>(this);
5865 // Operations
5866 HRESULT DoModal(HWND hWndParent = ::GetActiveWindow(), int* pnButton = NULL, int* pnRadioButton = NULL, BOOL* pfVerificationFlagChecked = NULL)
5868 if(m_tdc.hwndParent == NULL)
5869 m_tdc.hwndParent = hWndParent;
5871 #ifdef _WTL_TASKDIALOG_DIRECT
5872 return ::TaskDialogIndirect(&m_tdc, pnButton, pnRadioButton, pfVerificationFlagChecked);
5873 #else
5875 // This allows apps to run on older versions of Windows
5876 typedef HRESULT (STDAPICALLTYPE *PFN_TaskDialogIndirect)(const TASKDIALOGCONFIG* pTaskConfig, int* pnButton, int* pnRadioButton, BOOL* pfVerificationFlagChecked);
5878 HRESULT hRet = E_UNEXPECTED;
5879 HMODULE m_hCommCtrlDLL = ::LoadLibrary(_T("comctl32.dll"));
5880 if(m_hCommCtrlDLL != NULL)
5882 PFN_TaskDialogIndirect pfnTaskDialogIndirect = (PFN_TaskDialogIndirect)::GetProcAddress(m_hCommCtrlDLL, "TaskDialogIndirect");
5883 if(pfnTaskDialogIndirect != NULL)
5884 hRet = pfnTaskDialogIndirect(&m_tdc, pnButton, pnRadioButton, pfVerificationFlagChecked);
5886 ::FreeLibrary(m_hCommCtrlDLL);
5889 return hRet;
5890 #endif
5893 // Operations - setting values of TASKDIALOGCONFIG
5894 // common buttons
5895 void SetCommonButtons(TASKDIALOG_COMMON_BUTTON_FLAGS dwCommonButtons)
5896 { m_tdc.SetCommonButtons(dwCommonButtons); }
5897 // window title text
5898 void SetWindowTitle(UINT nID)
5899 { m_tdc.SetWindowTitle(nID); }
5900 void SetWindowTitle(LPCWSTR lpstrWindowTitle)
5901 { m_tdc.SetWindowTitle(lpstrWindowTitle); }
5902 // main icon
5903 void SetMainIcon(HICON hIcon)
5904 { m_tdc.SetMainIcon(hIcon); }
5905 void SetMainIcon(UINT nID)
5906 { m_tdc.SetMainIcon(nID); }
5907 void SetMainIcon(LPCWSTR lpstrMainIcon)
5908 { m_tdc.SetMainIcon(lpstrMainIcon); }
5909 // main instruction text
5910 void SetMainInstructionText(UINT nID)
5911 { m_tdc.SetMainInstructionText(nID); }
5912 void SetMainInstructionText(LPCWSTR lpstrMainInstruction)
5913 { m_tdc.SetMainInstructionText(lpstrMainInstruction); }
5914 // content text
5915 void SetContentText(UINT nID)
5916 { m_tdc.SetContentText(nID); }
5917 void SetContentText(LPCWSTR lpstrContent)
5918 { m_tdc.SetContentText(lpstrContent); }
5919 // buttons
5920 void SetButtons(const TASKDIALOG_BUTTON* pButtons, UINT cButtons, int nDefaultButton = 0)
5921 { m_tdc.SetButtons(pButtons, cButtons, nDefaultButton); }
5922 void SetDefaultButton(int nDefaultButton)
5923 { m_tdc.SetDefaultButton(nDefaultButton); }
5924 // radio buttons
5925 void SetRadioButtons(const TASKDIALOG_BUTTON* pRadioButtons, UINT cRadioButtons, int nDefaultRadioButton = 0)
5926 { m_tdc.SetRadioButtons(pRadioButtons, cRadioButtons, nDefaultRadioButton); }
5927 void SetDefaultRadioButton(int nDefaultRadioButton)
5928 { m_tdc.SetDefaultRadioButton(nDefaultRadioButton); }
5929 // verification text
5930 void SetVerificationText(UINT nID)
5931 { m_tdc.SetVerificationText(nID); }
5932 void SetVerificationText(LPCWSTR lpstrVerificationText)
5933 { m_tdc.SetVerificationText(lpstrVerificationText); }
5934 // expanded information text
5935 void SetExpandedInformationText(UINT nID)
5936 { m_tdc.SetExpandedInformationText(nID); }
5937 void SetExpandedInformationText(LPCWSTR lpstrExpandedInformation)
5938 { m_tdc.SetExpandedInformationText(lpstrExpandedInformation); }
5939 // expanded control text
5940 void SetExpandedControlText(UINT nID)
5941 { m_tdc.SetExpandedControlText(nID); }
5942 void SetExpandedControlText(LPCWSTR lpstrExpandedControlText)
5943 { m_tdc.SetExpandedControlText(lpstrExpandedControlText); }
5944 // collapsed control text
5945 void SetCollapsedControlText(UINT nID)
5946 { m_tdc.SetCollapsedControlText(nID); }
5947 void SetCollapsedControlText(LPCWSTR lpstrCollapsedControlText)
5948 { m_tdc.SetCollapsedControlText(lpstrCollapsedControlText); }
5949 // footer icon
5950 void SetFooterIcon(HICON hIcon)
5951 { m_tdc.SetFooterIcon(hIcon); }
5952 void SetFooterIcon(UINT nID)
5953 { m_tdc.SetFooterIcon(nID); }
5954 void SetFooterIcon(LPCWSTR lpstrFooterIcon)
5955 { m_tdc.SetFooterIcon(lpstrFooterIcon); }
5956 // footer text
5957 void SetFooterText(UINT nID)
5958 { m_tdc.SetFooterText(nID); }
5959 void SetFooterText(LPCWSTR lpstrFooterText)
5960 { m_tdc.SetFooterText(lpstrFooterText); }
5961 // width (in DLUs)
5962 void SetWidth(UINT cxWidth)
5963 { m_tdc.SetWidth(cxWidth); }
5964 // modify flags
5965 void ModifyFlags(DWORD dwRemove, DWORD dwAdd)
5966 { m_tdc.ModifyFlags(dwRemove, dwAdd); }
5968 // Implementation
5969 static HRESULT CALLBACK TaskDialogCallback(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam, LONG_PTR lpRefData)
5971 T* pT = (T*)lpRefData;
5972 ATLASSERT(pT->m_hWnd == NULL || pT->m_hWnd == hWnd);
5974 BOOL bRet = FALSE;
5975 switch(uMsg)
5977 case TDN_DIALOG_CONSTRUCTED:
5978 pT->m_hWnd = hWnd;
5979 pT->OnDialogConstructed();
5980 break;
5981 case TDN_CREATED:
5982 pT->OnCreated();
5983 break;
5984 case TDN_BUTTON_CLICKED:
5985 bRet = pT->OnButtonClicked((int)wParam);
5986 break;
5987 case TDN_RADIO_BUTTON_CLICKED:
5988 pT->OnRadioButtonClicked((int)wParam);
5989 break;
5990 case TDN_HYPERLINK_CLICKED:
5991 pT->OnHyperlinkClicked((LPCWSTR)lParam);
5992 break;
5993 case TDN_EXPANDO_BUTTON_CLICKED:
5994 pT->OnExpandoButtonClicked((wParam != 0));
5995 break;
5996 case TDN_VERIFICATION_CLICKED:
5997 pT->OnVerificationClicked((wParam != 0));
5998 break;
5999 case TDN_HELP:
6000 pT->OnHelp();
6001 break;
6002 case TDN_TIMER:
6003 bRet = pT->OnTimer((DWORD)wParam);
6004 break;
6005 case TDN_NAVIGATED:
6006 pT->OnNavigated();
6007 break;
6008 case TDN_DESTROYED:
6009 pT->OnDestroyed();
6010 pT->m_hWnd = NULL;
6011 break;
6012 default:
6013 ATLTRACE2(atlTraceUI, 0, _T("Unknown notification received in CTaskDialogImpl::TaskDialogCallback\n"));
6014 break;
6017 return (HRESULT)bRet;
6020 // Overrideables - notification handlers
6021 void OnDialogConstructed()
6025 void OnCreated()
6029 BOOL OnButtonClicked(int /*nButton*/)
6031 return FALSE; // don't prevent dialog to close
6034 void OnRadioButtonClicked(int /*nRadioButton*/)
6038 void OnHyperlinkClicked(LPCWSTR /*pszHREF*/)
6042 void OnExpandoButtonClicked(bool /*bExpanded*/)
6046 void OnVerificationClicked(bool /*bChecked*/)
6050 void OnHelp()
6054 BOOL OnTimer(DWORD /*dwTickCount*/)
6056 return FALSE; // don't reset counter
6059 void OnNavigated()
6063 void OnDestroyed()
6067 // Commands - valid to call only from handlers
6068 void NavigatePage(TASKDIALOGCONFIG& tdc)
6070 ATLASSERT(m_hWnd != NULL);
6072 tdc.cbSize = sizeof(TASKDIALOGCONFIG);
6073 if(tdc.hwndParent == NULL)
6074 tdc.hwndParent = m_tdc.hwndParent;
6075 tdc.pfCallback = m_tdc.pfCallback;
6076 tdc.lpCallbackData = m_tdc.lpCallbackData;
6077 (TASKDIALOGCONFIG)m_tdc = tdc;
6079 ::SendMessage(m_hWnd, TDM_NAVIGATE_PAGE, 0, (LPARAM)&tdc);
6082 // modify TASKDIALOGCONFIG values, then call this to update task dialog
6083 void NavigatePage()
6085 ATLASSERT(m_hWnd != NULL);
6086 ::SendMessage(m_hWnd, TDM_NAVIGATE_PAGE, 0, (LPARAM)&m_tdc);
6089 void ClickButton(int nButton)
6091 ATLASSERT(m_hWnd != NULL);
6092 ::SendMessage(m_hWnd, TDM_CLICK_BUTTON, nButton, 0L);
6095 void SetMarqueeProgressBar(BOOL bMarquee)
6097 ATLASSERT(m_hWnd != NULL);
6098 ::SendMessage(m_hWnd, TDM_SET_MARQUEE_PROGRESS_BAR, bMarquee, 0L);
6101 BOOL SetProgressBarState(int nNewState)
6103 ATLASSERT(m_hWnd != NULL);
6104 return (BOOL)::SendMessage(m_hWnd, TDM_SET_PROGRESS_BAR_STATE, nNewState, 0L);
6107 DWORD SetProgressBarRange(int nMinRange, int nMaxRange)
6109 ATLASSERT(m_hWnd != NULL);
6110 return (DWORD)::SendMessage(m_hWnd, TDM_SET_PROGRESS_BAR_RANGE, 0, MAKELPARAM(nMinRange, nMaxRange));
6113 int SetProgressBarPos(int nNewPos)
6115 ATLASSERT(m_hWnd != NULL);
6116 return (int)::SendMessage(m_hWnd, TDM_SET_PROGRESS_BAR_POS, nNewPos, 0L);
6119 BOOL SetProgressBarMarquee(BOOL bMarquee, UINT uSpeed)
6121 ATLASSERT(m_hWnd != NULL);
6122 return (BOOL)::SendMessage(m_hWnd, TDM_SET_PROGRESS_BAR_MARQUEE, bMarquee, uSpeed);
6125 void SetElementText(TASKDIALOG_ELEMENTS element, LPCWSTR lpstrText)
6127 ATLASSERT(m_hWnd != NULL);
6128 ::SendMessage(m_hWnd, TDM_SET_ELEMENT_TEXT, element, (LPARAM)lpstrText);
6131 void ClickRadioButton(int nRadioButton)
6133 ATLASSERT(m_hWnd != NULL);
6134 ::SendMessage(m_hWnd, TDM_CLICK_RADIO_BUTTON, nRadioButton, 0L);
6137 void EnableButton(int nButton, BOOL bEnable)
6139 ATLASSERT(m_hWnd != NULL);
6140 ::SendMessage(m_hWnd, TDM_ENABLE_BUTTON, nButton, bEnable);
6143 void EnableRadioButton(int nButton, BOOL bEnable)
6145 ATLASSERT(m_hWnd != NULL);
6146 ::SendMessage(m_hWnd, TDM_ENABLE_RADIO_BUTTON, nButton, bEnable);
6149 void ClickVerification(BOOL bCheck, BOOL bFocus)
6151 ATLASSERT(m_hWnd != NULL);
6152 ::SendMessage(m_hWnd, TDM_CLICK_VERIFICATION, bCheck, bFocus);
6155 void UpdateElementText(TASKDIALOG_ELEMENTS element, LPCWSTR lpstrText)
6157 ATLASSERT(m_hWnd != NULL);
6158 ::SendMessage(m_hWnd, TDM_UPDATE_ELEMENT_TEXT, element, (LPARAM)lpstrText);
6161 void SetButtonElevationRequiredState(int nButton, BOOL bElevation)
6163 ATLASSERT(m_hWnd != NULL);
6164 ::SendMessage(m_hWnd, TDM_SET_BUTTON_ELEVATION_REQUIRED_STATE, nButton, bElevation);
6167 void UpdateIcon(TASKDIALOG_ICON_ELEMENTS element, HICON hIcon)
6169 ATLASSERT(m_hWnd != NULL);
6170 #ifdef _DEBUG
6171 if(element == TDIE_ICON_MAIN)
6172 ATLASSERT((m_tdc.dwFlags & TDF_USE_HICON_MAIN) != 0);
6173 else if(element == TDIE_ICON_FOOTER)
6174 ATLASSERT((m_tdc.dwFlags & TDF_USE_HICON_FOOTER) != 0);
6175 #endif // _DEBUG
6176 ::SendMessage(m_hWnd, TDM_UPDATE_ICON, element, (LPARAM)hIcon);
6179 void UpdateIcon(TASKDIALOG_ICON_ELEMENTS element, LPCWSTR lpstrIcon)
6181 ATLASSERT(m_hWnd != NULL);
6182 #ifdef _DEBUG
6183 if(element == TDIE_ICON_MAIN)
6184 ATLASSERT((m_tdc.dwFlags & TDF_USE_HICON_MAIN) == 0);
6185 else if(element == TDIE_ICON_FOOTER)
6186 ATLASSERT((m_tdc.dwFlags & TDF_USE_HICON_FOOTER) == 0);
6187 #endif // _DEBUG
6188 ::SendMessage(m_hWnd, TDM_UPDATE_ICON, element, (LPARAM)lpstrIcon);
6193 ///////////////////////////////////////////////////////////////////////////////
6194 // CTaskDialog - for non-customized task dialogs
6196 class CTaskDialog : public CTaskDialogImpl<CTaskDialog>
6198 public:
6199 CTaskDialog(HWND hWndParent = NULL) : CTaskDialogImpl<CTaskDialog>(hWndParent)
6201 m_tdc.pfCallback = NULL;
6205 #endif // ((_WIN32_WINNT >= 0x0600) || defined(_WTL_TASKDIALOG)) && !defined(_WIN32_WCE)
6207 }; // namespace WTL
6209 #endif // __ATLDLGS_H__