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