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