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