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