crashrpt2
atldlgs.h
1 // Windows Template Library - WTL version 9.10
2 // Copyright (C) Microsoft Corporation, WTL Team. 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 Public License (http://opensource.org/licenses/MS-PL)
7 // which can be found in the file MS-PL.txt at the root folder.
8 
9 #ifndef __ATLDLGS_H__
10 #define __ATLDLGS_H__
11 
12 #pragma once
13 
14 #ifndef __ATLAPP_H__
15  #error atldlgs.h requires atlapp.h to be included first
16 #endif
17 
18 #ifndef __ATLWIN_H__
19  #error atldlgs.h requires atlwin.h to be included first
20 #endif
21 
22 #include <commdlg.h>
23 #include <shlobj.h>
24 
25 #if (_WIN32_WINNT >= 0x0600) && !defined(_WIN32_WCE)
26  #include <shobjidl.h>
27 #endif // (_WIN32_WINNT >= 0x0600) && !defined(_WIN32_WCE)
28 
29 
31 // Classes in this file:
32 //
33 // CFileDialogImpl<T>
34 // CFileDialog
35 // CFileDialogEx
36 // CMultiFileDialogImpl<T>
37 // CMultiFileDialog
38 // CShellFileDialogImpl<T>
39 // CShellFileOpenDialogImpl<T>
40 // CShellFileOpenDialog
41 // CShellFileSaveDialogImpl<T>
42 // CShellFileSaveDialog
43 // CFolderDialogImpl<T>
44 // CFolderDialog
45 // CFontDialogImpl<T>
46 // CFontDialog
47 // CRichEditFontDialogImpl<T>
48 // CRichEditFontDialog
49 // CColorDialogImpl<T>
50 // CColorDialog
51 // CPrintDialogImpl<T>
52 // CPrintDialog
53 // CPrintDialogExImpl<T>
54 // CPrintDialogEx
55 // CPageSetupDialogImpl<T>
56 // CPageSetupDialog
57 // CFindReplaceDialogImpl<T>
58 // CFindReplaceDialog
59 //
60 // CDialogBaseUnits
61 // CMemDlgTemplate
62 // CIndirectDialogImpl<T, TDlgTemplate, TBase>
63 //
64 // CPropertySheetWindow
65 // CPropertySheetImpl<T, TBase>
66 // CPropertySheet
67 // CPropertyPageWindow
68 // CPropertyPageImpl<T, TBase>
69 // CPropertyPage<t_wDlgTemplateID>
70 // CAxPropertyPageImpl<T, TBase>
71 // CAxPropertyPage<t_wDlgTemplateID>
72 //
73 // CWizard97SheetWindow
74 // CWizard97SheetImpl<T, TBase>
75 // CWizard97Sheet
76 // CWizard97PageWindow
77 // CWizard97PageImpl<T, TBase>
78 // CWizard97ExteriorPageImpl<T, TBase>
79 // CWizard97InteriorPageImpl<T, TBase>
80 //
81 // CAeroWizardFrameWindow
82 // CAeroWizardFrameImpl<T, TBase>
83 // CAeroWizardFrame
84 // CAeroWizardPageWindow
85 // CAeroWizardPageImpl<T, TBase>
86 // CAeroWizardPage<t_wDlgTemplateID>
87 // CAeroWizardAxPageImpl<T, TBase>
88 // CAeroWizardAxPage<t_wDlgTemplateID>
89 //
90 // CTaskDialogConfig
91 // CTaskDialogImpl<T>
92 // CTaskDialog
93 //
94 // Global functions:
95 // AtlTaskDialog()
96 
97 
98 namespace WTL
99 {
100 
102 // CFileDialogImpl - used for File Open or File Save As
103 
104 // compatibility with the old (vc6.0) headers
105 #if (_WIN32_WINNT >= 0x0500) && !defined(OPENFILENAME_SIZE_VERSION_400)
106  #ifndef CDSIZEOF_STRUCT
107  #define CDSIZEOF_STRUCT(structname, member) (((int)((LPBYTE)(&((structname*)0)->member) - ((LPBYTE)((structname*)0)))) + sizeof(((structname*)0)->member))
108  #endif
109  #define OPENFILENAME_SIZE_VERSION_400A CDSIZEOF_STRUCT(OPENFILENAMEA,lpTemplateName)
110  #define OPENFILENAME_SIZE_VERSION_400W CDSIZEOF_STRUCT(OPENFILENAMEW,lpTemplateName)
111  #ifdef UNICODE
112  #define OPENFILENAME_SIZE_VERSION_400 OPENFILENAME_SIZE_VERSION_400W
113  #else
114  #define OPENFILENAME_SIZE_VERSION_400 OPENFILENAME_SIZE_VERSION_400A
115  #endif // !UNICODE
116 #endif // (_WIN32_WINNT >= 0x0500) && !defined(OPENFILENAME_SIZE_VERSION_400)
117 
118 #if !defined(_WIN32_WCE) && !defined(CDN_INCLUDEITEM)
119  #define CDN_INCLUDEITEM (CDN_FIRST - 0x0007)
120 #endif
121 
122 template <class T>
123 class ATL_NO_VTABLE CFileDialogImpl : public ATL::CDialogImplBase
124 {
125 public:
126 #if defined(__AYGSHELL_H__) && (_WIN32_WCE >= 0x0501)
127  OPENFILENAMEEX m_ofn;
128 #else
129  OPENFILENAME m_ofn;
130 #endif
131  BOOL m_bOpenFileDialog; // TRUE for file open, FALSE for file save
132  TCHAR m_szFileTitle[_MAX_FNAME]; // contains file title after return
133  TCHAR m_szFileName[_MAX_PATH]; // contains full path name after return
134 
135  CFileDialogImpl(BOOL bOpenFileDialog, // TRUE for FileOpen, FALSE for FileSaveAs
136  LPCTSTR lpszDefExt = NULL,
137  LPCTSTR lpszFileName = NULL,
138  DWORD dwFlags = OFN_HIDEREADONLY | OFN_OVERWRITEPROMPT,
139  LPCTSTR lpszFilter = NULL,
140  HWND hWndParent = NULL)
141  {
142  memset(&m_ofn, 0, sizeof(m_ofn)); // initialize structure to 0/NULL
143  m_szFileName[0] = _T('\0');
144  m_szFileTitle[0] = _T('\0');
145 
146  m_bOpenFileDialog = bOpenFileDialog;
147 
148 #if defined(__AYGSHELL_H__) && (_WIN32_WCE >= 0x0501)
149  m_ofn.lStructSize = bOpenFileDialog ? sizeof(m_ofn) : sizeof(OPENFILENAME);
150 #else
151  m_ofn.lStructSize = sizeof(m_ofn);
152 #endif
153 
154 #if (_WIN32_WINNT >= 0x0500)
155  // adjust struct size if running on older version of Windows
156  if(AtlIsOldWindows())
157  {
158  ATLASSERT(sizeof(m_ofn) > OPENFILENAME_SIZE_VERSION_400); // must be
159  m_ofn.lStructSize = OPENFILENAME_SIZE_VERSION_400;
160  }
161 #endif // (_WIN32_WINNT >= 0x0500)
162  m_ofn.lpstrFile = m_szFileName;
163  m_ofn.nMaxFile = _MAX_PATH;
164  m_ofn.lpstrDefExt = lpszDefExt;
165  m_ofn.lpstrFileTitle = (LPTSTR)m_szFileTitle;
166  m_ofn.nMaxFileTitle = _MAX_FNAME;
167 #ifndef _WIN32_WCE
168  m_ofn.Flags = dwFlags | OFN_EXPLORER | OFN_ENABLEHOOK | OFN_ENABLESIZING;
169 #else // CE specific
170  m_ofn.Flags = dwFlags | OFN_EXPLORER | OFN_ENABLEHOOK;
171 #endif // !_WIN32_WCE
172  m_ofn.lpstrFilter = lpszFilter;
173  m_ofn.hInstance = ModuleHelper::GetResourceInstance();
174  m_ofn.lpfnHook = (LPOFNHOOKPROC)T::StartDialogProc;
175  m_ofn.hwndOwner = hWndParent;
176 
177  // setup initial file name
178  if(lpszFileName != NULL)
179  SecureHelper::strncpy_x(m_szFileName, _countof(m_szFileName), lpszFileName, _TRUNCATE);
180  }
181 
182  INT_PTR DoModal(HWND hWndParent = ::GetActiveWindow())
183  {
184  ATLASSERT((m_ofn.Flags & OFN_ENABLEHOOK) != 0);
185  ATLASSERT(m_ofn.lpfnHook != NULL); // can still be a user hook
186 
187  ATLASSERT((m_ofn.Flags & OFN_EXPLORER) != 0);
188 
189  if(m_ofn.hwndOwner == NULL) // set only if not specified before
190  m_ofn.hwndOwner = hWndParent;
191 
192  ATLASSERT(m_hWnd == NULL);
193 
194 #if (_ATL_VER >= 0x0800)
195  // Allocate the thunk structure here, where we can fail gracefully.
196  BOOL bRetTh = m_thunk.Init(NULL, NULL);
197  if(bRetTh == FALSE)
198  {
199  ::SetLastError(ERROR_OUTOFMEMORY);
200  return -1;
201  }
202 #endif // (_ATL_VER >= 0x0800)
203 
204  ModuleHelper::AddCreateWndData(&m_thunk.cd, (ATL::CDialogImplBase*)this);
205 
206  BOOL bRet;
207  if(m_bOpenFileDialog)
208 #if defined(__AYGSHELL_H__) && (_WIN32_WCE >= 0x0501)
209  bRet = ::GetOpenFileNameEx(&m_ofn);
210  else
211  bRet = ::GetSaveFileName((LPOPENFILENAME)&m_ofn);
212 #else
213  bRet = ::GetOpenFileName(&m_ofn);
214  else
215  bRet = ::GetSaveFileName(&m_ofn);
216 #endif
217 
218  m_hWnd = NULL;
219 
220  return bRet ? IDOK : IDCANCEL;
221  }
222 
223 // Attributes
224  ATL::CWindow GetFileDialogWindow() const
225  {
226  ATLASSERT(::IsWindow(m_hWnd));
227  return ATL::CWindow(GetParent());
228  }
229 
230  int GetFilePath(LPTSTR lpstrFilePath, int nLength) const
231  {
232  ATLASSERT(::IsWindow(m_hWnd));
233  ATLASSERT((m_ofn.Flags & OFN_EXPLORER) != 0);
234 
235  return (int)GetFileDialogWindow().SendMessage(CDM_GETFILEPATH, nLength, (LPARAM)lpstrFilePath);
236  }
237 
238  int GetFolderIDList(LPVOID lpBuff, int nLength) const
239  {
240  ATLASSERT(::IsWindow(m_hWnd));
241  ATLASSERT((m_ofn.Flags & OFN_EXPLORER) != 0);
242 
243  return (int)GetFileDialogWindow().SendMessage(CDM_GETFOLDERIDLIST, nLength, (LPARAM)lpBuff);
244  }
245 
246  int GetFolderPath(LPTSTR lpstrFolderPath, int nLength) const
247  {
248  ATLASSERT(::IsWindow(m_hWnd));
249  ATLASSERT((m_ofn.Flags & OFN_EXPLORER) != 0);
250 
251  return (int)GetFileDialogWindow().SendMessage(CDM_GETFOLDERPATH, nLength, (LPARAM)lpstrFolderPath);
252  }
253 
254  int GetSpec(LPTSTR lpstrSpec, int nLength) const
255  {
256  ATLASSERT(::IsWindow(m_hWnd));
257  ATLASSERT((m_ofn.Flags & OFN_EXPLORER) != 0);
258 
259  return (int)GetFileDialogWindow().SendMessage(CDM_GETSPEC, nLength, (LPARAM)lpstrSpec);
260  }
261 
262  void SetControlText(int nCtrlID, LPCTSTR lpstrText)
263  {
264  ATLASSERT(::IsWindow(m_hWnd));
265  ATLASSERT((m_ofn.Flags & OFN_EXPLORER) != 0);
266 
267  GetFileDialogWindow().SendMessage(CDM_SETCONTROLTEXT, nCtrlID, (LPARAM)lpstrText);
268  }
269 
270  void SetDefExt(LPCTSTR lpstrExt)
271  {
272  ATLASSERT(::IsWindow(m_hWnd));
273  ATLASSERT((m_ofn.Flags & OFN_EXPLORER) != 0);
274 
275  GetFileDialogWindow().SendMessage(CDM_SETDEFEXT, 0, (LPARAM)lpstrExt);
276  }
277 
278  BOOL GetReadOnlyPref() const // return TRUE if readonly checked
279  {
280  return ((m_ofn.Flags & OFN_READONLY) != 0) ? TRUE : FALSE;
281  }
282 
283 // Operations
284  void HideControl(int nCtrlID)
285  {
286  ATLASSERT(::IsWindow(m_hWnd));
287  ATLASSERT((m_ofn.Flags & OFN_EXPLORER) != 0);
288 
289  GetFileDialogWindow().SendMessage(CDM_HIDECONTROL, nCtrlID);
290  }
291 
292 // Special override for common dialogs
293  BOOL EndDialog(INT_PTR /*nRetCode*/ = 0)
294  {
295  ATLASSERT(::IsWindow(m_hWnd));
296  GetFileDialogWindow().SendMessage(WM_COMMAND, MAKEWPARAM(IDCANCEL, 0));
297  return TRUE;
298  }
299 
300 // Message map and handlers
301  BEGIN_MSG_MAP(CFileDialogImpl)
302  NOTIFY_CODE_HANDLER(CDN_FILEOK, _OnFileOK)
303  NOTIFY_CODE_HANDLER(CDN_FOLDERCHANGE, _OnFolderChange)
304  NOTIFY_CODE_HANDLER(CDN_HELP, _OnHelp)
305  NOTIFY_CODE_HANDLER(CDN_INITDONE, _OnInitDone)
306  NOTIFY_CODE_HANDLER(CDN_SELCHANGE, _OnSelChange)
307  NOTIFY_CODE_HANDLER(CDN_SHAREVIOLATION, _OnShareViolation)
308  NOTIFY_CODE_HANDLER(CDN_TYPECHANGE, _OnTypeChange)
309 #ifndef _WIN32_WCE
310  NOTIFY_CODE_HANDLER(CDN_INCLUDEITEM, _OnIncludeItem)
311 #endif // !_WIN32_WCE
312  END_MSG_MAP()
313 
314  LRESULT _OnFileOK(int /*idCtrl*/, LPNMHDR pnmh, BOOL& /*bHandled*/)
315  {
316  ATLASSERT(::IsWindow(m_hWnd));
317  T* pT = static_cast<T*>(this);
318  return !pT->OnFileOK((LPOFNOTIFY)pnmh);
319  }
320 
321  LRESULT _OnFolderChange(int /*idCtrl*/, LPNMHDR pnmh, BOOL& /*bHandled*/)
322  {
323  ATLASSERT(::IsWindow(m_hWnd));
324  T* pT = static_cast<T*>(this);
325  pT->OnFolderChange((LPOFNOTIFY)pnmh);
326  return 0;
327  }
328 
329  LRESULT _OnHelp(int /*idCtrl*/, LPNMHDR pnmh, BOOL& /*bHandled*/)
330  {
331  ATLASSERT(::IsWindow(m_hWnd));
332  T* pT = static_cast<T*>(this);
333  pT->OnHelp((LPOFNOTIFY)pnmh);
334  return 0;
335  }
336 
337  LRESULT _OnInitDone(int /*idCtrl*/, LPNMHDR pnmh, BOOL& /*bHandled*/)
338  {
339  ATLASSERT(::IsWindow(m_hWnd));
340  T* pT = static_cast<T*>(this);
341  pT->OnInitDone((LPOFNOTIFY)pnmh);
342  return 0;
343  }
344 
345  LRESULT _OnSelChange(int /*idCtrl*/, LPNMHDR pnmh, BOOL& /*bHandled*/)
346  {
347  ATLASSERT(::IsWindow(m_hWnd));
348  T* pT = static_cast<T*>(this);
349  pT->OnSelChange((LPOFNOTIFY)pnmh);
350  return 0;
351  }
352 
353  LRESULT _OnShareViolation(int /*idCtrl*/, LPNMHDR pnmh, BOOL& /*bHandled*/)
354  {
355  ATLASSERT(::IsWindow(m_hWnd));
356  T* pT = static_cast<T*>(this);
357  return pT->OnShareViolation((LPOFNOTIFY)pnmh);
358  }
359 
360  LRESULT _OnTypeChange(int /*idCtrl*/, LPNMHDR pnmh, BOOL& /*bHandled*/)
361  {
362  ATLASSERT(::IsWindow(m_hWnd));
363  T* pT = static_cast<T*>(this);
364  pT->OnTypeChange((LPOFNOTIFY)pnmh);
365  return 0;
366  }
367 
368 #ifndef _WIN32_WCE
369  LRESULT _OnIncludeItem(int /*idCtrl*/, LPNMHDR pnmh, BOOL& /*bHandled*/)
370  {
371  ATLASSERT(::IsWindow(m_hWnd));
372  T* pT = static_cast<T*>(this);
373  return pT->OnIncludeItem((LPOFNOTIFYEX)pnmh);
374  }
375 #endif // !_WIN32_WCE
376 
377 // Overrideables
378  BOOL OnFileOK(LPOFNOTIFY /*lpon*/)
379  {
380  return TRUE;
381  }
382 
383  void OnFolderChange(LPOFNOTIFY /*lpon*/)
384  {
385  }
386 
387  void OnHelp(LPOFNOTIFY /*lpon*/)
388  {
389  }
390 
391  void OnInitDone(LPOFNOTIFY /*lpon*/)
392  {
393  }
394 
395  void OnSelChange(LPOFNOTIFY /*lpon*/)
396  {
397  }
398 
399  int OnShareViolation(LPOFNOTIFY /*lpon*/)
400  {
401  return 0;
402  }
403 
404  void OnTypeChange(LPOFNOTIFY /*lpon*/)
405  {
406  }
407 
408 #ifndef _WIN32_WCE
409  BOOL OnIncludeItem(LPOFNOTIFYEX /*lponex*/)
410  {
411  return TRUE; // include item
412  }
413 #endif // !_WIN32_WCE
414 };
415 
416 class CFileDialog : public CFileDialogImpl<CFileDialog>
417 {
418 public:
419  CFileDialog(BOOL bOpenFileDialog, // TRUE for FileOpen, FALSE for FileSaveAs
420  LPCTSTR lpszDefExt = NULL,
421  LPCTSTR lpszFileName = NULL,
422  DWORD dwFlags = OFN_HIDEREADONLY | OFN_OVERWRITEPROMPT,
423  LPCTSTR lpszFilter = NULL,
424  HWND hWndParent = NULL)
425  : CFileDialogImpl<CFileDialog>(bOpenFileDialog, lpszDefExt, lpszFileName, dwFlags, lpszFilter, hWndParent)
426  { }
427 
428  // override base class map and references to handlers
429  DECLARE_EMPTY_MSG_MAP()
430 };
431 
432 #if defined(__AYGSHELL_H__) && (_WIN32_WCE >= 0x0501)
433 class CFileDialogEx : public CFileDialogImpl<CFileDialogEx>
434 {
435 public:
436  CFileDialogEx( // Supports only FileOpen
437  LPCTSTR lpszDefExt = NULL,
438  LPCTSTR lpszFileName = NULL,
439  DWORD dwFlags = OFN_HIDEREADONLY | OFN_OVERWRITEPROMPT,
440  OFN_EXFLAG ExFlags = OFN_EXFLAG_THUMBNAILVIEW,
441  OFN_SORTORDER dwSortOrder = OFN_SORTORDER_AUTO,
442  LPCTSTR lpszFilter = NULL,
443  HWND hWndParent = NULL)
444  : CFileDialogImpl<CFileDialogEx>(TRUE, lpszDefExt, lpszFileName, dwFlags, lpszFilter, hWndParent)
445  {
446  m_ofn.ExFlags = ExFlags;
447  m_ofn.dwSortOrder = dwSortOrder;
448  }
449 
450  // override base class map and references to handlers
451  DECLARE_EMPTY_MSG_MAP()
452 };
453 #endif // defined(__AYGSHELL_H__) && (_WIN32_WCE >= 0x0501)
454 
455 
457 // Multi File Dialog - Multi-select File Open dialog
458 
459 #ifndef _WIN32_WCE
460 
461 // The class dynamically resizes the buffer as the file selection changes
462 // (as described in Knowledge Base article 131462). It also expands selected
463 // shortcut files to take into account the full path of the target file.
464 // Note that this doesn't work on Win9x for the old style dialogs, as well as
465 // on NT for non-Unicode builds.
466 
467 #ifndef _WTL_FIXED_OFN_BUFFER_LENGTH
468  #define _WTL_FIXED_OFN_BUFFER_LENGTH 0x10000
469 #endif
470 
471 template <class T>
472 class ATL_NO_VTABLE CMultiFileDialogImpl : public CFileDialogImpl< T >
473 {
474 public:
475  mutable LPCTSTR m_pNextFile;
476 #ifndef _UNICODE
477  bool m_bIsNT;
478 #endif
479 
481  LPCTSTR lpszDefExt = NULL,
482  LPCTSTR lpszFileName = NULL,
483  DWORD dwFlags = OFN_HIDEREADONLY,
484  LPCTSTR lpszFilter = NULL,
485  HWND hWndParent = NULL)
486  : CFileDialogImpl<T>(TRUE, lpszDefExt, lpszFileName, dwFlags, lpszFilter, hWndParent),
487  m_pNextFile(NULL)
488  {
489  m_ofn.Flags |= OFN_ALLOWMULTISELECT; // Force multiple selection mode
490 
491 #ifndef _UNICODE
492 #ifdef _versionhelpers_H_INCLUDED_
493  OSVERSIONINFOEX ovi = { sizeof(OSVERSIONINFOEX) };
494  ovi.dwPlatformId = VER_PLATFORM_WIN32_NT;
495  DWORDLONG const dwlConditionMask = ::VerSetConditionMask(0, VER_PLATFORMID, VER_EQUAL);
496  m_bIsNT = (::VerifyVersionInfo(&ovi, VER_PLATFORMID, dwlConditionMask) != FALSE);
497 #else // !_versionhelpers_H_INCLUDED_
498  OSVERSIONINFO ovi = { sizeof(OSVERSIONINFO) };
499  ::GetVersionEx(&ovi);
500  m_bIsNT = (ovi.dwPlatformId == VER_PLATFORM_WIN32_NT);
501 #endif // _versionhelpers_H_INCLUDED_
502  if (m_bIsNT)
503  {
504  // On NT platforms, GetOpenFileNameA thunks to GetOpenFileNameW and there
505  // is absolutely nothing we can do except to start off with a large buffer.
506  ATLVERIFY(ResizeFilenameBuffer(_WTL_FIXED_OFN_BUFFER_LENGTH));
507  }
508 #endif
509  }
510 
512  {
513  if (m_ofn.lpstrFile != m_szFileName) // Free the buffer if we allocated it
514  delete[] m_ofn.lpstrFile;
515  }
516 
517 // Operations
518  // Get the directory that the files were chosen from.
519  // The function returns the number of characters copied, not including the terminating zero.
520  // If the buffer is NULL, the function returns the required size, in characters, including the terminating zero.
521  // If the function fails, the return value is zero.
522  int GetDirectory(LPTSTR pBuffer, int nBufLen) const
523  {
524  if (m_ofn.lpstrFile == NULL)
525  return 0;
526 
527  LPCTSTR pStr = m_ofn.lpstrFile;
528  int nLength = lstrlen(pStr);
529  if (pStr[nLength + 1] == 0)
530  {
531  // The OFN buffer contains a single item so extract its path.
532  LPCTSTR pSep = MinCrtHelper::_strrchr(pStr, _T('\\'));
533  if (pSep != NULL)
534  nLength = (int)(DWORD_PTR)(pSep - pStr);
535  }
536 
537  int nRet = 0;
538  if (pBuffer == NULL) // If the buffer is NULL, return the required length
539  {
540  nRet = nLength + 1;
541  }
542  else if (nBufLen > nLength)
543  {
544  SecureHelper::strncpy_x(pBuffer, nBufLen, pStr, nLength);
545  nRet = nLength;
546  }
547 
548  return nRet;
549  }
550 
551 #if defined(_WTL_USE_CSTRING) || defined(__ATLSTR_H__)
552  bool GetDirectory(_CSTRING_NS::CString& strDir) const
553  {
554  bool bRet = false;
555 
556  int nLength = GetDirectory(NULL, 0);
557  if (nLength > 0)
558  {
559  bRet = (GetDirectory(strDir.GetBuffer(nLength), nLength) > 0);
560  strDir.ReleaseBuffer(nLength - 1);
561  }
562 
563  return bRet;
564  }
565 #endif // defined(_WTL_USE_CSTRING) || defined(__ATLSTR_H__)
566 
567  // Get the first filename as a pointer into the buffer.
568  LPCTSTR GetFirstFileName() const
569  {
570  if (m_ofn.lpstrFile == NULL)
571  return NULL;
572 
573  m_pNextFile = NULL; // Reset internal buffer pointer
574 
575  LPCTSTR pStr = m_ofn.lpstrFile;
576  int nLength = lstrlen(pStr);
577  if (pStr[nLength + 1] != 0)
578  {
579  // Multiple items were selected. The first string is the directory,
580  // so skip forwards to the second string.
581  pStr += nLength + 1;
582 
583  // Set up m_pNext so it points to the second item (or null).
584  m_pNextFile = pStr;
585  GetNextFileName();
586  }
587  else
588  {
589  // A single item was selected. Skip forward past the path.
590  LPCTSTR pSep = MinCrtHelper::_strrchr(pStr, _T('\\'));
591  if (pSep != NULL)
592  pStr = pSep + 1;
593  }
594 
595  return pStr;
596  }
597 
598  // Get the next filename as a pointer into the buffer.
599  LPCTSTR GetNextFileName() const
600  {
601  if (m_pNextFile == NULL)
602  return NULL;
603 
604  LPCTSTR pStr = m_pNextFile;
605  // Set "m_pNextFile" to point to the next file name, or null if we
606  // have reached the last file in the list.
607  int nLength = lstrlen(pStr);
608  m_pNextFile = (pStr[nLength + 1] != 0) ? &pStr[nLength + 1] : NULL;
609 
610  return pStr;
611  }
612 
613  // Get the first filename as a full path.
614  // The function returns the number of characters copied, not including the terminating zero.
615  // If the buffer is NULL, the function returns the required size, in characters, including the terminating zero.
616  // If the function fails, the return value is zero.
617  int GetFirstPathName(LPTSTR pBuffer, int nBufLen) const
618  {
619  LPCTSTR pStr = GetFirstFileName();
620  int nLengthDir = GetDirectory(NULL, 0);
621  if((pStr == NULL) || (nLengthDir == 0))
622  return 0;
623 
624  // Figure out the required length.
625  int nLengthTotal = nLengthDir + lstrlen(pStr);
626 
627  int nRet = 0;
628  if(pBuffer == NULL) // If the buffer is NULL, return the required length
629  {
630  nRet = nLengthTotal + 1;
631  }
632  else if (nBufLen > nLengthTotal) // If the buffer is big enough, go ahead and construct the path
633  {
634  GetDirectory(pBuffer, nBufLen);
635  SecureHelper::strcat_x(pBuffer, nBufLen, _T("\\"));
636  SecureHelper::strcat_x(pBuffer, nBufLen, pStr);
637  nRet = nLengthTotal;
638  }
639 
640  return nRet;
641  }
642 
643 #if defined(_WTL_USE_CSTRING) || defined(__ATLSTR_H__)
644  bool GetFirstPathName(_CSTRING_NS::CString& strPath) const
645  {
646  bool bRet = false;
647 
648  int nLength = GetFirstPathName(NULL, 0);
649  if (nLength > 0)
650  {
651  bRet = (GetFirstPathName(strPath.GetBuffer(nLength), nLength) > 0);
652  strPath.ReleaseBuffer(nLength - 1);
653  }
654 
655  return bRet;
656  }
657 #endif // defined(_WTL_USE_CSTRING) || defined(__ATLSTR_H__)
658 
659  // Get the next filename as a full path.
660  // The function returns the number of characters copied, not including the terminating zero.
661  // If the buffer is NULL, the function returns the required size, in characters, including the terminating zero.
662  // If the function fails, the return value is zero.
663  // The internal position marker is moved forward only if the function succeeds and the buffer was large enough.
664  int GetNextPathName(LPTSTR pBuffer, int nBufLen) const
665  {
666  if (m_pNextFile == NULL)
667  return 0;
668 
669  int nRet = 0;
670  LPCTSTR pStr = m_pNextFile;
671  // Does the filename contain a backslash?
672  if (MinCrtHelper::_strrchr(pStr, _T('\\')) != NULL)
673  {
674  // Yes, so we'll assume it's a full path.
675  int nLength = lstrlen(pStr);
676 
677  if (pBuffer == NULL) // If the buffer is NULL, return the required length
678  {
679  nRet = nLength + 1;
680  }
681  else if (nBufLen > nLength) // The buffer is big enough, so go ahead and copy the filename
682  {
683  SecureHelper::strcpy_x(pBuffer, nBufLen, GetNextFileName());
684  nRet = nBufLen;
685  }
686  }
687  else
688  {
689  // The filename is relative, so construct the full path.
690  int nLengthDir = GetDirectory(NULL, 0);
691  if (nLengthDir > 0)
692  {
693  // Calculate the required space.
694  int nLengthTotal = nLengthDir + lstrlen(pStr);
695 
696  if(pBuffer == NULL) // If the buffer is NULL, return the required length
697  {
698  nRet = nLengthTotal + 1;
699  }
700  else if (nBufLen > nLengthTotal) // If the buffer is big enough, go ahead and construct the path
701  {
702  GetDirectory(pBuffer, nBufLen);
703  SecureHelper::strcat_x(pBuffer, nBufLen, _T("\\"));
704  SecureHelper::strcat_x(pBuffer, nBufLen, GetNextFileName());
705  nRet = nLengthTotal;
706  }
707  }
708  }
709 
710  return nRet;
711  }
712 
713 #if defined(_WTL_USE_CSTRING) || defined(__ATLSTR_H__)
714  bool GetNextPathName(_CSTRING_NS::CString& strPath) const
715  {
716  bool bRet = false;
717 
718  int nLength = GetNextPathName(NULL, 0);
719  if (nLength > 0)
720  {
721  bRet = (GetNextPathName(strPath.GetBuffer(nLength), nLength) > 0);
722  strPath.ReleaseBuffer(nLength - 1);
723  }
724 
725  return bRet;
726  }
727 #endif // defined(_WTL_USE_CSTRING) || defined(__ATLSTR_H__)
728 
729 // Implementation
730  bool ResizeFilenameBuffer(DWORD dwLength)
731  {
732  if (dwLength > m_ofn.nMaxFile)
733  {
734  // Free the old buffer.
735  if (m_ofn.lpstrFile != m_szFileName)
736  {
737  delete[] m_ofn.lpstrFile;
738  m_ofn.lpstrFile = NULL;
739  m_ofn.nMaxFile = 0;
740  }
741 
742  // Allocate the new buffer.
743  LPTSTR lpstrBuff = NULL;
744  ATLTRY(lpstrBuff = new TCHAR[dwLength]);
745  if (lpstrBuff != NULL)
746  {
747  m_ofn.lpstrFile = lpstrBuff;
748  m_ofn.lpstrFile[0] = 0;
749  m_ofn.nMaxFile = dwLength;
750  }
751  }
752 
753  return (m_ofn.lpstrFile != NULL);
754  }
755 
756  void OnSelChange(LPOFNOTIFY /*lpon*/)
757  {
758 #ifndef _UNICODE
759  // There is no point resizing the buffer in ANSI builds running on NT.
760  if (m_bIsNT)
761  return;
762 #endif
763 
764  // Get the buffer length required to hold the spec.
765  int nLength = GetSpec(NULL, 0);
766  if (nLength <= 1)
767  return; // no files are selected, presumably
768 
769  // Add room for the directory, and an extra terminating zero.
770  nLength += GetFolderPath(NULL, 0) + 1;
771 
772  if (!ResizeFilenameBuffer(nLength))
773  {
774  ATLASSERT(FALSE);
775  return;
776  }
777 
778  // If we are not following links then our work is done.
779  if ((m_ofn.Flags & OFN_NODEREFERENCELINKS) != 0)
780  return;
781 
782  // Get the file spec, which is the text in the edit control.
783  if (GetSpec(m_ofn.lpstrFile, m_ofn.nMaxFile) <= 0)
784  return;
785 
786  // Get the ID-list of the current folder.
787  int nBytes = GetFolderIDList(NULL, 0);
788 #ifdef STRICT_TYPED_ITEMIDS
790 #else
792 #endif
793  idlist.AllocateBytes(nBytes);
794  if ((nBytes <= 0) || (GetFolderIDList(idlist, nBytes) <= 0))
795  return;
796 
797  // First bind to the desktop folder, then to the current folder.
798  ATL::CComPtr<IShellFolder> pDesktop, pFolder;
799  if (FAILED(::SHGetDesktopFolder(&pDesktop)))
800  return;
801  if (FAILED(pDesktop->BindToObject(idlist, NULL, IID_IShellFolder, (void**)&pFolder)))
802  return;
803 
804  // Work through the file spec, looking for quoted filenames. If we find a shortcut file, then
805  // we need to add enough extra buffer space to hold its target path.
806  DWORD nExtraChars = 0;
807  bool bInsideQuotes = false;
808  LPCTSTR pAnchor = m_ofn.lpstrFile;
809  LPCTSTR pChar = m_ofn.lpstrFile;
810  for ( ; *pChar; ++pChar)
811  {
812  // Look for quotation marks.
813  if (*pChar == _T('\"'))
814  {
815  // We are either entering or leaving a passage of quoted text.
816  bInsideQuotes = !bInsideQuotes;
817 
818  // Is it an opening or closing quote?
819  if (bInsideQuotes)
820  {
821  // We found an opening quote, so set "pAnchor" to the following character.
822  pAnchor = pChar + 1;
823  }
824  else // closing quote
825  {
826  // Each quoted entity should be shorter than MAX_PATH.
827  if (pChar - pAnchor >= MAX_PATH)
828  return;
829 
830  // Get the ID-list and attributes of the file.
831  USES_CONVERSION;
832  int nFileNameLength = (int)(DWORD_PTR)(pChar - pAnchor);
833  TCHAR szFileName[MAX_PATH] = { 0 };
834  SecureHelper::strncpy_x(szFileName, MAX_PATH, pAnchor, nFileNameLength);
835 #ifdef STRICT_TYPED_ITEMIDS
836  PIDLIST_RELATIVE pidl = NULL;
837 #else
838  LPITEMIDLIST pidl = NULL;
839 #endif
840  DWORD dwAttrib = SFGAO_LINK;
841  if (SUCCEEDED(pFolder->ParseDisplayName(NULL, NULL, T2W(szFileName), NULL, &pidl, &dwAttrib)))
842  {
843  // Is it a shortcut file?
844  if (dwAttrib & SFGAO_LINK)
845  {
846  // Bind to its IShellLink interface.
847  ATL::CComPtr<IShellLink> pLink;
848  if (SUCCEEDED(pFolder->BindToObject(pidl, NULL, IID_IShellLink, (void**)&pLink)))
849  {
850  // Get the shortcut's target path.
851  TCHAR szPath[MAX_PATH] = { 0 };
852  if (SUCCEEDED(pLink->GetPath(szPath, MAX_PATH, NULL, 0)))
853  {
854  // If the target path is longer than the shortcut name, then add on the number
855  // of extra characters that are required.
856  int nNewLength = lstrlen(szPath);
857  if (nNewLength > nFileNameLength)
858  nExtraChars += nNewLength - nFileNameLength;
859  }
860  }
861  }
862 
863  // Free the ID-list returned by ParseDisplayName.
864  ::CoTaskMemFree(pidl);
865  }
866  }
867  }
868  }
869 
870  // If we need more space for shortcut targets, then reallocate.
871  if (nExtraChars > 0)
872  ATLVERIFY(ResizeFilenameBuffer(m_ofn.nMaxFile + nExtraChars));
873  }
874 };
875 
876 class CMultiFileDialog : public CMultiFileDialogImpl<CMultiFileDialog>
877 {
878 public:
880  LPCTSTR lpszDefExt = NULL,
881  LPCTSTR lpszFileName = NULL,
882  DWORD dwFlags = OFN_HIDEREADONLY,
883  LPCTSTR lpszFilter = NULL,
884  HWND hWndParent = NULL)
885  : CMultiFileDialogImpl<CMultiFileDialog>(lpszDefExt, lpszFileName, dwFlags, lpszFilter, hWndParent)
886  { }
887 
888  BEGIN_MSG_MAP(CMultiFileDialog)
890  END_MSG_MAP()
891 };
892 
893 #endif // !_WIN32_WCE
894 
895 
897 // Shell File Dialog - new Shell File Open and Save dialogs in Vista
898 
899 // Note: Use GetPtr() to access dialog interface methods.
900 // Example:
901 // CShellFileOpenDialog dlg;
902 // dlg.GetPtr()->SetTitle(L"MyFileOpenDialog");
903 
904 #if (_WIN32_WINNT >= 0x0600) && !defined(_WIN32_WCE)
905 
907 // CShellFileDialogImpl - base class for CShellFileOpenDialogImpl and CShellFileSaveDialogImpl
908 
909 template <class T>
910 class ATL_NO_VTABLE CShellFileDialogImpl : public IFileDialogEvents
911 {
912 public:
913 // Operations
914  INT_PTR DoModal(HWND hWndParent = ::GetActiveWindow())
915  {
916  INT_PTR nRet = -1;
917 
918  T* pT = static_cast<T*>(this);
919  if(pT->m_spFileDlg == NULL)
920  {
921  ATLASSERT(FALSE);
922  return nRet;
923  }
924 
925  DWORD dwCookie = 0;
926  pT->_Advise(dwCookie);
927 
928  HRESULT hRet = pT->m_spFileDlg->Show(hWndParent);
929  if(SUCCEEDED(hRet))
930  nRet = IDOK;
931  else if(hRet == HRESULT_FROM_WIN32(ERROR_CANCELLED))
932  nRet = IDCANCEL;
933  else
934  ATLASSERT(FALSE); // error
935 
936  pT->_Unadvise(dwCookie);
937 
938  return nRet;
939  }
940 
941  bool IsNull() const
942  {
943  const T* pT = static_cast<const T*>(this);
944  return (pT->m_spFileDlg == NULL);
945  }
946 
947 // Operations - get file path after dialog returns
948  HRESULT GetFilePath(LPWSTR lpstrFilePath, int cchLength)
949  {
950  T* pT = static_cast<T*>(this);
951  ATLASSERT(pT->m_spFileDlg != NULL);
952 
953  ATL::CComPtr<IShellItem> spItem;
954  HRESULT hRet = pT->m_spFileDlg->GetResult(&spItem);
955 
956  if(SUCCEEDED(hRet))
957  hRet = GetFileNameFromShellItem(spItem, SIGDN_FILESYSPATH, lpstrFilePath, cchLength);
958 
959  return hRet;
960  }
961 
962  HRESULT GetFileTitle(LPWSTR lpstrFileTitle, int cchLength)
963  {
964  T* pT = static_cast<T*>(this);
965  ATLASSERT(pT->m_spFileDlg != NULL);
966 
967  ATL::CComPtr<IShellItem> spItem;
968  HRESULT hRet = pT->m_spFileDlg->GetResult(&spItem);
969 
970  if(SUCCEEDED(hRet))
971  hRet = GetFileNameFromShellItem(spItem, SIGDN_NORMALDISPLAY, lpstrFileTitle, cchLength);
972 
973  return hRet;
974  }
975 
976 #if defined(_WTL_USE_CSTRING) || defined(__ATLSTR_H__)
977  HRESULT GetFilePath(_CSTRING_NS::CString& strFilePath)
978  {
979  T* pT = static_cast<T*>(this);
980  ATLASSERT(pT->m_spFileDlg != NULL);
981 
982  ATL::CComPtr<IShellItem> spItem;
983  HRESULT hRet = pT->m_spFileDlg->GetResult(&spItem);
984 
985  if(SUCCEEDED(hRet))
986  hRet = GetFileNameFromShellItem(spItem, SIGDN_FILESYSPATH, strFilePath);
987 
988  return hRet;
989  }
990 
991  HRESULT GetFileTitle(_CSTRING_NS::CString& strFileTitle)
992  {
993  T* pT = static_cast<T*>(this);
994  ATLASSERT(pT->m_spFileDlg != NULL);
995 
996  ATL::CComPtr<IShellItem> spItem;
997  HRESULT hRet = pT->m_spFileDlg->GetResult(&spItem);
998 
999  if(SUCCEEDED(hRet))
1000  hRet = GetFileNameFromShellItem(spItem, SIGDN_NORMALDISPLAY, strFileTitle);
1001 
1002  return hRet;
1003  }
1004 #endif // defined(_WTL_USE_CSTRING) || defined(__ATLSTR_H__)
1005 
1006 // Helpers for IShellItem
1007  static HRESULT GetFileNameFromShellItem(IShellItem* pShellItem, SIGDN type, LPWSTR lpstr, int cchLength)
1008  {
1009  ATLASSERT(pShellItem != NULL);
1010 
1011  LPWSTR lpstrName = NULL;
1012  HRESULT hRet = pShellItem->GetDisplayName(type, &lpstrName);
1013 
1014  if(SUCCEEDED(hRet))
1015  {
1016  if(lstrlenW(lpstrName) < cchLength)
1017  {
1018  SecureHelper::strcpyW_x(lpstr, cchLength, lpstrName);
1019  }
1020  else
1021  {
1022  ATLASSERT(FALSE);
1023  hRet = DISP_E_BUFFERTOOSMALL;
1024  }
1025 
1026  ::CoTaskMemFree(lpstrName);
1027  }
1028 
1029  return hRet;
1030  }
1031 
1032 #if defined(_WTL_USE_CSTRING) || defined(__ATLSTR_H__)
1033  static HRESULT GetFileNameFromShellItem(IShellItem* pShellItem, SIGDN type, _CSTRING_NS::CString& str)
1034  {
1035  ATLASSERT(pShellItem != NULL);
1036 
1037  LPWSTR lpstrName = NULL;
1038  HRESULT hRet = pShellItem->GetDisplayName(type, &lpstrName);
1039 
1040  if(SUCCEEDED(hRet))
1041  {
1042  str = lpstrName;
1043  ::CoTaskMemFree(lpstrName);
1044  }
1045 
1046  return hRet;
1047  }
1048 #endif // defined(_WTL_USE_CSTRING) || defined(__ATLSTR_H__)
1049 
1050 // Implementation
1051  void _Advise(DWORD& dwCookie)
1052  {
1053  T* pT = static_cast<T*>(this);
1054  ATLASSERT(pT->m_spFileDlg != NULL);
1055  HRESULT hRet = pT->m_spFileDlg->Advise((IFileDialogEvents*)this, &dwCookie);
1056  ATLVERIFY(SUCCEEDED(hRet));
1057  }
1058 
1059  void _Unadvise(DWORD dwCookie)
1060  {
1061  T* pT = static_cast<T*>(this);
1062  ATLASSERT(pT->m_spFileDlg != NULL);
1063  HRESULT hRet = pT->m_spFileDlg->Unadvise(dwCookie);
1064  ATLVERIFY(SUCCEEDED(hRet));
1065  }
1066 
1067  void _Init(LPCWSTR lpszFileName, DWORD dwOptions, LPCWSTR lpszDefExt, const COMDLG_FILTERSPEC* arrFilterSpec, UINT uFilterSpecCount)
1068  {
1069  T* pT = static_cast<T*>(this);
1070  ATLASSERT(pT->m_spFileDlg != NULL);
1071 
1072  HRESULT hRet = E_FAIL;
1073 
1074  if(lpszFileName != NULL)
1075  {
1076  hRet = pT->m_spFileDlg->SetFileName(lpszFileName);
1077  ATLASSERT(SUCCEEDED(hRet));
1078  }
1079 
1080  hRet = pT->m_spFileDlg->SetOptions(dwOptions);
1081  ATLASSERT(SUCCEEDED(hRet));
1082 
1083  if(lpszDefExt != NULL)
1084  {
1085  hRet = pT->m_spFileDlg->SetDefaultExtension(lpszDefExt);
1086  ATLASSERT(SUCCEEDED(hRet));
1087  }
1088 
1089  if(arrFilterSpec != NULL && uFilterSpecCount != 0U)
1090  {
1091  hRet = pT->m_spFileDlg->SetFileTypes(uFilterSpecCount, arrFilterSpec);
1092  ATLASSERT(SUCCEEDED(hRet));
1093  }
1094  }
1095 
1096 // Implementation - IUnknown interface
1097  STDMETHOD(QueryInterface)(REFIID riid, void** ppvObject)
1098  {
1099  if(ppvObject == NULL)
1100  return E_POINTER;
1101 
1102  T* pT = static_cast<T*>(this);
1103  if(IsEqualGUID(riid, IID_IUnknown) || IsEqualGUID(riid, IID_IFileDialogEvents))
1104  {
1105  *ppvObject = (IFileDialogEvents*)pT;
1106  // AddRef() not needed
1107  return S_OK;
1108  }
1109 
1110  return E_NOINTERFACE;
1111  }
1112 
1113  virtual ULONG STDMETHODCALLTYPE AddRef()
1114  {
1115  return 1;
1116  }
1117 
1118  virtual ULONG STDMETHODCALLTYPE Release()
1119  {
1120  return 1;
1121  }
1122 
1123 // Implementation - IFileDialogEvents interface
1124  virtual HRESULT STDMETHODCALLTYPE IFileDialogEvents::OnFileOk(IFileDialog* pfd)
1125  {
1126  T* pT = static_cast<T*>(this);
1127  ATLASSERT(pT->m_spFileDlg.IsEqualObject(pfd));
1128  pfd; // avoid level 4 warning
1129  return pT->OnFileOk();
1130  }
1131 
1132  virtual HRESULT STDMETHODCALLTYPE IFileDialogEvents::OnFolderChanging(IFileDialog* pfd, IShellItem* psiFolder)
1133  {
1134  T* pT = static_cast<T*>(this);
1135  ATLASSERT(pT->m_spFileDlg.IsEqualObject(pfd));
1136  pfd; // avoid level 4 warning
1137  return pT->OnFolderChanging(psiFolder);
1138  }
1139 
1140  virtual HRESULT STDMETHODCALLTYPE IFileDialogEvents::OnFolderChange(IFileDialog* pfd)
1141  {
1142  T* pT = static_cast<T*>(this);
1143  ATLASSERT(pT->m_spFileDlg.IsEqualObject(pfd));
1144  pfd; // avoid level 4 warning
1145  return pT->OnFolderChange();
1146  }
1147 
1148  virtual HRESULT STDMETHODCALLTYPE IFileDialogEvents::OnSelectionChange(IFileDialog* pfd)
1149  {
1150  T* pT = static_cast<T*>(this);
1151  ATLASSERT(pT->m_spFileDlg.IsEqualObject(pfd));
1152  pfd; // avoid level 4 warning
1153  return pT->OnSelectionChange();
1154  }
1155 
1156  virtual HRESULT STDMETHODCALLTYPE IFileDialogEvents::OnShareViolation(IFileDialog* pfd, IShellItem* psi, FDE_SHAREVIOLATION_RESPONSE* pResponse)
1157  {
1158  T* pT = static_cast<T*>(this);
1159  ATLASSERT(pT->m_spFileDlg.IsEqualObject(pfd));
1160  pfd; // avoid level 4 warning
1161  return pT->OnShareViolation(psi, pResponse);
1162  }
1163 
1164  virtual HRESULT STDMETHODCALLTYPE IFileDialogEvents::OnTypeChange(IFileDialog* pfd)
1165  {
1166  T* pT = static_cast<T*>(this);
1167  ATLASSERT(pT->m_spFileDlg.IsEqualObject(pfd));
1168  pfd; // avoid level 4 warning
1169  return pT->OnTypeChange();
1170  }
1171 
1172  virtual HRESULT STDMETHODCALLTYPE IFileDialogEvents::OnOverwrite(IFileDialog* pfd, IShellItem* psi, FDE_OVERWRITE_RESPONSE* pResponse)
1173  {
1174  T* pT = static_cast<T*>(this);
1175  ATLASSERT(pT->m_spFileDlg.IsEqualObject(pfd));
1176  pfd; // avoid level 4 warning
1177  return pT->OnOverwrite(psi, pResponse);
1178  }
1179 
1180 // Overrideables - Event handlers
1181  HRESULT OnFileOk()
1182  {
1183  return E_NOTIMPL;
1184  }
1185 
1186  HRESULT OnFolderChanging(IShellItem* /*psiFolder*/)
1187  {
1188  return E_NOTIMPL;
1189  }
1190 
1191  HRESULT OnFolderChange()
1192  {
1193  return E_NOTIMPL;
1194  }
1195 
1196  HRESULT OnSelectionChange()
1197  {
1198  return E_NOTIMPL;
1199  }
1200 
1201  HRESULT OnShareViolation(IShellItem* /*psi*/, FDE_SHAREVIOLATION_RESPONSE* /*pResponse*/)
1202  {
1203  return E_NOTIMPL;
1204  }
1205 
1206  HRESULT OnTypeChange()
1207  {
1208  return E_NOTIMPL;
1209  }
1210 
1211  HRESULT OnOverwrite(IShellItem* /*psi*/, FDE_OVERWRITE_RESPONSE* /*pResponse*/)
1212  {
1213  return E_NOTIMPL;
1214  }
1215 };
1216 
1217 
1219 // CShellFileOpenDialogImpl - implements new Shell File Open dialog
1220 
1221 template <class T>
1222 class ATL_NO_VTABLE CShellFileOpenDialogImpl : public CShellFileDialogImpl< T >
1223 {
1224 public:
1225  ATL::CComPtr<IFileOpenDialog> m_spFileDlg;
1226 
1227  CShellFileOpenDialogImpl(LPCWSTR lpszFileName = NULL,
1228  DWORD dwOptions = FOS_FORCEFILESYSTEM | FOS_PATHMUSTEXIST | FOS_FILEMUSTEXIST,
1229  LPCWSTR lpszDefExt = NULL,
1230  const COMDLG_FILTERSPEC* arrFilterSpec = NULL,
1231  UINT uFilterSpecCount = 0U)
1232  {
1233  HRESULT hRet = m_spFileDlg.CoCreateInstance(CLSID_FileOpenDialog);
1234 
1235  if(SUCCEEDED(hRet))
1236  _Init(lpszFileName, dwOptions, lpszDefExt, arrFilterSpec, uFilterSpecCount);
1237  }
1238 
1239  IFileOpenDialog* GetPtr()
1240  {
1241  return m_spFileDlg;
1242  }
1243 };
1244 
1245 
1247 // CShellFileOpenDialog - new Shell File Open dialog without events
1248 
1249 class CShellFileOpenDialog : public CShellFileOpenDialogImpl<CShellFileOpenDialog>
1250 {
1251 public:
1252  CShellFileOpenDialog(LPCWSTR lpszFileName = NULL,
1253  DWORD dwOptions = FOS_FORCEFILESYSTEM | FOS_PATHMUSTEXIST | FOS_FILEMUSTEXIST,
1254  LPCWSTR lpszDefExt = NULL,
1255  const COMDLG_FILTERSPEC* arrFilterSpec = NULL,
1256  UINT uFilterSpecCount = 0U) : CShellFileOpenDialogImpl<CShellFileOpenDialog>(lpszFileName, dwOptions, lpszDefExt, arrFilterSpec, uFilterSpecCount)
1257  { }
1258 
1259 // Implementation (remove _Advise/_Unadvise code using template magic)
1260  void _Advise(DWORD& /*dwCookie*/)
1261  { }
1262 
1263  void _Unadvise(DWORD /*dwCookie*/)
1264  { }
1265 };
1266 
1267 
1269 // CShellFileSaveDialogImpl - implements new Shell File Save dialog
1270 
1271 template <class T>
1272 class ATL_NO_VTABLE CShellFileSaveDialogImpl : public CShellFileDialogImpl< T >
1273 {
1274 public:
1275  ATL::CComPtr<IFileSaveDialog> m_spFileDlg;
1276 
1277  CShellFileSaveDialogImpl(LPCWSTR lpszFileName = NULL,
1278  DWORD dwOptions = FOS_FORCEFILESYSTEM | FOS_PATHMUSTEXIST | FOS_OVERWRITEPROMPT,
1279  LPCWSTR lpszDefExt = NULL,
1280  const COMDLG_FILTERSPEC* arrFilterSpec = NULL,
1281  UINT uFilterSpecCount = 0U)
1282  {
1283  HRESULT hRet = m_spFileDlg.CoCreateInstance(CLSID_FileSaveDialog);
1284 
1285  if(SUCCEEDED(hRet))
1286  _Init(lpszFileName, dwOptions, lpszDefExt, arrFilterSpec, uFilterSpecCount);
1287  }
1288 
1289  IFileSaveDialog* GetPtr()
1290  {
1291  return m_spFileDlg;
1292  }
1293 };
1294 
1295 
1297 // CShellFileSaveDialog - new Shell File Save dialog without events
1298 
1299 class CShellFileSaveDialog : public CShellFileSaveDialogImpl<CShellFileSaveDialog>
1300 {
1301 public:
1302  CShellFileSaveDialog(LPCWSTR lpszFileName = NULL,
1303  DWORD dwOptions = FOS_FORCEFILESYSTEM | FOS_PATHMUSTEXIST | FOS_OVERWRITEPROMPT,
1304  LPCWSTR lpszDefExt = NULL,
1305  const COMDLG_FILTERSPEC* arrFilterSpec = NULL,
1306  UINT uFilterSpecCount = 0U) : CShellFileSaveDialogImpl<CShellFileSaveDialog>(lpszFileName, dwOptions, lpszDefExt, arrFilterSpec, uFilterSpecCount)
1307  { }
1308 
1309 // Implementation (remove _Advise/_Unadvise code using template magic)
1310  void _Advise(DWORD& /*dwCookie*/)
1311  { }
1312 
1313  void _Unadvise(DWORD /*dwCookie*/)
1314  { }
1315 };
1316 
1317 #endif // (_WIN32_WINNT >= 0x0600) && !defined(_WIN32_WCE)
1318 
1319 
1321 // CFolderDialogImpl - used for browsing for a folder
1322 
1323 #ifndef _WIN32_WCE
1324 
1325 template <class T>
1326 class ATL_NO_VTABLE CFolderDialogImpl
1327 {
1328 public:
1329  BROWSEINFO m_bi;
1330  LPCTSTR m_lpstrInitialFolder;
1331  LPCITEMIDLIST m_pidlInitialSelection;
1332  bool m_bExpandInitialSelection;
1333  TCHAR m_szFolderDisplayName[MAX_PATH];
1334  TCHAR m_szFolderPath[MAX_PATH];
1335 #ifdef STRICT_TYPED_ITEMIDS
1336  PIDLIST_ABSOLUTE m_pidlSelected;
1337 #else
1338  LPITEMIDLIST m_pidlSelected;
1339 #endif
1340  HWND m_hWnd; // used only in the callback function
1341 
1342 // Constructor
1343  CFolderDialogImpl(HWND hWndParent = NULL, LPCTSTR lpstrTitle = NULL, UINT uFlags = BIF_RETURNONLYFSDIRS) :
1344  m_lpstrInitialFolder(NULL), m_pidlInitialSelection(NULL), m_bExpandInitialSelection(false), m_pidlSelected(NULL), m_hWnd(NULL)
1345  {
1346  memset(&m_bi, 0, sizeof(m_bi)); // initialize structure to 0/NULL
1347 
1348  m_bi.hwndOwner = hWndParent;
1349  m_bi.pidlRoot = NULL;
1350  m_bi.pszDisplayName = m_szFolderDisplayName;
1351  m_bi.lpszTitle = lpstrTitle;
1352  m_bi.ulFlags = uFlags;
1353  m_bi.lpfn = BrowseCallbackProc;
1354  m_bi.lParam = (LPARAM)static_cast<T*>(this);
1355 
1356  m_szFolderPath[0] = 0;
1357  m_szFolderDisplayName[0] = 0;
1358  }
1359 
1361  {
1362  ::CoTaskMemFree(m_pidlSelected);
1363  }
1364 
1365 // Operations
1366  INT_PTR DoModal(HWND hWndParent = ::GetActiveWindow())
1367  {
1368  if(m_bi.hwndOwner == NULL) // set only if not specified before
1369  m_bi.hwndOwner = hWndParent;
1370 
1371  // Clear out any previous results
1372  m_szFolderPath[0] = 0;
1373  m_szFolderDisplayName[0] = 0;
1374  ::CoTaskMemFree(m_pidlSelected);
1375 
1376  INT_PTR nRet = IDCANCEL;
1377  m_pidlSelected = ::SHBrowseForFolder(&m_bi);
1378 
1379  if(m_pidlSelected != NULL)
1380  {
1381  nRet = IDOK;
1382 
1383  // If BIF_RETURNONLYFSDIRS is set, we try to get the filesystem path.
1384  // Otherwise, the caller must handle the ID-list directly.
1385  if((m_bi.ulFlags & BIF_RETURNONLYFSDIRS) != 0)
1386  {
1387  if(::SHGetPathFromIDList(m_pidlSelected, m_szFolderPath) == FALSE)
1388  nRet = IDCANCEL;
1389  }
1390  }
1391 
1392  return nRet;
1393  }
1394 
1395  // Methods to call before DoModal
1396  void SetInitialFolder(LPCTSTR lpstrInitialFolder, bool bExpand = true)
1397  {
1398  // lpstrInitialFolder may be a file if BIF_BROWSEINCLUDEFILES is specified
1399  m_lpstrInitialFolder = lpstrInitialFolder;
1400  m_bExpandInitialSelection = bExpand;
1401  }
1402 
1403  void SetInitialSelection(LPCITEMIDLIST pidl, bool bExpand = true)
1404  {
1405  m_pidlInitialSelection = pidl;
1406  m_bExpandInitialSelection = bExpand;
1407  }
1408 
1409 #ifdef STRICT_TYPED_ITEMIDS
1410  void SetRootFolder(PCIDLIST_ABSOLUTE pidl)
1411 #else
1412  void SetRootFolder(LPCITEMIDLIST pidl)
1413 #endif
1414  {
1415  m_bi.pidlRoot = pidl;
1416  }
1417 
1418  // Methods to call after DoModal
1419  LPITEMIDLIST GetSelectedItem(bool bDetach = false)
1420  {
1421  LPITEMIDLIST pidl = m_pidlSelected;
1422  if(bDetach)
1423  m_pidlSelected = NULL;
1424 
1425  return pidl;
1426  }
1427 
1428  LPCTSTR GetFolderPath() const
1429  {
1430  return m_szFolderPath;
1431  }
1432 
1433  LPCTSTR GetFolderDisplayName() const
1434  {
1435  return m_szFolderDisplayName;
1436  }
1437 
1438  int GetFolderImageIndex() const
1439  {
1440  return m_bi.iImage;
1441  }
1442 
1443 // Callback function and overrideables
1444  static int CALLBACK BrowseCallbackProc(HWND hWnd, UINT uMsg, LPARAM lParam, LPARAM lpData)
1445  {
1446 #ifndef BFFM_VALIDATEFAILED
1447  #ifdef UNICODE
1448  const int BFFM_VALIDATEFAILED = 4;
1449  #else
1450  const int BFFM_VALIDATEFAILED = 3;
1451  #endif
1452 #endif // !BFFM_VALIDATEFAILED
1453 #ifndef BFFM_IUNKNOWN
1454  const int BFFM_IUNKNOWN = 5;
1455 #endif // !BFFM_IUNKNOWN
1456 #ifndef BIF_NEWDIALOGSTYLE
1457  const UINT BIF_NEWDIALOGSTYLE = 0x0040;
1458 #endif // !BIF_NEWDIALOGSTYLE
1459 
1460  int nRet = 0;
1461  T* pT = (T*)lpData;
1462  bool bClear = false;
1463  if(pT->m_hWnd == NULL)
1464  {
1465  pT->m_hWnd = hWnd;
1466  bClear = true;
1467  }
1468  else
1469  {
1470  ATLASSERT(pT->m_hWnd == hWnd);
1471  }
1472 
1473  switch(uMsg)
1474  {
1475  case BFFM_INITIALIZED:
1476  // Set initial selection
1477  // Note that m_pidlInitialSelection, if set, takes precedence over m_lpstrInitialFolder
1478  if(pT->m_pidlInitialSelection != NULL)
1479  pT->SetSelection(pT->m_pidlInitialSelection);
1480  else if(pT->m_lpstrInitialFolder != NULL)
1481  pT->SetSelection(pT->m_lpstrInitialFolder);
1482 
1483  // Expand initial selection if appropriate
1484  if(pT->m_bExpandInitialSelection && ((pT->m_bi.ulFlags & BIF_NEWDIALOGSTYLE) != 0))
1485  {
1486  if(pT->m_pidlInitialSelection != NULL)
1487  pT->SetExpanded(pT->m_pidlInitialSelection);
1488  else if(pT->m_lpstrInitialFolder != NULL)
1489  pT->SetExpanded(pT->m_lpstrInitialFolder);
1490  }
1491  pT->OnInitialized();
1492  break;
1493  case BFFM_SELCHANGED:
1494  pT->OnSelChanged((LPITEMIDLIST)lParam);
1495  break;
1496  case BFFM_VALIDATEFAILED:
1497  nRet = pT->OnValidateFailed((LPCTSTR)lParam);
1498  break;
1499  case BFFM_IUNKNOWN:
1500  pT->OnIUnknown((IUnknown*)lParam);
1501  break;
1502  default:
1503  ATLTRACE2(atlTraceUI, 0, _T("Unknown message received in CFolderDialogImpl::BrowseCallbackProc\n"));
1504  break;
1505  }
1506 
1507  if(bClear)
1508  pT->m_hWnd = NULL;
1509  return nRet;
1510  }
1511 
1512  void OnInitialized()
1513  {
1514  }
1515 
1516  void OnSelChanged(LPITEMIDLIST /*pItemIDList*/)
1517  {
1518  }
1519 
1520  int OnValidateFailed(LPCTSTR /*lpstrFolderPath*/)
1521  {
1522  return 1; // 1=continue, 0=EndDialog
1523  }
1524 
1525  void OnIUnknown(IUnknown* /*pUnknown*/)
1526  {
1527  }
1528 
1529  // Commands - valid to call only from handlers
1530  void EnableOK(BOOL bEnable)
1531  {
1532  ATLASSERT(m_hWnd != NULL);
1533  ::SendMessage(m_hWnd, BFFM_ENABLEOK, 0, bEnable);
1534  }
1535 
1536  void SetSelection(LPCITEMIDLIST pItemIDList)
1537  {
1538  ATLASSERT(m_hWnd != NULL);
1539  ::SendMessage(m_hWnd, BFFM_SETSELECTION, FALSE, (LPARAM)pItemIDList);
1540  }
1541 
1542  void SetSelection(LPCTSTR lpstrFolderPath)
1543  {
1544  ATLASSERT(m_hWnd != NULL);
1545  ::SendMessage(m_hWnd, BFFM_SETSELECTION, TRUE, (LPARAM)lpstrFolderPath);
1546  }
1547 
1548  void SetStatusText(LPCTSTR lpstrText)
1549  {
1550  ATLASSERT(m_hWnd != NULL);
1551  ::SendMessage(m_hWnd, BFFM_SETSTATUSTEXT, 0, (LPARAM)lpstrText);
1552  }
1553 
1554  void SetOKText(LPCTSTR lpstrOKText)
1555  {
1556 #ifndef BFFM_SETOKTEXT
1557  const UINT BFFM_SETOKTEXT = WM_USER + 105;
1558 #endif
1559  ATLASSERT(m_hWnd != NULL);
1560  USES_CONVERSION;
1561  LPCWSTR lpstr = T2CW(lpstrOKText);
1562  ::SendMessage(m_hWnd, BFFM_SETOKTEXT, 0, (LPARAM)lpstr);
1563  }
1564 
1565  void SetExpanded(LPCITEMIDLIST pItemIDList)
1566  {
1567 #ifndef BFFM_SETEXPANDED
1568  const UINT BFFM_SETEXPANDED = WM_USER + 106;
1569 #endif
1570  ATLASSERT(m_hWnd != NULL);
1571  ::SendMessage(m_hWnd, BFFM_SETEXPANDED, FALSE, (LPARAM)pItemIDList);
1572  }
1573 
1574  void SetExpanded(LPCTSTR lpstrFolderPath)
1575  {
1576 #ifndef BFFM_SETEXPANDED
1577  const UINT BFFM_SETEXPANDED = WM_USER + 106;
1578 #endif
1579  ATLASSERT(m_hWnd != NULL);
1580  USES_CONVERSION;
1581  LPCWSTR lpstr = T2CW(lpstrFolderPath);
1582  ::SendMessage(m_hWnd, BFFM_SETEXPANDED, TRUE, (LPARAM)lpstr);
1583  }
1584 };
1585 
1586 class CFolderDialog : public CFolderDialogImpl<CFolderDialog>
1587 {
1588 public:
1589  CFolderDialog(HWND hWndParent = NULL, LPCTSTR lpstrTitle = NULL, UINT uFlags = BIF_RETURNONLYFSDIRS)
1590  : CFolderDialogImpl<CFolderDialog>(hWndParent, lpstrTitle, uFlags)
1591  { }
1592 };
1593 
1594 #endif // !_WIN32_WCE
1595 
1596 
1598 // CCommonDialogImplBase - base class for common dialog classes
1599 
1600 class ATL_NO_VTABLE CCommonDialogImplBase : public ATL::CWindowImplBase
1601 {
1602 public:
1603  static UINT_PTR APIENTRY HookProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
1604  {
1605  if(uMsg != WM_INITDIALOG)
1606  return 0;
1607  CCommonDialogImplBase* pT = (CCommonDialogImplBase*)ModuleHelper::ExtractCreateWndData();
1608  ATLASSERT(pT != NULL);
1609  ATLASSERT(pT->m_hWnd == NULL);
1610  ATLASSERT(::IsWindow(hWnd));
1611  // subclass dialog's window
1612  if(!pT->SubclassWindow(hWnd))
1613  {
1614  ATLTRACE2(atlTraceUI, 0, _T("Subclassing a common dialog failed\n"));
1615  return 0;
1616  }
1617  // check message map for WM_INITDIALOG handler
1618  LRESULT lRes = 0;
1619  if(pT->ProcessWindowMessage(pT->m_hWnd, uMsg, wParam, lParam, lRes, 0) == FALSE)
1620  return 0;
1621  return lRes;
1622  }
1623 
1624 // Special override for common dialogs
1625  BOOL EndDialog(INT_PTR /*nRetCode*/ = 0)
1626  {
1627  ATLASSERT(::IsWindow(m_hWnd));
1628  SendMessage(WM_COMMAND, MAKEWPARAM(IDABORT, 0));
1629  return TRUE;
1630  }
1631 
1632 // Implementation - try to override these, to prevent errors
1633  HWND Create(HWND, ATL::_U_RECT, LPCTSTR, DWORD, DWORD, ATL::_U_MENUorID, ATOM, LPVOID)
1634  {
1635  ATLASSERT(FALSE); // should not be called
1636  return NULL;
1637  }
1638 
1639  static LRESULT CALLBACK StartWindowProc(HWND /*hWnd*/, UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/)
1640  {
1641  ATLASSERT(FALSE); // should not be called
1642  return 0;
1643  }
1644 };
1645 
1646 
1648 // CFontDialogImpl - font selection dialog
1649 
1650 #ifndef _WIN32_WCE
1651 
1652 template <class T>
1653 class ATL_NO_VTABLE CFontDialogImpl : public CCommonDialogImplBase
1654 {
1655 public:
1656  enum { _cchStyleName = 64 };
1657 
1658  CHOOSEFONT m_cf;
1659  TCHAR m_szStyleName[_cchStyleName]; // contains style name after return
1660  LOGFONT m_lf; // default LOGFONT to store the info
1661 
1662 // Constructors
1663  CFontDialogImpl(LPLOGFONT lplfInitial = NULL,
1664  DWORD dwFlags = CF_EFFECTS | CF_SCREENFONTS,
1665  HDC hDCPrinter = NULL,
1666  HWND hWndParent = NULL)
1667  {
1668  memset(&m_cf, 0, sizeof(m_cf));
1669  memset(&m_lf, 0, sizeof(m_lf));
1670  memset(&m_szStyleName, 0, sizeof(m_szStyleName));
1671 
1672  m_cf.lStructSize = sizeof(m_cf);
1673  m_cf.hwndOwner = hWndParent;
1674  m_cf.rgbColors = RGB(0, 0, 0);
1675  m_cf.lpszStyle = (LPTSTR)&m_szStyleName;
1676  m_cf.Flags = dwFlags | CF_ENABLEHOOK;
1677  m_cf.lpfnHook = (LPCFHOOKPROC)T::HookProc;
1678 
1679  if(lplfInitial != NULL)
1680  {
1681  m_cf.lpLogFont = lplfInitial;
1682  m_cf.Flags |= CF_INITTOLOGFONTSTRUCT;
1683  m_lf = *lplfInitial;
1684  }
1685  else
1686  {
1687  m_cf.lpLogFont = &m_lf;
1688  }
1689 
1690  if(hDCPrinter != NULL)
1691  {
1692  m_cf.hDC = hDCPrinter;
1693  m_cf.Flags |= CF_PRINTERFONTS;
1694  }
1695  }
1696 
1697 // Operations
1698  INT_PTR DoModal(HWND hWndParent = ::GetActiveWindow())
1699  {
1700  ATLASSERT((m_cf.Flags & CF_ENABLEHOOK) != 0);
1701  ATLASSERT(m_cf.lpfnHook != NULL); // can still be a user hook
1702 
1703  if(m_cf.hwndOwner == NULL) // set only if not specified before
1704  m_cf.hwndOwner = hWndParent;
1705 
1706  ATLASSERT(m_hWnd == NULL);
1707 
1708 #if (_ATL_VER >= 0x0800)
1709  // Allocate the thunk structure here, where we can fail gracefully.
1710  BOOL bRetTh = m_thunk.Init(NULL, NULL);
1711  if(bRetTh == FALSE)
1712  {
1713  ::SetLastError(ERROR_OUTOFMEMORY);
1714  return -1;
1715  }
1716 #endif // (_ATL_VER >= 0x0800)
1717 
1718  ModuleHelper::AddCreateWndData(&m_thunk.cd, (CCommonDialogImplBase*)this);
1719 
1720  BOOL bRet = ::ChooseFont(&m_cf);
1721 
1722  m_hWnd = NULL;
1723 
1724  if(bRet) // copy logical font from user's initialization buffer (if needed)
1725  SecureHelper::memcpy_x(&m_lf, sizeof(m_lf), m_cf.lpLogFont, sizeof(m_lf));
1726 
1727  return bRet ? IDOK : IDCANCEL;
1728  }
1729 
1730  // works only when the dialog is dislayed or after
1731  void GetCurrentFont(LPLOGFONT lplf) const
1732  {
1733  ATLASSERT(lplf != NULL);
1734 
1735  if(m_hWnd != NULL)
1736  ::SendMessage(m_hWnd, WM_CHOOSEFONT_GETLOGFONT, 0, (LPARAM)lplf);
1737  else
1738  *lplf = m_lf;
1739  }
1740 
1741  // works only when the dialog is dislayed or before
1742 #ifndef _WIN32_WCE
1743  void SetLogFont(LPLOGFONT lplf)
1744  {
1745  ATLASSERT(lplf != NULL);
1746 #ifndef WM_CHOOSEFONT_SETLOGFONT
1747  const UINT WM_CHOOSEFONT_SETLOGFONT = (WM_USER + 101);
1748 #endif
1749  if(m_hWnd != NULL)
1750  {
1751  ::SendMessage(m_hWnd, WM_CHOOSEFONT_SETLOGFONT, 0, (LPARAM)lplf);
1752  }
1753  else
1754  {
1755  m_lf = *lplf;
1756  m_cf.Flags |= CF_INITTOLOGFONTSTRUCT;
1757  }
1758  }
1759 
1760  void SetFlags(DWORD dwFlags)
1761  {
1762 #ifndef WM_CHOOSEFONT_SETFLAGS
1763  const UINT WM_CHOOSEFONT_SETFLAGS = (WM_USER + 102);
1764 #endif
1765  if(m_hWnd != NULL)
1766  {
1767  CHOOSEFONT cf = { sizeof(CHOOSEFONT) };
1768  cf.Flags = dwFlags;
1769  ::SendMessage(m_hWnd, WM_CHOOSEFONT_SETFLAGS, 0, (LPARAM)&cf);
1770  }
1771  else
1772  {
1773  m_cf.Flags = dwFlags;
1774  }
1775  }
1776 #endif // !_WIN32_WCE
1777 
1778  // Helpers for parsing information after successful return
1779  LPCTSTR GetFaceName() const // return the face name of the font
1780  {
1781  return (LPCTSTR)m_cf.lpLogFont->lfFaceName;
1782  }
1783 
1784  LPCTSTR GetStyleName() const // return the style name of the font
1785  {
1786  return m_cf.lpszStyle;
1787  }
1788 
1789  int GetSize() const // return the pt size of the font
1790  {
1791  return m_cf.iPointSize;
1792  }
1793 
1794  COLORREF GetColor() const // return the color of the font
1795  {
1796  return m_cf.rgbColors;
1797  }
1798 
1799  int GetWeight() const // return the chosen font weight
1800  {
1801  return (int)m_cf.lpLogFont->lfWeight;
1802  }
1803 
1804  BOOL IsStrikeOut() const // return TRUE if strikeout
1805  {
1806  return (m_cf.lpLogFont->lfStrikeOut) ? TRUE : FALSE;
1807  }
1808 
1809  BOOL IsUnderline() const // return TRUE if underline
1810  {
1811  return (m_cf.lpLogFont->lfUnderline) ? TRUE : FALSE;
1812  }
1813 
1814  BOOL IsBold() const // return TRUE if bold font
1815  {
1816  return (m_cf.lpLogFont->lfWeight == FW_BOLD) ? TRUE : FALSE;
1817  }
1818 
1819  BOOL IsItalic() const // return TRUE if italic font
1820  {
1821  return m_cf.lpLogFont->lfItalic ? TRUE : FALSE;
1822  }
1823 };
1824 
1825 class CFontDialog : public CFontDialogImpl<CFontDialog>
1826 {
1827 public:
1828  CFontDialog(LPLOGFONT lplfInitial = NULL,
1829  DWORD dwFlags = CF_EFFECTS | CF_SCREENFONTS,
1830  HDC hDCPrinter = NULL,
1831  HWND hWndParent = NULL)
1832  : CFontDialogImpl<CFontDialog>(lplfInitial, dwFlags, hDCPrinter, hWndParent)
1833  { }
1834 
1835  DECLARE_EMPTY_MSG_MAP()
1836 };
1837 
1838 #endif // _WIN32_WCE
1839 
1840 
1842 // CRichEditFontDialogImpl - font selection for the Rich Edit ctrl
1843 
1844 #if defined(_RICHEDIT_) && !defined(_WIN32_WCE)
1845 
1846 template <class T>
1847 class ATL_NO_VTABLE CRichEditFontDialogImpl : public CFontDialogImpl< T >
1848 {
1849 public:
1850  CRichEditFontDialogImpl(const CHARFORMAT& charformat,
1851  DWORD dwFlags = CF_SCREENFONTS,
1852  HDC hDCPrinter = NULL,
1853  HWND hWndParent = NULL)
1854  : CFontDialogImpl< T >(NULL, dwFlags, hDCPrinter, hWndParent)
1855  {
1856  m_cf.Flags |= CF_INITTOLOGFONTSTRUCT;
1857  m_cf.Flags |= FillInLogFont(charformat);
1858  m_cf.lpLogFont = &m_lf;
1859 
1860  if((charformat.dwMask & CFM_COLOR) != 0)
1861  m_cf.rgbColors = charformat.crTextColor;
1862  }
1863 
1864  void GetCharFormat(CHARFORMAT& cf) const
1865  {
1866  USES_CONVERSION;
1867  cf.dwEffects = 0;
1868  cf.dwMask = 0;
1869  if((m_cf.Flags & CF_NOSTYLESEL) == 0)
1870  {
1871  cf.dwMask |= CFM_BOLD | CFM_ITALIC;
1872  cf.dwEffects |= IsBold() ? CFE_BOLD : 0;
1873  cf.dwEffects |= IsItalic() ? CFE_ITALIC : 0;
1874  }
1875  if((m_cf.Flags & CF_NOSIZESEL) == 0)
1876  {
1877  cf.dwMask |= CFM_SIZE;
1878  // GetSize() returns in tenths of points so mulitply by 2 to get twips
1879  cf.yHeight = GetSize() * 2;
1880  }
1881 
1882  if((m_cf.Flags & CF_NOFACESEL) == 0)
1883  {
1884  cf.dwMask |= CFM_FACE;
1885  cf.bPitchAndFamily = m_cf.lpLogFont->lfPitchAndFamily;
1886 #if (_RICHEDIT_VER >= 0x0200)
1887  SecureHelper::strcpy_x(cf.szFaceName, _countof(cf.szFaceName), GetFaceName());
1888 #else // !(_RICHEDIT_VER >= 0x0200)
1889  SecureHelper::strcpyA_x(cf.szFaceName, _countof(cf.szFaceName), T2A((LPTSTR)(LPCTSTR)GetFaceName()));
1890 #endif // !(_RICHEDIT_VER >= 0x0200)
1891  }
1892 
1893  if((m_cf.Flags & CF_EFFECTS) != 0)
1894  {
1895  cf.dwMask |= CFM_UNDERLINE | CFM_STRIKEOUT | CFM_COLOR;
1896  cf.dwEffects |= IsUnderline() ? CFE_UNDERLINE : 0;
1897  cf.dwEffects |= IsStrikeOut() ? CFE_STRIKEOUT : 0;
1898  cf.crTextColor = GetColor();
1899  }
1900  if((m_cf.Flags & CF_NOSCRIPTSEL) == 0)
1901  {
1902  cf.bCharSet = m_cf.lpLogFont->lfCharSet;
1903  cf.dwMask |= CFM_CHARSET;
1904  }
1905  cf.yOffset = 0;
1906  }
1907 
1908  DWORD FillInLogFont(const CHARFORMAT& cf)
1909  {
1910  USES_CONVERSION;
1911  DWORD dwFlags = 0;
1912  if((cf.dwMask & CFM_SIZE) != 0)
1913  {
1914  HDC hDC = ::CreateDC(_T("DISPLAY"), NULL, NULL, NULL);
1915  LONG yPerInch = ::GetDeviceCaps(hDC, LOGPIXELSY);
1916  m_lf.lfHeight = -(int)((cf.yHeight * yPerInch) / 1440);
1917  }
1918  else
1919  m_lf.lfHeight = 0;
1920 
1921  m_lf.lfWidth = 0;
1922  m_lf.lfEscapement = 0;
1923  m_lf.lfOrientation = 0;
1924 
1925  if((cf.dwMask & (CFM_ITALIC | CFM_BOLD)) == (CFM_ITALIC | CFM_BOLD))
1926  {
1927  m_lf.lfWeight = ((cf.dwEffects & CFE_BOLD) != 0) ? FW_BOLD : FW_NORMAL;
1928  m_lf.lfItalic = (BYTE)(((cf.dwEffects & CFE_ITALIC) != 0) ? TRUE : FALSE);
1929  }
1930  else
1931  {
1932  dwFlags |= CF_NOSTYLESEL;
1933  m_lf.lfWeight = FW_DONTCARE;
1934  m_lf.lfItalic = FALSE;
1935  }
1936 
1937  if((cf.dwMask & (CFM_UNDERLINE | CFM_STRIKEOUT | CFM_COLOR)) == (CFM_UNDERLINE|CFM_STRIKEOUT|CFM_COLOR))
1938  {
1939  dwFlags |= CF_EFFECTS;
1940  m_lf.lfUnderline = (BYTE)(((cf.dwEffects & CFE_UNDERLINE) != 0) ? TRUE : FALSE);
1941  m_lf.lfStrikeOut = (BYTE)(((cf.dwEffects & CFE_STRIKEOUT) != 0) ? TRUE : FALSE);
1942  }
1943  else
1944  {
1945  m_lf.lfUnderline = (BYTE)FALSE;
1946  m_lf.lfStrikeOut = (BYTE)FALSE;
1947  }
1948 
1949  if((cf.dwMask & CFM_CHARSET) != 0)
1950  m_lf.lfCharSet = cf.bCharSet;
1951  else
1952  dwFlags |= CF_NOSCRIPTSEL;
1953  m_lf.lfOutPrecision = OUT_DEFAULT_PRECIS;
1954  m_lf.lfClipPrecision = CLIP_DEFAULT_PRECIS;
1955  m_lf.lfQuality = DEFAULT_QUALITY;
1956  if((cf.dwMask & CFM_FACE) != 0)
1957  {
1958  m_lf.lfPitchAndFamily = cf.bPitchAndFamily;
1959 #if (_RICHEDIT_VER >= 0x0200)
1960  SecureHelper::strcpy_x(m_lf.lfFaceName, _countof(m_lf.lfFaceName), cf.szFaceName);
1961 #else // !(_RICHEDIT_VER >= 0x0200)
1962  SecureHelper::strcpy_x(m_lf.lfFaceName, _countof(m_lf.lfFaceName), A2T((LPSTR)cf.szFaceName));
1963 #endif // !(_RICHEDIT_VER >= 0x0200)
1964  }
1965  else
1966  {
1967  m_lf.lfPitchAndFamily = DEFAULT_PITCH|FF_DONTCARE;
1968  m_lf.lfFaceName[0] = (TCHAR)0;
1969  }
1970  return dwFlags;
1971  }
1972 };
1973 
1974 class CRichEditFontDialog : public CRichEditFontDialogImpl<CRichEditFontDialog>
1975 {
1976 public:
1977  CRichEditFontDialog(const CHARFORMAT& charformat,
1978  DWORD dwFlags = CF_SCREENFONTS,
1979  HDC hDCPrinter = NULL,
1980  HWND hWndParent = NULL)
1981  : CRichEditFontDialogImpl<CRichEditFontDialog>(charformat, dwFlags, hDCPrinter, hWndParent)
1982  { }
1983 
1984  DECLARE_EMPTY_MSG_MAP()
1985 };
1986 
1987 #endif // defined(_RICHEDIT_) && !defined(_WIN32_WCE)
1988 
1989 
1991 // CColorDialogImpl - color selection
1992 
1993 #if !defined(_WIN32_WCE) || ((_WIN32_WCE > 420) && !(defined(WIN32_PLATFORM_WFSP) && (_WIN32_WCE > 0x0500)))
1994 
1995 #ifdef _WIN32_WCE
1996  #pragma comment(lib, "commdlg.lib")
1997 
1998  #ifndef SETRGBSTRING
1999  #define SETRGBSTRING _T("commdlg_SetRGBColor")
2000  #endif
2001 
2002  #ifndef COLOROKSTRING
2003  #define COLOROKSTRING _T("commdlg_ColorOK")
2004  #endif
2005 #endif
2006 
2007 template <class T>
2008 class ATL_NO_VTABLE CColorDialogImpl : public CCommonDialogImplBase
2009 {
2010 public:
2011  CHOOSECOLOR m_cc;
2012 
2013 // Constructor
2014  CColorDialogImpl(COLORREF clrInit = 0, DWORD dwFlags = 0, HWND hWndParent = NULL)
2015  {
2016  memset(&m_cc, 0, sizeof(m_cc));
2017 
2018  m_cc.lStructSize = sizeof(m_cc);
2019  m_cc.lpCustColors = GetCustomColors();
2020  m_cc.hwndOwner = hWndParent;
2021  m_cc.Flags = dwFlags | CC_ENABLEHOOK;
2022  m_cc.lpfnHook = (LPCCHOOKPROC)T::HookProc;
2023 
2024  if(clrInit != 0)
2025  {
2026  m_cc.rgbResult = clrInit;
2027  m_cc.Flags |= CC_RGBINIT;
2028  }
2029  }
2030 
2031 // Operations
2032  INT_PTR DoModal(HWND hWndParent = ::GetActiveWindow())
2033  {
2034  ATLASSERT((m_cc.Flags & CC_ENABLEHOOK) != 0);
2035  ATLASSERT(m_cc.lpfnHook != NULL); // can still be a user hook
2036 
2037  if(m_cc.hwndOwner == NULL) // set only if not specified before
2038  m_cc.hwndOwner = hWndParent;
2039 
2040  ATLASSERT(m_hWnd == NULL);
2041 
2042 #if (_ATL_VER >= 0x0800)
2043  // Allocate the thunk structure here, where we can fail gracefully.
2044  BOOL bRetTh = m_thunk.Init(NULL, NULL);
2045  if(bRetTh == FALSE)
2046  {
2047  ::SetLastError(ERROR_OUTOFMEMORY);
2048  return -1;
2049  }
2050 #endif // (_ATL_VER >= 0x0800)
2051 
2052  ModuleHelper::AddCreateWndData(&m_thunk.cd, (CCommonDialogImplBase*)this);
2053 
2054  BOOL bRet = ::ChooseColor(&m_cc);
2055 
2056  m_hWnd = NULL;
2057 
2058  return bRet ? IDOK : IDCANCEL;
2059  }
2060 
2061  // Set the current color while dialog is displayed
2062  void SetCurrentColor(COLORREF clr)
2063  {
2064  ATLASSERT(::IsWindow(m_hWnd));
2065  SendMessage(_GetSetRGBMessage(), 0, (LPARAM)clr);
2066  }
2067 
2068  // Get the selected color after DoModal returns, or in OnColorOK
2069  COLORREF GetColor() const
2070  {
2071  return m_cc.rgbResult;
2072  }
2073 
2074 // Special override for the color dialog
2075  static UINT_PTR APIENTRY HookProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
2076  {
2077  if(uMsg != WM_INITDIALOG && uMsg != _GetColorOKMessage())
2078  return 0;
2079 
2080  LPCHOOSECOLOR lpCC = (LPCHOOSECOLOR)lParam;
2081  CCommonDialogImplBase* pT = NULL;
2082 
2083  if(uMsg == WM_INITDIALOG)
2084  {
2085  pT = (CCommonDialogImplBase*)ModuleHelper::ExtractCreateWndData();
2086  lpCC->lCustData = (LPARAM)pT;
2087  ATLASSERT(pT != NULL);
2088  ATLASSERT(pT->m_hWnd == NULL);
2089  ATLASSERT(::IsWindow(hWnd));
2090  // subclass dialog's window
2091  if(!pT->SubclassWindow(hWnd))
2092  {
2093  ATLTRACE2(atlTraceUI, 0, _T("Subclassing a Color common dialog failed\n"));
2094  return 0;
2095  }
2096  }
2097  else if(uMsg == _GetColorOKMessage())
2098  {
2099  pT = (CCommonDialogImplBase*)lpCC->lCustData;
2100  ATLASSERT(pT != NULL);
2101  ATLASSERT(::IsWindow(pT->m_hWnd));
2102  }
2103  else
2104  {
2105  ATLASSERT(FALSE);
2106  return 0;
2107  }
2108 
2109  // pass to the message map
2110  LRESULT lRes = 0;
2111  if(pT->ProcessWindowMessage(pT->m_hWnd, uMsg, wParam, lParam, lRes, 0) == FALSE)
2112  return 0;
2113 
2114  return lRes;
2115  }
2116 
2117 // Helpers
2118  static COLORREF* GetCustomColors()
2119  {
2120  static COLORREF rgbCustomColors[16] =
2121  {
2122  RGB(255, 255, 255), RGB(255, 255, 255),
2123  RGB(255, 255, 255), RGB(255, 255, 255),
2124  RGB(255, 255, 255), RGB(255, 255, 255),
2125  RGB(255, 255, 255), RGB(255, 255, 255),
2126  RGB(255, 255, 255), RGB(255, 255, 255),
2127  RGB(255, 255, 255), RGB(255, 255, 255),
2128  RGB(255, 255, 255), RGB(255, 255, 255),
2129  RGB(255, 255, 255), RGB(255, 255, 255),
2130  };
2131 
2132  return rgbCustomColors;
2133  }
2134 
2135  static UINT _GetSetRGBMessage()
2136  {
2137  static UINT uSetRGBMessage = 0;
2138  if(uSetRGBMessage == 0)
2139  {
2141  if(FAILED(lock.Lock()))
2142  {
2143  ATLTRACE2(atlTraceUI, 0, _T("ERROR : Unable to lock critical section in CColorDialogImpl::_GetSetRGBMessage.\n"));
2144  ATLASSERT(FALSE);
2145  return 0;
2146  }
2147 
2148  if(uSetRGBMessage == 0)
2149  uSetRGBMessage = ::RegisterWindowMessage(SETRGBSTRING);
2150 
2151  lock.Unlock();
2152  }
2153  ATLASSERT(uSetRGBMessage != 0);
2154  return uSetRGBMessage;
2155  }
2156 
2157  static UINT _GetColorOKMessage()
2158  {
2159  static UINT uColorOKMessage = 0;
2160  if(uColorOKMessage == 0)
2161  {
2163  if(FAILED(lock.Lock()))
2164  {
2165  ATLTRACE2(atlTraceUI, 0, _T("ERROR : Unable to lock critical section in CColorDialogImpl::_GetColorOKMessage.\n"));
2166  ATLASSERT(FALSE);
2167  return 0;
2168  }
2169 
2170  if(uColorOKMessage == 0)
2171  uColorOKMessage = ::RegisterWindowMessage(COLOROKSTRING);
2172 
2173  lock.Unlock();
2174  }
2175  ATLASSERT(uColorOKMessage != 0);
2176  return uColorOKMessage;
2177  }
2178 
2179 // Message map and handlers
2180  BEGIN_MSG_MAP(CColorDialogImpl)
2181  MESSAGE_HANDLER(_GetColorOKMessage(), _OnColorOK)
2182  END_MSG_MAP()
2183 
2184  LRESULT _OnColorOK(UINT, WPARAM, LPARAM, BOOL&)
2185  {
2186  T* pT = static_cast<T*>(this);
2187  return pT->OnColorOK();
2188  }
2189 
2190 // Overrideable
2191  BOOL OnColorOK() // validate color
2192  {
2193  return FALSE;
2194  }
2195 };
2196 
2197 class CColorDialog : public CColorDialogImpl<CColorDialog>
2198 {
2199 public:
2200  CColorDialog(COLORREF clrInit = 0, DWORD dwFlags = 0, HWND hWndParent = NULL)
2201  : CColorDialogImpl<CColorDialog>(clrInit, dwFlags, hWndParent)
2202  { }
2203 
2204  // override base class map and references to handlers
2205  DECLARE_EMPTY_MSG_MAP()
2206 };
2207 
2208 #endif // !defined(_WIN32_WCE) || ((_WIN32_WCE > 420) && !(defined(WIN32_PLATFORM_WFSP) && (_WIN32_WCE > 0x0500)))
2209 
2210 
2212 // CPrintDialogImpl - used for Print... and PrintSetup...
2213 
2214 #ifndef _WIN32_WCE
2215 
2216 // global helper
2217 static inline HDC _AtlCreateDC(HGLOBAL hDevNames, HGLOBAL hDevMode)
2218 {
2219  if(hDevNames == NULL)
2220  return NULL;
2221 
2222  LPDEVNAMES lpDevNames = (LPDEVNAMES)::GlobalLock(hDevNames);
2223  LPDEVMODE lpDevMode = (hDevMode != NULL) ? (LPDEVMODE)::GlobalLock(hDevMode) : NULL;
2224 
2225  if(lpDevNames == NULL)
2226  return NULL;
2227 
2228  HDC hDC = ::CreateDC((LPCTSTR)lpDevNames + lpDevNames->wDriverOffset,
2229  (LPCTSTR)lpDevNames + lpDevNames->wDeviceOffset,
2230  (LPCTSTR)lpDevNames + lpDevNames->wOutputOffset,
2231  lpDevMode);
2232 
2233  ::GlobalUnlock(hDevNames);
2234  if(hDevMode != NULL)
2235  ::GlobalUnlock(hDevMode);
2236  return hDC;
2237 }
2238 
2239 #pragma warning(push)
2240 #pragma warning(disable: 4512) // assignment operator could not be generated
2241 
2242 template <class T>
2243 class ATL_NO_VTABLE CPrintDialogImpl : public CCommonDialogImplBase
2244 {
2245 public:
2246  // print dialog parameter block (note this is a reference)
2247  PRINTDLG& m_pd;
2248 
2249 // Constructors
2250  CPrintDialogImpl(BOOL bPrintSetupOnly = FALSE, // TRUE for Print Setup, FALSE for Print Dialog
2251  DWORD dwFlags = PD_ALLPAGES | PD_USEDEVMODECOPIES | PD_NOPAGENUMS | PD_NOSELECTION,
2252  HWND hWndParent = NULL)
2253  : m_pd(m_pdActual)
2254  {
2255  memset(&m_pdActual, 0, sizeof(m_pdActual));
2256 
2257  m_pd.lStructSize = sizeof(m_pdActual);
2258  m_pd.hwndOwner = hWndParent;
2259  m_pd.Flags = (dwFlags | PD_ENABLEPRINTHOOK | PD_ENABLESETUPHOOK);
2260  m_pd.lpfnPrintHook = (LPPRINTHOOKPROC)T::HookProc;
2261  m_pd.lpfnSetupHook = (LPSETUPHOOKPROC)T::HookProc;
2262 
2263  if(bPrintSetupOnly)
2264  m_pd.Flags |= PD_PRINTSETUP;
2265  else
2266  m_pd.Flags |= PD_RETURNDC;
2267 
2268  m_pd.Flags &= ~PD_RETURNIC; // do not support information context
2269  }
2270 
2271 // Operations
2272  INT_PTR DoModal(HWND hWndParent = ::GetActiveWindow())
2273  {
2274  ATLASSERT((m_pd.Flags & PD_ENABLEPRINTHOOK) != 0);
2275  ATLASSERT((m_pd.Flags & PD_ENABLESETUPHOOK) != 0);
2276  ATLASSERT(m_pd.lpfnPrintHook != NULL); // can still be a user hook
2277  ATLASSERT(m_pd.lpfnSetupHook != NULL); // can still be a user hook
2278  ATLASSERT((m_pd.Flags & PD_RETURNDEFAULT) == 0); // use GetDefaults for this
2279 
2280  if(m_pd.hwndOwner == NULL) // set only if not specified before
2281  m_pd.hwndOwner = hWndParent;
2282 
2283  ATLASSERT(m_hWnd == NULL);
2284 
2285 #if (_ATL_VER >= 0x0800)
2286  // Allocate the thunk structure here, where we can fail gracefully.
2287  BOOL bRetTh = m_thunk.Init(NULL, NULL);
2288  if(bRetTh == FALSE)
2289  {
2290  ::SetLastError(ERROR_OUTOFMEMORY);
2291  return -1;
2292  }
2293 #endif // (_ATL_VER >= 0x0800)
2294 
2295  ModuleHelper::AddCreateWndData(&m_thunk.cd, (CCommonDialogImplBase*)this);
2296 
2297  BOOL bRet = ::PrintDlg(&m_pd);
2298 
2299  m_hWnd = NULL;
2300 
2301  return bRet ? IDOK : IDCANCEL;
2302  }
2303 
2304  // GetDefaults will not display a dialog but will get device defaults
2305  BOOL GetDefaults()
2306  {
2307  m_pd.Flags |= PD_RETURNDEFAULT;
2308  ATLASSERT(m_pd.hDevMode == NULL); // must be NULL
2309  ATLASSERT(m_pd.hDevNames == NULL); // must be NULL
2310 
2311  return ::PrintDlg(&m_pd);
2312  }
2313 
2314  // Helpers for parsing information after successful return num. copies requested
2315  int GetCopies() const
2316  {
2317  if((m_pd.Flags & PD_USEDEVMODECOPIES) != 0)
2318  {
2319  LPDEVMODE lpDevMode = GetDevMode();
2320  return (lpDevMode != NULL) ? lpDevMode->dmCopies : -1;
2321  }
2322 
2323  return m_pd.nCopies;
2324  }
2325 
2326  BOOL PrintCollate() const // TRUE if collate checked
2327  {
2328  return ((m_pd.Flags & PD_COLLATE) != 0) ? TRUE : FALSE;
2329  }
2330 
2331  BOOL PrintSelection() const // TRUE if printing selection
2332  {
2333  return ((m_pd.Flags & PD_SELECTION) != 0) ? TRUE : FALSE;
2334  }
2335 
2336  BOOL PrintAll() const // TRUE if printing all pages
2337  {
2338  return (!PrintRange() && !PrintSelection()) ? TRUE : FALSE;
2339  }
2340 
2341  BOOL PrintRange() const // TRUE if printing page range
2342  {
2343  return ((m_pd.Flags & PD_PAGENUMS) != 0) ? TRUE : FALSE;
2344  }
2345 
2346  BOOL PrintToFile() const // TRUE if printing to a file
2347  {
2348  return ((m_pd.Flags & PD_PRINTTOFILE) != 0) ? TRUE : FALSE;
2349  }
2350 
2351  int GetFromPage() const // starting page if valid
2352  {
2353  return PrintRange() ? m_pd.nFromPage : -1;
2354  }
2355 
2356  int GetToPage() const // ending page if valid
2357  {
2358  return PrintRange() ? m_pd.nToPage : -1;
2359  }
2360 
2361  LPDEVMODE GetDevMode() const // return DEVMODE
2362  {
2363  if(m_pd.hDevMode == NULL)
2364  return NULL;
2365 
2366  return (LPDEVMODE)::GlobalLock(m_pd.hDevMode);
2367  }
2368 
2369  LPCTSTR GetDriverName() const // return driver name
2370  {
2371  if(m_pd.hDevNames == NULL)
2372  return NULL;
2373 
2374  LPDEVNAMES lpDev = (LPDEVNAMES)::GlobalLock(m_pd.hDevNames);
2375  if(lpDev == NULL)
2376  return NULL;
2377 
2378  return (LPCTSTR)lpDev + lpDev->wDriverOffset;
2379  }
2380 
2381  LPCTSTR GetDeviceName() const // return device name
2382  {
2383  if(m_pd.hDevNames == NULL)
2384  return NULL;
2385 
2386  LPDEVNAMES lpDev = (LPDEVNAMES)::GlobalLock(m_pd.hDevNames);
2387  if(lpDev == NULL)
2388  return NULL;
2389 
2390  return (LPCTSTR)lpDev + lpDev->wDeviceOffset;
2391  }
2392 
2393  LPCTSTR GetPortName() const // return output port name
2394  {
2395  if(m_pd.hDevNames == NULL)
2396  return NULL;
2397 
2398  LPDEVNAMES lpDev = (LPDEVNAMES)::GlobalLock(m_pd.hDevNames);
2399  if(lpDev == NULL)
2400  return NULL;
2401 
2402  return (LPCTSTR)lpDev + lpDev->wOutputOffset;
2403  }
2404 
2405  HDC GetPrinterDC() const // return HDC (caller must delete)
2406  {
2407  ATLASSERT((m_pd.Flags & PD_RETURNDC) != 0);
2408  return m_pd.hDC;
2409  }
2410 
2411  // This helper creates a DC based on the DEVNAMES and DEVMODE structures.
2412  // This DC is returned, but also stored in m_pd.hDC as though it had been
2413  // returned by CommDlg. It is assumed that any previously obtained DC
2414  // has been/will be deleted by the user. This may be
2415  // used without ever invoking the print/print setup dialogs.
2416  HDC CreatePrinterDC()
2417  {
2418  m_pd.hDC = _AtlCreateDC(m_pd.hDevNames, m_pd.hDevMode);
2419  return m_pd.hDC;
2420  }
2421 
2422 // Implementation
2423  PRINTDLG m_pdActual; // the Print/Print Setup need to share this
2424 
2425  // The following handle the case of print setup... from the print dialog
2426  CPrintDialogImpl(PRINTDLG& pdInit) : m_pd(pdInit)
2427  { }
2428 
2429  BEGIN_MSG_MAP(CPrintDialogImpl)
2430 #ifdef psh1
2431  COMMAND_ID_HANDLER(psh1, OnPrintSetup) // print setup button when print is displayed
2432 #else // !psh1
2433  COMMAND_ID_HANDLER(0x0400, OnPrintSetup) // value from dlgs.h
2434 #endif // !psh1
2435  END_MSG_MAP()
2436 
2437  LRESULT OnPrintSetup(WORD wNotifyCode, WORD wID, HWND hWndCtl, BOOL& /*bHandled*/)
2438  {
2439  T dlgSetup(m_pd);
2440  ModuleHelper::AddCreateWndData(&dlgSetup.m_thunk.cd, (CCommonDialogImplBase*)&dlgSetup);
2441  return DefWindowProc(WM_COMMAND, MAKEWPARAM(wID, wNotifyCode), (LPARAM)hWndCtl);
2442  }
2443 };
2444 
2445 class CPrintDialog : public CPrintDialogImpl<CPrintDialog>
2446 {
2447 public:
2448  CPrintDialog(BOOL bPrintSetupOnly = FALSE,
2449  DWORD dwFlags = PD_ALLPAGES | PD_USEDEVMODECOPIES | PD_NOPAGENUMS | PD_NOSELECTION,
2450  HWND hWndParent = NULL)
2451  : CPrintDialogImpl<CPrintDialog>(bPrintSetupOnly, dwFlags, hWndParent)
2452  { }
2453 
2454  CPrintDialog(PRINTDLG& pdInit) : CPrintDialogImpl<CPrintDialog>(pdInit)
2455  { }
2456 };
2457 
2458 #pragma warning(pop)
2459 
2460 #endif // _WIN32_WCE
2461 
2462 
2464 // CPrintDialogExImpl - new print dialog for Windows 2000
2465 
2466 #if (WINVER >= 0x0500) && !defined(_WIN32_WCE)
2467 
2468 }; // namespace WTL
2469 
2470 #include <atlcom.h>
2471 
2472 extern "C" const __declspec(selectany) IID IID_IPrintDialogCallback = {0x5852a2c3, 0x6530, 0x11d1, {0xb6, 0xa3, 0x0, 0x0, 0xf8, 0x75, 0x7b, 0xf9}};
2473 extern "C" const __declspec(selectany) IID IID_IPrintDialogServices = {0x509aaeda, 0x5639, 0x11d1, {0xb6, 0xa1, 0x0, 0x0, 0xf8, 0x75, 0x7b, 0xf9}};
2474 
2475 namespace WTL
2476 {
2477 
2478 template <class T>
2479 class ATL_NO_VTABLE CPrintDialogExImpl :
2480  public ATL::CWindow,
2481  public ATL::CMessageMap,
2482  public IPrintDialogCallback,
2483  public ATL::IObjectWithSiteImpl< T >
2484 {
2485 public:
2486  PRINTDLGEX m_pdex;
2487 
2488 // Constructor
2489  CPrintDialogExImpl(DWORD dwFlags = PD_ALLPAGES | PD_USEDEVMODECOPIES | PD_NOPAGENUMS | PD_NOSELECTION | PD_NOCURRENTPAGE,
2490  HWND hWndParent = NULL)
2491  {
2492  memset(&m_pdex, 0, sizeof(m_pdex));
2493 
2494  m_pdex.lStructSize = sizeof(PRINTDLGEX);
2495  m_pdex.hwndOwner = hWndParent;
2496  m_pdex.Flags = dwFlags;
2497  m_pdex.nStartPage = START_PAGE_GENERAL;
2498  // callback object will be set in DoModal
2499 
2500  m_pdex.Flags &= ~PD_RETURNIC; // do not support information context
2501  }
2502 
2503 // Operations
2504  HRESULT DoModal(HWND hWndParent = ::GetActiveWindow())
2505  {
2506  ATLASSERT(m_hWnd == NULL);
2507  ATLASSERT((m_pdex.Flags & PD_RETURNDEFAULT) == 0); // use GetDefaults for this
2508 
2509  if(m_pdex.hwndOwner == NULL) // set only if not specified before
2510  m_pdex.hwndOwner = hWndParent;
2511 
2512  T* pT = static_cast<T*>(this);
2513  m_pdex.lpCallback = (IUnknown*)(IPrintDialogCallback*)pT;
2514 
2515  HRESULT hResult = ::PrintDlgEx(&m_pdex);
2516 
2517  m_hWnd = NULL;
2518 
2519  return hResult;
2520  }
2521 
2522  BOOL EndDialog(INT_PTR /*nRetCode*/ = 0)
2523  {
2524  ATLASSERT(::IsWindow(m_hWnd));
2525  SendMessage(WM_COMMAND, MAKEWPARAM(IDABORT, 0));
2526  return TRUE;
2527  }
2528 
2529  // GetDefaults will not display a dialog but will get device defaults
2530  HRESULT GetDefaults()
2531  {
2532  ATLASSERT(m_pdex.hDevMode == NULL); // must be NULL
2533  ATLASSERT(m_pdex.hDevNames == NULL); // must be NULL
2534 
2535  if(m_pdex.hwndOwner == NULL) // set only if not specified before
2536  m_pdex.hwndOwner = ::GetActiveWindow();
2537 
2538  m_pdex.Flags |= PD_RETURNDEFAULT;
2539  HRESULT hRet = ::PrintDlgEx(&m_pdex);
2540  m_pdex.Flags &= ~PD_RETURNDEFAULT;
2541 
2542  return hRet;
2543  }
2544 
2545  // Helpers for parsing information after successful return num. copies requested
2546  int GetCopies() const
2547  {
2548  if((m_pdex.Flags & PD_USEDEVMODECOPIES) != 0)
2549  {
2550  LPDEVMODE lpDevMode = GetDevMode();
2551  return (lpDevMode != NULL) ? lpDevMode->dmCopies : -1;
2552  }
2553 
2554  return m_pdex.nCopies;
2555  }
2556 
2557  BOOL PrintCollate() const // TRUE if collate checked
2558  {
2559  return ((m_pdex.Flags & PD_COLLATE) != 0) ? TRUE : FALSE;
2560  }
2561 
2562  BOOL PrintSelection() const // TRUE if printing selection
2563  {
2564  return ((m_pdex.Flags & PD_SELECTION) != 0) ? TRUE : FALSE;
2565  }
2566 
2567  BOOL PrintAll() const // TRUE if printing all pages
2568  {
2569  return (!PrintRange() && !PrintSelection()) ? TRUE : FALSE;
2570  }
2571 
2572  BOOL PrintRange() const // TRUE if printing page range
2573  {
2574  return ((m_pdex.Flags & PD_PAGENUMS) != 0) ? TRUE : FALSE;
2575  }
2576 
2577  BOOL PrintToFile() const // TRUE if printing to a file
2578  {
2579  return ((m_pdex.Flags & PD_PRINTTOFILE) != 0) ? TRUE : FALSE;
2580  }
2581 
2582  LPDEVMODE GetDevMode() const // return DEVMODE
2583  {
2584  if(m_pdex.hDevMode == NULL)
2585  return NULL;
2586 
2587  return (LPDEVMODE)::GlobalLock(m_pdex.hDevMode);
2588  }
2589 
2590  LPCTSTR GetDriverName() const // return driver name
2591  {
2592  if(m_pdex.hDevNames == NULL)
2593  return NULL;
2594 
2595  LPDEVNAMES lpDev = (LPDEVNAMES)::GlobalLock(m_pdex.hDevNames);
2596  if(lpDev == NULL)
2597  return NULL;
2598 
2599  return (LPCTSTR)lpDev + lpDev->wDriverOffset;
2600  }
2601 
2602  LPCTSTR GetDeviceName() const // return device name
2603  {
2604  if(m_pdex.hDevNames == NULL)
2605  return NULL;
2606 
2607  LPDEVNAMES lpDev = (LPDEVNAMES)::GlobalLock(m_pdex.hDevNames);
2608  if(lpDev == NULL)
2609  return NULL;
2610 
2611  return (LPCTSTR)lpDev + lpDev->wDeviceOffset;
2612  }
2613 
2614  LPCTSTR GetPortName() const // return output port name
2615  {
2616  if(m_pdex.hDevNames == NULL)
2617  return NULL;
2618 
2619  LPDEVNAMES lpDev = (LPDEVNAMES)::GlobalLock(m_pdex.hDevNames);
2620  if(lpDev == NULL)
2621  return NULL;
2622 
2623  return (LPCTSTR)lpDev + lpDev->wOutputOffset;
2624  }
2625 
2626  HDC GetPrinterDC() const // return HDC (caller must delete)
2627  {
2628  ATLASSERT((m_pdex.Flags & PD_RETURNDC) != 0);
2629  return m_pdex.hDC;
2630  }
2631 
2632  // This helper creates a DC based on the DEVNAMES and DEVMODE structures.
2633  // This DC is returned, but also stored in m_pdex.hDC as though it had been
2634  // returned by CommDlg. It is assumed that any previously obtained DC
2635  // has been/will be deleted by the user. This may be
2636  // used without ever invoking the print/print setup dialogs.
2637  HDC CreatePrinterDC()
2638  {
2639  m_pdex.hDC = _AtlCreateDC(m_pdex.hDevNames, m_pdex.hDevMode);
2640  return m_pdex.hDC;
2641  }
2642 
2643 // Implementation - interfaces
2644 
2645 // IUnknown
2646  STDMETHOD(QueryInterface)(REFIID riid, void** ppvObject)
2647  {
2648  if(ppvObject == NULL)
2649  return E_POINTER;
2650 
2651  T* pT = static_cast<T*>(this);
2652  if(IsEqualGUID(riid, IID_IUnknown) || IsEqualGUID(riid, IID_IPrintDialogCallback))
2653  {
2654  *ppvObject = (IPrintDialogCallback*)pT;
2655  // AddRef() not needed
2656  return S_OK;
2657  }
2658  else if(IsEqualGUID(riid, IID_IObjectWithSite))
2659  {
2660  *ppvObject = (IObjectWithSite*)pT;
2661  // AddRef() not needed
2662  return S_OK;
2663  }
2664 
2665  return E_NOINTERFACE;
2666  }
2667 
2668  virtual ULONG STDMETHODCALLTYPE AddRef()
2669  {
2670  return 1;
2671  }
2672 
2673  virtual ULONG STDMETHODCALLTYPE Release()
2674  {
2675  return 1;
2676  }
2677 
2678 // IPrintDialogCallback
2679  STDMETHOD(InitDone)()
2680  {
2681  return S_FALSE;
2682  }
2683 
2684  STDMETHOD(SelectionChange)()
2685  {
2686  return S_FALSE;
2687  }
2688 
2689  STDMETHOD(HandleMessage)(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam, LRESULT* plResult)
2690  {
2691  // set up m_hWnd the first time
2692  if(m_hWnd == NULL)
2693  Attach(hWnd);
2694 
2695  // call message map
2696  HRESULT hRet = ProcessWindowMessage(hWnd, uMsg, wParam, lParam, *plResult, 0) ? S_OK : S_FALSE;
2697  if(hRet == S_OK && uMsg == WM_NOTIFY) // return in DWLP_MSGRESULT
2698  ::SetWindowLongPtr(GetParent(), DWLP_MSGRESULT, (LONG_PTR)*plResult);
2699 
2700  if(uMsg == WM_INITDIALOG && hRet == S_OK && (BOOL)*plResult != FALSE)
2701  hRet = S_FALSE;
2702 
2703  return hRet;
2704  }
2705 };
2706 
2707 class CPrintDialogEx : public CPrintDialogExImpl<CPrintDialogEx>
2708 {
2709 public:
2710  CPrintDialogEx(
2711  DWORD dwFlags = PD_ALLPAGES | PD_USEDEVMODECOPIES | PD_NOPAGENUMS | PD_NOSELECTION | PD_NOCURRENTPAGE,
2712  HWND hWndParent = NULL)
2713  : CPrintDialogExImpl<CPrintDialogEx>(dwFlags, hWndParent)
2714  { }
2715 
2716  DECLARE_EMPTY_MSG_MAP()
2717 };
2718 
2719 #endif // (WINVER >= 0x0500) && !defined(_WIN32_WCE)
2720 
2721 
2723 // CPageSetupDialogImpl - Page Setup dialog
2724 
2725 #ifndef _WIN32_WCE
2726 
2727 template <class T>
2728 class ATL_NO_VTABLE CPageSetupDialogImpl : public CCommonDialogImplBase
2729 {
2730 public:
2731  PAGESETUPDLG m_psd;
2732  ATL::CWndProcThunk m_thunkPaint;
2733 
2734 // Constructors
2735  CPageSetupDialogImpl(DWORD dwFlags = PSD_MARGINS | PSD_INWININIINTLMEASURE, HWND hWndParent = NULL)
2736  {
2737  memset(&m_psd, 0, sizeof(m_psd));
2738 
2739  m_psd.lStructSize = sizeof(m_psd);
2740  m_psd.hwndOwner = hWndParent;
2741  m_psd.Flags = (dwFlags | PSD_ENABLEPAGESETUPHOOK | PSD_ENABLEPAGEPAINTHOOK);
2742  m_psd.lpfnPageSetupHook = (LPPAGESETUPHOOK)T::HookProc;
2743  m_thunkPaint.Init((WNDPROC)T::PaintHookProc, this);
2744 #if (_ATL_VER >= 0x0700)
2745  m_psd.lpfnPagePaintHook = (LPPAGEPAINTHOOK)m_thunkPaint.GetWNDPROC();
2746 #else
2747  m_psd.lpfnPagePaintHook = (LPPAGEPAINTHOOK)&(m_thunkPaint.thunk);
2748 #endif
2749  }
2750 
2751  DECLARE_EMPTY_MSG_MAP()
2752 
2753 // Attributes
2754  LPDEVMODE GetDevMode() const // return DEVMODE
2755  {
2756  if(m_psd.hDevMode == NULL)
2757  return NULL;
2758 
2759  return (LPDEVMODE)::GlobalLock(m_psd.hDevMode);
2760  }
2761 
2762  LPCTSTR GetDriverName() const // return driver name
2763  {
2764  if(m_psd.hDevNames == NULL)
2765  return NULL;
2766 
2767  LPDEVNAMES lpDev = (LPDEVNAMES)::GlobalLock(m_psd.hDevNames);
2768  return (LPCTSTR)lpDev + lpDev->wDriverOffset;
2769  }
2770 
2771  LPCTSTR GetDeviceName() const // return device name
2772  {
2773  if(m_psd.hDevNames == NULL)
2774  return NULL;
2775 
2776  LPDEVNAMES lpDev = (LPDEVNAMES)::GlobalLock(m_psd.hDevNames);
2777  return (LPCTSTR)lpDev + lpDev->wDeviceOffset;
2778  }
2779 
2780  LPCTSTR GetPortName() const // return output port name
2781  {
2782  if(m_psd.hDevNames == NULL)
2783  return NULL;
2784 
2785  LPDEVNAMES lpDev = (LPDEVNAMES)::GlobalLock(m_psd.hDevNames);
2786  return (LPCTSTR)lpDev + lpDev->wOutputOffset;
2787  }
2788 
2789  HDC CreatePrinterDC()
2790  {
2791  return _AtlCreateDC(m_psd.hDevNames, m_psd.hDevMode);
2792  }
2793 
2794  SIZE GetPaperSize() const
2795  {
2796  SIZE size = { m_psd.ptPaperSize.x, m_psd.ptPaperSize.y };
2797  return size;
2798  }
2799 
2800  void GetMargins(LPRECT lpRectMargins, LPRECT lpRectMinMargins) const
2801  {
2802  if(lpRectMargins != NULL)
2803  *lpRectMargins = m_psd.rtMargin;
2804  if(lpRectMinMargins != NULL)
2805  *lpRectMinMargins = m_psd.rtMinMargin;
2806  }
2807 
2808 // Operations
2809  INT_PTR DoModal(HWND hWndParent = ::GetActiveWindow())
2810  {
2811  ATLASSERT((m_psd.Flags & PSD_ENABLEPAGESETUPHOOK) != 0);
2812  ATLASSERT((m_psd.Flags & PSD_ENABLEPAGEPAINTHOOK) != 0);
2813  ATLASSERT(m_psd.lpfnPageSetupHook != NULL); // can still be a user hook
2814  ATLASSERT(m_psd.lpfnPagePaintHook != NULL); // can still be a user hook
2815 
2816  if(m_psd.hwndOwner == NULL) // set only if not specified before
2817  m_psd.hwndOwner = hWndParent;
2818 
2819  ATLASSERT(m_hWnd == NULL);
2820 
2821 #if (_ATL_VER >= 0x0800)
2822  // Allocate the thunk structure here, where we can fail gracefully.
2823  BOOL bRetTh = m_thunk.Init(NULL, NULL);
2824  if(bRetTh == FALSE)
2825  {
2826  ::SetLastError(ERROR_OUTOFMEMORY);
2827  return -1;
2828  }
2829 #endif // (_ATL_VER >= 0x0800)
2830 
2831  ModuleHelper::AddCreateWndData(&m_thunk.cd, (CCommonDialogImplBase*)this);
2832 
2833  BOOL bRet = ::PageSetupDlg(&m_psd);
2834 
2835  m_hWnd = NULL;
2836 
2837  return bRet ? IDOK : IDCANCEL;
2838  }
2839 
2840 // Implementation
2841  static UINT_PTR CALLBACK PaintHookProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
2842  {
2843  T* pT = (T*)hWnd;
2844  UINT_PTR uRet = 0;
2845  switch(uMsg)
2846  {
2847  case WM_PSD_PAGESETUPDLG:
2848  uRet = pT->PreDrawPage(LOWORD(wParam), HIWORD(wParam), (LPPAGESETUPDLG)lParam);
2849  break;
2850  case WM_PSD_FULLPAGERECT:
2851  case WM_PSD_MINMARGINRECT:
2852  case WM_PSD_MARGINRECT:
2853  case WM_PSD_GREEKTEXTRECT:
2854  case WM_PSD_ENVSTAMPRECT:
2855  case WM_PSD_YAFULLPAGERECT:
2856  uRet = pT->OnDrawPage(uMsg, (HDC)wParam, (LPRECT)lParam);
2857  break;
2858  default:
2859  ATLTRACE2(atlTraceUI, 0, _T("CPageSetupDialogImpl::PaintHookProc - unknown message received\n"));
2860  break;
2861  }
2862  return uRet;
2863  }
2864 
2865 // Overridables
2866  UINT_PTR PreDrawPage(WORD /*wPaper*/, WORD /*wFlags*/, LPPAGESETUPDLG /*pPSD*/)
2867  {
2868  // return 1 to prevent any more drawing
2869  return 0;
2870  }
2871 
2872  UINT_PTR OnDrawPage(UINT /*uMsg*/, HDC /*hDC*/, LPRECT /*lpRect*/)
2873  {
2874  return 0; // do the default
2875  }
2876 };
2877 
2878 class CPageSetupDialog : public CPageSetupDialogImpl<CPageSetupDialog>
2879 {
2880 public:
2881  CPageSetupDialog(DWORD dwFlags = PSD_MARGINS | PSD_INWININIINTLMEASURE, HWND hWndParent = NULL)
2882  : CPageSetupDialogImpl<CPageSetupDialog>(dwFlags, hWndParent)
2883  { }
2884 
2885  // override PaintHookProc and references to handlers
2886  static UINT_PTR CALLBACK PaintHookProc(HWND, UINT, WPARAM, LPARAM)
2887  {
2888  return 0;
2889  }
2890 };
2891 
2892 #endif // _WIN32_WCE
2893 
2894 
2896 // CFindReplaceDialogImpl - Find/FindReplace modeless dialogs
2897 
2898 #ifndef _WIN32_WCE
2899 
2900 template <class T>
2901 class ATL_NO_VTABLE CFindReplaceDialogImpl : public CCommonDialogImplBase
2902 {
2903 public:
2904  enum { _cchFindReplaceBuffer = 128 };
2905 
2906  FINDREPLACE m_fr;
2907  TCHAR m_szFindWhat[_cchFindReplaceBuffer];
2908  TCHAR m_szReplaceWith[_cchFindReplaceBuffer];
2909 
2910 // Constructors
2912  {
2913  memset(&m_fr, 0, sizeof(m_fr));
2914  m_szFindWhat[0] = _T('\0');
2915  m_szReplaceWith[0] = _T('\0');
2916 
2917  m_fr.lStructSize = sizeof(m_fr);
2918  m_fr.Flags = FR_ENABLEHOOK;
2919  m_fr.lpfnHook = (LPFRHOOKPROC)T::HookProc;
2920  m_fr.lpstrFindWhat = (LPTSTR)m_szFindWhat;
2921  m_fr.wFindWhatLen = _cchFindReplaceBuffer;
2922  m_fr.lpstrReplaceWith = (LPTSTR)m_szReplaceWith;
2923  m_fr.wReplaceWithLen = _cchFindReplaceBuffer;
2924  }
2925 
2926  // Note: You must allocate the object on the heap.
2927  // If you do not, you must override OnFinalMessage()
2928  virtual void OnFinalMessage(HWND /*hWnd*/)
2929  {
2930  delete this;
2931  }
2932 
2933  HWND Create(BOOL bFindDialogOnly, // TRUE for Find, FALSE for FindReplace
2934  LPCTSTR lpszFindWhat,
2935  LPCTSTR lpszReplaceWith = NULL,
2936  DWORD dwFlags = FR_DOWN,
2937  HWND hWndParent = NULL)
2938  {
2939  ATLASSERT((m_fr.Flags & FR_ENABLEHOOK) != 0);
2940  ATLASSERT(m_fr.lpfnHook != NULL);
2941 
2942  m_fr.Flags |= dwFlags;
2943 
2944  if(hWndParent == NULL)
2945  m_fr.hwndOwner = ::GetActiveWindow();
2946  else
2947  m_fr.hwndOwner = hWndParent;
2948  ATLASSERT(m_fr.hwndOwner != NULL); // must have an owner for modeless dialog
2949 
2950  if(lpszFindWhat != NULL)
2951  SecureHelper::strncpy_x(m_szFindWhat, _countof(m_szFindWhat), lpszFindWhat, _TRUNCATE);
2952 
2953  if(lpszReplaceWith != NULL)
2954  SecureHelper::strncpy_x(m_szReplaceWith, _countof(m_szReplaceWith), lpszReplaceWith, _TRUNCATE);
2955 
2956  ATLASSERT(m_hWnd == NULL);
2957 
2958 #if (_ATL_VER >= 0x0800)
2959  // Allocate the thunk structure here, where we can fail gracefully.
2960  BOOL bRet = m_thunk.Init(NULL, NULL);
2961  if(bRet == FALSE)
2962  {
2963  ::SetLastError(ERROR_OUTOFMEMORY);
2964  return NULL;
2965  }
2966 #endif // (_ATL_VER >= 0x0800)
2967 
2968  ModuleHelper::AddCreateWndData(&m_thunk.cd, (CCommonDialogImplBase*)this);
2969 
2970  HWND hWnd = NULL;
2971  if(bFindDialogOnly)
2972  hWnd = ::FindText(&m_fr);
2973  else
2974  hWnd = ::ReplaceText(&m_fr);
2975 
2976  ATLASSERT(m_hWnd == hWnd);
2977  return hWnd;
2978  }
2979 
2980  static const UINT GetFindReplaceMsg()
2981  {
2982  static const UINT nMsgFindReplace = ::RegisterWindowMessage(FINDMSGSTRING);
2983  return nMsgFindReplace;
2984  }
2985  // call while handling FINDMSGSTRING registered message
2986  // to retreive the object
2987  static T* PASCAL GetNotifier(LPARAM lParam)
2988  {
2989  ATLASSERT(lParam != NULL);
2990  T* pDlg = (T*)(lParam - offsetof(T, m_fr));
2991  return pDlg;
2992  }
2993 
2994 // Operations
2995  // Helpers for parsing information after successful return
2996  LPCTSTR GetFindString() const // get find string
2997  {
2998  return (LPCTSTR)m_fr.lpstrFindWhat;
2999  }
3000 
3001  LPCTSTR GetReplaceString() const // get replacement string
3002  {
3003  return (LPCTSTR)m_fr.lpstrReplaceWith;
3004  }
3005 
3006  BOOL SearchDown() const // TRUE if search down, FALSE is up
3007  {
3008  return ((m_fr.Flags & FR_DOWN) != 0) ? TRUE : FALSE;
3009  }
3010 
3011  BOOL FindNext() const // TRUE if command is find next
3012  {
3013  return ((m_fr.Flags & FR_FINDNEXT) != 0) ? TRUE : FALSE;
3014  }
3015 
3016  BOOL MatchCase() const // TRUE if matching case
3017  {
3018  return ((m_fr.Flags & FR_MATCHCASE) != 0) ? TRUE : FALSE;
3019  }
3020 
3021  BOOL MatchWholeWord() const // TRUE if matching whole words only
3022  {
3023  return ((m_fr.Flags & FR_WHOLEWORD) != 0) ? TRUE : FALSE;
3024  }
3025 
3026  BOOL ReplaceCurrent() const // TRUE if replacing current string
3027  {
3028  return ((m_fr. Flags & FR_REPLACE) != 0) ? TRUE : FALSE;
3029  }
3030 
3031  BOOL ReplaceAll() const // TRUE if replacing all occurrences
3032  {
3033  return ((m_fr.Flags & FR_REPLACEALL) != 0) ? TRUE : FALSE;
3034  }
3035 
3036  BOOL IsTerminating() const // TRUE if terminating dialog
3037  {
3038  return ((m_fr.Flags & FR_DIALOGTERM) != 0) ? TRUE : FALSE ;
3039  }
3040 };
3041 
3042 class CFindReplaceDialog : public CFindReplaceDialogImpl<CFindReplaceDialog>
3043 {
3044 public:
3045  DECLARE_EMPTY_MSG_MAP()
3046 };
3047 
3048 #endif // !_WIN32_WCE
3049 
3050 
3052 // CDialogBaseUnits - Dialog Units helper
3053 //
3054 
3056 {
3057 public:
3058  SIZE m_sizeUnits;
3059 
3060 // Constructors
3062  {
3063  // The base units of the out-dated System Font
3064  LONG nDlgBaseUnits = ::GetDialogBaseUnits();
3065  m_sizeUnits.cx = LOWORD(nDlgBaseUnits);
3066  m_sizeUnits.cy = HIWORD(nDlgBaseUnits);
3067  }
3068 
3069  CDialogBaseUnits(HWND hWnd)
3070  {
3071  if(!InitDialogBaseUnits(hWnd)) {
3072  LONG nDlgBaseUnits = ::GetDialogBaseUnits();
3073  m_sizeUnits.cx = LOWORD(nDlgBaseUnits);
3074  m_sizeUnits.cy = HIWORD(nDlgBaseUnits);
3075  }
3076  }
3077 
3078  CDialogBaseUnits(HFONT hFont, HWND hWnd = NULL)
3079  {
3080  if(!InitDialogBaseUnits(hFont, hWnd)) {
3081  LONG nDlgBaseUnits = ::GetDialogBaseUnits();
3082  m_sizeUnits.cx = LOWORD(nDlgBaseUnits);
3083  m_sizeUnits.cy = HIWORD(nDlgBaseUnits);
3084  }
3085  }
3086 
3087  CDialogBaseUnits(LOGFONT lf, HWND hWnd = NULL)
3088  {
3089  if(!InitDialogBaseUnits(lf, hWnd)) {
3090  LONG nDlgBaseUnits = ::GetDialogBaseUnits();
3091  m_sizeUnits.cx = LOWORD(nDlgBaseUnits);
3092  m_sizeUnits.cy = HIWORD(nDlgBaseUnits);
3093  }
3094  }
3095 
3096 // Operations
3097  BOOL InitDialogBaseUnits(HWND hWnd)
3098  {
3099  ATLASSERT(::IsWindow(hWnd));
3100  RECT rc = { 0, 0, 4, 8 };
3101  if(!::MapDialogRect(hWnd, &rc)) return FALSE;
3102  m_sizeUnits.cx = rc.right;
3103  m_sizeUnits.cy = rc.bottom;
3104  return TRUE;
3105  }
3106 
3107  BOOL InitDialogBaseUnits(LOGFONT lf, HWND hWnd = NULL)
3108  {
3109  CFont font;
3110  font.CreateFontIndirect(&lf);
3111  if(font.IsNull()) return FALSE;
3112  return InitDialogBaseUnits(font, hWnd);
3113  }
3114 
3115  BOOL InitDialogBaseUnits(HFONT hFont, HWND hWnd = NULL)
3116  {
3117  ATLASSERT(hFont != NULL);
3118  CWindowDC dc = hWnd;
3119  TEXTMETRIC tmText = { 0 };
3120  SIZE sizeText = { 0 };
3121  HFONT hFontOld = dc.SelectFont(hFont);
3122  dc.GetTextMetrics(&tmText);
3123  m_sizeUnits.cy = tmText.tmHeight + tmText.tmExternalLeading;
3124  dc.GetTextExtent(_T("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz"), 52, &sizeText);
3125  m_sizeUnits.cx = (sizeText.cx + 26) / 52;
3126  dc.SelectFont(hFontOld);
3127  return TRUE;
3128  }
3129 
3130  SIZE GetDialogBaseUnits() const
3131  {
3132  return m_sizeUnits;
3133  }
3134 
3135  INT MapDialogPixelsX(INT x) const
3136  {
3137  return ::MulDiv(x, 4, m_sizeUnits.cx); // Pixels X to DLU
3138  }
3139 
3140  INT MapDialogPixelsY(INT y) const
3141  {
3142  return ::MulDiv(y, 8, m_sizeUnits.cy); // Pixels Y to DLU
3143  }
3144 
3145  POINT MapDialogPixels(POINT pt) const
3146  {
3147  POINT out = { MapDialogPixelsX(pt.x), MapDialogPixelsY(pt.y) };
3148  return out;
3149  }
3150 
3151  SIZE MapDialogPixels(SIZE input) const
3152  {
3153  SIZE out = { MapDialogPixelsX(input.cx), MapDialogPixelsY(input.cy) };
3154  return out;
3155  }
3156 
3157  RECT MapDialogPixels(const RECT& input) const
3158  {
3159  RECT out = { MapDialogPixelsX(input.left), MapDialogPixelsY(input.top), MapDialogPixelsX(input.right), MapDialogPixelsY(input.bottom) };
3160  return out;
3161  }
3162 
3163  INT MapDialogUnitsX(INT x) const
3164  {
3165  return ::MulDiv(x, m_sizeUnits.cx, 4); // DLU to Pixels X
3166  }
3167 
3168  INT MapDialogUnitsY(INT y) const
3169  {
3170  return ::MulDiv(y, m_sizeUnits.cy, 8); // DLU to Pixels Y
3171  }
3172 
3173  POINT MapDialogUnits(POINT pt) const
3174  {
3175  POINT out = { MapDialogUnitsX(pt.x), MapDialogUnitsY(pt.y) };
3176  return out;
3177  }
3178 
3179  SIZE MapDialogUnits(SIZE input) const
3180  {
3181  SIZE out = { MapDialogUnitsX(input.cx), MapDialogUnitsY(input.cy) };
3182  return out;
3183  }
3184 
3185  RECT MapDialogUnits(const RECT& input) const
3186  {
3187  RECT out = { MapDialogUnitsX(input.left), MapDialogUnitsY(input.top), MapDialogUnitsX(input.right), MapDialogUnitsY(input.bottom) };
3188  return out;
3189  }
3190 };
3191 
3192 
3194 // CMemDlgTemplate - in-memory dialog template - DLGTEMPLATE or DLGTEMPLATEEX
3195 
3196 #if (_ATL_VER >= 0x800)
3197  typedef ATL::_DialogSplitHelper::DLGTEMPLATEEX DLGTEMPLATEEX;
3198  typedef ATL::_DialogSplitHelper::DLGITEMTEMPLATEEX DLGITEMTEMPLATEEX;
3199 #else // (_ATL_VER >= 0x800)
3200  typedef ATL::_DialogSizeHelper::_ATL_DLGTEMPLATEEX DLGTEMPLATEEX;
3201  #pragma pack(push, 4)
3202  struct DLGITEMTEMPLATEEX
3203  {
3204  DWORD helpID;
3205  DWORD exStyle;
3206  DWORD style;
3207  short x;
3208  short y;
3209  short cx;
3210  short cy;
3211  DWORD id;
3212  };
3213  #pragma pack(pop)
3214 #endif // (_ATL_VER >= 0x800)
3215 
3216 
3217 template <class TWinTraits>
3219 {
3220 public:
3221  enum StdCtrlType
3222  {
3223  CTRL_BUTTON = 0x0080,
3224  CTRL_EDIT = 0x0081,
3225  CTRL_STATIC = 0x0082,
3226  CTRL_LISTBOX = 0x0083,
3227  CTRL_SCROLLBAR = 0x0084,
3228  CTRL_COMBOBOX = 0x0085
3229  };
3230 
3231  HANDLE m_hData;
3232  LPBYTE m_pData;
3233  LPBYTE m_pPtr;
3234  SIZE_T m_cAllocated;
3235 
3236  CMemDlgTemplateT() : m_hData(NULL), m_pData(NULL), m_pPtr(NULL), m_cAllocated(0)
3237  { }
3238 
3239  ~CMemDlgTemplateT()
3240  {
3241  Reset();
3242  }
3243 
3244  bool IsValid() const
3245  {
3246  return (m_pData != NULL);
3247  }
3248 
3249  bool IsTemplateEx() const
3250  {
3251  return (IsValid() && ((DLGTEMPLATEEX*)m_pData)->signature == 0xFFFF);
3252  }
3253 
3254  LPDLGTEMPLATE GetTemplatePtr()
3255  {
3256  return reinterpret_cast<LPDLGTEMPLATE>(m_pData);
3257  }
3258 
3259  DLGTEMPLATEEX* GetTemplateExPtr()
3260  {
3261  return reinterpret_cast<DLGTEMPLATEEX*>(m_pData);
3262  }
3263 
3264  void Reset()
3265  {
3266  if (IsValid()) {
3267 #ifndef UNDER_CE
3268  ::GlobalUnlock(m_pData);
3269 #endif
3270  ATLVERIFY(::GlobalFree(m_hData) == NULL);
3271  }
3272 
3273  m_hData = NULL;
3274  m_pData = NULL;
3275  m_pPtr = NULL;
3276  m_cAllocated = 0;
3277  }
3278 
3279  void Create(bool bDlgEx, LPCTSTR lpszCaption, const RECT& rc, DWORD dwStyle = 0, DWORD dwExStyle = 0,
3280  LPCTSTR lpstrFontName = NULL, WORD wFontSize = 0, WORD wWeight = 0, BYTE bItalic = 0, BYTE bCharset = 0, DWORD dwHelpID = 0,
3281  ATL::_U_STRINGorID ClassName = 0U, ATL::_U_STRINGorID Menu = 0U)
3282  {
3283  Create(bDlgEx, lpszCaption, (short) rc.left, (short) rc.top, (short) (rc.right - rc.left), (short) (rc.bottom - rc.top), dwStyle, dwExStyle,
3284  lpstrFontName, wFontSize, wWeight, bItalic, bCharset, dwHelpID, ClassName.m_lpstr, Menu.m_lpstr);
3285  }
3286 
3287  void Create(bool bDlgEx, LPCTSTR lpszCaption, short nX, short nY, short nWidth, short nHeight, DWORD dwStyle = 0, DWORD dwExStyle = 0,
3288  LPCTSTR lpstrFontName = NULL, WORD wFontSize = 0, WORD wWeight = 0, BYTE bItalic = 0, BYTE bCharset = 0, DWORD dwHelpID = 0,
3289  ATL::_U_STRINGorID ClassName = 0U, ATL::_U_STRINGorID Menu = 0U)
3290  {
3291  // Should have DS_SETFONT style to set the dialog font name and size
3292  if (lpstrFontName != NULL)
3293  {
3294  dwStyle |= DS_SETFONT;
3295  }
3296  else
3297  {
3298  dwStyle &= ~DS_SETFONT;
3299  }
3300 
3301  if (bDlgEx)
3302  {
3303  DLGTEMPLATEEX dlg = {1, 0xFFFF, dwHelpID, dwExStyle, dwStyle, 0, nX, nY, nWidth, nHeight};
3304  AddData(&dlg, sizeof(dlg));
3305  }
3306  else
3307  {
3308  DLGTEMPLATE dlg = {dwStyle, dwExStyle, 0, nX, nY, nWidth, nHeight};
3309  AddData(&dlg, sizeof(dlg));
3310  }
3311 
3312 #ifndef _WIN32_WCE
3313  if (Menu.m_lpstr == NULL)
3314  {
3315  WORD menuData = 0;
3316  AddData(&menuData, sizeof(WORD));
3317  }
3318  else if (IS_INTRESOURCE(Menu.m_lpstr))
3319  {
3320  WORD menuData[] = { 0xFFFF, LOWORD(Menu.m_lpstr) };
3321  AddData(menuData, sizeof(menuData));
3322  }
3323  else
3324  {
3325  AddString(Menu.m_lpstr);
3326  }
3327 #else // _WIN32_WCE
3328  // Windows CE doesn't support the addition of menus to a dialog box
3329  ATLASSERT(Menu.m_lpstr == NULL);
3330  Menu.m_lpstr; // avoid level 4 warning
3331  WORD menuData = 0;
3332  AddData(&menuData, sizeof(WORD));
3333 #endif // _WIN32_WCE
3334 
3335  if (ClassName.m_lpstr == NULL)
3336  {
3337  WORD classData = 0;
3338  AddData(&classData, sizeof(WORD));
3339  }
3340  else if (IS_INTRESOURCE(ClassName.m_lpstr))
3341  {
3342  WORD classData[] = { 0xFFFF, LOWORD(ClassName.m_lpstr) };
3343  AddData(classData, sizeof(classData));
3344  }
3345  else
3346  {
3347  AddString(ClassName.m_lpstr);
3348  }
3349 
3350  // Set dialog caption
3351  AddString(lpszCaption);
3352 
3353  if (lpstrFontName != NULL)
3354  {
3355  AddData(&wFontSize, sizeof(wFontSize));
3356 
3357  if (bDlgEx)
3358  {
3359  AddData(&wWeight, sizeof(wWeight));
3360  AddData(&bItalic, sizeof(bItalic));
3361  AddData(&bCharset, sizeof(bCharset));
3362  }
3363 
3364  AddString(lpstrFontName);
3365  }
3366  }
3367 
3368  void AddControl(ATL::_U_STRINGorID ClassName, WORD wId, const RECT& rc, DWORD dwStyle, DWORD dwExStyle,
3369  ATL::_U_STRINGorID Text, const WORD* pCreationData = NULL, WORD nCreationData = 0, DWORD dwHelpID = 0)
3370  {
3371  AddControl(ClassName.m_lpstr, wId, (short) rc.left, (short) rc.top, (short) (rc.right - rc.left), (short) (rc.bottom - rc.top), dwStyle, dwExStyle,
3372  Text.m_lpstr, pCreationData, nCreationData, dwHelpID);
3373  }
3374 
3375  void AddControl(ATL::_U_STRINGorID ClassName, WORD wId, short nX, short nY, short nWidth, short nHeight, DWORD dwStyle, DWORD dwExStyle,
3376  ATL::_U_STRINGorID Text, const WORD* pCreationData = NULL, WORD nCreationData = 0, DWORD dwHelpID = 0)
3377  {
3378  ATLASSERT(IsValid());
3379 
3380  // DWORD align data
3381  const DWORD_PTR dwDwordAlignBits = sizeof(DWORD) - 1;
3382  m_pPtr = (LPBYTE)(((DWORD_PTR)m_pPtr + dwDwordAlignBits) & (~dwDwordAlignBits));
3383 
3384  if (IsTemplateEx())
3385  {
3386  DLGTEMPLATEEX* dlg = (DLGTEMPLATEEX*)m_pData;
3387  dlg->cDlgItems++;
3388 
3389  DLGITEMTEMPLATEEX item = {dwHelpID, TWinTraits::GetWndExStyle(0) | dwExStyle, TWinTraits::GetWndStyle(0) | dwStyle, nX, nY, nWidth, nHeight, wId};
3390  AddData(&item, sizeof(item));
3391  }
3392  else
3393  {
3394  LPDLGTEMPLATE dlg = (LPDLGTEMPLATE)m_pData;
3395  dlg->cdit++;
3396 
3397  DLGITEMTEMPLATE item = {TWinTraits::GetWndStyle(0) | dwStyle, TWinTraits::GetWndExStyle(0) | dwExStyle, nX, nY, nWidth, nHeight, wId};
3398  AddData(&item, sizeof(item));
3399  }
3400 
3401  ATLASSERT(ClassName.m_lpstr != NULL);
3402  if (IS_INTRESOURCE(ClassName.m_lpstr))
3403  {
3404  WORD wData[] = { 0xFFFF, LOWORD(ClassName.m_lpstr) };
3405  AddData(wData, sizeof(wData));
3406  }
3407  else
3408  {
3409  AddString(ClassName.m_lpstr);
3410  }
3411 
3412  if (Text.m_lpstr == NULL)
3413  {
3414  WORD classData = 0;
3415  AddData(&classData, sizeof(WORD));
3416  }
3417  else if (IS_INTRESOURCE(Text.m_lpstr))
3418  {
3419  WORD wData[] = { 0xFFFF, LOWORD(Text.m_lpstr) };
3420  AddData(wData, sizeof(wData));
3421  }
3422  else
3423  {
3424  AddString(Text.m_lpstr);
3425  }
3426 
3427  AddData(&nCreationData, sizeof(nCreationData));
3428 
3429  if ((nCreationData != 0))
3430  {
3431  ATLASSERT(pCreationData != NULL);
3432  AddData(pCreationData, nCreationData * sizeof(WORD));
3433  }
3434  }
3435 
3436  void AddStdControl(StdCtrlType CtrlType, WORD wId, short nX, short nY, short nWidth, short nHeight,
3437  DWORD dwStyle, DWORD dwExStyle, ATL::_U_STRINGorID Text, const WORD* pCreationData = NULL, WORD nCreationData = 0, DWORD dwHelpID = 0)
3438  {
3439  AddControl(CtrlType, wId, nX, nY, nWidth, nHeight, dwStyle, dwExStyle, Text, pCreationData, nCreationData, dwHelpID);
3440  }
3441 
3442  void AddData(LPCVOID pData, size_t nData)
3443  {
3444  ATLASSERT(pData != NULL);
3445 
3446  const SIZE_T ALLOCATION_INCREMENT = 1024;
3447 
3448  if (m_pData == NULL)
3449  {
3450  m_cAllocated = ((nData / ALLOCATION_INCREMENT) + 1) * ALLOCATION_INCREMENT;
3451  m_hData = ::GlobalAlloc(GMEM_MOVEABLE | GMEM_ZEROINIT, m_cAllocated);
3452  ATLASSERT(m_hData != NULL);
3453 #ifndef UNDER_CE
3454  m_pPtr = m_pData = static_cast<LPBYTE>(::GlobalLock(m_hData));
3455 #else
3456  m_pPtr = m_pData = static_cast<LPBYTE>(m_hData);
3457 #endif
3458  ATLASSERT(m_pData != NULL);
3459  }
3460  else if (((m_pPtr - m_pData) + nData) > m_cAllocated)
3461  {
3462  SIZE_T ptrPos = (m_pPtr - m_pData);
3463  m_cAllocated += ((nData / ALLOCATION_INCREMENT) + 1) * ALLOCATION_INCREMENT;
3464 #ifndef UNDER_CE
3465  ::GlobalUnlock(m_pData);
3466 #endif
3467  m_hData = ::GlobalReAlloc(m_hData, m_cAllocated, GMEM_MOVEABLE | GMEM_ZEROINIT);
3468  ATLASSERT(m_hData != NULL);
3469 #ifndef UNDER_CE
3470  m_pData = static_cast<LPBYTE>(::GlobalLock(m_hData));
3471 #else
3472  m_pData = static_cast<LPBYTE>(m_hData);
3473 #endif
3474  ATLASSERT(m_pData != NULL);
3475  m_pPtr = m_pData + ptrPos;
3476  }
3477 
3478  SecureHelper::memcpy_x(m_pPtr, m_cAllocated - (m_pPtr - m_pData), pData, nData);
3479 
3480  m_pPtr += nData;
3481  }
3482 
3483  void AddString(LPCTSTR lpszStr)
3484  {
3485  if (lpszStr == NULL)
3486  {
3487  WCHAR szEmpty = 0;
3488  AddData(&szEmpty, sizeof(szEmpty));
3489  }
3490  else
3491  {
3492  USES_CONVERSION;
3493  LPCWSTR lpstr = T2CW(lpszStr);
3494  int nSize = lstrlenW(lpstr) + 1;
3495  AddData(lpstr, nSize * sizeof(WCHAR));
3496  }
3497  }
3498 };
3499 
3501 
3502 
3504 // Dialog and control macros for indirect dialogs
3505 
3506 // for DLGTEMPLATE
3507 #define BEGIN_DIALOG(x, y, width, height) \
3508  void DoInitTemplate() \
3509  { \
3510  bool bExTemplate = false; \
3511  short nX = x, nY = y, nWidth = width, nHeight = height; \
3512  LPCTSTR szCaption = NULL; \
3513  DWORD dwStyle = WS_POPUP | WS_BORDER | WS_SYSMENU; \
3514  DWORD dwExStyle = 0; \
3515  LPCTSTR szFontName = NULL; \
3516  WORD wFontSize = 0; \
3517  WORD wWeight = 0; \
3518  BYTE bItalic = 0; \
3519  BYTE bCharset = 0; \
3520  DWORD dwHelpID = 0; \
3521  ATL::_U_STRINGorID Menu = 0U; \
3522  ATL::_U_STRINGorID ClassName = 0U;
3523 
3524 // for DLGTEMPLATEEX
3525 #define BEGIN_DIALOG_EX(x, y, width, height, helpID) \
3526  void DoInitTemplate() \
3527  { \
3528  bool bExTemplate = true; \
3529  short nX = x, nY = y, nWidth = width, nHeight = height; \
3530  LPCTSTR szCaption = NULL; \
3531  DWORD dwStyle = WS_POPUP | WS_BORDER | WS_SYSMENU; \
3532  DWORD dwExStyle = 0; \
3533  LPCTSTR szFontName = NULL; \
3534  WORD wFontSize = 0; \
3535  WORD wWeight = 0; \
3536  BYTE bItalic = 0; \
3537  BYTE bCharset = 0; \
3538  DWORD dwHelpID = helpID; \
3539  ATL::_U_STRINGorID Menu = 0U; \
3540  ATL::_U_STRINGorID ClassName = 0U;
3541 
3542 #define END_DIALOG() \
3543  m_Template.Create(bExTemplate, szCaption, nX, nY, nWidth, nHeight, dwStyle, dwExStyle, szFontName, wFontSize, wWeight, bItalic, bCharset, dwHelpID, ClassName, Menu); \
3544  };
3545 
3546 #define DIALOG_CAPTION(caption) \
3547  szCaption = caption;
3548 #define DIALOG_STYLE(style) \
3549  dwStyle = style;
3550 #define DIALOG_EXSTYLE(exStyle) \
3551  dwExStyle = exStyle;
3552 #define DIALOG_FONT(pointSize, typeFace) \
3553  wFontSize = pointSize; \
3554  szFontName = typeFace;
3555 #define DIALOG_FONT_EX(pointsize, typeface, weight, italic, charset) \
3556  ATLASSERT(bExTemplate); \
3557  wFontSize = pointsize; \
3558  szFontName = typeface; \
3559  wWeight = weight; \
3560  bItalic = italic; \
3561  bCharset = charset;
3562 #define DIALOG_MENU(menuName) \
3563  Menu = menuName;
3564 #define DIALOG_CLASS(className) \
3565  ClassName = className;
3566 
3567 #define BEGIN_CONTROLS_MAP() \
3568  void DoInitControls() \
3569  {
3570 
3571 #define END_CONTROLS_MAP() \
3572  };
3573 
3574 
3575 #define CONTROL_LTEXT(text, id, x, y, width, height, style, exStyle) \
3576  m_Template.AddStdControl(m_Template.CTRL_STATIC, (WORD)id, x, y, width, height, style | SS_LEFT | WS_GROUP, exStyle, text, NULL, 0);
3577 #define CONTROL_CTEXT(text, id, x, y, width, height, style, exStyle) \
3578  m_Template.AddStdControl(m_Template.CTRL_STATIC, (WORD)id, x, y, width, height, style | SS_CENTER | WS_GROUP, exStyle, text, NULL, 0);
3579 #define CONTROL_RTEXT(text, id, x, y, width, height, style, exStyle) \
3580  m_Template.AddStdControl(m_Template.CTRL_STATIC, (WORD)id, x, y, width, height, style | SS_RIGHT | WS_GROUP, exStyle, text, NULL, 0);
3581 #define CONTROL_PUSHBUTTON(text, id, x, y, width, height, style, exStyle) \
3582  m_Template.AddStdControl(m_Template.CTRL_BUTTON, (WORD)id, x, y, width, height, style | BS_PUSHBUTTON | WS_TABSTOP, exStyle, text, NULL, 0);
3583 #define CONTROL_DEFPUSHBUTTON(text, id, x, y, width, height, style, exStyle) \
3584  m_Template.AddStdControl(m_Template.CTRL_BUTTON, (WORD)id, x, y, width, height, style | BS_DEFPUSHBUTTON | WS_TABSTOP, exStyle, text, NULL, 0);
3585 #ifndef _WIN32_WCE
3586 #define CONTROL_PUSHBOX(text, id, x, y, width, height, style, exStyle) \
3587  m_Template.AddStdControl(m_Template.CTRL_BUTTON, (WORD)id, x, y, width, height, style | BS_PUSHBOX | WS_TABSTOP, exStyle, text, NULL, 0);
3588 #endif // !_WIN32_WCE
3589 #define CONTROL_STATE3(text, id, x, y, width, height, style, exStyle) \
3590  m_Template.AddStdControl(m_Template.CTRL_BUTTON, (WORD)id, x, y, width, height, style | BS_3STATE | WS_TABSTOP, exStyle, text, NULL, 0);
3591 #define CONTROL_AUTO3STATE(text, id, x, y, width, height, style, exStyle) \
3592  m_Template.AddStdControl(m_Template.CTRL_BUTTON, (WORD)id, x, y, width, height, style | BS_AUTO3STATE | WS_TABSTOP, exStyle, text, NULL, 0);
3593 #define CONTROL_CHECKBOX(text, id, x, y, width, height, style, exStyle) \
3594  m_Template.AddStdControl(m_Template.CTRL_BUTTON, (WORD)id, x, y, width, height, style | BS_CHECKBOX | WS_TABSTOP, exStyle, text, NULL, 0);
3595 #define CONTROL_AUTOCHECKBOX(text, id, x, y, width, height, style, exStyle) \
3596  m_Template.AddStdControl(m_Template.CTRL_BUTTON, (WORD)id, x, y, width, height, style | BS_AUTOCHECKBOX | WS_TABSTOP, exStyle, text, NULL, 0);
3597 #define CONTROL_RADIOBUTTON(text, id, x, y, width, height, style, exStyle) \
3598  m_Template.AddStdControl(m_Template.CTRL_BUTTON, (WORD)id, x, y, width, height, style | BS_RADIOBUTTON | WS_TABSTOP, exStyle, text, NULL, 0);
3599 #define CONTROL_AUTORADIOBUTTON(text, id, x, y, width, height, style, exStyle) \
3600  m_Template.AddStdControl(m_Template.CTRL_BUTTON, (WORD)id, x, y, width, height, style | BS_AUTORADIOBUTTON | WS_TABSTOP, exStyle, text, NULL, 0);
3601 #define CONTROL_COMBOBOX(id, x, y, width, height, style, exStyle) \
3602  m_Template.AddStdControl(m_Template.CTRL_COMBOBOX, (WORD)id, x, y, width, height, style | CBS_DROPDOWN | WS_TABSTOP, exStyle, (LPCTSTR)NULL, NULL, 0);
3603 #define CONTROL_EDITTEXT(id, x, y, width, height, style, exStyle) \
3604  m_Template.AddStdControl(m_Template.CTRL_EDIT, (WORD)id, x, y, width, height, style | ES_LEFT | WS_BORDER | WS_TABSTOP, exStyle, (LPCTSTR)NULL, NULL, 0);
3605 #define CONTROL_GROUPBOX(text, id, x, y, width, height, style, exStyle) \
3606  m_Template.AddStdControl(m_Template.CTRL_BUTTON, (WORD)id, x, y, width, height, style | BS_GROUPBOX, exStyle, text, NULL, 0);
3607 #define CONTROL_LISTBOX(id, x, y, width, height, style, exStyle) \
3608  m_Template.AddStdControl(m_Template.CTRL_LISTBOX, (WORD)id, x, y, width, height, style | LBS_NOTIFY | WS_BORDER, exStyle, (LPCTSTR)NULL, NULL, 0);
3609 #define CONTROL_SCROLLBAR(id, x, y, width, height, style, exStyle) \
3610  m_Template.AddStdControl(m_Template.CTRL_SCROLLBAR, (WORD)id, x, y, width, height, style | SBS_HORZ, exStyle, (LPCTSTR)NULL, NULL, 0);
3611 #define CONTROL_ICON(text, id, x, y, width, height, style, exStyle) \
3612  m_Template.AddStdControl(m_Template.CTRL_STATIC, (WORD)id, x, y, width, height, style | SS_ICON, exStyle, text, NULL, 0);
3613 #define CONTROL_CONTROL(text, id, className, style, x, y, width, height, exStyle) \
3614  m_Template.AddControl(className, (WORD)id, x, y, width, height, style, exStyle, text, NULL, 0);
3615 
3616 
3618 // CIndirectDialogImpl - dialogs with template in memory
3619 
3620 template <class T, class TDlgTemplate = CMemDlgTemplate, class TBase = ATL::CWindow>
3621 class ATL_NO_VTABLE CIndirectDialogImpl : public ATL::CDialogImpl< T, TBase >
3622 {
3623 public:
3624  enum { IDD = 0 }; // no dialog template resource
3625 
3626  TDlgTemplate m_Template;
3627 
3628  void CreateTemplate()
3629  {
3630  T* pT = static_cast<T*>(this);
3631  pT->DoInitTemplate();
3632  pT->DoInitControls();
3633  }
3634 
3635  INT_PTR DoModal(HWND hWndParent = ::GetActiveWindow(), LPARAM dwInitParam = NULL)
3636  {
3637  T* pT = static_cast<T*>(this);
3638  ATLASSERT(pT->m_hWnd == NULL);
3639 
3640  if(!m_Template.IsValid())
3641  CreateTemplate();
3642 
3643 #if (_ATL_VER >= 0x0800)
3644  // Allocate the thunk structure here, where we can fail gracefully.
3645  BOOL bRet = m_thunk.Init(NULL, NULL);
3646  if(bRet == FALSE)
3647  {
3648  ::SetLastError(ERROR_OUTOFMEMORY);
3649  return -1;
3650  }
3651 #endif // (_ATL_VER >= 0x0800)
3652 
3653  ModuleHelper::AddCreateWndData(&m_thunk.cd, (ATL::CDialogImplBaseT< TBase >*)pT);
3654 
3655 #ifdef _DEBUG
3656  m_bModal = true;
3657 #endif // _DEBUG
3658 
3659  return ::DialogBoxIndirectParam(ModuleHelper::GetResourceInstance(), m_Template.GetTemplatePtr(), hWndParent, (DLGPROC)T::StartDialogProc, dwInitParam);
3660  }
3661 
3662  HWND Create(HWND hWndParent, LPARAM dwInitParam = NULL)
3663  {
3664  T* pT = static_cast<T*>(this);
3665  ATLASSERT(pT->m_hWnd == NULL);
3666 
3667  if(!m_Template.IsValid())
3668  CreateTemplate();
3669 
3670 #if (_ATL_VER >= 0x0800)
3671  // Allocate the thunk structure here, where we can fail gracefully.
3672  BOOL bRet = m_thunk.Init(NULL, NULL);
3673  if(bRet == FALSE)
3674  {
3675  ::SetLastError(ERROR_OUTOFMEMORY);
3676  return NULL;
3677  }
3678 #endif // (_ATL_VER >= 0x0800)
3679 
3680  ModuleHelper::AddCreateWndData(&m_thunk.cd, (ATL::CDialogImplBaseT< TBase >*)pT);
3681 
3682 #ifdef _DEBUG
3683  m_bModal = false;
3684 #endif // _DEBUG
3685 
3686  HWND hWnd = ::CreateDialogIndirectParam(ModuleHelper::GetResourceInstance(), (LPCDLGTEMPLATE)m_Template.GetTemplatePtr(), hWndParent, (DLGPROC)T::StartDialogProc, dwInitParam);
3687  ATLASSERT(m_hWnd == hWnd);
3688 
3689  return hWnd;
3690  }
3691 
3692  // for CComControl
3693  HWND Create(HWND hWndParent, RECT&, LPARAM dwInitParam = NULL)
3694  {
3695  return Create(hWndParent, dwInitParam);
3696  }
3697 
3698  void DoInitTemplate()
3699  {
3700  ATLASSERT(FALSE); // MUST be defined in derived class
3701  }
3702 
3703  void DoInitControls()
3704  {
3705  ATLASSERT(FALSE); // MUST be defined in derived class
3706  }
3707 };
3708 
3709 
3711 // CPropertySheetWindow - client side for a property sheet
3712 
3713 class CPropertySheetWindow : public ATL::CWindow
3714 {
3715 public:
3716 // Constructors
3717  CPropertySheetWindow(HWND hWnd = NULL) : ATL::CWindow(hWnd)
3718  { }
3719 
3720  CPropertySheetWindow& operator =(HWND hWnd)
3721  {
3722  m_hWnd = hWnd;
3723  return *this;
3724  }
3725 
3726 // Attributes
3727  int GetPageCount() const
3728  {
3729  ATLASSERT(::IsWindow(m_hWnd));
3730  HWND hWndTabCtrl = GetTabControl();
3731  ATLASSERT(hWndTabCtrl != NULL);
3732  return (int)::SendMessage(hWndTabCtrl, TCM_GETITEMCOUNT, 0, 0L);
3733  }
3734 
3735  HWND GetActivePage() const
3736  {
3737  ATLASSERT(::IsWindow(m_hWnd));
3738  return (HWND)::SendMessage(m_hWnd, PSM_GETCURRENTPAGEHWND, 0, 0L);
3739  }
3740 
3741  int GetActiveIndex() const
3742  {
3743  ATLASSERT(::IsWindow(m_hWnd));
3744  HWND hWndTabCtrl = GetTabControl();
3745  ATLASSERT(hWndTabCtrl != NULL);
3746  return (int)::SendMessage(hWndTabCtrl, TCM_GETCURSEL, 0, 0L);
3747  }
3748 
3749  BOOL SetActivePage(int nPageIndex)
3750  {
3751  ATLASSERT(::IsWindow(m_hWnd));
3752  return (BOOL)::SendMessage(m_hWnd, PSM_SETCURSEL, nPageIndex, 0L);
3753  }
3754 
3755  BOOL SetActivePage(HPROPSHEETPAGE hPage)
3756  {
3757  ATLASSERT(::IsWindow(m_hWnd));
3758  ATLASSERT(hPage != NULL);
3759  return (BOOL)::SendMessage(m_hWnd, PSM_SETCURSEL, 0, (LPARAM)hPage);
3760  }
3761 
3762  BOOL SetActivePageByID(int nPageID)
3763  {
3764  ATLASSERT(::IsWindow(m_hWnd));
3765  return (BOOL)::SendMessage(m_hWnd, PSM_SETCURSELID, 0, nPageID);
3766  }
3767 
3768  void SetTitle(LPCTSTR lpszText, UINT nStyle = 0)
3769  {
3770  ATLASSERT(::IsWindow(m_hWnd));
3771  ATLASSERT((nStyle & ~PSH_PROPTITLE) == 0); // only PSH_PROPTITLE is valid
3772  ATLASSERT(lpszText != NULL);
3773  ::SendMessage(m_hWnd, PSM_SETTITLE, nStyle, (LPARAM)lpszText);
3774  }
3775 
3776  HWND GetTabControl() const
3777  {
3778  ATLASSERT(::IsWindow(m_hWnd));
3779  return (HWND)::SendMessage(m_hWnd, PSM_GETTABCONTROL, 0, 0L);
3780  }
3781 
3782  void SetFinishText(LPCTSTR lpszText)
3783  {
3784  ATLASSERT(::IsWindow(m_hWnd));
3785  ::SendMessage(m_hWnd, PSM_SETFINISHTEXT, 0, (LPARAM)lpszText);
3786  }
3787 
3788  void SetWizardButtons(DWORD dwFlags)
3789  {
3790  ATLASSERT(::IsWindow(m_hWnd));
3791  ::PostMessage(m_hWnd, PSM_SETWIZBUTTONS, 0, dwFlags);
3792  }
3793 
3794 // Operations
3795  BOOL AddPage(HPROPSHEETPAGE hPage)
3796  {
3797  ATLASSERT(::IsWindow(m_hWnd));
3798  ATLASSERT(hPage != NULL);
3799  return (BOOL)::SendMessage(m_hWnd, PSM_ADDPAGE, 0, (LPARAM)hPage);
3800  }
3801 
3802  BOOL AddPage(LPCPROPSHEETPAGE pPage)
3803  {
3804  ATLASSERT(::IsWindow(m_hWnd));
3805  ATLASSERT(pPage != NULL);
3806  HPROPSHEETPAGE hPage = ::CreatePropertySheetPage(pPage);
3807  if(hPage == NULL)
3808  return FALSE;
3809  return (BOOL)::SendMessage(m_hWnd, PSM_ADDPAGE, 0, (LPARAM)hPage);
3810  }
3811 
3812 #ifndef _WIN32_WCE
3813  BOOL InsertPage(int nNewPageIndex, HPROPSHEETPAGE hPage)
3814  {
3815  ATLASSERT(::IsWindow(m_hWnd));
3816  ATLASSERT(hPage != NULL);
3817  return (BOOL)::SendMessage(m_hWnd, PSM_INSERTPAGE, nNewPageIndex, (LPARAM)hPage);
3818  }
3819 
3820  BOOL InsertPage(int nNewPageIndex, LPCPROPSHEETPAGE pPage)
3821  {
3822  ATLASSERT(::IsWindow(m_hWnd));
3823  ATLASSERT(pPage != NULL);
3824  HPROPSHEETPAGE hPage = ::CreatePropertySheetPage(pPage);
3825  if(hPage == NULL)
3826  return FALSE;
3827  return (BOOL)::SendMessage(m_hWnd, PSM_INSERTPAGE, nNewPageIndex, (LPARAM)hPage);
3828  }
3829 
3830  BOOL InsertPage(HPROPSHEETPAGE hPageInsertAfter, HPROPSHEETPAGE hPage)
3831  {
3832  ATLASSERT(::IsWindow(m_hWnd));
3833  ATLASSERT(hPage != NULL);
3834  return (BOOL)::SendMessage(m_hWnd, PSM_INSERTPAGE, (WPARAM)hPageInsertAfter, (LPARAM)hPage);
3835  }
3836 
3837  BOOL InsertPage(HPROPSHEETPAGE hPageInsertAfter, LPCPROPSHEETPAGE pPage)
3838  {
3839  ATLASSERT(::IsWindow(m_hWnd));
3840  ATLASSERT(pPage != NULL);
3841  HPROPSHEETPAGE hPage = ::CreatePropertySheetPage(pPage);
3842  if(hPage == NULL)
3843  return FALSE;
3844  return (BOOL)::SendMessage(m_hWnd, PSM_INSERTPAGE, (WPARAM)hPageInsertAfter, (LPARAM)hPage);
3845  }
3846 #endif // !_WIN32_WCE
3847 
3848  void RemovePage(int nPageIndex)
3849  {
3850  ATLASSERT(::IsWindow(m_hWnd));
3851  ::SendMessage(m_hWnd, PSM_REMOVEPAGE, nPageIndex, 0L);
3852  }
3853 
3854  void RemovePage(HPROPSHEETPAGE hPage)
3855  {
3856  ATLASSERT(::IsWindow(m_hWnd));
3857  ATLASSERT(hPage != NULL);
3858  ::SendMessage(m_hWnd, PSM_REMOVEPAGE, 0, (LPARAM)hPage);
3859  }
3860 
3861  BOOL PressButton(int nButton)
3862  {
3863  ATLASSERT(::IsWindow(m_hWnd));
3864  return (BOOL)::SendMessage(m_hWnd, PSM_PRESSBUTTON, nButton, 0L);
3865  }
3866 
3867  BOOL Apply()
3868  {
3869  ATLASSERT(::IsWindow(m_hWnd));
3870  return (BOOL)::SendMessage(m_hWnd, PSM_APPLY, 0, 0L);
3871  }
3872 
3873  void CancelToClose()
3874  {
3875  ATLASSERT(::IsWindow(m_hWnd));
3876  ::SendMessage(m_hWnd, PSM_CANCELTOCLOSE, 0, 0L);
3877  }
3878 
3879  void SetModified(HWND hWndPage, BOOL bChanged = TRUE)
3880  {
3881  ATLASSERT(::IsWindow(m_hWnd));
3882  ATLASSERT(::IsWindow(hWndPage));
3883  UINT uMsg = bChanged ? PSM_CHANGED : PSM_UNCHANGED;
3884  ::SendMessage(m_hWnd, uMsg, (WPARAM)hWndPage, 0L);
3885  }
3886 
3887  LRESULT QuerySiblings(WPARAM wParam, LPARAM lParam)
3888  {
3889  ATLASSERT(::IsWindow(m_hWnd));
3890  return ::SendMessage(m_hWnd, PSM_QUERYSIBLINGS, wParam, lParam);
3891  }
3892 
3893  void RebootSystem()
3894  {
3895  ATLASSERT(::IsWindow(m_hWnd));
3896  ::SendMessage(m_hWnd, PSM_REBOOTSYSTEM, 0, 0L);
3897  }
3898 
3899  void RestartWindows()
3900  {
3901  ATLASSERT(::IsWindow(m_hWnd));
3902  ::SendMessage(m_hWnd, PSM_RESTARTWINDOWS, 0, 0L);
3903  }
3904 
3905  BOOL IsDialogMessage(LPMSG lpMsg)
3906  {
3907  ATLASSERT(::IsWindow(m_hWnd));
3908  return (BOOL)::SendMessage(m_hWnd, PSM_ISDIALOGMESSAGE, 0, (LPARAM)lpMsg);
3909  }
3910 
3911 #if (_WIN32_IE >= 0x0500) && !defined(_WIN32_WCE)
3912  int HwndToIndex(HWND hWnd) const
3913  {
3914  ATLASSERT(::IsWindow(m_hWnd));
3915  return (int)::SendMessage(m_hWnd, PSM_HWNDTOINDEX, (WPARAM)hWnd, 0L);
3916  }
3917 
3918  HWND IndexToHwnd(int nIndex) const
3919  {
3920  ATLASSERT(::IsWindow(m_hWnd));
3921  return (HWND)::SendMessage(m_hWnd, PSM_INDEXTOHWND, nIndex, 0L);
3922  }
3923 
3924  int PageToIndex(HPROPSHEETPAGE hPage) const
3925  {
3926  ATLASSERT(::IsWindow(m_hWnd));
3927  return (int)::SendMessage(m_hWnd, PSM_PAGETOINDEX, 0, (LPARAM)hPage);
3928  }
3929 
3930  HPROPSHEETPAGE IndexToPage(int nIndex) const
3931  {
3932  ATLASSERT(::IsWindow(m_hWnd));
3933  return (HPROPSHEETPAGE)::SendMessage(m_hWnd, PSM_INDEXTOPAGE, nIndex, 0L);
3934  }
3935 
3936  int IdToIndex(int nID) const
3937  {
3938  ATLASSERT(::IsWindow(m_hWnd));
3939  return (int)::SendMessage(m_hWnd, PSM_IDTOINDEX, 0, nID);
3940  }
3941 
3942  int IndexToId(int nIndex) const
3943  {
3944  ATLASSERT(::IsWindow(m_hWnd));
3945  return (int)::SendMessage(m_hWnd, PSM_INDEXTOID, nIndex, 0L);
3946  }
3947 
3948  int GetResult() const
3949  {
3950  ATLASSERT(::IsWindow(m_hWnd));
3951  return (int)::SendMessage(m_hWnd, PSM_GETRESULT, 0, 0L);
3952  }
3953 
3954  BOOL RecalcPageSizes()
3955  {
3956  ATLASSERT(::IsWindow(m_hWnd));
3957  return (BOOL)::SendMessage(m_hWnd, PSM_RECALCPAGESIZES, 0, 0L);
3958  }
3959 
3960  void SetHeaderTitle(int nIndex, LPCTSTR lpstrHeaderTitle)
3961  {
3962  ATLASSERT(::IsWindow(m_hWnd));
3963  ::SendMessage(m_hWnd, PSM_SETHEADERTITLE, nIndex, (LPARAM)lpstrHeaderTitle);
3964  }
3965 
3966  void SetHeaderSubTitle(int nIndex, LPCTSTR lpstrHeaderSubTitle)
3967  {
3968  ATLASSERT(::IsWindow(m_hWnd));
3969  ::SendMessage(m_hWnd, PSM_SETHEADERSUBTITLE, nIndex, (LPARAM)lpstrHeaderSubTitle);
3970  }
3971 #endif // (_WIN32_IE >= 0x0500) && !defined(_WIN32_WCE)
3972 
3973 // Implementation - override to prevent usage
3974  HWND Create(LPCTSTR, HWND, ATL::_U_RECT = NULL, LPCTSTR = NULL, DWORD = 0, DWORD = 0, ATL::_U_MENUorID = 0U, LPVOID = NULL)
3975  {
3976  ATLASSERT(FALSE);
3977  return NULL;
3978  }
3979 };
3980 
3982 // CPropertySheetImpl - implements a property sheet
3983 
3984 template <class T, class TBase = CPropertySheetWindow>
3985 class ATL_NO_VTABLE CPropertySheetImpl : public ATL::CWindowImplBaseT< TBase >
3986 {
3987 public:
3988  PROPSHEETHEADER m_psh;
3989  ATL::CSimpleArray<HPROPSHEETPAGE> m_arrPages;
3990 
3991 #if defined(_AYGSHELL_H_) || defined(__AYGSHELL_H__) // PPC specific
3992  #ifndef PROPSHEET_LINK_SIZE
3993  #define PROPSHEET_LINK_SIZE 128
3994  #endif // PROPSHEET_LINK_SIZE
3995  TCHAR m_szLink[PROPSHEET_LINK_SIZE];
3996  static LPCTSTR m_pszTitle;
3997  static LPCTSTR m_pszLink;
3998 #endif // defined(_AYGSHELL_H_) || defined(__AYGSHELL_H__)
3999 
4000 // Construction/Destruction
4001  CPropertySheetImpl(ATL::_U_STRINGorID title = (LPCTSTR)NULL, UINT uStartPage = 0, HWND hWndParent = NULL)
4002  {
4003  memset(&m_psh, 0, sizeof(PROPSHEETHEADER));
4004  m_psh.dwSize = sizeof(PROPSHEETHEADER);
4005  m_psh.dwFlags = PSH_USECALLBACK;
4006  m_psh.hInstance = ModuleHelper::GetResourceInstance();
4007  m_psh.phpage = NULL; // will be set later
4008  m_psh.nPages = 0; // will be set later
4009  m_psh.pszCaption = title.m_lpstr;
4010  m_psh.nStartPage = uStartPage;
4011  m_psh.hwndParent = hWndParent; // if NULL, will be set in DoModal/Create
4012  m_psh.pfnCallback = T::PropSheetCallback;
4013 
4014 #if defined(_AYGSHELL_H_) || defined(__AYGSHELL_H__) // PPC specific
4015  m_psh.dwFlags |= PSH_MAXIMIZE;
4016  m_szLink[0] = 0;
4017 #endif // defined(_AYGSHELL_H_) || defined(__AYGSHELL_H__)
4018  }
4019 
4021  {
4022  if(m_arrPages.GetSize() > 0) // sheet never created, destroy all pages
4023  {
4024  for(int i = 0; i < m_arrPages.GetSize(); i++)
4025  ::DestroyPropertySheetPage((HPROPSHEETPAGE)m_arrPages[i]);
4026  }
4027  }
4028 
4029 // Callback function and overrideables
4030  static int CALLBACK PropSheetCallback(HWND hWnd, UINT uMsg, LPARAM lParam)
4031  {
4032  lParam; // avoid level 4 warning
4033  int nRet = 0;
4034 
4035  if(uMsg == PSCB_INITIALIZED)
4036  {
4037  ATLASSERT(hWnd != NULL);
4038  T* pT = (T*)ModuleHelper::ExtractCreateWndData();
4039  // subclass the sheet window
4040  pT->SubclassWindow(hWnd);
4041  // remove page handles array
4042  pT->_CleanUpPages();
4043 
4044 #if defined(_AYGSHELL_H_) || defined(__AYGSHELL_H__) // PPC specific
4045  m_pszTitle = pT->m_psh.pszCaption;
4046  if(*pT->m_szLink != 0)
4047  m_pszLink = pT->m_szLink;
4048 #endif // defined(_AYGSHELL_H_) || defined(__AYGSHELL_H__) // PPC specific
4049 
4050  pT->OnSheetInitialized();
4051  }
4052 #if defined(_AYGSHELL_H_) || defined(__AYGSHELL_H__) // PPC specific uMsg
4053  else
4054  {
4055  switch(uMsg)
4056  {
4057  case PSCB_GETVERSION :
4058  nRet = COMCTL32_VERSION;
4059  break;
4060  case PSCB_GETTITLE :
4061  if(m_pszTitle != NULL)
4062  {
4063  lstrcpy((LPTSTR)lParam, m_pszTitle);
4064  m_pszTitle = NULL;
4065  }
4066  break;
4067  case PSCB_GETLINKTEXT:
4068  if(m_pszLink != NULL)
4069  {
4070  lstrcpy((LPTSTR)lParam, m_pszLink);
4071  m_pszLink = NULL;
4072  }
4073  break;
4074  default:
4075  break;
4076  }
4077  }
4078 #endif // defined(_AYGSHELL_H_) || defined(__AYGSHELL_H__)
4079 
4080  return nRet;
4081  }
4082 
4083  void OnSheetInitialized()
4084  {
4085  }
4086 
4087 // Create method
4088  HWND Create(HWND hWndParent = NULL)
4089  {
4090  ATLASSERT(m_hWnd == NULL);
4091 
4092  m_psh.dwFlags |= PSH_MODELESS;
4093  if(m_psh.hwndParent == NULL)
4094  m_psh.hwndParent = hWndParent;
4095  m_psh.phpage = (HPROPSHEETPAGE*)m_arrPages.GetData();
4096  m_psh.nPages = m_arrPages.GetSize();
4097 
4098  T* pT = static_cast<T*>(this);
4099 
4100 #if (_ATL_VER >= 0x0800)
4101  // Allocate the thunk structure here, where we can fail gracefully.
4102  BOOL bRet = pT->m_thunk.Init(NULL, NULL);
4103  if(bRet == FALSE)
4104  {
4105  ::SetLastError(ERROR_OUTOFMEMORY);
4106  return NULL;
4107  }
4108 #endif // (_ATL_VER >= 0x0800)
4109 
4110  ModuleHelper::AddCreateWndData(&pT->m_thunk.cd, pT);
4111 
4112  HWND hWnd = (HWND)::PropertySheet(&m_psh);
4113  _CleanUpPages(); // ensure clean-up, required if call failed
4114 
4115  ATLASSERT(m_hWnd == hWnd);
4116 
4117  return hWnd;
4118  }
4119 
4120  INT_PTR DoModal(HWND hWndParent = ::GetActiveWindow())
4121  {
4122  ATLASSERT(m_hWnd == NULL);
4123 
4124  m_psh.dwFlags &= ~PSH_MODELESS;
4125  if(m_psh.hwndParent == NULL)
4126  m_psh.hwndParent = hWndParent;
4127  m_psh.phpage = (HPROPSHEETPAGE*)m_arrPages.GetData();
4128  m_psh.nPages = m_arrPages.GetSize();
4129 
4130  T* pT = static_cast<T*>(this);
4131 
4132 #if (_ATL_VER >= 0x0800)
4133  // Allocate the thunk structure here, where we can fail gracefully.
4134  BOOL bRet = pT->m_thunk.Init(NULL, NULL);
4135  if(bRet == FALSE)
4136  {
4137  ::SetLastError(ERROR_OUTOFMEMORY);
4138  return -1;
4139  }
4140 #endif // (_ATL_VER >= 0x0800)
4141 
4142  ModuleHelper::AddCreateWndData(&pT->m_thunk.cd, pT);
4143 
4144  INT_PTR nRet = ::PropertySheet(&m_psh);
4145  _CleanUpPages(); // ensure clean-up, required if call failed
4146 
4147  return nRet;
4148  }
4149 
4150  // implementation helper - clean up pages array
4151  void _CleanUpPages()
4152  {
4153  m_psh.nPages = 0;
4154  m_psh.phpage = NULL;
4155  m_arrPages.RemoveAll();
4156  }
4157 
4158 // Attributes (extended overrides of client class methods)
4159 // These now can be called before the sheet is created
4160 // Note: Calling these after the sheet is created gives unpredictable results
4161  int GetPageCount() const
4162  {
4163  if(m_hWnd == NULL) // not created yet
4164  return m_arrPages.GetSize();
4165  return TBase::GetPageCount();
4166  }
4167 
4168  int GetActiveIndex() const
4169  {
4170  if(m_hWnd == NULL) // not created yet
4171  return m_psh.nStartPage;
4172  return TBase::GetActiveIndex();
4173  }
4174 
4175  HPROPSHEETPAGE GetPage(int nPageIndex) const
4176  {
4177  ATLASSERT(m_hWnd == NULL); // can't do this after it's created
4178  return (HPROPSHEETPAGE)m_arrPages[nPageIndex];
4179  }
4180 
4181  int GetPageIndex(HPROPSHEETPAGE hPage) const
4182  {
4183  ATLASSERT(m_hWnd == NULL); // can't do this after it's created
4184  return m_arrPages.Find((HPROPSHEETPAGE&)hPage);
4185  }
4186 
4187  BOOL SetActivePage(int nPageIndex)
4188  {
4189  if(m_hWnd == NULL) // not created yet
4190  {
4191  ATLASSERT(nPageIndex >= 0 && nPageIndex < m_arrPages.GetSize());
4192  m_psh.nStartPage = nPageIndex;
4193  return TRUE;
4194  }
4195  return TBase::SetActivePage(nPageIndex);
4196  }
4197 
4198  BOOL SetActivePage(HPROPSHEETPAGE hPage)
4199  {
4200  ATLASSERT(hPage != NULL);
4201  if (m_hWnd == NULL) // not created yet
4202  {
4203  int nPageIndex = GetPageIndex(hPage);
4204  if(nPageIndex == -1)
4205  return FALSE;
4206 
4207  return SetActivePage(nPageIndex);
4208  }
4209  return TBase::SetActivePage(hPage);
4210 
4211  }
4212 
4213  void SetTitle(LPCTSTR lpszText, UINT nStyle = 0)
4214  {
4215  ATLASSERT((nStyle & ~PSH_PROPTITLE) == 0); // only PSH_PROPTITLE is valid
4216  ATLASSERT(lpszText != NULL);
4217 
4218  if(m_hWnd == NULL)
4219  {
4220  // set internal state
4221  m_psh.pszCaption = lpszText; // must exist until sheet is created
4222  m_psh.dwFlags &= ~PSH_PROPTITLE;
4223  m_psh.dwFlags |= nStyle;
4224  }
4225  else
4226  {
4227  // set external state
4228  TBase::SetTitle(lpszText, nStyle);
4229  }
4230  }
4231 
4232 #if defined(_AYGSHELL_H_) || defined(__AYGSHELL_H__) // PPC specific Link field
4233  void SetLinkText(LPCTSTR lpszText)
4234  {
4235  ATLASSERT(lpszText != NULL);
4236  ATLASSERT(lstrlen(lpszText) < PROPSHEET_LINK_SIZE);
4237  lstrcpy(m_szLink, lpszText);
4238  }
4239 #endif // defined(_AYGSHELL_H_) || defined(__AYGSHELL_H__)
4240 
4241  void SetWizardMode()
4242  {
4243  m_psh.dwFlags |= PSH_WIZARD;
4244  }
4245 
4246  void EnableHelp()
4247  {
4248  m_psh.dwFlags |= PSH_HASHELP;
4249  }
4250 
4251 // Operations
4252  BOOL AddPage(HPROPSHEETPAGE hPage)
4253  {
4254  ATLASSERT(hPage != NULL);
4255  BOOL bRet = FALSE;
4256  if(m_hWnd != NULL)
4257  bRet = TBase::AddPage(hPage);
4258  else // sheet not created yet, use internal data
4259  bRet = m_arrPages.Add((HPROPSHEETPAGE&)hPage);
4260  return bRet;
4261  }
4262 
4263  BOOL AddPage(LPCPROPSHEETPAGE pPage)
4264  {
4265  ATLASSERT(pPage != NULL);
4266  HPROPSHEETPAGE hPage = ::CreatePropertySheetPage(pPage);
4267  if(hPage == NULL)
4268  return FALSE;
4269  BOOL bRet = AddPage(hPage);
4270  if(!bRet)
4271  ::DestroyPropertySheetPage(hPage);
4272  return bRet;
4273  }
4274 
4275  BOOL RemovePage(HPROPSHEETPAGE hPage)
4276  {
4277  ATLASSERT(hPage != NULL);
4278  if (m_hWnd == NULL) // not created yet
4279  {
4280  int nPage = GetPageIndex(hPage);
4281  if(nPage == -1)
4282  return FALSE;
4283  return RemovePage(nPage);
4284  }
4285  TBase::RemovePage(hPage);
4286  return TRUE;
4287 
4288  }
4289 
4290  BOOL RemovePage(int nPageIndex)
4291  {
4292  BOOL bRet = TRUE;
4293  if(m_hWnd != NULL)
4294  TBase::RemovePage(nPageIndex);
4295  else // sheet not created yet, use internal data
4296  bRet = m_arrPages.RemoveAt(nPageIndex);
4297  return bRet;
4298  }
4299 
4300 #if (_WIN32_IE >= 0x0400) && !defined(_WIN32_WCE)
4301  void SetHeader(LPCTSTR szbmHeader)
4302  {
4303  ATLASSERT(m_hWnd == NULL); // can't do this after it's created
4304 
4305  m_psh.dwFlags &= ~PSH_WIZARD;
4306  m_psh.dwFlags |= (PSH_HEADER | PSH_WIZARD97);
4307  m_psh.pszbmHeader = szbmHeader;
4308  }
4309 
4310  void SetHeader(HBITMAP hbmHeader)
4311  {
4312  ATLASSERT(m_hWnd == NULL); // can't do this after it's created
4313 
4314  m_psh.dwFlags &= ~PSH_WIZARD;
4315  m_psh.dwFlags |= (PSH_HEADER | PSH_USEHBMHEADER | PSH_WIZARD97);
4316  m_psh.hbmHeader = hbmHeader;
4317  }
4318 
4319  void SetWatermark(LPCTSTR szbmWatermark, HPALETTE hplWatermark = NULL)
4320  {
4321  ATLASSERT(m_hWnd == NULL); // can't do this after it's created
4322 
4323  m_psh.dwFlags &= ~PSH_WIZARD;
4324  m_psh.dwFlags |= PSH_WATERMARK | PSH_WIZARD97;
4325  m_psh.pszbmWatermark = szbmWatermark;
4326 
4327  if (hplWatermark != NULL)
4328  {
4329  m_psh.dwFlags |= PSH_USEHPLWATERMARK;
4330  m_psh.hplWatermark = hplWatermark;
4331  }
4332  }
4333 
4334  void SetWatermark(HBITMAP hbmWatermark, HPALETTE hplWatermark = NULL)
4335  {
4336  ATLASSERT(m_hWnd == NULL); // can't do this after it's created
4337 
4338  m_psh.dwFlags &= ~PSH_WIZARD;
4339  m_psh.dwFlags |= (PSH_WATERMARK | PSH_USEHBMWATERMARK | PSH_WIZARD97);
4340  m_psh.hbmWatermark = hbmWatermark;
4341 
4342  if (hplWatermark != NULL)
4343  {
4344  m_psh.dwFlags |= PSH_USEHPLWATERMARK;
4345  m_psh.hplWatermark = hplWatermark;
4346  }
4347  }
4348 
4349  void StretchWatermark(bool bStretchWatermark)
4350  {
4351  ATLASSERT(m_hWnd == NULL); // can't do this after it's created
4352  if (bStretchWatermark)
4353  m_psh.dwFlags |= PSH_STRETCHWATERMARK;
4354  else
4355  m_psh.dwFlags &= ~PSH_STRETCHWATERMARK;
4356  }
4357 #endif // (_WIN32_IE >= 0x0400) && !defined(_WIN32_WCE)
4358 
4359 // Message map and handlers
4360  BEGIN_MSG_MAP(CPropertySheetImpl)
4361  MESSAGE_HANDLER(WM_COMMAND, OnCommand)
4362  MESSAGE_HANDLER(WM_SYSCOMMAND, OnSysCommand)
4363  END_MSG_MAP()
4364 
4365  LRESULT OnCommand(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& /*bHandled*/)
4366  {
4367  LRESULT lRet = DefWindowProc(uMsg, wParam, lParam);
4368  if(HIWORD(wParam) == BN_CLICKED && (LOWORD(wParam) == IDOK || LOWORD(wParam) == IDCANCEL) &&
4369  ((m_psh.dwFlags & PSH_MODELESS) != 0) && (GetActivePage() == NULL))
4370  DestroyWindow();
4371  return lRet;
4372  }
4373 
4374  LRESULT OnSysCommand(UINT /*uMsg*/, WPARAM wParam, LPARAM /*lParam*/, BOOL& bHandled)
4375  {
4376  if(((m_psh.dwFlags & PSH_MODELESS) == PSH_MODELESS) && ((wParam & 0xFFF0) == SC_CLOSE))
4377  SendMessage(WM_CLOSE);
4378  else
4379  bHandled = FALSE;
4380  return 0;
4381  }
4382 };
4383 
4384 #if defined(_AYGSHELL_H_) || defined(__AYGSHELL_H__) // PPC static pointers
4385 template < class T, class TBase >
4387 template < class T, class TBase>
4389 #endif // defined(_AYGSHELL_H_) || defined(__AYGSHELL_H__)
4390 
4391 // for non-customized sheets
4392 class CPropertySheet : public CPropertySheetImpl<CPropertySheet>
4393 {
4394 public:
4395  CPropertySheet(ATL::_U_STRINGorID title = (LPCTSTR)NULL, UINT uStartPage = 0, HWND hWndParent = NULL)
4396  : CPropertySheetImpl<CPropertySheet>(title, uStartPage, hWndParent)
4397  { }
4398 };
4399 
4400 
4402 // CPropertyPageWindow - client side for a property page
4403 
4404 class CPropertyPageWindow : public ATL::CWindow
4405 {
4406 public:
4407 // Constructors
4408  CPropertyPageWindow(HWND hWnd = NULL) : ATL::CWindow(hWnd)
4409  { }
4410 
4411  CPropertyPageWindow& operator =(HWND hWnd)
4412  {
4413  m_hWnd = hWnd;
4414  return *this;
4415  }
4416 
4417 // Attributes
4418  CPropertySheetWindow GetPropertySheet() const
4419  {
4420  ATLASSERT(::IsWindow(m_hWnd));
4421  return CPropertySheetWindow(GetParent());
4422  }
4423 
4424 // Operations
4425  BOOL Apply()
4426  {
4427  ATLASSERT(::IsWindow(m_hWnd));
4428  ATLASSERT(GetParent() != NULL);
4429  return GetPropertySheet().Apply();
4430  }
4431 
4432  void CancelToClose()
4433  {
4434  ATLASSERT(::IsWindow(m_hWnd));
4435  ATLASSERT(GetParent() != NULL);
4436  GetPropertySheet().CancelToClose();
4437  }
4438 
4439  void SetModified(BOOL bChanged = TRUE)
4440  {
4441  ATLASSERT(::IsWindow(m_hWnd));
4442  ATLASSERT(GetParent() != NULL);
4443  GetPropertySheet().SetModified(m_hWnd, bChanged);
4444  }
4445 
4446  LRESULT QuerySiblings(WPARAM wParam, LPARAM lParam)
4447  {
4448  ATLASSERT(::IsWindow(m_hWnd));
4449  ATLASSERT(GetParent() != NULL);
4450  return GetPropertySheet().QuerySiblings(wParam, lParam);
4451  }
4452 
4453  void RebootSystem()
4454  {
4455  ATLASSERT(::IsWindow(m_hWnd));
4456  ATLASSERT(GetParent() != NULL);
4457  GetPropertySheet().RebootSystem();
4458  }
4459 
4460  void RestartWindows()
4461  {
4462  ATLASSERT(::IsWindow(m_hWnd));
4463  ATLASSERT(GetParent() != NULL);
4464  GetPropertySheet().RestartWindows();
4465  }
4466 
4467  void SetWizardButtons(DWORD dwFlags)
4468  {
4469  ATLASSERT(::IsWindow(m_hWnd));
4470  ATLASSERT(GetParent() != NULL);
4471  GetPropertySheet().SetWizardButtons(dwFlags);
4472  }
4473 
4474 // Implementation - overrides to prevent usage
4475  HWND Create(LPCTSTR, HWND, ATL::_U_RECT = NULL, LPCTSTR = NULL, DWORD = 0, DWORD = 0, ATL::_U_MENUorID = 0U, LPVOID = NULL)
4476  {
4477  ATLASSERT(FALSE);
4478  return NULL;
4479  }
4480 };
4481 
4483 // CPropertyPageImpl - implements a property page
4484 
4485 template <class T, class TBase = CPropertyPageWindow>
4486 class ATL_NO_VTABLE CPropertyPageImpl : public ATL::CDialogImplBaseT< TBase >
4487 {
4488 public:
4489  PROPSHEETPAGE m_psp;
4490 
4491  operator PROPSHEETPAGE*() { return &m_psp; }
4492 
4493 // Construction
4494  CPropertyPageImpl(ATL::_U_STRINGorID title = (LPCTSTR)NULL)
4495  {
4496  // initialize PROPSHEETPAGE struct
4497  memset(&m_psp, 0, sizeof(PROPSHEETPAGE));
4498  m_psp.dwSize = sizeof(PROPSHEETPAGE);
4499  m_psp.dwFlags = PSP_USECALLBACK;
4500  m_psp.hInstance = ModuleHelper::GetResourceInstance();
4501  T* pT = static_cast<T*>(this);
4502  m_psp.pszTemplate = MAKEINTRESOURCE(pT->IDD);
4503  m_psp.pfnDlgProc = (DLGPROC)T::StartDialogProc;
4504  m_psp.pfnCallback = T::PropPageCallback;
4505  m_psp.lParam = (LPARAM)pT;
4506 
4507  if(title.m_lpstr != NULL)
4508  SetTitle(title);
4509  }
4510 
4511 // Callback function and overrideables
4512  static UINT CALLBACK PropPageCallback(HWND hWnd, UINT uMsg, LPPROPSHEETPAGE ppsp)
4513  {
4514  hWnd; // avoid level 4 warning
4515  ATLASSERT(hWnd == NULL);
4516  T* pT = (T*)ppsp->lParam;
4517  UINT uRet = 0;
4518 
4519  switch(uMsg)
4520  {
4521  case PSPCB_CREATE:
4522  {
4523  ATL::CDialogImplBaseT< TBase >* pPage = (ATL::CDialogImplBaseT< TBase >*)pT;
4524  ModuleHelper::AddCreateWndData(&pPage->m_thunk.cd, pPage);
4525  uRet = pT->OnPageCreate() ? 1 : 0;
4526  }
4527  break;
4528 #if (_WIN32_IE >= 0x0500)
4529  case PSPCB_ADDREF:
4530  pT->OnPageAddRef();
4531  break;
4532 #endif // (_WIN32_IE >= 0x0500)
4533  case PSPCB_RELEASE:
4534  pT->OnPageRelease();
4535  break;
4536  default:
4537  break;
4538  }
4539 
4540  return uRet;
4541  }
4542 
4543  bool OnPageCreate()
4544  {
4545  return true; // true - allow page to be created, false - prevent creation
4546  }
4547 
4548 #if (_WIN32_IE >= 0x0500)
4549  void OnPageAddRef()
4550  {
4551  }
4552 #endif // (_WIN32_IE >= 0x0500)
4553 
4554  void OnPageRelease()
4555  {
4556  }
4557 
4558 // Create method
4559  HPROPSHEETPAGE Create()
4560  {
4561  return ::CreatePropertySheetPage(&m_psp);
4562  }
4563 
4564 // Attributes
4565  void SetTitle(ATL::_U_STRINGorID title)
4566  {
4567  m_psp.pszTitle = title.m_lpstr;
4568  m_psp.dwFlags |= PSP_USETITLE;
4569  }
4570 
4571 #if (_WIN32_IE >= 0x0500) && !defined(_WIN32_WCE)
4572  void SetHeaderTitle(LPCTSTR lpstrHeaderTitle)
4573  {
4574  ATLASSERT(m_hWnd == NULL); // can't do this after it's created
4575  m_psp.dwFlags |= PSP_USEHEADERTITLE;
4576  m_psp.pszHeaderTitle = lpstrHeaderTitle;
4577  }
4578 
4579  void SetHeaderSubTitle(LPCTSTR lpstrHeaderSubTitle)
4580  {
4581  ATLASSERT(m_hWnd == NULL); // can't do this after it's created
4582  m_psp.dwFlags |= PSP_USEHEADERSUBTITLE;
4583  m_psp.pszHeaderSubTitle = lpstrHeaderSubTitle;
4584  }
4585 #endif // (_WIN32_IE >= 0x0500) && !defined(_WIN32_WCE)
4586 
4587 // Operations
4588  void EnableHelp()
4589  {
4590  m_psp.dwFlags |= PSP_HASHELP;
4591  }
4592 
4593 // Message map and handlers
4594  BEGIN_MSG_MAP(CPropertyPageImpl)
4595  MESSAGE_HANDLER(WM_NOTIFY, OnNotify)
4596  END_MSG_MAP()
4597 
4598  // NOTE: Define _WTL_NEW_PAGE_NOTIFY_HANDLERS to use new notification
4599  // handlers that return direct values without any restrictions
4600  LRESULT OnNotify(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM lParam, BOOL& bHandled)
4601  {
4602 #ifndef _WIN32_WCE
4603  // This notification is sometimes received on Windows CE after the window is already destroyed
4604  ATLASSERT(::IsWindow(m_hWnd));
4605 #endif
4606  NMHDR* pNMHDR = (NMHDR*)lParam;
4607 
4608  // don't handle messages not from the page/sheet itself
4609  if(pNMHDR->hwndFrom != m_hWnd && pNMHDR->hwndFrom != ::GetParent(m_hWnd))
4610  {
4611  bHandled = FALSE;
4612  return 1;
4613  }
4614 #ifdef _WIN32_WCE
4615  ATLASSERT(::IsWindow(m_hWnd));
4616 #endif
4617 
4618  T* pT = static_cast<T*>(this);
4619  LRESULT lResult = 0;
4620  switch(pNMHDR->code)
4621  {
4622 #ifdef _WTL_NEW_PAGE_NOTIFY_HANDLERS
4623  case PSN_SETACTIVE:
4624  lResult = pT->OnSetActive();
4625  break;
4626  case PSN_KILLACTIVE:
4627  lResult = pT->OnKillActive();
4628  break;
4629  case PSN_APPLY:
4630  lResult = pT->OnApply();
4631  break;
4632  case PSN_RESET:
4633  pT->OnReset();
4634  break;
4635  case PSN_QUERYCANCEL:
4636  lResult = pT->OnQueryCancel();
4637  break;
4638  case PSN_WIZNEXT:
4639  lResult = pT->OnWizardNext();
4640  break;
4641  case PSN_WIZBACK:
4642  lResult = pT->OnWizardBack();
4643  break;
4644  case PSN_WIZFINISH:
4645  lResult = pT->OnWizardFinish();
4646  break;
4647  case PSN_HELP:
4648  pT->OnHelp();
4649  break;
4650 #ifndef _WIN32_WCE
4651 #if (_WIN32_IE >= 0x0400)
4652  case PSN_GETOBJECT:
4653  if(!pT->OnGetObject((LPNMOBJECTNOTIFY)lParam))
4654  bHandled = FALSE;
4655  break;
4656 #endif // (_WIN32_IE >= 0x0400)
4657 #if (_WIN32_IE >= 0x0500)
4658  case PSN_TRANSLATEACCELERATOR:
4659  {
4660  LPPSHNOTIFY lpPSHNotify = (LPPSHNOTIFY)lParam;
4661  lResult = pT->OnTranslateAccelerator((LPMSG)lpPSHNotify->lParam);
4662  }
4663  break;
4664  case PSN_QUERYINITIALFOCUS:
4665  {
4666  LPPSHNOTIFY lpPSHNotify = (LPPSHNOTIFY)lParam;
4667  lResult = (LRESULT)pT->OnQueryInitialFocus((HWND)lpPSHNotify->lParam);
4668  }
4669  break;
4670 #endif // (_WIN32_IE >= 0x0500)
4671 #endif // !_WIN32_WCE
4672 
4673 #else // !_WTL_NEW_PAGE_NOTIFY_HANDLERS
4674  case PSN_SETACTIVE:
4675  lResult = pT->OnSetActive() ? 0 : -1;
4676  break;
4677  case PSN_KILLACTIVE:
4678  lResult = !pT->OnKillActive();
4679  break;
4680  case PSN_APPLY:
4681  lResult = pT->OnApply() ? PSNRET_NOERROR : PSNRET_INVALID_NOCHANGEPAGE;
4682  break;
4683  case PSN_RESET:
4684  pT->OnReset();
4685  break;
4686  case PSN_QUERYCANCEL:
4687  lResult = !pT->OnQueryCancel();
4688  break;
4689  case PSN_WIZNEXT:
4690  lResult = pT->OnWizardNext();
4691  break;
4692  case PSN_WIZBACK:
4693  lResult = pT->OnWizardBack();
4694  break;
4695  case PSN_WIZFINISH:
4696  lResult = !pT->OnWizardFinish();
4697  break;
4698  case PSN_HELP:
4699  pT->OnHelp();
4700  break;
4701 #ifndef _WIN32_WCE
4702 #if (_WIN32_IE >= 0x0400)
4703  case PSN_GETOBJECT:
4704  if(!pT->OnGetObject((LPNMOBJECTNOTIFY)lParam))
4705  bHandled = FALSE;
4706  break;
4707 #endif // (_WIN32_IE >= 0x0400)
4708 #if (_WIN32_IE >= 0x0500)
4709  case PSN_TRANSLATEACCELERATOR:
4710  {
4711  LPPSHNOTIFY lpPSHNotify = (LPPSHNOTIFY)lParam;
4712  lResult = pT->OnTranslateAccelerator((LPMSG)lpPSHNotify->lParam) ? PSNRET_MESSAGEHANDLED : PSNRET_NOERROR;
4713  }
4714  break;
4715  case PSN_QUERYINITIALFOCUS:
4716  {
4717  LPPSHNOTIFY lpPSHNotify = (LPPSHNOTIFY)lParam;
4718  lResult = (LRESULT)pT->OnQueryInitialFocus((HWND)lpPSHNotify->lParam);
4719  }
4720  break;
4721 #endif // (_WIN32_IE >= 0x0500)
4722 #endif // !_WIN32_WCE
4723 
4724 #endif // !_WTL_NEW_PAGE_NOTIFY_HANDLERS
4725  default:
4726  bHandled = FALSE; // not handled
4727  }
4728 
4729  return lResult;
4730  }
4731 
4732 // Overridables
4733  // NOTE: Define _WTL_NEW_PAGE_NOTIFY_HANDLERS to use new notification
4734  // handlers that return direct values without any restrictions
4735 #ifdef _WTL_NEW_PAGE_NOTIFY_HANDLERS
4736  int OnSetActive()
4737  {
4738  // 0 = allow activate
4739  // -1 = go back that was active
4740  // page ID = jump to page
4741  return 0;
4742  }
4743 
4744  BOOL OnKillActive()
4745  {
4746  // FALSE = allow deactivate
4747  // TRUE = prevent deactivation
4748  return FALSE;
4749  }
4750 
4751  int OnApply()
4752  {
4753  // PSNRET_NOERROR = apply OK
4754  // PSNRET_INVALID = apply not OK, return to this page
4755  // PSNRET_INVALID_NOCHANGEPAGE = apply not OK, don't change focus
4756  return PSNRET_NOERROR;
4757  }
4758 
4759  void OnReset()
4760  {
4761  }
4762 
4763  BOOL OnQueryCancel()
4764  {
4765  // FALSE = allow cancel
4766  // TRUE = prevent cancel
4767  return FALSE;
4768  }
4769 
4770  int OnWizardBack()
4771  {
4772  // 0 = goto previous page
4773  // -1 = prevent page change
4774  // >0 = jump to page by dlg ID
4775  return 0;
4776  }
4777 
4778  int OnWizardNext()
4779  {
4780  // 0 = goto next page
4781  // -1 = prevent page change
4782  // >0 = jump to page by dlg ID
4783  return 0;
4784  }
4785 
4786  INT_PTR OnWizardFinish()
4787  {
4788  // FALSE = allow finish
4789  // TRUE = prevent finish
4790  // HWND = prevent finish and set focus to HWND (CommCtrl 5.80 only)
4791  return FALSE;
4792  }
4793 
4794  void OnHelp()
4795  {
4796  }
4797 
4798 #ifndef _WIN32_WCE
4799 #if (_WIN32_IE >= 0x0400)
4800  BOOL OnGetObject(LPNMOBJECTNOTIFY /*lpObjectNotify*/)
4801  {
4802  return FALSE; // not processed
4803  }
4804 #endif // (_WIN32_IE >= 0x0400)
4805 
4806 #if (_WIN32_IE >= 0x0500)
4807  int OnTranslateAccelerator(LPMSG /*lpMsg*/)
4808  {
4809  // PSNRET_NOERROR - message not handled
4810  // PSNRET_MESSAGEHANDLED - message handled
4811  return PSNRET_NOERROR;
4812  }
4813 
4814  HWND OnQueryInitialFocus(HWND /*hWndFocus*/)
4815  {
4816  // NULL = set focus to default control
4817  // HWND = set focus to HWND
4818  return NULL;
4819  }
4820 #endif // (_WIN32_IE >= 0x0500)
4821 #endif // !_WIN32_WCE
4822 
4823 #else // !_WTL_NEW_PAGE_NOTIFY_HANDLERS
4824  BOOL OnSetActive()
4825  {
4826  return TRUE;
4827  }
4828 
4829  BOOL OnKillActive()
4830  {
4831  return TRUE;
4832  }
4833 
4834  BOOL OnApply()
4835  {
4836  return TRUE;
4837  }
4838 
4839  void OnReset()
4840  {
4841  }
4842 
4843  BOOL OnQueryCancel()
4844  {
4845  return TRUE; // ok to cancel
4846  }
4847 
4848  int OnWizardBack()
4849  {
4850  // 0 = goto previous page
4851  // -1 = prevent page change
4852  // >0 = jump to page by dlg ID
4853  return 0;
4854  }
4855 
4856  int OnWizardNext()
4857  {
4858  // 0 = goto next page
4859  // -1 = prevent page change
4860  // >0 = jump to page by dlg ID
4861  return 0;
4862  }
4863 
4864  BOOL OnWizardFinish()
4865  {
4866  return TRUE;
4867  }
4868 
4869  void OnHelp()
4870  {
4871  }
4872 
4873 #ifndef _WIN32_WCE
4874 #if (_WIN32_IE >= 0x0400)
4875  BOOL OnGetObject(LPNMOBJECTNOTIFY /*lpObjectNotify*/)
4876  {
4877  return FALSE; // not processed
4878  }
4879 #endif // (_WIN32_IE >= 0x0400)
4880 
4881 #if (_WIN32_IE >= 0x0500)
4882  BOOL OnTranslateAccelerator(LPMSG /*lpMsg*/)
4883  {
4884  return FALSE; // not translated
4885  }
4886 
4887  HWND OnQueryInitialFocus(HWND /*hWndFocus*/)
4888  {
4889  return NULL; // default
4890  }
4891 #endif // (_WIN32_IE >= 0x0500)
4892 #endif // !_WIN32_WCE
4893 
4894 #endif // !_WTL_NEW_PAGE_NOTIFY_HANDLERS
4895 };
4896 
4897 // for non-customized pages
4898 template <WORD t_wDlgTemplateID>
4899 class CPropertyPage : public CPropertyPageImpl<CPropertyPage<t_wDlgTemplateID> >
4900 {
4901 public:
4902  enum { IDD = t_wDlgTemplateID };
4903 
4904  CPropertyPage(ATL::_U_STRINGorID title = (LPCTSTR)NULL) : CPropertyPageImpl<CPropertyPage>(title)
4905  { }
4906 
4907  DECLARE_EMPTY_MSG_MAP()
4908 };
4909 
4911 // CAxPropertyPageImpl - property page that hosts ActiveX controls
4912 
4913 #ifndef _ATL_NO_HOSTING
4914 
4915 // Note: You must #include <atlhost.h> to use these classes
4916 
4917 template <class T, class TBase = CPropertyPageWindow>
4918 class ATL_NO_VTABLE CAxPropertyPageImpl : public CPropertyPageImpl< T, TBase >
4919 {
4920 public:
4921 // Data members
4922  HGLOBAL m_hInitData;
4923  HGLOBAL m_hDlgRes;
4924  HGLOBAL m_hDlgResSplit;
4925 
4926 // Constructor/destructor
4927  CAxPropertyPageImpl(ATL::_U_STRINGorID title = (LPCTSTR)NULL) :
4929  m_hInitData(NULL), m_hDlgRes(NULL), m_hDlgResSplit(NULL)
4930  {
4931  T* pT = static_cast<T*>(this);
4932  pT; // avoid level 4 warning
4933 
4934  // initialize ActiveX hosting and modify dialog template
4935  ATL::AtlAxWinInit();
4936 
4937  HINSTANCE hInstance = ModuleHelper::GetResourceInstance();
4938  LPCTSTR lpTemplateName = MAKEINTRESOURCE(pT->IDD);
4939  HRSRC hDlg = ::FindResource(hInstance, lpTemplateName, (LPTSTR)RT_DIALOG);
4940  if(hDlg != NULL)
4941  {
4942  HRSRC hDlgInit = ::FindResource(hInstance, lpTemplateName, (LPTSTR)_ATL_RT_DLGINIT);
4943 
4944  BYTE* pInitData = NULL;
4945  if(hDlgInit != NULL)
4946  {
4947  m_hInitData = ::LoadResource(hInstance, hDlgInit);
4948  pInitData = (BYTE*)::LockResource(m_hInitData);
4949  }
4950 
4951  m_hDlgRes = ::LoadResource(hInstance, hDlg);
4952  DLGTEMPLATE* pDlg = (DLGTEMPLATE*)::LockResource(m_hDlgRes);
4953  LPCDLGTEMPLATE lpDialogTemplate = ATL::_DialogSplitHelper::SplitDialogTemplate(pDlg, pInitData);
4954  if(lpDialogTemplate != pDlg)
4955  m_hDlgResSplit = GlobalHandle(lpDialogTemplate);
4956 
4957  // set up property page to use in-memory dialog template
4958  if(lpDialogTemplate != NULL)
4959  {
4960  m_psp.dwFlags |= PSP_DLGINDIRECT;
4961  m_psp.pResource = lpDialogTemplate;
4962  }
4963  else
4964  {
4965  ATLASSERT(FALSE && _T("CAxPropertyPageImpl - ActiveX initializtion failed!"));
4966  }
4967  }
4968  else
4969  {
4970  ATLASSERT(FALSE && _T("CAxPropertyPageImpl - Cannot find dialog template!"));
4971  }
4972  }
4973 
4975  {
4976  if(m_hInitData != NULL)
4977  {
4978  UnlockResource(m_hInitData);
4979  FreeResource(m_hInitData);
4980  }
4981  if(m_hDlgRes != NULL)
4982  {
4983  UnlockResource(m_hDlgRes);
4984  FreeResource(m_hDlgRes);
4985  }
4986  if(m_hDlgResSplit != NULL)
4987  {
4988  ::GlobalFree(m_hDlgResSplit);
4989  }
4990  }
4991 
4992 // Methods
4993  // call this one to handle keyboard message for ActiveX controls
4994  BOOL PreTranslateMessage(LPMSG pMsg)
4995  {
4996  if ((pMsg->message < WM_KEYFIRST || pMsg->message > WM_KEYLAST) &&
4997  (pMsg->message < WM_MOUSEFIRST || pMsg->message > WM_MOUSELAST))
4998  return FALSE;
4999  // find a direct child of the dialog from the window that has focus
5000  HWND hWndCtl = ::GetFocus();
5001  if (IsChild(hWndCtl) && ::GetParent(hWndCtl) != m_hWnd)
5002  {
5003  do
5004  {
5005  hWndCtl = ::GetParent(hWndCtl);
5006  }
5007  while (::GetParent(hWndCtl) != m_hWnd);
5008  }
5009  // give controls a chance to translate this message
5010  return (BOOL)::SendMessage(hWndCtl, WM_FORWARDMSG, 0, (LPARAM)pMsg);
5011  }
5012 
5013 // Overridables
5014 #if (_WIN32_IE >= 0x0500)
5015  // new default implementation for ActiveX hosting pages
5016 #ifdef _WTL_NEW_PAGE_NOTIFY_HANDLERS
5017  int OnTranslateAccelerator(LPMSG lpMsg)
5018  {
5019  T* pT = static_cast<T*>(this);
5020  return (pT->PreTranslateMessage(lpMsg) != FALSE) ? PSNRET_MESSAGEHANDLED : PSNRET_NOERROR;
5021  }
5022 #else // !_WTL_NEW_PAGE_NOTIFY_HANDLERS
5023  BOOL OnTranslateAccelerator(LPMSG lpMsg)
5024  {
5025  T* pT = static_cast<T*>(this);
5026  return pT->PreTranslateMessage(lpMsg);
5027  }
5028 #endif // !_WTL_NEW_PAGE_NOTIFY_HANDLERS
5029 #endif // (_WIN32_IE >= 0x0500)
5030 
5031 // Support for new stuff in ATL7
5032 #if (_ATL_VER >= 0x0700)
5033  int GetIDD()
5034  {
5035  return( static_cast<T*>(this)->IDD );
5036  }
5037 
5038  virtual DLGPROC GetDialogProc()
5039  {
5040  return DialogProc;
5041  }
5042 
5043  static INT_PTR CALLBACK DialogProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
5044  {
5046  if (uMsg == WM_INITDIALOG)
5047  {
5048  HRESULT hr;
5049  if (FAILED(hr = pThis->CreateActiveXControls(pThis->GetIDD())))
5050  {
5051  ATLASSERT(FALSE);
5052  return FALSE;
5053  }
5054  }
5055  return CPropertyPageImpl< T, TBase >::DialogProc(hWnd, uMsg, wParam, lParam);
5056  }
5057 
5058 // ActiveX controls creation
5059  virtual HRESULT CreateActiveXControls(UINT nID)
5060  {
5061  // Load dialog template and InitData
5062  HRSRC hDlgInit = ::FindResource(ATL::_AtlBaseModule.GetResourceInstance(), MAKEINTRESOURCE(nID), (LPTSTR)_ATL_RT_DLGINIT);
5063  BYTE* pInitData = NULL;
5064  HGLOBAL hData = NULL;
5065  HRESULT hr = S_OK;
5066  if (hDlgInit != NULL)
5067  {
5068  hData = ::LoadResource(ATL::_AtlBaseModule.GetResourceInstance(), hDlgInit);
5069  if (hData != NULL)
5070  pInitData = (BYTE*) ::LockResource(hData);
5071  }
5072 
5073  HRSRC hDlg = ::FindResource(ATL::_AtlBaseModule.GetResourceInstance(), MAKEINTRESOURCE(nID), (LPTSTR)RT_DIALOG);
5074  if (hDlg != NULL)
5075  {
5076  HGLOBAL hResource = ::LoadResource(ATL::_AtlBaseModule.GetResourceInstance(), hDlg);
5077  DLGTEMPLATE* pDlg = NULL;
5078  if (hResource != NULL)
5079  {
5080  pDlg = (DLGTEMPLATE*) ::LockResource(hResource);
5081  if (pDlg != NULL)
5082  {
5083  // Get first control on the template
5084  BOOL bDialogEx = ATL::_DialogSplitHelper::IsDialogEx(pDlg);
5085  WORD nItems = ATL::_DialogSplitHelper::DlgTemplateItemCount(pDlg);
5086 
5087  // Get first control on the dialog
5088  DLGITEMTEMPLATE* pItem = ATL::_DialogSplitHelper::FindFirstDlgItem(pDlg);
5089  HWND hWndPrev = GetWindow(GW_CHILD);
5090 
5091  // Create all ActiveX cotnrols in the dialog template and place them in the correct tab order (z-order)
5092  for (WORD nItem = 0; nItem < nItems; nItem++)
5093  {
5094  DWORD wID = bDialogEx ? ((ATL::_DialogSplitHelper::DLGITEMTEMPLATEEX*)pItem)->id : pItem->id;
5095  if (ATL::_DialogSplitHelper::IsActiveXControl(pItem, bDialogEx))
5096  {
5097  BYTE* pData = NULL;
5098  DWORD dwLen = ATL::_DialogSplitHelper::FindCreateData(wID, pInitData, &pData);
5099  ATL::CComPtr<IStream> spStream;
5100  if (dwLen != 0)
5101  {
5102  HGLOBAL h = GlobalAlloc(GHND, dwLen);
5103  if (h != NULL)
5104  {
5105  BYTE* pBytes = (BYTE*) GlobalLock(h);
5106  BYTE* pSource = pData;
5107  SecureHelper::memcpy_x(pBytes, dwLen, pSource, dwLen);
5108  GlobalUnlock(h);
5109  CreateStreamOnHGlobal(h, TRUE, &spStream);
5110  }
5111  else
5112  {
5113  hr = E_OUTOFMEMORY;
5114  break;
5115  }
5116  }
5117 
5118  ATL::CComBSTR bstrLicKey;
5119  hr = ATL::_DialogSplitHelper::ParseInitData(spStream, &bstrLicKey.m_str);
5120  if (SUCCEEDED(hr))
5121  {
5122  ATL::CAxWindow2 wnd;
5123  // Get control caption.
5124  LPWSTR pszClassName =
5125  bDialogEx ?
5126  (LPWSTR)(((ATL::_DialogSplitHelper::DLGITEMTEMPLATEEX*)pItem) + 1) :
5127  (LPWSTR)(pItem + 1);
5128  // Get control rect.
5129  RECT rect = { 0 };
5130  rect.left = bDialogEx ? ((ATL::_DialogSplitHelper::DLGITEMTEMPLATEEX*)pItem)->x : pItem->x;
5131  rect.top = bDialogEx ? ((ATL::_DialogSplitHelper::DLGITEMTEMPLATEEX*)pItem)->y : pItem->y;
5132  rect.right = rect.left + (bDialogEx ? ((ATL::_DialogSplitHelper::DLGITEMTEMPLATEEX*)pItem)->cx : pItem->cx);
5133  rect.bottom = rect.top + (bDialogEx ? ((ATL::_DialogSplitHelper::DLGITEMTEMPLATEEX*)pItem)->cy : pItem->cy);
5134 
5135  // Convert from dialog units to screen units
5136  MapDialogRect(&rect);
5137 
5138  // Create AxWindow with a NULL caption.
5139  wnd.Create(m_hWnd,
5140  &rect,
5141  NULL,
5142  (bDialogEx ?
5143  ((ATL::_DialogSplitHelper::DLGITEMTEMPLATEEX*)pItem)->style :
5144  pItem->style) | WS_TABSTOP,
5145  bDialogEx ?
5146  ((ATL::_DialogSplitHelper::DLGITEMTEMPLATEEX*)pItem)->exStyle :
5147  0,
5148  bDialogEx ?
5149  ((ATL::_DialogSplitHelper::DLGITEMTEMPLATEEX*)pItem)->id :
5150  pItem->id,
5151  NULL);
5152 
5153  if (wnd != NULL)
5154  {
5155 #ifndef _WIN32_WCE
5156  // Set the Help ID
5157  if (bDialogEx && ((ATL::_DialogSplitHelper::DLGITEMTEMPLATEEX*)pItem)->helpID != 0)
5158  wnd.SetWindowContextHelpId(((ATL::_DialogSplitHelper::DLGITEMTEMPLATEEX*)pItem)->helpID);
5159 #endif // !_WIN32_WCE
5160  // Try to create the ActiveX control.
5161  hr = wnd.CreateControlLic(pszClassName, spStream, NULL, bstrLicKey);
5162  if (FAILED(hr))
5163  break;
5164  // Set the correct tab position.
5165  if (nItem == 0)
5166  hWndPrev = HWND_TOP;
5167  wnd.SetWindowPos(hWndPrev, 0,0,0,0,SWP_NOACTIVATE | SWP_NOMOVE | SWP_NOSIZE);
5168  hWndPrev = wnd;
5169  }
5170  else
5171  {
5172  hr = ATL::AtlHresultFromLastError();
5173  }
5174  }
5175  }
5176  else
5177  {
5178  if (nItem != 0)
5179  hWndPrev = ::GetWindow(hWndPrev, GW_HWNDNEXT);
5180  }
5181  pItem = ATL::_DialogSplitHelper::FindNextDlgItem(pItem, bDialogEx);
5182  }
5183  }
5184  else
5185  hr = ATL::AtlHresultFromLastError();
5186  }
5187  else
5188  hr = ATL::AtlHresultFromLastError();
5189  }
5190  return hr;
5191  }
5192 
5193 // Event handling support
5194  HRESULT AdviseSinkMap(bool bAdvise)
5195  {
5196  if(!bAdvise && m_hWnd == NULL)
5197  {
5198  // window is gone, controls are already unadvised
5199  ATLTRACE2(atlTraceUI, 0, _T("CAxPropertyPageImpl::AdviseSinkMap called after the window was destroyed\n"));
5200  return S_OK;
5201  }
5202  HRESULT hRet = E_NOTIMPL;
5203  __if_exists(T::_GetSinkMapFinder)
5204  {
5205  T* pT = static_cast<T*>(this);
5206  hRet = AtlAdviseSinkMap(pT, bAdvise);
5207  }
5208  return hRet;
5209  }
5210 
5211 // Message map and handlers
5212  typedef CPropertyPageImpl< T, TBase> _baseClass;
5213  BEGIN_MSG_MAP(CAxPropertyPageImpl)
5214  MESSAGE_HANDLER(WM_INITDIALOG, OnInitDialog)
5215  MESSAGE_HANDLER(WM_DESTROY, OnDestroy)
5216  CHAIN_MSG_MAP(_baseClass)
5217  END_MSG_MAP()
5218 
5219  LRESULT OnInitDialog(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& bHandled)
5220  {
5221  // initialize controls in dialog with DLGINIT resource section
5222  ExecuteDlgInit(static_cast<T*>(this)->IDD);
5223  AdviseSinkMap(true);
5224  bHandled = FALSE;
5225  return 1;
5226  }
5227 
5228  LRESULT OnDestroy(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& bHandled)
5229  {
5230  AdviseSinkMap(false);
5231  bHandled = FALSE;
5232  return 1;
5233  }
5234 #endif // (_ATL_VER >= 0x0700)
5235 };
5236 
5237 // for non-customized pages
5238 template <WORD t_wDlgTemplateID>
5239 class CAxPropertyPage : public CAxPropertyPageImpl<CAxPropertyPage<t_wDlgTemplateID> >
5240 {
5241 public:
5242  enum { IDD = t_wDlgTemplateID };
5243 
5245  { }
5246 
5247 #if (_WIN32_IE >= 0x0500) || (_ATL_VER >= 0x0700)
5248  // not empty so we handle accelerators/create controls
5249  BEGIN_MSG_MAP(CAxPropertyPage)
5251  END_MSG_MAP()
5252 #else // !((_WIN32_IE >= 0x0500) || (_ATL_VER >= 0x0700))
5253  DECLARE_EMPTY_MSG_MAP()
5254 #endif // !((_WIN32_IE >= 0x0500) || (_ATL_VER >= 0x0700))
5255 };
5256 
5257 #endif // _ATL_NO_HOSTING
5258 
5259 
5261 // Wizard97 Support
5262 
5263 #if (_WIN32_IE >= 0x0500) && !defined(_WIN32_WCE)
5264 
5265 // Sample wizard dialog resources:
5266 //
5267 // IDD_WIZ97_INTERIOR_BLANK DIALOG 0, 0, 317, 143
5268 // STYLE DS_SETFONT | WS_CHILD | WS_DISABLED | WS_CAPTION
5269 // CAPTION "Wizard97 Property Page - Interior"
5270 // FONT 8, "MS Shell Dlg"
5271 // BEGIN
5272 // END
5273 //
5274 // IDD_WIZ97_EXTERIOR_BLANK DIALOGEX 0, 0, 317, 193
5275 // STYLE DS_SETFONT | DS_FIXEDSYS | WS_CHILD | WS_DISABLED | WS_CAPTION
5276 // CAPTION "Wizard97 Property Page - Welcome/Complete"
5277 // FONT 8, "MS Shell Dlg", 0, 0, 0x0
5278 // BEGIN
5279 // LTEXT "Welcome to the X Wizard",IDC_WIZ97_EXTERIOR_TITLE,115,8,
5280 // 195,24
5281 // LTEXT "Wizard Explanation\r\n(The height of the static text should be in multiples of 8 dlus)",
5282 // IDC_STATIC,115,40,195,16
5283 // LTEXT "h",IDC_WIZ97_BULLET1,118,64,8,8
5284 // LTEXT "List Item 1 (the h is turned into a bullet)",IDC_STATIC,
5285 // 127,63,122,8
5286 // LTEXT "h",IDC_WIZ97_BULLET2,118,79,8,8
5287 // LTEXT "List Item 2. Keep 7 dlus between paragraphs",IDC_STATIC,
5288 // 127,78,33,8
5289 // CONTROL "&Do not show this Welcome page again",
5290 // IDC_WIZ97_WELCOME_NOTAGAIN,"Button",BS_AUTOCHECKBOX |
5291 // WS_TABSTOP,115,169,138,10
5292 // END
5293 //
5294 // GUIDELINES DESIGNINFO
5295 // BEGIN
5296 // IDD_WIZ97_INTERIOR_BLANK, DIALOG
5297 // BEGIN
5298 // LEFTMARGIN, 7
5299 // RIGHTMARGIN, 310
5300 // VERTGUIDE, 21
5301 // VERTGUIDE, 31
5302 // VERTGUIDE, 286
5303 // VERTGUIDE, 296
5304 // TOPMARGIN, 7
5305 // BOTTOMMARGIN, 136
5306 // HORZGUIDE, 8
5307 // END
5308 //
5309 // IDD_WIZ97_EXTERIOR_BLANK, DIALOG
5310 // BEGIN
5311 // RIGHTMARGIN, 310
5312 // VERTGUIDE, 115
5313 // VERTGUIDE, 118
5314 // VERTGUIDE, 127
5315 // TOPMARGIN, 7
5316 // BOTTOMMARGIN, 186
5317 // HORZGUIDE, 8
5318 // HORZGUIDE, 32
5319 // HORZGUIDE, 40
5320 // HORZGUIDE, 169
5321 // END
5322 // END
5323 
5325 // CWizard97SheetWindow - client side for a Wizard 97 style wizard sheet
5326 
5327 class CWizard97SheetWindow : public CPropertySheetWindow
5328 {
5329 public:
5330 // Constructors
5331  CWizard97SheetWindow(HWND hWnd = NULL) : CPropertySheetWindow(hWnd)
5332  { }
5333 
5334  CWizard97SheetWindow& operator =(HWND hWnd)
5335  {
5336  m_hWnd = hWnd;
5337  return *this;
5338  }
5339 
5340 // Operations
5341  HFONT GetExteriorPageTitleFont(void)
5342  {
5343  ATLASSERT(::IsWindow(m_hWnd));
5344  return (HFONT)::SendMessage(m_hWnd, GetMessage_GetExteriorPageTitleFont(), 0, 0L);
5345  }
5346 
5347  HFONT GetBulletFont(void)
5348  {
5349  ATLASSERT(::IsWindow(m_hWnd));
5350  return (HFONT)::SendMessage(m_hWnd, GetMessage_GetBulletFont(), 0, 0L);
5351  }
5352 
5353 // Helpers
5354  static UINT GetMessage_GetExteriorPageTitleFont()
5355  {
5356  static UINT uGetExteriorPageTitleFont = 0;
5357  if(uGetExteriorPageTitleFont == 0)
5358  {
5360  if(FAILED(lock.Lock()))
5361  {
5362  ATLTRACE2(atlTraceUI, 0, _T("ERROR : Unable to lock critical section in CWizard97SheetWindow::GetMessage_GetExteriorPageTitleFont().\n"));
5363  ATLASSERT(FALSE);
5364  return 0;
5365  }
5366 
5367  if(uGetExteriorPageTitleFont == 0)
5368  uGetExteriorPageTitleFont = ::RegisterWindowMessage(_T("GetExteriorPageTitleFont_531AF056-B8BE-4c4c-B786-AC608DF0DF12"));
5369 
5370  lock.Unlock();
5371  }
5372  ATLASSERT(uGetExteriorPageTitleFont != 0);
5373  return uGetExteriorPageTitleFont;
5374  }
5375 
5376  static UINT GetMessage_GetBulletFont()
5377  {
5378  static UINT uGetBulletFont = 0;
5379  if(uGetBulletFont == 0)
5380  {
5382  if(FAILED(lock.Lock()))
5383  {
5384  ATLTRACE2(atlTraceUI, 0, _T("ERROR : Unable to lock critical section in CWizard97SheetWindow::GetMessage_GetBulletFont().\n"));
5385  ATLASSERT(FALSE);
5386  return 0;
5387  }
5388 
5389  if(uGetBulletFont == 0)
5390  uGetBulletFont = ::RegisterWindowMessage(_T("GetBulletFont_AD347D08-8F65-45ef-982E-6352E8218AD5"));
5391 
5392  lock.Unlock();
5393  }
5394  ATLASSERT(uGetBulletFont != 0);
5395  return uGetBulletFont;
5396  }
5397 
5398 // Implementation - override to prevent usage
5399  HWND Create(LPCTSTR, HWND, ATL::_U_RECT = NULL, LPCTSTR = NULL, DWORD = 0, DWORD = 0, ATL::_U_MENUorID = 0U, LPVOID = NULL)
5400  {
5401  ATLASSERT(FALSE);
5402  return NULL;
5403  }
5404 };
5405 
5406 
5408 // CWizard97SheetImpl - implements a Wizard 97 style wizard sheet
5409 
5410 template <class T, class TBase = CWizard97SheetWindow>
5411 class ATL_NO_VTABLE CWizard97SheetImpl : public CPropertySheetImpl< T, TBase >
5412 {
5413 protected:
5414 // Typedefs
5415  typedef CWizard97SheetImpl< T, TBase > thisClass;
5416  typedef CPropertySheetImpl< T, TBase > baseClass;
5417 
5418 // Member variables
5419  CFont m_fontExteriorPageTitle; // Welcome and Completion page title font
5420  CFont m_fontBullet; // Bullet font (used on static text 'h' to produce a small bullet)
5421  bool m_bReceivedFirstSizeMessage;
5422 
5423 public:
5424  CWizard97SheetImpl(ATL::_U_STRINGorID title, ATL::_U_STRINGorID headerBitmap, ATL::_U_STRINGorID watermarkBitmap, UINT uStartPage = 0, HWND hWndParent = NULL) :
5425  baseClass(title, uStartPage, hWndParent),
5426  m_bReceivedFirstSizeMessage(false)
5427  {
5428  m_psh.dwFlags &= ~(PSH_NOCONTEXTHELP);
5429  m_psh.dwFlags &= ~(PSH_WIZARD | PSH_WIZARD_LITE);
5430 
5431  m_psh.dwFlags |= (PSH_HASHELP | PSH_WIZARDCONTEXTHELP);
5432  m_psh.dwFlags |= PSH_WIZARD97;
5433 
5434  baseClass::SetHeader(headerBitmap.m_lpstr);
5435  baseClass::SetWatermark(watermarkBitmap.m_lpstr);
5436  }
5437 
5438 // Overrides from base class
5439  void OnSheetInitialized()
5440  {
5441  T* pT = static_cast<T*>(this);
5442  pT->_InitializeFonts();
5443 
5444  // We'd like to center the wizard here, but its too early.
5445  // Instead, we'll do CenterWindow upon our first WM_SIZE message
5446  }
5447 
5448 // Initialization
5449  void _InitializeFonts()
5450  {
5451  // Setup the Title and Bullet Font
5452  // (Property pages can send the "get external page title font" and "get bullet font" messages)
5453  // The derived class needs to do the actual SetFont for the dialog items)
5454 
5455  CFontHandle fontThisDialog = this->GetFont();
5456  CClientDC dcScreen(NULL);
5457 
5458  LOGFONT titleLogFont = {0};
5459  LOGFONT bulletLogFont = {0};
5460  fontThisDialog.GetLogFont(&titleLogFont);
5461  fontThisDialog.GetLogFont(&bulletLogFont);
5462 
5463  // The Wizard 97 Spec recommends to do the Title Font
5464  // as Verdana Bold, 12pt.
5465  titleLogFont.lfCharSet = DEFAULT_CHARSET;
5466  titleLogFont.lfWeight = FW_BOLD;
5467  SecureHelper::strcpy_x(titleLogFont.lfFaceName, _countof(titleLogFont.lfFaceName), _T("Verdana Bold"));
5468  INT titleFontPointSize = 12;
5469  titleLogFont.lfHeight = -::MulDiv(titleFontPointSize, dcScreen.GetDeviceCaps(LOGPIXELSY), 72);
5470  m_fontExteriorPageTitle.CreateFontIndirect(&titleLogFont);
5471 
5472  // The Wizard 97 Spec recommends to do Bullets by having
5473  // static text of "h" in the Marlett font.
5474  bulletLogFont.lfCharSet = DEFAULT_CHARSET;
5475  bulletLogFont.lfWeight = FW_NORMAL;
5476  SecureHelper::strcpy_x(bulletLogFont.lfFaceName, _countof(bulletLogFont.lfFaceName), _T("Marlett"));
5477  INT bulletFontSize = 8;
5478  bulletLogFont.lfHeight = -::MulDiv(bulletFontSize, dcScreen.GetDeviceCaps(LOGPIXELSY), 72);
5479  m_fontBullet.CreateFontIndirect(&bulletLogFont);
5480  }
5481 
5482 // Message Handling
5483  BEGIN_MSG_MAP(thisClass)
5484  MESSAGE_HANDLER(CWizard97SheetWindow::GetMessage_GetExteriorPageTitleFont(), OnGetExteriorPageTitleFont)
5485  MESSAGE_HANDLER(CWizard97SheetWindow::GetMessage_GetBulletFont(), OnGetBulletFont)
5486  MESSAGE_HANDLER(WM_SIZE, OnSize)
5487  CHAIN_MSG_MAP(baseClass)
5488  END_MSG_MAP()
5489 
5490  LRESULT OnGetExteriorPageTitleFont(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& /*bHandled*/)
5491  {
5492  return (LRESULT)(HFONT)m_fontExteriorPageTitle;
5493  }
5494 
5495  LRESULT OnGetBulletFont(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& /*bHandled*/)
5496  {
5497  return (LRESULT)(HFONT)m_fontBullet;
5498  }
5499 
5500  LRESULT OnSize(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& bHandled)
5501  {
5502  if(!m_bReceivedFirstSizeMessage)
5503  {
5504  m_bReceivedFirstSizeMessage = true;
5505  this->CenterWindow();
5506  }
5507 
5508  bHandled = FALSE;
5509  return 0;
5510  }
5511 };
5512 
5513 // for non-customized sheets
5514 class CWizard97Sheet : public CWizard97SheetImpl<CWizard97Sheet>
5515 {
5516 protected:
5517 // Typedefs
5518  typedef CWizard97Sheet thisClass;
5519  typedef CWizard97SheetImpl<CWizard97Sheet> baseClass;
5520 
5521 public:
5522  CWizard97Sheet(ATL::_U_STRINGorID title, ATL::_U_STRINGorID headerBitmap, ATL::_U_STRINGorID watermarkBitmap, UINT uStartPage = 0, HWND hWndParent = NULL) :
5523  baseClass(title, headerBitmap, watermarkBitmap, uStartPage, hWndParent)
5524  { }
5525 
5526  BEGIN_MSG_MAP(thisClass)
5527  CHAIN_MSG_MAP(baseClass)
5528  END_MSG_MAP()
5529 };
5530 
5531 
5533 // CWizard97PageWindow - client side for a Wizard 97 style wizard page
5534 
5535 #define WIZARD97_EXTERIOR_CXDLG 317
5536 #define WIZARD97_EXTERIOR_CYDLG 193
5537 
5538 #define WIZARD97_INTERIOR_CXDLG 317
5539 #define WIZARD97_INTERIOR_CYDLG 143
5540 
5541 class CWizard97PageWindow : public CPropertyPageWindow
5542 {
5543 public:
5544 // Constructors
5545  CWizard97PageWindow(HWND hWnd = NULL) : CPropertyPageWindow(hWnd)
5546  { }
5547 
5548  CWizard97PageWindow& operator =(HWND hWnd)
5549  {
5550  m_hWnd = hWnd;
5551  return *this;
5552  }
5553 
5554 // Attributes
5555  CWizard97SheetWindow GetPropertySheet() const
5556  {
5557  ATLASSERT(::IsWindow(m_hWnd));
5558  return CWizard97SheetWindow(GetParent());
5559  }
5560 
5561 // Operations
5562  HFONT GetExteriorPageTitleFont(void)
5563  {
5564  ATLASSERT(::IsWindow(m_hWnd));
5565  return GetPropertySheet().GetExteriorPageTitleFont();
5566  }
5567 
5568  HFONT GetBulletFont(void)
5569  {
5570  ATLASSERT(::IsWindow(m_hWnd));
5571  return GetPropertySheet().GetBulletFont();
5572  }
5573 
5574 // Implementation - overrides to prevent usage
5575  HWND Create(LPCTSTR, HWND, ATL::_U_RECT = NULL, LPCTSTR = NULL, DWORD = 0, DWORD = 0, ATL::_U_MENUorID = 0U, LPVOID = NULL)
5576  {
5577  ATLASSERT(FALSE);
5578  return NULL;
5579  }
5580 
5581 };
5582 
5583 
5585 // CWizard97PageImpl - implements a Wizard 97 style wizard page
5586 
5587 template <class T, class TBase = CWizard97PageWindow>
5588 class ATL_NO_VTABLE CWizard97PageImpl : public CPropertyPageImpl< T, TBase >
5589 {
5590 protected:
5591 // Typedefs
5592  typedef CWizard97PageImpl< T, TBase > thisClass;
5593  typedef CPropertyPageImpl< T, TBase > baseClass;
5594 
5595 public:
5596  CWizard97PageImpl(ATL::_U_STRINGorID title = (LPCTSTR)NULL) : baseClass(title)
5597  { }
5598 
5599 // Message Handling
5600  BEGIN_MSG_MAP(thisClass)
5601  CHAIN_MSG_MAP(baseClass)
5602  END_MSG_MAP()
5603 };
5604 
5605 
5607 // CWizard97ExteriorPageImpl - implements a Wizard 97 style exterior wizard page
5608 
5609 template <class T, class TBase = CWizard97PageWindow>
5610 class ATL_NO_VTABLE CWizard97ExteriorPageImpl : public CPropertyPageImpl< T, TBase >
5611 {
5612 protected:
5613 // Typedefs
5614  typedef CWizard97ExteriorPageImpl< T, TBase > thisClass;
5615  typedef CPropertyPageImpl< T, TBase > baseClass;
5616 
5617 public:
5618 // Constructors
5619  CWizard97ExteriorPageImpl(ATL::_U_STRINGorID title = (LPCTSTR)NULL) : baseClass(title)
5620  {
5621  m_psp.dwFlags |= PSP_HASHELP;
5622  m_psp.dwFlags |= PSP_HIDEHEADER;
5623  }
5624 
5625 // Message Handling
5626  BEGIN_MSG_MAP(thisClass)
5627  CHAIN_MSG_MAP(baseClass)
5628  END_MSG_MAP()
5629 };
5630 
5631 
5633 // CWizard97InteriorPageImpl - implements a Wizard 97 style interior wizard page
5634 
5635 template <class T, class TBase = CWizard97PageWindow>
5636 class ATL_NO_VTABLE CWizard97InteriorPageImpl : public CPropertyPageImpl< T, TBase >
5637 {
5638 protected:
5639 // Typedefs
5640  typedef CWizard97InteriorPageImpl< T, TBase > thisClass;
5641  typedef CPropertyPageImpl< T, TBase > baseClass;
5642 
5643 public:
5644 // Constructors
5645  CWizard97InteriorPageImpl(ATL::_U_STRINGorID title = (LPCTSTR)NULL) : baseClass(title)
5646  {
5647  m_psp.dwFlags |= PSP_HASHELP;
5648  m_psp.dwFlags &= ~PSP_HIDEHEADER;
5649  m_psp.dwFlags |= PSP_USEHEADERTITLE | PSP_USEHEADERSUBTITLE;
5650 
5651  // Be sure to have the derived class define this in the constructor.
5652  // We'll default it to something obvious in case its forgotten.
5653  baseClass::SetHeaderTitle(_T("Call SetHeaderTitle in Derived Class"));
5654  baseClass::SetHeaderSubTitle(_T("Call SetHeaderSubTitle in the constructor of the Derived Class."));
5655  }
5656 
5657 // Message Handling
5658  BEGIN_MSG_MAP(thisClass)
5659  CHAIN_MSG_MAP(baseClass)
5660  END_MSG_MAP()
5661 };
5662 
5663 #endif // (_WIN32_IE >= 0x0500) && !defined(_WIN32_WCE)
5664 
5665 
5667 // Aero Wizard support
5668 
5669 #if (_WIN32_WINNT >= 0x0600) && !defined(_WIN32_WCE)
5670 
5672 // CAeroWizardFrameWindow - client side for an Aero Wizard frame window
5673 
5674 class CAeroWizardFrameWindow : public CPropertySheetWindow
5675 {
5676 public:
5677 // Constructors
5678  CAeroWizardFrameWindow(HWND hWnd = NULL) : CPropertySheetWindow(hWnd)
5679  { }
5680 
5681  CAeroWizardFrameWindow& operator =(HWND hWnd)
5682  {
5683  m_hWnd = hWnd;
5684  return *this;
5685  }
5686 
5687 // Operations - new, Aero Wizard only
5688  void SetNextText(LPCWSTR lpszText)
5689  {
5690  ATLASSERT(::IsWindow(m_hWnd));
5691  ::SendMessage(m_hWnd, PSM_SETNEXTTEXT, 0, (LPARAM)lpszText);
5692  }
5693 
5694  void ShowWizardButtons(DWORD dwButtons, DWORD dwStates)
5695  {
5696  ATLASSERT(::IsWindow(m_hWnd));
5697  ::PostMessage(m_hWnd, PSM_SHOWWIZBUTTONS, (WPARAM)dwStates, (LPARAM)dwButtons);
5698  }
5699 
5700  void EnableWizardButtons(DWORD dwButtons, DWORD dwStates)
5701  {
5702  ATLASSERT(::IsWindow(m_hWnd));
5703  ::PostMessage(m_hWnd, PSM_ENABLEWIZBUTTONS, (WPARAM)dwStates, (LPARAM)dwButtons);
5704  }
5705 
5706  void SetButtonText(DWORD dwButton, LPCWSTR lpszText)
5707  {
5708  ATLASSERT(::IsWindow(m_hWnd));
5709  ::SendMessage(m_hWnd, PSM_SETBUTTONTEXT, (WPARAM)dwButton, (LPARAM)lpszText);
5710  }
5711 };
5712 
5713 
5715 // CAeroWizardFrameImpl - implements an Aero Wizard frame
5716 
5717 template <class T, class TBase = CAeroWizardFrameWindow>
5718 class ATL_NO_VTABLE CAeroWizardFrameImpl : public CPropertySheetImpl<T, TBase >
5719 {
5720 public:
5721 // Constructor
5722  CAeroWizardFrameImpl(ATL::_U_STRINGorID title = (LPCTSTR)NULL, UINT uStartPage = 0, HWND hWndParent = NULL) :
5723  CPropertySheetImpl<T, TBase >(title, uStartPage, hWndParent)
5724  {
5725  m_psh.dwFlags |= PSH_WIZARD | PSH_AEROWIZARD;
5726  }
5727 
5728 // Operations
5729  void EnableResizing()
5730  {
5731  ATLASSERT(m_hWnd == NULL); // can't do this after it's created
5732  m_psh.dwFlags |= PSH_RESIZABLE;
5733  }
5734 
5735  void UseHeaderBitmap()
5736  {
5737  ATLASSERT(m_hWnd == NULL); // can't do this after it's created
5738  m_psh.dwFlags |= PSH_HEADERBITMAP;
5739  }
5740 
5741  void SetNoMargin()
5742  {
5743  ATLASSERT(m_hWnd == NULL); // can't do this after it's created
5744  m_psh.dwFlags |= PSH_NOMARGIN;
5745  }
5746 
5747 // Override to prevent use
5748  HWND Create(HWND /*hWndParent*/ = NULL)
5749  {
5750  ATLASSERT(FALSE); // not supported for Aero Wizard
5751  return NULL;
5752  }
5753 };
5754 
5755 
5757 // CAeroWizardFrame - for non-customized frames
5758 
5759 class CAeroWizardFrame : public CAeroWizardFrameImpl<CAeroWizardFrame>
5760 {
5761 public:
5762  CAeroWizardFrame(ATL::_U_STRINGorID title = (LPCTSTR)NULL, UINT uStartPage = 0, HWND hWndParent = NULL)
5763  : CAeroWizardFrameImpl<CAeroWizardFrame>(title, uStartPage, hWndParent)
5764  { }
5765 
5766  BEGIN_MSG_MAP(CAeroWizardFrame)
5767  MESSAGE_HANDLER(WM_COMMAND, CAeroWizardFrameImpl<CAeroWizardFrame>::OnCommand)
5768  END_MSG_MAP()
5769 };
5770 
5771 
5773 // CAeroWizardPageWindow - client side for an Aero Wizard page
5774 
5775 class CAeroWizardPageWindow : public CPropertyPageWindow
5776 {
5777 public:
5778 // Constructors
5779  CAeroWizardPageWindow(HWND hWnd = NULL) : CPropertyPageWindow(hWnd)
5780  { }
5781 
5782  CAeroWizardPageWindow& operator =(HWND hWnd)
5783  {
5784  m_hWnd = hWnd;
5785  return *this;
5786  }
5787 
5788 // Attributes
5789  CAeroWizardFrameWindow GetAeroWizardFrame() const
5790  {
5791  ATLASSERT(::IsWindow(m_hWnd));
5792  // This is not really top-level frame window, but it processes all frame messages
5793  return CAeroWizardFrameWindow(GetParent());
5794  }
5795 
5796 // Operations - new, Aero Wizard only
5797  void SetNextText(LPCWSTR lpszText)
5798  {
5799  ATLASSERT(::IsWindow(m_hWnd));
5800  ATLASSERT(GetParent() != NULL);
5801  GetAeroWizardFrame().SetNextText(lpszText);
5802  }
5803 
5804  void ShowWizardButtons(DWORD dwButtons, DWORD dwStates)
5805  {
5806  ATLASSERT(::IsWindow(m_hWnd));
5807  ATLASSERT(GetParent() != NULL);
5808  GetAeroWizardFrame().ShowWizardButtons(dwButtons, dwStates);
5809  }
5810 
5811  void EnableWizardButtons(DWORD dwButtons, DWORD dwStates)
5812  {
5813  ATLASSERT(::IsWindow(m_hWnd));
5814  ATLASSERT(GetParent() != NULL);
5815  GetAeroWizardFrame().EnableWizardButtons(dwButtons, dwStates);
5816  }
5817 
5818  void SetButtonText(DWORD dwButton, LPCWSTR lpszText)
5819  {
5820  ATLASSERT(::IsWindow(m_hWnd));
5821  ATLASSERT(GetParent() != NULL);
5822  GetAeroWizardFrame().SetButtonText(dwButton, lpszText);
5823  }
5824 };
5825 
5826 
5828 // CAeroWizardPageImpl - implements an Aero Wizard page
5829 
5830 template <class T, class TBase = CAeroWizardPageWindow>
5831 class ATL_NO_VTABLE CAeroWizardPageImpl : public CPropertyPageImpl<T, TBase >
5832 {
5833 public:
5834  CAeroWizardPageImpl(ATL::_U_STRINGorID title = (LPCTSTR)NULL) : CPropertyPageImpl<T, TBase >(title)
5835  { }
5836 };
5837 
5838 
5840 // CAeroWizardPage - for non-customized pages
5841 
5842 template <WORD t_wDlgTemplateID>
5843 class CAeroWizardPage : public CAeroWizardPageImpl<CAeroWizardPage<t_wDlgTemplateID> >
5844 {
5845 public:
5846  enum { IDD = t_wDlgTemplateID };
5847 
5848  CAeroWizardPage(ATL::_U_STRINGorID title = (LPCTSTR)NULL) : CAeroWizardPageImpl<CAeroWizardPage>(title)
5849  { }
5850 
5851  DECLARE_EMPTY_MSG_MAP()
5852 };
5853 
5854 
5855 #ifndef _ATL_NO_HOSTING
5856 
5857 // Note: You must #include <atlhost.h> to use these classes
5858 
5860 // CAeroWizardAxPageImpl - Aero Wizard page that hosts ActiveX controls
5861 
5862 template <class T, class TBase = CAeroWizardPageWindow>
5863 class ATL_NO_VTABLE CAeroWizardAxPageImpl : public CAxPropertyPageImpl< T, TBase >
5864 {
5865 public:
5866  CAeroWizardAxPageImpl(ATL::_U_STRINGorID title = (LPCTSTR)NULL) : CAxPropertyPageImpl< T, TBase >(title)
5867  { }
5868 };
5869 
5870 
5872 // CAeroWizardAxPage - for non-customized pages
5873 
5874 template <WORD t_wDlgTemplateID>
5875 class CAeroWizardAxPage : public CAeroWizardAxPageImpl<CAeroWizardAxPage<t_wDlgTemplateID> >
5876 {
5877 public:
5878  enum { IDD = t_wDlgTemplateID };
5879 
5880  CAeroWizardAxPage(ATL::_U_STRINGorID title = (LPCTSTR)NULL) : CAeroWizardAxPageImpl<CAeroWizardAxPage>(title)
5881  { }
5882 
5883 #if (_WIN32_IE >= 0x0500) || (_ATL_VER >= 0x0700)
5884  // not empty so we handle accelerators/create controls
5885  BEGIN_MSG_MAP(CAeroWizardAxPage)
5886  CHAIN_MSG_MAP(CAeroWizardAxPageImpl<CAeroWizardAxPage<t_wDlgTemplateID> >)
5887  END_MSG_MAP()
5888 #else // !((_WIN32_IE >= 0x0500) || (_ATL_VER >= 0x0700))
5889  DECLARE_EMPTY_MSG_MAP()
5890 #endif // !((_WIN32_IE >= 0x0500) || (_ATL_VER >= 0x0700))
5891 };
5892 
5893 #endif // _ATL_NO_HOSTING
5894 
5895 #endif // (_WIN32_WINNT >= 0x0600) && !defined(_WIN32_WCE)
5896 
5897 
5899 // TaskDialog support
5900 
5901 #if ((_WIN32_WINNT >= 0x0600) || defined(_WTL_TASKDIALOG)) && !defined(_WIN32_WCE)
5902 
5904 // AtlTaskDialog - support for TaskDialog() function
5905 
5906 inline int AtlTaskDialog(HWND hWndParent,
5907  ATL::_U_STRINGorID WindowTitle, ATL::_U_STRINGorID MainInstructionText, ATL::_U_STRINGorID ContentText,
5908  TASKDIALOG_COMMON_BUTTON_FLAGS dwCommonButtons = 0U, ATL::_U_STRINGorID Icon = (LPCTSTR)NULL)
5909 {
5910  int nRet = -1;
5911 
5912 #ifdef _WTL_TASKDIALOG_DIRECT
5913  USES_CONVERSION;
5914  HRESULT hRet = ::TaskDialog(hWndParent, ModuleHelper::GetResourceInstance(),
5915  IS_INTRESOURCE(WindowTitle.m_lpstr) ? (LPCWSTR) WindowTitle.m_lpstr : T2CW(WindowTitle.m_lpstr),
5916  IS_INTRESOURCE(MainInstructionText.m_lpstr) ? (LPCWSTR) MainInstructionText.m_lpstr : T2CW(MainInstructionText.m_lpstr),
5917  IS_INTRESOURCE(ContentText.m_lpstr) ? (LPCWSTR) ContentText.m_lpstr : T2CW(ContentText.m_lpstr),
5918  dwCommonButtons,
5919  IS_INTRESOURCE(Icon.m_lpstr) ? (LPCWSTR) Icon.m_lpstr : T2CW(Icon.m_lpstr),
5920  &nRet);
5921  ATLVERIFY(SUCCEEDED(hRet));
5922 #else
5923  // This allows apps to run on older versions of Windows
5924  typedef HRESULT (STDAPICALLTYPE *PFN_TaskDialog)(HWND hwndParent, HINSTANCE hInstance, PCWSTR pszWindowTitle, PCWSTR pszMainInstruction, PCWSTR pszContent, TASKDIALOG_COMMON_BUTTON_FLAGS dwCommonButtons, PCWSTR pszIcon, int* pnButton);
5925 
5926  HMODULE m_hCommCtrlDLL = ::LoadLibrary(_T("comctl32.dll"));
5927  if(m_hCommCtrlDLL != NULL)
5928  {
5929  PFN_TaskDialog pfnTaskDialog = (PFN_TaskDialog)::GetProcAddress(m_hCommCtrlDLL, "TaskDialog");
5930  if(pfnTaskDialog != NULL)
5931  {
5932  USES_CONVERSION;
5933  HRESULT hRet = pfnTaskDialog(hWndParent, ModuleHelper::GetResourceInstance(),
5934  IS_INTRESOURCE(WindowTitle.m_lpstr) ? (LPCWSTR) WindowTitle.m_lpstr : T2CW(WindowTitle.m_lpstr),
5935  IS_INTRESOURCE(MainInstructionText.m_lpstr) ? (LPCWSTR) MainInstructionText.m_lpstr : T2CW(MainInstructionText.m_lpstr),
5936  IS_INTRESOURCE(ContentText.m_lpstr) ? (LPCWSTR) ContentText.m_lpstr : T2CW(ContentText.m_lpstr),
5937  dwCommonButtons,
5938  IS_INTRESOURCE(Icon.m_lpstr) ? (LPCWSTR) Icon.m_lpstr : T2CW(Icon.m_lpstr),
5939  &nRet);
5940  ATLVERIFY(SUCCEEDED(hRet));
5941  }
5942 
5943  ::FreeLibrary(m_hCommCtrlDLL);
5944  }
5945 #endif
5946 
5947  return nRet;
5948 }
5949 
5950 
5952 // CTaskDialogConfig - TASKDIALOGCONFIG wrapper
5953 
5954 class CTaskDialogConfig : public TASKDIALOGCONFIG
5955 {
5956 public:
5957 // Constructor
5958  CTaskDialogConfig()
5959  {
5960  Init();
5961  }
5962 
5963  void Init()
5964  {
5965  memset(this, 0, sizeof(TASKDIALOGCONFIG)); // initialize structure to 0/NULL
5966  this->cbSize = sizeof(TASKDIALOGCONFIG);
5967  this->hInstance = ModuleHelper::GetResourceInstance();
5968  }
5969 
5970 // Operations - setting values
5971  // common buttons
5972  void SetCommonButtons(TASKDIALOG_COMMON_BUTTON_FLAGS dwCommonButtonsArg)
5973  {
5974  this->dwCommonButtons = dwCommonButtonsArg;
5975  }
5976 
5977  // window title text
5978  void SetWindowTitle(UINT nID)
5979  {
5980  this->pszWindowTitle = MAKEINTRESOURCEW(nID);
5981  }
5982 
5983  void SetWindowTitle(LPCWSTR lpstrWindowTitle)
5984  {
5985  this->pszWindowTitle = lpstrWindowTitle;
5986  }
5987 
5988  // main icon
5989  void SetMainIcon(HICON hIcon)
5990  {
5991  this->dwFlags |= TDF_USE_HICON_MAIN;
5992  this->hMainIcon = hIcon;
5993  }
5994 
5995  void SetMainIcon(UINT nID)
5996  {
5997  this->dwFlags &= ~TDF_USE_HICON_MAIN;
5998  this->pszMainIcon = MAKEINTRESOURCEW(nID);
5999  }
6000 
6001  void SetMainIcon(LPCWSTR lpstrMainIcon)
6002  {
6003  this->dwFlags &= ~TDF_USE_HICON_MAIN;
6004  this->pszMainIcon = lpstrMainIcon;
6005  }
6006 
6007  // main instruction text
6008  void SetMainInstructionText(UINT nID)
6009  {
6010  this->pszMainInstruction = MAKEINTRESOURCEW(nID);
6011  }
6012 
6013  void SetMainInstructionText(LPCWSTR lpstrMainInstruction)
6014  {
6015  this->pszMainInstruction = lpstrMainInstruction;
6016  }
6017 
6018  // content text
6019  void SetContentText(UINT nID)
6020  {
6021  this->pszContent = MAKEINTRESOURCEW(nID);
6022  }
6023 
6024  void SetContentText(LPCWSTR lpstrContent)
6025  {
6026  this->pszContent = lpstrContent;
6027  }
6028 
6029  // buttons
6030  void SetButtons(const TASKDIALOG_BUTTON* pButtonsArg, UINT cButtonsArg, int nDefaultButtonArg = 0)
6031  {
6032  this->pButtons = pButtonsArg;
6033  this->cButtons = cButtonsArg;
6034  if(nDefaultButtonArg != 0)
6035  this->nDefaultButton = nDefaultButtonArg;
6036  }
6037 
6038  void SetDefaultButton(int nDefaultButtonArg)
6039  {
6040  this->nDefaultButton = nDefaultButtonArg;
6041  }
6042 
6043  // radio buttons
6044  void SetRadioButtons(const TASKDIALOG_BUTTON* pRadioButtonsArg, UINT cRadioButtonsArg, int nDefaultRadioButtonArg = 0)
6045  {
6046  this->pRadioButtons = pRadioButtonsArg;
6047  this->cRadioButtons = cRadioButtonsArg;
6048  if(nDefaultRadioButtonArg != 0)
6049  this->nDefaultRadioButton = nDefaultRadioButtonArg;
6050  }
6051 
6052  void SetDefaultRadioButton(int nDefaultRadioButtonArg)
6053  {
6054  this->nDefaultRadioButton = nDefaultRadioButtonArg;
6055  }
6056 
6057  // verification text
6058  void SetVerificationText(UINT nID)
6059  {
6060  this->pszVerificationText = MAKEINTRESOURCEW(nID);
6061  }
6062 
6063  void SetVerificationText(LPCWSTR lpstrVerificationText)
6064  {
6065  this->pszVerificationText = lpstrVerificationText;
6066  }
6067 
6068  // expanded information text
6069  void SetExpandedInformationText(UINT nID)
6070  {
6071  this->pszExpandedInformation = MAKEINTRESOURCEW(nID);
6072  }
6073 
6074  void SetExpandedInformationText(LPCWSTR lpstrExpandedInformation)
6075  {
6076  this->pszExpandedInformation = lpstrExpandedInformation;
6077  }
6078 
6079  // expanded control text
6080  void SetExpandedControlText(UINT nID)
6081  {
6082  this->pszExpandedControlText = MAKEINTRESOURCEW(nID);
6083  }
6084 
6085  void SetExpandedControlText(LPCWSTR lpstrExpandedControlText)
6086  {
6087  this->pszExpandedControlText = lpstrExpandedControlText;
6088  }
6089 
6090  // collapsed control text
6091  void SetCollapsedControlText(UINT nID)
6092  {
6093  this->pszCollapsedControlText = MAKEINTRESOURCEW(nID);
6094  }
6095 
6096  void SetCollapsedControlText(LPCWSTR lpstrCollapsedControlText)
6097  {
6098  this->pszCollapsedControlText = lpstrCollapsedControlText;
6099  }
6100 
6101  // footer icon
6102  void SetFooterIcon(HICON hIcon)
6103  {
6104  this->dwFlags |= TDF_USE_HICON_FOOTER;
6105  this->hFooterIcon = hIcon;
6106  }
6107 
6108  void SetFooterIcon(UINT nID)
6109  {
6110  this->dwFlags &= ~TDF_USE_HICON_FOOTER;
6111  this->pszFooterIcon = MAKEINTRESOURCEW(nID);
6112  }
6113 
6114  void SetFooterIcon(LPCWSTR lpstrFooterIcon)
6115  {
6116  this->dwFlags &= ~TDF_USE_HICON_FOOTER;
6117  this->pszFooterIcon = lpstrFooterIcon;
6118  }
6119 
6120  // footer text
6121  void SetFooterText(UINT nID)
6122  {
6123  this->pszFooter = MAKEINTRESOURCEW(nID);
6124  }
6125 
6126  void SetFooterText(LPCWSTR lpstrFooterText)
6127  {
6128  this->pszFooter = lpstrFooterText;
6129  }
6130 
6131  // width (in DLUs)
6132  void SetWidth(UINT cxWidthArg)
6133  {
6134  this->cxWidth = cxWidthArg;
6135  }
6136 
6137  // modify flags
6138  void ModifyFlags(DWORD dwRemove, DWORD dwAdd)
6139  {
6140  this->dwFlags = (this->dwFlags & ~dwRemove) | dwAdd;
6141  }
6142 };
6143 
6144 
6146 // CTaskDialogImpl - implements a Task Dialog
6147 
6148 template <class T>
6149 class ATL_NO_VTABLE CTaskDialogImpl
6150 {
6151 public:
6152  CTaskDialogConfig m_tdc;
6153  HWND m_hWnd; // used only in callback functions
6154 
6155 // Constructor
6156  CTaskDialogImpl(HWND hWndParent = NULL) : m_hWnd(NULL)
6157  {
6158  m_tdc.hwndParent = hWndParent;
6159  m_tdc.pfCallback = T::TaskDialogCallback;
6160  m_tdc.lpCallbackData = (LONG_PTR)static_cast<T*>(this);
6161  }
6162 
6163 // Operations
6164  HRESULT DoModal(HWND hWndParent = ::GetActiveWindow(), int* pnButton = NULL, int* pnRadioButton = NULL, BOOL* pfVerificationFlagChecked = NULL)
6165  {
6166  if(m_tdc.hwndParent == NULL)
6167  m_tdc.hwndParent = hWndParent;
6168 
6169 #ifdef _WTL_TASKDIALOG_DIRECT
6170  return ::TaskDialogIndirect(&m_tdc, pnButton, pnRadioButton, pfVerificationFlagChecked);
6171 #else
6172 
6173  // This allows apps to run on older versions of Windows
6174  typedef HRESULT (STDAPICALLTYPE *PFN_TaskDialogIndirect)(const TASKDIALOGCONFIG* pTaskConfig, int* pnButton, int* pnRadioButton, BOOL* pfVerificationFlagChecked);
6175 
6176  HRESULT hRet = E_UNEXPECTED;
6177  HMODULE m_hCommCtrlDLL = ::LoadLibrary(_T("comctl32.dll"));
6178  if(m_hCommCtrlDLL != NULL)
6179  {
6180  PFN_TaskDialogIndirect pfnTaskDialogIndirect = (PFN_TaskDialogIndirect)::GetProcAddress(m_hCommCtrlDLL, "TaskDialogIndirect");
6181  if(pfnTaskDialogIndirect != NULL)
6182  hRet = pfnTaskDialogIndirect(&m_tdc, pnButton, pnRadioButton, pfVerificationFlagChecked);
6183 
6184  ::FreeLibrary(m_hCommCtrlDLL);
6185  }
6186 
6187  return hRet;
6188 #endif
6189  }
6190 
6191 // Operations - setting values of TASKDIALOGCONFIG
6192  // common buttons
6193  void SetCommonButtons(TASKDIALOG_COMMON_BUTTON_FLAGS dwCommonButtons)
6194  { m_tdc.SetCommonButtons(dwCommonButtons); }
6195  // window title text
6196  void SetWindowTitle(UINT nID)
6197  { m_tdc.SetWindowTitle(nID); }
6198  void SetWindowTitle(LPCWSTR lpstrWindowTitle)
6199  { m_tdc.SetWindowTitle(lpstrWindowTitle); }
6200  // main icon
6201  void SetMainIcon(HICON hIcon)
6202  { m_tdc.SetMainIcon(hIcon); }
6203  void SetMainIcon(UINT nID)
6204  { m_tdc.SetMainIcon(nID); }
6205  void SetMainIcon(LPCWSTR lpstrMainIcon)
6206  { m_tdc.SetMainIcon(lpstrMainIcon); }
6207  // main instruction text
6208  void SetMainInstructionText(UINT nID)
6209  { m_tdc.SetMainInstructionText(nID); }
6210  void SetMainInstructionText(LPCWSTR lpstrMainInstruction)
6211  { m_tdc.SetMainInstructionText(lpstrMainInstruction); }
6212  // content text
6213  void SetContentText(UINT nID)
6214  { m_tdc.SetContentText(nID); }
6215  void SetContentText(LPCWSTR lpstrContent)
6216  { m_tdc.SetContentText(lpstrContent); }
6217  // buttons
6218  void SetButtons(const TASKDIALOG_BUTTON* pButtons, UINT cButtons, int nDefaultButton = 0)
6219  { m_tdc.SetButtons(pButtons, cButtons, nDefaultButton); }
6220  void SetDefaultButton(int nDefaultButton)
6221  { m_tdc.SetDefaultButton(nDefaultButton); }
6222  // radio buttons
6223  void SetRadioButtons(const TASKDIALOG_BUTTON* pRadioButtons, UINT cRadioButtons, int nDefaultRadioButton = 0)
6224  { m_tdc.SetRadioButtons(pRadioButtons, cRadioButtons, nDefaultRadioButton); }
6225  void SetDefaultRadioButton(int nDefaultRadioButton)
6226  { m_tdc.SetDefaultRadioButton(nDefaultRadioButton); }
6227  // verification text
6228  void SetVerificationText(UINT nID)
6229  { m_tdc.SetVerificationText(nID); }
6230  void SetVerificationText(LPCWSTR lpstrVerificationText)
6231  { m_tdc.SetVerificationText(lpstrVerificationText); }
6232  // expanded information text
6233  void SetExpandedInformationText(UINT nID)
6234  { m_tdc.SetExpandedInformationText(nID); }
6235  void SetExpandedInformationText(LPCWSTR lpstrExpandedInformation)
6236  { m_tdc.SetExpandedInformationText(lpstrExpandedInformation); }
6237  // expanded control text
6238  void SetExpandedControlText(UINT nID)
6239  { m_tdc.SetExpandedControlText(nID); }
6240  void SetExpandedControlText(LPCWSTR lpstrExpandedControlText)
6241  { m_tdc.SetExpandedControlText(lpstrExpandedControlText); }
6242  // collapsed control text
6243  void SetCollapsedControlText(UINT nID)
6244  { m_tdc.SetCollapsedControlText(nID); }
6245  void SetCollapsedControlText(LPCWSTR lpstrCollapsedControlText)
6246  { m_tdc.SetCollapsedControlText(lpstrCollapsedControlText); }
6247  // footer icon
6248  void SetFooterIcon(HICON hIcon)
6249  { m_tdc.SetFooterIcon(hIcon); }
6250  void SetFooterIcon(UINT nID)
6251  { m_tdc.SetFooterIcon(nID); }
6252  void SetFooterIcon(LPCWSTR lpstrFooterIcon)
6253  { m_tdc.SetFooterIcon(lpstrFooterIcon); }
6254  // footer text
6255  void SetFooterText(UINT nID)
6256  { m_tdc.SetFooterText(nID); }
6257  void SetFooterText(LPCWSTR lpstrFooterText)
6258  { m_tdc.SetFooterText(lpstrFooterText); }
6259  // width (in DLUs)
6260  void SetWidth(UINT cxWidth)
6261  { m_tdc.SetWidth(cxWidth); }
6262  // modify flags
6263  void ModifyFlags(DWORD dwRemove, DWORD dwAdd)
6264  { m_tdc.ModifyFlags(dwRemove, dwAdd); }
6265 
6266 // Implementation
6267  static HRESULT CALLBACK TaskDialogCallback(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam, LONG_PTR lpRefData)
6268  {
6269  T* pT = (T*)lpRefData;
6270  ATLASSERT(pT->m_hWnd == NULL || pT->m_hWnd == hWnd);
6271 
6272  BOOL bRet = FALSE;
6273  switch(uMsg)
6274  {
6275  case TDN_DIALOG_CONSTRUCTED:
6276  pT->m_hWnd = hWnd;
6277  pT->OnDialogConstructed();
6278  break;
6279  case TDN_CREATED:
6280  pT->OnCreated();
6281  break;
6282  case TDN_BUTTON_CLICKED:
6283  bRet = pT->OnButtonClicked((int)wParam);
6284  break;
6285  case TDN_RADIO_BUTTON_CLICKED:
6286  pT->OnRadioButtonClicked((int)wParam);
6287  break;
6288  case TDN_HYPERLINK_CLICKED:
6289  pT->OnHyperlinkClicked((LPCWSTR)lParam);
6290  break;
6291  case TDN_EXPANDO_BUTTON_CLICKED:
6292  pT->OnExpandoButtonClicked((wParam != 0));
6293  break;
6294  case TDN_VERIFICATION_CLICKED:
6295  pT->OnVerificationClicked((wParam != 0));
6296  break;
6297  case TDN_HELP:
6298  pT->OnHelp();
6299  break;
6300  case TDN_TIMER:
6301  bRet = pT->OnTimer((DWORD)wParam);
6302  break;
6303  case TDN_NAVIGATED:
6304  pT->OnNavigated();
6305  break;
6306  case TDN_DESTROYED:
6307  pT->OnDestroyed();
6308  pT->m_hWnd = NULL;
6309  break;
6310  default:
6311  ATLTRACE2(atlTraceUI, 0, _T("Unknown notification received in CTaskDialogImpl::TaskDialogCallback\n"));
6312  break;
6313  }
6314 
6315  return (bRet != FALSE) ? S_OK : S_FALSE;
6316  }
6317 
6318 // Overrideables - notification handlers
6319  void OnDialogConstructed()
6320  {
6321  }
6322 
6323  void OnCreated()
6324  {
6325  }
6326 
6327  BOOL OnButtonClicked(int /*nButton*/)
6328  {
6329  return FALSE; // don't prevent dialog to close
6330  }
6331 
6332  void OnRadioButtonClicked(int /*nRadioButton*/)
6333  {
6334  }
6335 
6336  void OnHyperlinkClicked(LPCWSTR /*pszHREF*/)
6337  {
6338  }
6339 
6340  void OnExpandoButtonClicked(bool /*bExpanded*/)
6341  {
6342  }
6343 
6344  void OnVerificationClicked(bool /*bChecked*/)
6345  {
6346  }
6347 
6348  void OnHelp()
6349  {
6350  }
6351 
6352  BOOL OnTimer(DWORD /*dwTickCount*/)
6353  {
6354  return FALSE; // don't reset counter
6355  }
6356 
6357  void OnNavigated()
6358  {
6359  }
6360 
6361  void OnDestroyed()
6362  {
6363  }
6364 
6365 // Commands - valid to call only from handlers
6366  void NavigatePage(TASKDIALOGCONFIG& tdc)
6367  {
6368  ATLASSERT(m_hWnd != NULL);
6369 
6370  tdc.cbSize = sizeof(TASKDIALOGCONFIG);
6371  if(tdc.hwndParent == NULL)
6372  tdc.hwndParent = m_tdc.hwndParent;
6373  tdc.pfCallback = m_tdc.pfCallback;
6374  tdc.lpCallbackData = m_tdc.lpCallbackData;
6375  (TASKDIALOGCONFIG)m_tdc = tdc;
6376 
6377  ::SendMessage(m_hWnd, TDM_NAVIGATE_PAGE, 0, (LPARAM)&tdc);
6378  }
6379 
6380  // modify TASKDIALOGCONFIG values, then call this to update task dialog
6381  void NavigatePage()
6382  {
6383  ATLASSERT(m_hWnd != NULL);
6384  ::SendMessage(m_hWnd, TDM_NAVIGATE_PAGE, 0, (LPARAM)&m_tdc);
6385  }
6386 
6387  void ClickButton(int nButton)
6388  {
6389  ATLASSERT(m_hWnd != NULL);
6390  ::SendMessage(m_hWnd, TDM_CLICK_BUTTON, nButton, 0L);
6391  }
6392 
6393  void SetMarqueeProgressBar(BOOL bMarquee)
6394  {
6395  ATLASSERT(m_hWnd != NULL);
6396  ::SendMessage(m_hWnd, TDM_SET_MARQUEE_PROGRESS_BAR, bMarquee, 0L);
6397  }
6398 
6399  BOOL SetProgressBarState(int nNewState)
6400  {
6401  ATLASSERT(m_hWnd != NULL);
6402  return (BOOL)::SendMessage(m_hWnd, TDM_SET_PROGRESS_BAR_STATE, nNewState, 0L);
6403  }
6404 
6405  DWORD SetProgressBarRange(int nMinRange, int nMaxRange)
6406  {
6407  ATLASSERT(m_hWnd != NULL);
6408  return (DWORD)::SendMessage(m_hWnd, TDM_SET_PROGRESS_BAR_RANGE, 0, MAKELPARAM(nMinRange, nMaxRange));
6409  }
6410 
6411  int SetProgressBarPos(int nNewPos)
6412  {
6413  ATLASSERT(m_hWnd != NULL);
6414  return (int)::SendMessage(m_hWnd, TDM_SET_PROGRESS_BAR_POS, nNewPos, 0L);
6415  }
6416 
6417  BOOL SetProgressBarMarquee(BOOL bMarquee, UINT uSpeed)
6418  {
6419  ATLASSERT(m_hWnd != NULL);
6420  return (BOOL)::SendMessage(m_hWnd, TDM_SET_PROGRESS_BAR_MARQUEE, bMarquee, uSpeed);
6421  }
6422 
6423  void SetElementText(TASKDIALOG_ELEMENTS element, LPCWSTR lpstrText)
6424  {
6425  ATLASSERT(m_hWnd != NULL);
6426  ::SendMessage(m_hWnd, TDM_SET_ELEMENT_TEXT, element, (LPARAM)lpstrText);
6427  }
6428 
6429  void ClickRadioButton(int nRadioButton)
6430  {
6431  ATLASSERT(m_hWnd != NULL);
6432  ::SendMessage(m_hWnd, TDM_CLICK_RADIO_BUTTON, nRadioButton, 0L);
6433  }
6434 
6435  void EnableButton(int nButton, BOOL bEnable)
6436  {
6437  ATLASSERT(m_hWnd != NULL);
6438  ::SendMessage(m_hWnd, TDM_ENABLE_BUTTON, nButton, bEnable);
6439  }
6440 
6441  void EnableRadioButton(int nButton, BOOL bEnable)
6442  {
6443  ATLASSERT(m_hWnd != NULL);
6444  ::SendMessage(m_hWnd, TDM_ENABLE_RADIO_BUTTON, nButton, bEnable);
6445  }
6446 
6447  void ClickVerification(BOOL bCheck, BOOL bFocus)
6448  {
6449  ATLASSERT(m_hWnd != NULL);
6450  ::SendMessage(m_hWnd, TDM_CLICK_VERIFICATION, bCheck, bFocus);
6451  }
6452 
6453  void UpdateElementText(TASKDIALOG_ELEMENTS element, LPCWSTR lpstrText)
6454  {
6455  ATLASSERT(m_hWnd != NULL);
6456  ::SendMessage(m_hWnd, TDM_UPDATE_ELEMENT_TEXT, element, (LPARAM)lpstrText);
6457  }
6458 
6459  void SetButtonElevationRequiredState(int nButton, BOOL bElevation)
6460  {
6461  ATLASSERT(m_hWnd != NULL);
6462  ::SendMessage(m_hWnd, TDM_SET_BUTTON_ELEVATION_REQUIRED_STATE, nButton, bElevation);
6463  }
6464 
6465  void UpdateIcon(TASKDIALOG_ICON_ELEMENTS element, HICON hIcon)
6466  {
6467  ATLASSERT(m_hWnd != NULL);
6468 #ifdef _DEBUG
6469  if(element == TDIE_ICON_MAIN)
6470  ATLASSERT((m_tdc.dwFlags & TDF_USE_HICON_MAIN) != 0);
6471  else if(element == TDIE_ICON_FOOTER)
6472  ATLASSERT((m_tdc.dwFlags & TDF_USE_HICON_FOOTER) != 0);
6473 #endif // _DEBUG
6474  ::SendMessage(m_hWnd, TDM_UPDATE_ICON, element, (LPARAM)hIcon);
6475  }
6476 
6477  void UpdateIcon(TASKDIALOG_ICON_ELEMENTS element, LPCWSTR lpstrIcon)
6478  {
6479  ATLASSERT(m_hWnd != NULL);
6480 #ifdef _DEBUG
6481  if(element == TDIE_ICON_MAIN)
6482  ATLASSERT((m_tdc.dwFlags & TDF_USE_HICON_MAIN) == 0);
6483  else if(element == TDIE_ICON_FOOTER)
6484  ATLASSERT((m_tdc.dwFlags & TDF_USE_HICON_FOOTER) == 0);
6485 #endif // _DEBUG
6486  ::SendMessage(m_hWnd, TDM_UPDATE_ICON, element, (LPARAM)lpstrIcon);
6487  }
6488 };
6489 
6490 
6492 // CTaskDialog - for non-customized task dialogs
6493 
6494 class CTaskDialog : public CTaskDialogImpl<CTaskDialog>
6495 {
6496 public:
6497  CTaskDialog(HWND hWndParent = NULL) : CTaskDialogImpl<CTaskDialog>(hWndParent)
6498  {
6499  m_tdc.pfCallback = NULL;
6500  }
6501 };
6502 
6503 #endif // ((_WIN32_WINNT >= 0x0600) || defined(_WTL_TASKDIALOG)) && !defined(_WIN32_WCE)
6504 
6505 }; // namespace WTL
6506 
6507 #endif // __ATLDLGS_H__
Definition: atlwinx.h:452
Definition: atldlgs.h:3218
Definition: atldlgs.h:3985
Definition: atldlgs.h:1600
Definition: atldlgs.h:2197
Definition: atldlgs.h:3621
Definition: atldlgs.h:4392
Definition: atldlgs.h:1653
Definition: atldlgs.h:5239
Definition: atldlgs.h:4918
Definition: atldlgs.h:2728
Definition: atldlgs.h:2878
Definition: atlgdi.h:3386
Definition: atldlgs.h:2243
Definition: atldlgs.h:4404
Definition: atldlgs.h:876
Definition: atldlgs.h:1326
Definition: atldlgs.h:3202
Definition: atldlgs.h:416
Definition: atlwinx.h:442
Definition: atlapp.h:553
Definition: atldlgs.h:2901
Definition: atldlgs.h:2008
Definition: atlapp.h:1455
Definition: atldlgs.h:2445
Definition: atldlgs.h:1825
Definition: atldlgs.h:3055
Definition: atlwinx.h:432
Definition: atlgdi.h:3407
Definition: atldlgs.h:3713
Definition: atldlgs.h:472
Definition: atldlgs.h:1586
Definition: atldlgs.h:4899
Definition: atldlgs.h:123
Definition: atldlgs.h:3042
Definition: atldlgs.h:4486