Mercurial > foo_out_sdl
comparison foosdk/wtl/Include/atldlgs.h @ 1:20d02a178406 default tip
*: check in everything else
yay
| author | Paper <paper@tflc.us> |
|---|---|
| date | Mon, 05 Jan 2026 02:15:46 -0500 |
| parents | |
| children |
comparison
equal
deleted
inserted
replaced
| 0:e9bb126753e7 | 1:20d02a178406 |
|---|---|
| 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, | |
| 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 | |
| 170 ATL::CWindow GetFileDialogWindow() const | |
| 171 { | |
| 172 ATLASSERT(::IsWindow(m_hWnd)); | |
| 173 return ATL::CWindow(GetParent()); | |
| 174 } | |
| 175 | |
| 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 | |
| 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 | |
| 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 | |
| 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 | |
| 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 | |
| 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 | |
| 224 BOOL GetReadOnlyPref() const // return TRUE if readonly checked | |
| 225 { | |
| 226 return ((m_ofn.Flags & OFN_READONLY) != 0) ? TRUE : FALSE; | |
| 227 } | |
| 228 | |
| 229 // Operations | |
| 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) | |
| 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 | |
| 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 | |
| 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 | |
| 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 | |
| 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 | |
| 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 | |
| 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 | |
| 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 | |
| 320 BOOL OnFileOK(LPOFNOTIFY /*lpon*/) | |
| 321 { | |
| 322 return TRUE; | |
| 323 } | |
| 324 | |
| 325 void OnFolderChange(LPOFNOTIFY /*lpon*/) | |
| 326 { | |
| 327 } | |
| 328 | |
| 329 void OnHelp(LPOFNOTIFY /*lpon*/) | |
| 330 { | |
| 331 } | |
| 332 | |
| 333 void OnInitDone(LPOFNOTIFY /*lpon*/) | |
| 334 { | |
| 335 } | |
| 336 | |
| 337 void OnSelChange(LPOFNOTIFY /*lpon*/) | |
| 338 { | |
| 339 } | |
| 340 | |
| 341 int OnShareViolation(LPOFNOTIFY /*lpon*/) | |
| 342 { | |
| 343 return 0; | |
| 344 } | |
| 345 | |
| 346 void OnTypeChange(LPOFNOTIFY /*lpon*/) | |
| 347 { | |
| 348 } | |
| 349 | |
| 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, | |
| 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 | |
| 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. | |
| 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__ | |
| 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. | |
| 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. | |
| 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. | |
| 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__ | |
| 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. | |
| 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__ | |
| 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 | |
| 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 | |
| 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 | |
| 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 | |
| 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 | |
| 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__ | |
| 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 | |
| 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 | |
| 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__ | |
| 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 | |
| 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 | |
| 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 | |
| 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 | |
| 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 | |
| 1078 virtual ULONG STDMETHODCALLTYPE AddRef() | |
| 1079 { | |
| 1080 return 1; | |
| 1081 } | |
| 1082 | |
| 1083 virtual ULONG STDMETHODCALLTYPE Release() | |
| 1084 { | |
| 1085 return 1; | |
| 1086 } | |
| 1087 | |
| 1088 // Implementation - IFileDialogEvents interface | |
| 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 | |
| 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 | |
| 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 | |
| 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 | |
| 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 | |
| 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 | |
| 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 | |
| 1146 HRESULT OnFileOk() | |
| 1147 { | |
| 1148 return E_NOTIMPL; | |
| 1149 } | |
| 1150 | |
| 1151 HRESULT OnFolderChanging(IShellItem* /*psiFolder*/) | |
| 1152 { | |
| 1153 return E_NOTIMPL; | |
| 1154 } | |
| 1155 | |
| 1156 HRESULT OnFolderChange() | |
| 1157 { | |
| 1158 return E_NOTIMPL; | |
| 1159 } | |
| 1160 | |
| 1161 HRESULT OnSelectionChange() | |
| 1162 { | |
| 1163 return E_NOTIMPL; | |
| 1164 } | |
| 1165 | |
| 1166 HRESULT OnShareViolation(IShellItem* /*psi*/, FDE_SHAREVIOLATION_RESPONSE* /*pResponse*/) | |
| 1167 { | |
| 1168 return E_NOTIMPL; | |
| 1169 } | |
| 1170 | |
| 1171 HRESULT OnTypeChange() | |
| 1172 { | |
| 1173 return E_NOTIMPL; | |
| 1174 } | |
| 1175 | |
| 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 | |
| 1204 virtual ~CShellFileOpenDialogImpl() | |
| 1205 { } | |
| 1206 | |
| 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 | |
| 1227 virtual ~CShellFileOpenDialog() | |
| 1228 { } | |
| 1229 | |
| 1230 // Implementation (remove _Advise/_Unadvise code using template magic) | |
| 1231 void _Advise(DWORD& /*dwCookie*/) | |
| 1232 { } | |
| 1233 | |
| 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 | |
| 1260 virtual ~CShellFileSaveDialogImpl() | |
| 1261 { } | |
| 1262 | |
| 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 | |
| 1283 virtual ~CShellFileSaveDialog() | |
| 1284 { } | |
| 1285 | |
| 1286 // Implementation (remove _Advise/_Unadvise code using template magic) | |
| 1287 void _Advise(DWORD& /*dwCookie*/) | |
| 1288 { } | |
| 1289 | |
| 1290 void _Unadvise(DWORD /*dwCookie*/) | |
| 1291 { } | |
| 1292 }; | |
| 1293 | |
| 1294 #endif // (_WIN32_WINNT >= 0x0600) | |
| 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) : | |
| 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 | |
| 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 | |
| 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 | |
| 1403 LPCTSTR GetFolderPath() const | |
| 1404 { | |
| 1405 return m_szFolderPath; | |
| 1406 } | |
| 1407 | |
| 1408 LPCTSTR GetFolderDisplayName() const | |
| 1409 { | |
| 1410 return m_szFolderDisplayName; | |
| 1411 } | |
| 1412 | |
| 1413 int GetFolderImageIndex() const | |
| 1414 { | |
| 1415 return m_bi.iImage; | |
| 1416 } | |
| 1417 | |
| 1418 // Callback function and overrideables | |
| 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 | |
| 1473 void OnInitialized() | |
| 1474 { | |
| 1475 } | |
| 1476 | |
| 1477 void OnSelChanged(LPITEMIDLIST /*pItemIDList*/) | |
| 1478 { | |
| 1479 } | |
| 1480 | |
| 1481 int OnValidateFailed(LPCTSTR /*lpstrFolderPath*/) | |
| 1482 { | |
| 1483 return 1; // 1=continue, 0=EndDialog | |
| 1484 } | |
| 1485 | |
| 1486 void OnIUnknown(IUnknown* /*pUnknown*/) | |
| 1487 { | |
| 1488 } | |
| 1489 | |
| 1490 // Commands - valid to call only from handlers | |
| 1491 void EnableOK(BOOL bEnable) | |
| 1492 { | |
| 1493 ATLASSERT(m_hWnd != NULL); | |
| 1494 ::SendMessage(m_hWnd, BFFM_ENABLEOK, 0, bEnable); | |
| 1495 } | |
| 1496 | |
| 1497 void SetSelection(LPCITEMIDLIST pItemIDList) | |
| 1498 { | |
| 1499 ATLASSERT(m_hWnd != NULL); | |
| 1500 ::SendMessage(m_hWnd, BFFM_SETSELECTION, FALSE, (LPARAM)pItemIDList); | |
| 1501 } | |
| 1502 | |
| 1503 void SetSelection(LPCTSTR lpstrFolderPath) | |
| 1504 { | |
| 1505 ATLASSERT(m_hWnd != NULL); | |
| 1506 ::SendMessage(m_hWnd, BFFM_SETSELECTION, TRUE, (LPARAM)lpstrFolderPath); | |
| 1507 } | |
| 1508 | |
| 1509 void SetStatusText(LPCTSTR lpstrText) | |
| 1510 { | |
| 1511 ATLASSERT(m_hWnd != NULL); | |
| 1512 ::SendMessage(m_hWnd, BFFM_SETSTATUSTEXT, 0, (LPARAM)lpstrText); | |
| 1513 } | |
| 1514 | |
| 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 | |
| 1523 void SetExpanded(LPCITEMIDLIST pItemIDList) | |
| 1524 { | |
| 1525 ATLASSERT(m_hWnd != NULL); | |
| 1526 ::SendMessage(m_hWnd, BFFM_SETEXPANDED, FALSE, (LPARAM)pItemIDList); | |
| 1527 } | |
| 1528 | |
| 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: | |
| 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 | |
| 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 | |
| 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 | |
| 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 | |
| 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 | |
| 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 | |
| 1718 LPCTSTR GetFaceName() const // return the face name of the font | |
| 1719 { | |
| 1720 return (LPCTSTR)m_cf.lpLogFont->lfFaceName; | |
| 1721 } | |
| 1722 | |
| 1723 LPCTSTR GetStyleName() const // return the style name of the font | |
| 1724 { | |
| 1725 return m_cf.lpszStyle; | |
| 1726 } | |
| 1727 | |
| 1728 int GetSize() const // return the pt size of the font | |
| 1729 { | |
| 1730 return m_cf.iPointSize; | |
| 1731 } | |
| 1732 | |
| 1733 COLORREF GetColor() const // return the color of the font | |
| 1734 { | |
| 1735 return m_cf.rgbColors; | |
| 1736 } | |
| 1737 | |
| 1738 int GetWeight() const // return the chosen font weight | |
| 1739 { | |
| 1740 return (int)m_cf.lpLogFont->lfWeight; | |
| 1741 } | |
| 1742 | |
| 1743 BOOL IsStrikeOut() const // return TRUE if strikeout | |
| 1744 { | |
| 1745 return (m_cf.lpLogFont->lfStrikeOut) ? TRUE : FALSE; | |
| 1746 } | |
| 1747 | |
| 1748 BOOL IsUnderline() const // return TRUE if underline | |
| 1749 { | |
| 1750 return (m_cf.lpLogFont->lfUnderline) ? TRUE : FALSE; | |
| 1751 } | |
| 1752 | |
| 1753 BOOL IsBold() const // return TRUE if bold font | |
| 1754 { | |
| 1755 return (m_cf.lpLogFont->lfWeight == FW_BOLD) ? TRUE : FALSE; | |
| 1756 } | |
| 1757 | |
| 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 | |
| 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 | |
| 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 | |
| 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 | |
| 1982 COLORREF GetColor() const | |
| 1983 { | |
| 1984 return m_cc.rgbResult; | |
| 1985 } | |
| 1986 | |
| 1987 // Special override for the color dialog | |
| 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 | |
| 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 | |
| 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 | |
| 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) | |
| 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 | |
| 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 | |
| 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) | |
| 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 | |
| 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 | |
| 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 | |
| 2233 BOOL PrintCollate() const // TRUE if collate checked | |
| 2234 { | |
| 2235 return ((m_pd.Flags & PD_COLLATE) != 0) ? TRUE : FALSE; | |
| 2236 } | |
| 2237 | |
| 2238 BOOL PrintSelection() const // TRUE if printing selection | |
| 2239 { | |
| 2240 return ((m_pd.Flags & PD_SELECTION) != 0) ? TRUE : FALSE; | |
| 2241 } | |
| 2242 | |
| 2243 BOOL PrintAll() const // TRUE if printing all pages | |
| 2244 { | |
| 2245 return (!PrintRange() && !PrintSelection()) ? TRUE : FALSE; | |
| 2246 } | |
| 2247 | |
| 2248 BOOL PrintRange() const // TRUE if printing page range | |
| 2249 { | |
| 2250 return ((m_pd.Flags & PD_PAGENUMS) != 0) ? TRUE : FALSE; | |
| 2251 } | |
| 2252 | |
| 2253 BOOL PrintToFile() const // TRUE if printing to a file | |
| 2254 { | |
| 2255 return ((m_pd.Flags & PD_PRINTTOFILE) != 0) ? TRUE : FALSE; | |
| 2256 } | |
| 2257 | |
| 2258 int GetFromPage() const // starting page if valid | |
| 2259 { | |
| 2260 return PrintRange() ? m_pd.nFromPage : -1; | |
| 2261 } | |
| 2262 | |
| 2263 int GetToPage() const // ending page if valid | |
| 2264 { | |
| 2265 return PrintRange() ? m_pd.nToPage : -1; | |
| 2266 } | |
| 2267 | |
| 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 | |
| 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 | |
| 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 | |
| 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 | |
| 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. | |
| 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 | |
| 2333 CPrintDialogImpl(PRINTDLG& pdInit) : m_pd(pdInit) | |
| 2334 { } | |
| 2335 | |
| 2336 BEGIN_MSG_MAP(CPrintDialogImpl) | |
| 2337 #ifdef psh1 | |
| 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 | |
| 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 | |
| 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 | |
| 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 | |
| 2460 BOOL PrintCollate() const // TRUE if collate checked | |
| 2461 { | |
| 2462 return ((m_pdex.Flags & PD_COLLATE) != 0) ? TRUE : FALSE; | |
| 2463 } | |
| 2464 | |
| 2465 BOOL PrintSelection() const // TRUE if printing selection | |
| 2466 { | |
| 2467 return ((m_pdex.Flags & PD_SELECTION) != 0) ? TRUE : FALSE; | |
| 2468 } | |
| 2469 | |
| 2470 BOOL PrintAll() const // TRUE if printing all pages | |
| 2471 { | |
| 2472 return (!PrintRange() && !PrintSelection()) ? TRUE : FALSE; | |
| 2473 } | |
| 2474 | |
| 2475 BOOL PrintRange() const // TRUE if printing page range | |
| 2476 { | |
| 2477 return ((m_pdex.Flags & PD_PAGENUMS) != 0) ? TRUE : FALSE; | |
| 2478 } | |
| 2479 | |
| 2480 BOOL PrintToFile() const // TRUE if printing to a file | |
| 2481 { | |
| 2482 return ((m_pdex.Flags & PD_PRINTTOFILE) != 0) ? TRUE : FALSE; | |
| 2483 } | |
| 2484 | |
| 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 | |
| 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 | |
| 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 | |
| 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 | |
| 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. | |
| 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 | |
| 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 | |
| 2571 virtual ULONG STDMETHODCALLTYPE AddRef() | |
| 2572 { | |
| 2573 return 1; | |
| 2574 } | |
| 2575 | |
| 2576 virtual ULONG STDMETHODCALLTYPE Release() | |
| 2577 { | |
| 2578 return 1; | |
| 2579 } | |
| 2580 | |
| 2581 // IPrintDialogCallback | |
| 2582 STDMETHOD(InitDone)() | |
| 2583 { | |
| 2584 return S_FALSE; | |
| 2585 } | |
| 2586 | |
| 2587 STDMETHOD(SelectionChange)() | |
| 2588 { | |
| 2589 return S_FALSE; | |
| 2590 } | |
| 2591 | |
| 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 | |
| 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 | |
| 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 | |
| 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 | |
| 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 | |
| 2684 HDC CreatePrinterDC() | |
| 2685 { | |
| 2686 return _AtlCreateDC(m_psd.hDevNames, m_psd.hDevMode); | |
| 2687 } | |
| 2688 | |
| 2689 SIZE GetPaperSize() const | |
| 2690 { | |
| 2691 SIZE size = { m_psd.ptPaperSize.x, m_psd.ptPaperSize.y }; | |
| 2692 return size; | |
| 2693 } | |
| 2694 | |
| 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 | |
| 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 | |
| 2759 UINT_PTR PreDrawPage(WORD /*wPaper*/, WORD /*wFlags*/, LPPAGESETUPDLG /*pPSD*/) | |
| 2760 { | |
| 2761 // return 1 to prevent any more drawing | |
| 2762 return 0; | |
| 2763 } | |
| 2764 | |
| 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 | |
| 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 | |
| 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() | |
| 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 | |
| 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 | |
| 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 | |
| 2883 LPCTSTR GetFindString() const // get find string | |
| 2884 { | |
| 2885 return (LPCTSTR)m_fr.lpstrFindWhat; | |
| 2886 } | |
| 2887 | |
| 2888 LPCTSTR GetReplaceString() const // get replacement string | |
| 2889 { | |
| 2890 return (LPCTSTR)m_fr.lpstrReplaceWith; | |
| 2891 } | |
| 2892 | |
| 2893 BOOL SearchDown() const // TRUE if search down, FALSE is up | |
| 2894 { | |
| 2895 return ((m_fr.Flags & FR_DOWN) != 0) ? TRUE : FALSE; | |
| 2896 } | |
| 2897 | |
| 2898 BOOL FindNext() const // TRUE if command is find next | |
| 2899 { | |
| 2900 return ((m_fr.Flags & FR_FINDNEXT) != 0) ? TRUE : FALSE; | |
| 2901 } | |
| 2902 | |
| 2903 BOOL MatchCase() const // TRUE if matching case | |
| 2904 { | |
| 2905 return ((m_fr.Flags & FR_MATCHCASE) != 0) ? TRUE : FALSE; | |
| 2906 } | |
| 2907 | |
| 2908 BOOL MatchWholeWord() const // TRUE if matching whole words only | |
| 2909 { | |
| 2910 return ((m_fr.Flags & FR_WHOLEWORD) != 0) ? TRUE : FALSE; | |
| 2911 } | |
| 2912 | |
| 2913 BOOL ReplaceCurrent() const // TRUE if replacing current string | |
| 2914 { | |
| 2915 return ((m_fr. Flags & FR_REPLACE) != 0) ? TRUE : FALSE; | |
| 2916 } | |
| 2917 | |
| 2918 BOOL ReplaceAll() const // TRUE if replacing all occurrences | |
| 2919 { | |
| 2920 return ((m_fr.Flags & FR_REPLACEALL) != 0) ? TRUE : FALSE; | |
| 2921 } | |
| 2922 | |
| 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 | |
| 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 | |
| 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 | |
| 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 | |
| 3015 SIZE GetDialogBaseUnits() const | |
| 3016 { | |
| 3017 return m_sizeUnits; | |
| 3018 } | |
| 3019 | |
| 3020 INT MapDialogPixelsX(INT x) const | |
| 3021 { | |
| 3022 return ::MulDiv(x, 4, m_sizeUnits.cx); // Pixels X to DLU | |
| 3023 } | |
| 3024 | |
| 3025 INT MapDialogPixelsY(INT y) const | |
| 3026 { | |
| 3027 return ::MulDiv(y, 8, m_sizeUnits.cy); // Pixels Y to DLU | |
| 3028 } | |
| 3029 | |
| 3030 POINT MapDialogPixels(POINT pt) const | |
| 3031 { | |
| 3032 POINT out = { MapDialogPixelsX(pt.x), MapDialogPixelsY(pt.y) }; | |
| 3033 return out; | |
| 3034 } | |
| 3035 | |
| 3036 SIZE MapDialogPixels(SIZE input) const | |
| 3037 { | |
| 3038 SIZE out = { MapDialogPixelsX(input.cx), MapDialogPixelsY(input.cy) }; | |
| 3039 return out; | |
| 3040 } | |
| 3041 | |
| 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 | |
| 3048 INT MapDialogUnitsX(INT x) const | |
| 3049 { | |
| 3050 return ::MulDiv(x, m_sizeUnits.cx, 4); // DLU to Pixels X | |
| 3051 } | |
| 3052 | |
| 3053 INT MapDialogUnitsY(INT y) const | |
| 3054 { | |
| 3055 return ::MulDiv(y, m_sizeUnits.cy, 8); // DLU to Pixels Y | |
| 3056 } | |
| 3057 | |
| 3058 POINT MapDialogUnits(POINT pt) const | |
| 3059 { | |
| 3060 POINT out = { MapDialogUnitsX(pt.x), MapDialogUnitsY(pt.y) }; | |
| 3061 return out; | |
| 3062 } | |
| 3063 | |
| 3064 SIZE MapDialogUnits(SIZE input) const | |
| 3065 { | |
| 3066 SIZE out = { MapDialogUnitsX(input.cx), MapDialogUnitsY(input.cy) }; | |
| 3067 return out; | |
| 3068 } | |
| 3069 | |
| 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 | |
| 3106 CMemDlgTemplateT() : m_hData(NULL), m_pData(NULL), m_pPtr(NULL), m_cAllocated(0) | |
| 3107 { } | |
| 3108 | |
| 3109 ~CMemDlgTemplateT() | |
| 3110 { | |
| 3111 Reset(); | |
| 3112 } | |
| 3113 | |
| 3114 bool IsValid() const | |
| 3115 { | |
| 3116 return (m_pData != NULL); | |
| 3117 } | |
| 3118 | |
| 3119 bool IsTemplateEx() const | |
| 3120 { | |
| 3121 return (IsValid() && ((DLGTEMPLATEEX*)m_pData)->signature == 0xFFFF); | |
| 3122 } | |
| 3123 | |
| 3124 LPDLGTEMPLATE GetTemplatePtr() | |
| 3125 { | |
| 3126 return reinterpret_cast<LPDLGTEMPLATE>(m_pData); | |
| 3127 } | |
| 3128 | |
| 3129 DLGTEMPLATEEX* GetTemplateExPtr() | |
| 3130 { | |
| 3131 return reinterpret_cast<DLGTEMPLATEEX*>(m_pData); | |
| 3132 } | |
| 3133 | |
| 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 | |
| 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 | |
| 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 | |
| 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 | |
| 3543 void DoInitTemplate() | |
| 3544 { | |
| 3545 ATLASSERT(FALSE); // MUST be defined in derived class | |
| 3546 } | |
| 3547 | |
| 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 | |
| 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 | |
| 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 | |
| 3580 HWND GetActivePage() const | |
| 3581 { | |
| 3582 ATLASSERT(::IsWindow(m_hWnd)); | |
| 3583 return (HWND)::SendMessage(m_hWnd, PSM_GETCURRENTPAGEHWND, 0, 0L); | |
| 3584 } | |
| 3585 | |
| 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 | |
| 3594 BOOL SetActivePage(int nPageIndex) | |
| 3595 { | |
| 3596 ATLASSERT(::IsWindow(m_hWnd)); | |
| 3597 return (BOOL)::SendMessage(m_hWnd, PSM_SETCURSEL, nPageIndex, 0L); | |
| 3598 } | |
| 3599 | |
| 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 | |
| 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 | |
| 3621 HWND GetTabControl() const | |
| 3622 { | |
| 3623 ATLASSERT(::IsWindow(m_hWnd)); | |
| 3624 return (HWND)::SendMessage(m_hWnd, PSM_GETTABCONTROL, 0, 0L); | |
| 3625 } | |
| 3626 | |
| 3627 void SetFinishText(LPCTSTR lpszText) | |
| 3628 { | |
| 3629 ATLASSERT(::IsWindow(m_hWnd)); | |
| 3630 ::SendMessage(m_hWnd, PSM_SETFINISHTEXT, 0, (LPARAM)lpszText); | |
| 3631 } | |
| 3632 | |
| 3633 void SetWizardButtons(DWORD dwFlags) | |
| 3634 { | |
| 3635 ATLASSERT(::IsWindow(m_hWnd)); | |
| 3636 ::PostMessage(m_hWnd, PSM_SETWIZBUTTONS, 0, dwFlags); | |
| 3637 } | |
| 3638 | |
| 3639 // Operations | |
| 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 | |
| 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 | |
| 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 | |
| 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 | |
| 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 | |
| 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 | |
| 3691 void RemovePage(int nPageIndex) | |
| 3692 { | |
| 3693 ATLASSERT(::IsWindow(m_hWnd)); | |
| 3694 ::SendMessage(m_hWnd, PSM_REMOVEPAGE, nPageIndex, 0L); | |
| 3695 } | |
| 3696 | |
| 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 | |
| 3704 BOOL PressButton(int nButton) | |
| 3705 { | |
| 3706 ATLASSERT(::IsWindow(m_hWnd)); | |
| 3707 return (BOOL)::SendMessage(m_hWnd, PSM_PRESSBUTTON, nButton, 0L); | |
| 3708 } | |
| 3709 | |
| 3710 BOOL Apply() | |
| 3711 { | |
| 3712 ATLASSERT(::IsWindow(m_hWnd)); | |
| 3713 return (BOOL)::SendMessage(m_hWnd, PSM_APPLY, 0, 0L); | |
| 3714 } | |
| 3715 | |
| 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 | |
| 3730 LRESULT QuerySiblings(WPARAM wParam, LPARAM lParam) | |
| 3731 { | |
| 3732 ATLASSERT(::IsWindow(m_hWnd)); | |
| 3733 return ::SendMessage(m_hWnd, PSM_QUERYSIBLINGS, wParam, lParam); | |
| 3734 } | |
| 3735 | |
| 3736 void RebootSystem() | |
| 3737 { | |
| 3738 ATLASSERT(::IsWindow(m_hWnd)); | |
| 3739 ::SendMessage(m_hWnd, PSM_REBOOTSYSTEM, 0, 0L); | |
| 3740 } | |
| 3741 | |
| 3742 void RestartWindows() | |
| 3743 { | |
| 3744 ATLASSERT(::IsWindow(m_hWnd)); | |
| 3745 ::SendMessage(m_hWnd, PSM_RESTARTWINDOWS, 0, 0L); | |
| 3746 } | |
| 3747 | |
| 3748 BOOL IsDialogMessage(LPMSG lpMsg) | |
| 3749 { | |
| 3750 ATLASSERT(::IsWindow(m_hWnd)); | |
| 3751 return (BOOL)::SendMessage(m_hWnd, PSM_ISDIALOGMESSAGE, 0, (LPARAM)lpMsg); | |
| 3752 } | |
| 3753 | |
| 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 | |
| 3760 HWND IndexToHwnd(int nIndex) const | |
| 3761 { | |
| 3762 ATLASSERT(::IsWindow(m_hWnd)); | |
| 3763 return (HWND)::SendMessage(m_hWnd, PSM_INDEXTOHWND, nIndex, 0L); | |
| 3764 } | |
| 3765 | |
| 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 | |
| 3772 HPROPSHEETPAGE IndexToPage(int nIndex) const | |
| 3773 { | |
| 3774 ATLASSERT(::IsWindow(m_hWnd)); | |
| 3775 return (HPROPSHEETPAGE)::SendMessage(m_hWnd, PSM_INDEXTOPAGE, nIndex, 0L); | |
| 3776 } | |
| 3777 | |
| 3778 int IdToIndex(int nID) const | |
| 3779 { | |
| 3780 ATLASSERT(::IsWindow(m_hWnd)); | |
| 3781 return (int)::SendMessage(m_hWnd, PSM_IDTOINDEX, 0, nID); | |
| 3782 } | |
| 3783 | |
| 3784 int IndexToId(int nIndex) const | |
| 3785 { | |
| 3786 ATLASSERT(::IsWindow(m_hWnd)); | |
| 3787 return (int)::SendMessage(m_hWnd, PSM_INDEXTOID, nIndex, 0L); | |
| 3788 } | |
| 3789 | |
| 3790 int GetResult() const | |
| 3791 { | |
| 3792 ATLASSERT(::IsWindow(m_hWnd)); | |
| 3793 return (int)::SendMessage(m_hWnd, PSM_GETRESULT, 0, 0L); | |
| 3794 } | |
| 3795 | |
| 3796 BOOL RecalcPageSizes() | |
| 3797 { | |
| 3798 ATLASSERT(::IsWindow(m_hWnd)); | |
| 3799 return (BOOL)::SendMessage(m_hWnd, PSM_RECALCPAGESIZES, 0, 0L); | |
| 3800 } | |
| 3801 | |
| 3802 void SetHeaderTitle(int nIndex, LPCTSTR lpstrHeaderTitle) | |
| 3803 { | |
| 3804 ATLASSERT(::IsWindow(m_hWnd)); | |
| 3805 ::SendMessage(m_hWnd, PSM_SETHEADERTITLE, nIndex, (LPARAM)lpstrHeaderTitle); | |
| 3806 } | |
| 3807 | |
| 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 | |
| 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 | |
| 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 | |
| 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 | |
| 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 | |
| 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 | |
| 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 | |
| 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 | |
| 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 | |
| 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 | |
| 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 | |
| 4022 void SetWizardMode() | |
| 4023 { | |
| 4024 m_psh.dwFlags |= PSH_WIZARD; | |
| 4025 } | |
| 4026 | |
| 4027 void EnableHelp() | |
| 4028 { | |
| 4029 m_psh.dwFlags |= PSH_HASHELP; | |
| 4030 } | |
| 4031 | |
| 4032 // Operations | |
| 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 | |
| 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 | |
| 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 | |
| 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 | |
| 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 | |
| 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 | |
| 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) | |
| 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 | |
| 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 | |
| 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 | |
| 4190 CPropertySheetWindow GetPropertySheet() const | |
| 4191 { | |
| 4192 ATLASSERT(::IsWindow(m_hWnd)); | |
| 4193 return CPropertySheetWindow(GetParent()); | |
| 4194 } | |
| 4195 | |
| 4196 // Operations | |
| 4197 BOOL Apply() | |
| 4198 { | |
| 4199 ATLASSERT(::IsWindow(m_hWnd)); | |
| 4200 ATLASSERT(GetParent() != NULL); | |
| 4201 return GetPropertySheet().Apply(); | |
| 4202 } | |
| 4203 | |
| 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 | |
| 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 | |
| 4225 void RebootSystem() | |
| 4226 { | |
| 4227 ATLASSERT(::IsWindow(m_hWnd)); | |
| 4228 ATLASSERT(GetParent() != NULL); | |
| 4229 GetPropertySheet().RebootSystem(); | |
| 4230 } | |
| 4231 | |
| 4232 void RestartWindows() | |
| 4233 { | |
| 4234 ATLASSERT(::IsWindow(m_hWnd)); | |
| 4235 ATLASSERT(GetParent() != NULL); | |
| 4236 GetPropertySheet().RestartWindows(); | |
| 4237 } | |
| 4238 | |
| 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 | |
| 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 | |
| 4326 bool OnPageCreate() | |
| 4327 { | |
| 4328 return true; // true - allow page to be created, false - prevent creation | |
| 4329 } | |
| 4330 | |
| 4331 void OnPageAddRef() | |
| 4332 { | |
| 4333 } | |
| 4334 | |
| 4335 void OnPageRelease() | |
| 4336 { | |
| 4337 } | |
| 4338 | |
| 4339 // Create method | |
| 4340 HPROPSHEETPAGE Create() | |
| 4341 { | |
| 4342 return ::CreatePropertySheetPage(&m_psp); | |
| 4343 } | |
| 4344 | |
| 4345 // Attributes | |
| 4346 void SetTitle(ATL::_U_STRINGorID title) | |
| 4347 { | |
| 4348 m_psp.pszTitle = title.m_lpstr; | |
| 4349 m_psp.dwFlags |= PSP_USETITLE; | |
| 4350 } | |
| 4351 | |
| 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 | |
| 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 | |
| 4367 void EnableHelp() | |
| 4368 { | |
| 4369 m_psp.dwFlags |= PSP_HASHELP; | |
| 4370 } | |
| 4371 | |
| 4372 // Message map and handlers | |
| 4373 BEGIN_MSG_MAP(CPropertyPageImpl) | |
| 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 | |
| 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 | |
| 4501 BOOL OnKillActive() | |
| 4502 { | |
| 4503 // FALSE = allow deactivate | |
| 4504 // TRUE = prevent deactivation | |
| 4505 return FALSE; | |
| 4506 } | |
| 4507 | |
| 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 | |
| 4516 void OnReset() | |
| 4517 { | |
| 4518 } | |
| 4519 | |
| 4520 BOOL OnQueryCancel() | |
| 4521 { | |
| 4522 // FALSE = allow cancel | |
| 4523 // TRUE = prevent cancel | |
| 4524 return FALSE; | |
| 4525 } | |
| 4526 | |
| 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 | |
| 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 | |
| 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 | |
| 4551 void OnHelp() | |
| 4552 { | |
| 4553 } | |
| 4554 | |
| 4555 BOOL OnGetObject(LPNMOBJECTNOTIFY /*lpObjectNotify*/) | |
| 4556 { | |
| 4557 return FALSE; // not processed | |
| 4558 } | |
| 4559 | |
| 4560 int OnTranslateAccelerator(LPMSG /*lpMsg*/) | |
| 4561 { | |
| 4562 // PSNRET_NOERROR - message not handled | |
| 4563 // PSNRET_MESSAGEHANDLED - message handled | |
| 4564 return PSNRET_NOERROR; | |
| 4565 } | |
| 4566 | |
| 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 | |
| 4575 BOOL OnSetActive() | |
| 4576 { | |
| 4577 return TRUE; | |
| 4578 } | |
| 4579 | |
| 4580 BOOL OnKillActive() | |
| 4581 { | |
| 4582 return TRUE; | |
| 4583 } | |
| 4584 | |
| 4585 BOOL OnApply() | |
| 4586 { | |
| 4587 return TRUE; | |
| 4588 } | |
| 4589 | |
| 4590 void OnReset() | |
| 4591 { | |
| 4592 } | |
| 4593 | |
| 4594 BOOL OnQueryCancel() | |
| 4595 { | |
| 4596 return TRUE; // ok to cancel | |
| 4597 } | |
| 4598 | |
| 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 | |
| 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 | |
| 4615 BOOL OnWizardFinish() | |
| 4616 { | |
| 4617 return TRUE; | |
| 4618 } | |
| 4619 | |
| 4620 void OnHelp() | |
| 4621 { | |
| 4622 } | |
| 4623 | |
| 4624 BOOL OnGetObject(LPNMOBJECTNOTIFY /*lpObjectNotify*/) | |
| 4625 { | |
| 4626 return FALSE; // not processed | |
| 4627 } | |
| 4628 | |
| 4629 BOOL OnTranslateAccelerator(LPMSG /*lpMsg*/) | |
| 4630 { | |
| 4631 return FALSE; // not translated | |
| 4632 } | |
| 4633 | |
| 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 | |
| 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 | |
| 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 | |
| 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 | |
| 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 | |
| 4774 int GetIDD() | |
| 4775 { | |
| 4776 return( static_cast<T*>(this)->IDD ); | |
| 4777 } | |
| 4778 | |
| 4779 virtual DLGPROC GetDialogProc() | |
| 4780 { | |
| 4781 return DialogProc; | |
| 4782 } | |
| 4783 | |
| 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 | |
| 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 | |
| 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) | |
| 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 | |
| 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 | |
| 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 | |
| 5072 HFONT GetExteriorPageTitleFont(void) | |
| 5073 { | |
| 5074 ATLASSERT(::IsWindow(m_hWnd)); | |
| 5075 return (HFONT)::SendMessage(m_hWnd, GetMessage_GetExteriorPageTitleFont(), 0, 0L); | |
| 5076 } | |
| 5077 | |
| 5078 HFONT GetBulletFont(void) | |
| 5079 { | |
| 5080 ATLASSERT(::IsWindow(m_hWnd)); | |
| 5081 return (HFONT)::SendMessage(m_hWnd, GetMessage_GetBulletFont(), 0, 0L); | |
| 5082 } | |
| 5083 | |
| 5084 // Helpers | |
| 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 | |
| 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) : | |
| 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 | |
| 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 | |
| 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) | |
| 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 | |
| 5226 LRESULT OnGetBulletFont(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& /*bHandled*/) | |
| 5227 { | |
| 5228 return (LRESULT)(HFONT)m_fontBullet; | |
| 5229 } | |
| 5230 | |
| 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) : | |
| 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 | |
| 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 | |
| 5286 CWizard97SheetWindow GetPropertySheet() const | |
| 5287 { | |
| 5288 ATLASSERT(::IsWindow(m_hWnd)); | |
| 5289 return CWizard97SheetWindow(GetParent()); | |
| 5290 } | |
| 5291 | |
| 5292 // Operations | |
| 5293 HFONT GetExteriorPageTitleFont(void) | |
| 5294 { | |
| 5295 ATLASSERT(::IsWindow(m_hWnd)); | |
| 5296 return GetPropertySheet().GetExteriorPageTitleFont(); | |
| 5297 } | |
| 5298 | |
| 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: | |
| 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 | |
| 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 | |
| 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 | |
| 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 | |
| 5417 void SetNextText(LPCWSTR lpszText) | |
| 5418 { | |
| 5419 ATLASSERT(::IsWindow(m_hWnd)); | |
| 5420 ::SendMessage(m_hWnd, PSM_SETNEXTTEXT, 0, (LPARAM)lpszText); | |
| 5421 } | |
| 5422 | |
| 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 | |
| 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 | |
| 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 | |
| 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 | |
| 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 | |
| 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 | |
| 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 | |
| 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 | |
| 5526 void SetNextText(LPCWSTR lpszText) | |
| 5527 { | |
| 5528 ATLASSERT(::IsWindow(m_hWnd)); | |
| 5529 ATLASSERT(GetParent() != NULL); | |
| 5530 GetAeroWizardFrame().SetNextText(lpszText); | |
| 5531 } | |
| 5532 | |
| 5533 void ShowWizardButtons(DWORD dwButtons, DWORD dwStates) | |
| 5534 { | |
| 5535 ATLASSERT(::IsWindow(m_hWnd)); | |
| 5536 ATLASSERT(GetParent() != NULL); | |
| 5537 GetAeroWizardFrame().ShowWizardButtons(dwButtons, dwStates); | |
| 5538 } | |
| 5539 | |
| 5540 void EnableWizardButtons(DWORD dwButtons, DWORD dwStates) | |
| 5541 { | |
| 5542 ATLASSERT(::IsWindow(m_hWnd)); | |
| 5543 ATLASSERT(GetParent() != NULL); | |
| 5544 GetAeroWizardFrame().EnableWizardButtons(dwButtons, dwStates); | |
| 5545 } | |
| 5546 | |
| 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 | |
| 5682 CTaskDialogConfig() | |
| 5683 { | |
| 5684 Init(); | |
| 5685 } | |
| 5686 | |
| 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 | |
| 5696 void SetCommonButtons(TASKDIALOG_COMMON_BUTTON_FLAGS dwCommonButtonsArg) | |
| 5697 { | |
| 5698 this->dwCommonButtons = dwCommonButtonsArg; | |
| 5699 } | |
| 5700 | |
| 5701 // window title text | |
| 5702 void SetWindowTitle(UINT nID) | |
| 5703 { | |
| 5704 this->pszWindowTitle = MAKEINTRESOURCEW(nID); | |
| 5705 } | |
| 5706 | |
| 5707 void SetWindowTitle(LPCWSTR lpstrWindowTitle) | |
| 5708 { | |
| 5709 this->pszWindowTitle = lpstrWindowTitle; | |
| 5710 } | |
| 5711 | |
| 5712 // main icon | |
| 5713 void SetMainIcon(HICON hIcon) | |
| 5714 { | |
| 5715 this->dwFlags |= TDF_USE_HICON_MAIN; | |
| 5716 this->hMainIcon = hIcon; | |
| 5717 } | |
| 5718 | |
| 5719 void SetMainIcon(UINT nID) | |
| 5720 { | |
| 5721 this->dwFlags &= ~TDF_USE_HICON_MAIN; | |
| 5722 this->pszMainIcon = MAKEINTRESOURCEW(nID); | |
| 5723 } | |
| 5724 | |
| 5725 void SetMainIcon(LPCWSTR lpstrMainIcon) | |
| 5726 { | |
| 5727 this->dwFlags &= ~TDF_USE_HICON_MAIN; | |
| 5728 this->pszMainIcon = lpstrMainIcon; | |
| 5729 } | |
| 5730 | |
| 5731 // main instruction text | |
| 5732 void SetMainInstructionText(UINT nID) | |
| 5733 { | |
| 5734 this->pszMainInstruction = MAKEINTRESOURCEW(nID); | |
| 5735 } | |
| 5736 | |
| 5737 void SetMainInstructionText(LPCWSTR lpstrMainInstruction) | |
| 5738 { | |
| 5739 this->pszMainInstruction = lpstrMainInstruction; | |
| 5740 } | |
| 5741 | |
| 5742 // content text | |
| 5743 void SetContentText(UINT nID) | |
| 5744 { | |
| 5745 this->pszContent = MAKEINTRESOURCEW(nID); | |
| 5746 } | |
| 5747 | |
| 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 | |
| 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 | |
| 5776 void SetDefaultRadioButton(int nDefaultRadioButtonArg) | |
| 5777 { | |
| 5778 this->nDefaultRadioButton = nDefaultRadioButtonArg; | |
| 5779 } | |
| 5780 | |
| 5781 // verification text | |
| 5782 void SetVerificationText(UINT nID) | |
| 5783 { | |
| 5784 this->pszVerificationText = MAKEINTRESOURCEW(nID); | |
| 5785 } | |
| 5786 | |
| 5787 void SetVerificationText(LPCWSTR lpstrVerificationText) | |
| 5788 { | |
| 5789 this->pszVerificationText = lpstrVerificationText; | |
| 5790 } | |
| 5791 | |
| 5792 // expanded information text | |
| 5793 void SetExpandedInformationText(UINT nID) | |
| 5794 { | |
| 5795 this->pszExpandedInformation = MAKEINTRESOURCEW(nID); | |
| 5796 } | |
| 5797 | |
| 5798 void SetExpandedInformationText(LPCWSTR lpstrExpandedInformation) | |
| 5799 { | |
| 5800 this->pszExpandedInformation = lpstrExpandedInformation; | |
| 5801 } | |
| 5802 | |
| 5803 // expanded control text | |
| 5804 void SetExpandedControlText(UINT nID) | |
| 5805 { | |
| 5806 this->pszExpandedControlText = MAKEINTRESOURCEW(nID); | |
| 5807 } | |
| 5808 | |
| 5809 void SetExpandedControlText(LPCWSTR lpstrExpandedControlText) | |
| 5810 { | |
| 5811 this->pszExpandedControlText = lpstrExpandedControlText; | |
| 5812 } | |
| 5813 | |
| 5814 // collapsed control text | |
| 5815 void SetCollapsedControlText(UINT nID) | |
| 5816 { | |
| 5817 this->pszCollapsedControlText = MAKEINTRESOURCEW(nID); | |
| 5818 } | |
| 5819 | |
| 5820 void SetCollapsedControlText(LPCWSTR lpstrCollapsedControlText) | |
| 5821 { | |
| 5822 this->pszCollapsedControlText = lpstrCollapsedControlText; | |
| 5823 } | |
| 5824 | |
| 5825 // footer icon | |
| 5826 void SetFooterIcon(HICON hIcon) | |
| 5827 { | |
| 5828 this->dwFlags |= TDF_USE_HICON_FOOTER; | |
| 5829 this->hFooterIcon = hIcon; | |
| 5830 } | |
| 5831 | |
| 5832 void SetFooterIcon(UINT nID) | |
| 5833 { | |
| 5834 this->dwFlags &= ~TDF_USE_HICON_FOOTER; | |
| 5835 this->pszFooterIcon = MAKEINTRESOURCEW(nID); | |
| 5836 } | |
| 5837 | |
| 5838 void SetFooterIcon(LPCWSTR lpstrFooterIcon) | |
| 5839 { | |
| 5840 this->dwFlags &= ~TDF_USE_HICON_FOOTER; | |
| 5841 this->pszFooterIcon = lpstrFooterIcon; | |
| 5842 } | |
| 5843 | |
| 5844 // footer text | |
| 5845 void SetFooterText(UINT nID) | |
| 5846 { | |
| 5847 this->pszFooter = MAKEINTRESOURCEW(nID); | |
| 5848 } | |
| 5849 | |
| 5850 void SetFooterText(LPCWSTR lpstrFooterText) | |
| 5851 { | |
| 5852 this->pszFooter = lpstrFooterText; | |
| 5853 } | |
| 5854 | |
| 5855 // width (in DLUs) | |
| 5856 void SetWidth(UINT cxWidthArg) | |
| 5857 { | |
| 5858 this->cxWidth = cxWidthArg; | |
| 5859 } | |
| 5860 | |
| 5861 // modify flags | |
| 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 | |
| 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 | |
| 5917 void SetCommonButtons(TASKDIALOG_COMMON_BUTTON_FLAGS dwCommonButtons) | |
| 5918 { m_tdc.SetCommonButtons(dwCommonButtons); } | |
| 5919 // window title text | |
| 5920 void SetWindowTitle(UINT nID) | |
| 5921 { m_tdc.SetWindowTitle(nID); } | |
| 5922 void SetWindowTitle(LPCWSTR lpstrWindowTitle) | |
| 5923 { m_tdc.SetWindowTitle(lpstrWindowTitle); } | |
| 5924 // main icon | |
| 5925 void SetMainIcon(HICON hIcon) | |
| 5926 { m_tdc.SetMainIcon(hIcon); } | |
| 5927 void SetMainIcon(UINT nID) | |
| 5928 { m_tdc.SetMainIcon(nID); } | |
| 5929 void SetMainIcon(LPCWSTR lpstrMainIcon) | |
| 5930 { m_tdc.SetMainIcon(lpstrMainIcon); } | |
| 5931 // main instruction text | |
| 5932 void SetMainInstructionText(UINT nID) | |
| 5933 { m_tdc.SetMainInstructionText(nID); } | |
| 5934 void SetMainInstructionText(LPCWSTR lpstrMainInstruction) | |
| 5935 { m_tdc.SetMainInstructionText(lpstrMainInstruction); } | |
| 5936 // content text | |
| 5937 void SetContentText(UINT nID) | |
| 5938 { m_tdc.SetContentText(nID); } | |
| 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); } | |
| 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); } | |
| 5949 void SetDefaultRadioButton(int nDefaultRadioButton) | |
| 5950 { m_tdc.SetDefaultRadioButton(nDefaultRadioButton); } | |
| 5951 // verification text | |
| 5952 void SetVerificationText(UINT nID) | |
| 5953 { m_tdc.SetVerificationText(nID); } | |
| 5954 void SetVerificationText(LPCWSTR lpstrVerificationText) | |
| 5955 { m_tdc.SetVerificationText(lpstrVerificationText); } | |
| 5956 // expanded information text | |
| 5957 void SetExpandedInformationText(UINT nID) | |
| 5958 { m_tdc.SetExpandedInformationText(nID); } | |
| 5959 void SetExpandedInformationText(LPCWSTR lpstrExpandedInformation) | |
| 5960 { m_tdc.SetExpandedInformationText(lpstrExpandedInformation); } | |
| 5961 // expanded control text | |
| 5962 void SetExpandedControlText(UINT nID) | |
| 5963 { m_tdc.SetExpandedControlText(nID); } | |
| 5964 void SetExpandedControlText(LPCWSTR lpstrExpandedControlText) | |
| 5965 { m_tdc.SetExpandedControlText(lpstrExpandedControlText); } | |
| 5966 // collapsed control text | |
| 5967 void SetCollapsedControlText(UINT nID) | |
| 5968 { m_tdc.SetCollapsedControlText(nID); } | |
| 5969 void SetCollapsedControlText(LPCWSTR lpstrCollapsedControlText) | |
| 5970 { m_tdc.SetCollapsedControlText(lpstrCollapsedControlText); } | |
| 5971 // footer icon | |
| 5972 void SetFooterIcon(HICON hIcon) | |
| 5973 { m_tdc.SetFooterIcon(hIcon); } | |
| 5974 void SetFooterIcon(UINT nID) | |
| 5975 { m_tdc.SetFooterIcon(nID); } | |
| 5976 void SetFooterIcon(LPCWSTR lpstrFooterIcon) | |
| 5977 { m_tdc.SetFooterIcon(lpstrFooterIcon); } | |
| 5978 // footer text | |
| 5979 void SetFooterText(UINT nID) | |
| 5980 { m_tdc.SetFooterText(nID); } | |
| 5981 void SetFooterText(LPCWSTR lpstrFooterText) | |
| 5982 { m_tdc.SetFooterText(lpstrFooterText); } | |
| 5983 // width (in DLUs) | |
| 5984 void SetWidth(UINT cxWidth) | |
| 5985 { m_tdc.SetWidth(cxWidth); } | |
| 5986 // modify flags | |
| 5987 void ModifyFlags(DWORD dwRemove, DWORD dwAdd) | |
| 5988 { m_tdc.ModifyFlags(dwRemove, dwAdd); } | |
| 5989 | |
| 5990 // Implementation | |
| 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 | |
| 6043 void OnDialogConstructed() | |
| 6044 { | |
| 6045 } | |
| 6046 | |
| 6047 void OnCreated() | |
| 6048 { | |
| 6049 } | |
| 6050 | |
| 6051 BOOL OnButtonClicked(int /*nButton*/) | |
| 6052 { | |
| 6053 return FALSE; // don't prevent dialog to close | |
| 6054 } | |
| 6055 | |
| 6056 void OnRadioButtonClicked(int /*nRadioButton*/) | |
| 6057 { | |
| 6058 } | |
| 6059 | |
| 6060 void OnHyperlinkClicked(LPCWSTR /*pszHREF*/) | |
| 6061 { | |
| 6062 } | |
| 6063 | |
| 6064 void OnExpandoButtonClicked(bool /*bExpanded*/) | |
| 6065 { | |
| 6066 } | |
| 6067 | |
| 6068 void OnVerificationClicked(bool /*bChecked*/) | |
| 6069 { | |
| 6070 } | |
| 6071 | |
| 6072 void OnHelp() | |
| 6073 { | |
| 6074 } | |
| 6075 | |
| 6076 BOOL OnTimer(DWORD /*dwTickCount*/) | |
| 6077 { | |
| 6078 return FALSE; // don't reset counter | |
| 6079 } | |
| 6080 | |
| 6081 void OnNavigated() | |
| 6082 { | |
| 6083 } | |
| 6084 | |
| 6085 void OnDestroyed() | |
| 6086 { | |
| 6087 } | |
| 6088 | |
| 6089 // Commands - valid to call only from handlers | |
| 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 | |
| 6105 void NavigatePage() | |
| 6106 { | |
| 6107 ATLASSERT(m_hWnd != NULL); | |
| 6108 ::SendMessage(m_hWnd, TDM_NAVIGATE_PAGE, 0, (LPARAM)&m_tdc); | |
| 6109 } | |
| 6110 | |
| 6111 void ClickButton(int nButton) | |
| 6112 { | |
| 6113 ATLASSERT(m_hWnd != NULL); | |
| 6114 ::SendMessage(m_hWnd, TDM_CLICK_BUTTON, nButton, 0L); | |
| 6115 } | |
| 6116 | |
| 6117 void SetMarqueeProgressBar(BOOL bMarquee) | |
| 6118 { | |
| 6119 ATLASSERT(m_hWnd != NULL); | |
| 6120 ::SendMessage(m_hWnd, TDM_SET_MARQUEE_PROGRESS_BAR, bMarquee, 0L); | |
| 6121 } | |
| 6122 | |
| 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 | |
| 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 | |
| 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 | |
| 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 | |
| 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 | |
| 6153 void ClickRadioButton(int nRadioButton) | |
| 6154 { | |
| 6155 ATLASSERT(m_hWnd != NULL); | |
| 6156 ::SendMessage(m_hWnd, TDM_CLICK_RADIO_BUTTON, nRadioButton, 0L); | |
| 6157 } | |
| 6158 | |
| 6159 void EnableButton(int nButton, BOOL bEnable) | |
| 6160 { | |
| 6161 ATLASSERT(m_hWnd != NULL); | |
| 6162 ::SendMessage(m_hWnd, TDM_ENABLE_BUTTON, nButton, bEnable); | |
| 6163 } | |
| 6164 | |
| 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 | |
| 6171 void ClickVerification(BOOL bCheck, BOOL bFocus) | |
| 6172 { | |
| 6173 ATLASSERT(m_hWnd != NULL); | |
| 6174 ::SendMessage(m_hWnd, TDM_CLICK_VERIFICATION, bCheck, bFocus); | |
| 6175 } | |
| 6176 | |
| 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 | |
| 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 | |
| 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 | |
| 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__ |
