Mercurial > foo_out_sdl
comparison foosdk/wtl/Include/atlprint.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 __ATLPRINT_H__ | |
| 10 #define __ATLPRINT_H__ | |
| 11 | |
| 12 #pragma once | |
| 13 | |
| 14 #ifndef __ATLAPP_H__ | |
| 15 #error atlprint.h requires atlapp.h to be included first | |
| 16 #endif | |
| 17 | |
| 18 #ifndef __ATLWIN_H__ | |
| 19 #error atlprint.h requires atlwin.h to be included first | |
| 20 #endif | |
| 21 | |
| 22 #include <winspool.h> | |
| 23 | |
| 24 | |
| 25 /////////////////////////////////////////////////////////////////////////////// | |
| 26 // Classes in this file: | |
| 27 // | |
| 28 // CPrinterInfo<t_nInfo> | |
| 29 // CPrinterT<t_bManaged> | |
| 30 // CDevModeT<t_bManaged> | |
| 31 // CPrinterDC | |
| 32 // CPrintJobInfo | |
| 33 // CPrintJob | |
| 34 // CPrintPreview | |
| 35 // CPrintPreviewWindowImpl<T, TBase, TWinTraits> | |
| 36 // CPrintPreviewWindow | |
| 37 // CZoomPrintPreviewWindowImpl<T, TBase, TWinTraits> | |
| 38 // CZoomPrintPreviewWindow | |
| 39 | |
| 40 namespace WTL | |
| 41 { | |
| 42 | |
| 43 /////////////////////////////////////////////////////////////////////////////// | |
| 44 // CPrinterInfo - This class wraps all of the PRINTER_INFO_* structures | |
| 45 // and provided by ::GetPrinter. | |
| 46 | |
| 47 template <unsigned int t_nInfo> | |
| 48 class _printer_info | |
| 49 { | |
| 50 public: | |
| 51 typedef void infotype; | |
| 52 }; | |
| 53 | |
| 54 template <> class _printer_info<1> { public: typedef PRINTER_INFO_1 infotype; }; | |
| 55 template <> class _printer_info<2> { public: typedef PRINTER_INFO_2 infotype; }; | |
| 56 template <> class _printer_info<3> { public: typedef PRINTER_INFO_3 infotype; }; | |
| 57 template <> class _printer_info<4> { public: typedef PRINTER_INFO_4 infotype; }; | |
| 58 template <> class _printer_info<5> { public: typedef PRINTER_INFO_5 infotype; }; | |
| 59 template <> class _printer_info<6> { public: typedef PRINTER_INFO_6 infotype; }; | |
| 60 template <> class _printer_info<7> { public: typedef PRINTER_INFO_7 infotype; }; | |
| 61 template <> class _printer_info<8> { public: typedef PRINTER_INFO_8 infotype; }; | |
| 62 template <> class _printer_info<9> { public: typedef PRINTER_INFO_9 infotype; }; | |
| 63 | |
| 64 | |
| 65 template <unsigned int t_nInfo> | |
| 66 class CPrinterInfo | |
| 67 { | |
| 68 public: | |
| 69 // Data members | |
| 70 typename _printer_info<t_nInfo>::infotype* m_pi; | |
| 71 | |
| 72 // Constructor/destructor | |
| 73 CPrinterInfo() : m_pi(NULL) | |
| 74 { } | |
| 75 | |
| 76 CPrinterInfo(HANDLE hPrinter) : m_pi(NULL) | |
| 77 { | |
| 78 GetPrinterInfo(hPrinter); | |
| 79 } | |
| 80 | |
| 81 ~CPrinterInfo() | |
| 82 { | |
| 83 Cleanup(); | |
| 84 } | |
| 85 | |
| 86 // Operations | |
| 87 bool GetPrinterInfo(HANDLE hPrinter) | |
| 88 { | |
| 89 Cleanup(); | |
| 90 return GetPrinterInfoHelper(hPrinter, (BYTE**)&m_pi, t_nInfo); | |
| 91 } | |
| 92 | |
| 93 // Implementation | |
| 94 void Cleanup() | |
| 95 { | |
| 96 delete [] (BYTE*)m_pi; | |
| 97 m_pi = NULL; | |
| 98 } | |
| 99 | |
| 100 static bool GetPrinterInfoHelper(HANDLE hPrinter, BYTE** pi, int nIndex) | |
| 101 { | |
| 102 ATLASSERT(pi != NULL); | |
| 103 DWORD dw = 0; | |
| 104 BYTE* pb = NULL; | |
| 105 ::GetPrinter(hPrinter, nIndex, NULL, 0, &dw); | |
| 106 if (dw > 0) | |
| 107 { | |
| 108 ATLTRY(pb = new BYTE[dw]); | |
| 109 if (pb != NULL) | |
| 110 { | |
| 111 memset(pb, 0, dw); | |
| 112 DWORD dwNew; | |
| 113 if (!::GetPrinter(hPrinter, nIndex, pb, dw, &dwNew)) | |
| 114 { | |
| 115 delete [] pb; | |
| 116 pb = NULL; | |
| 117 } | |
| 118 } | |
| 119 } | |
| 120 *pi = pb; | |
| 121 return (pb != NULL); | |
| 122 } | |
| 123 }; | |
| 124 | |
| 125 | |
| 126 /////////////////////////////////////////////////////////////////////////////// | |
| 127 // CPrinter - Wrapper class for a HANDLE to a printer | |
| 128 | |
| 129 template <bool t_bManaged> | |
| 130 class CPrinterT | |
| 131 { | |
| 132 public: | |
| 133 // Data members | |
| 134 HANDLE m_hPrinter; | |
| 135 | |
| 136 // Constructor/destructor | |
| 137 CPrinterT(HANDLE hPrinter = NULL) : m_hPrinter(hPrinter) | |
| 138 { } | |
| 139 | |
| 140 ~CPrinterT() | |
| 141 { | |
| 142 ClosePrinter(); | |
| 143 } | |
| 144 | |
| 145 // Operations | |
| 146 CPrinterT& operator =(HANDLE hPrinter) | |
| 147 { | |
| 148 if (hPrinter != m_hPrinter) | |
| 149 { | |
| 150 ClosePrinter(); | |
| 151 m_hPrinter = hPrinter; | |
| 152 } | |
| 153 return *this; | |
| 154 } | |
| 155 | |
| 156 bool IsNull() const { return (m_hPrinter == NULL); } | |
| 157 | |
| 158 bool OpenPrinter(HANDLE hDevNames, const DEVMODE* pDevMode = NULL) | |
| 159 { | |
| 160 bool b = false; | |
| 161 DEVNAMES* pdn = (DEVNAMES*)::GlobalLock(hDevNames); | |
| 162 if (pdn != NULL) | |
| 163 { | |
| 164 LPTSTR lpszPrinterName = (LPTSTR)pdn + pdn->wDeviceOffset; | |
| 165 b = OpenPrinter(lpszPrinterName, pDevMode); | |
| 166 ::GlobalUnlock(hDevNames); | |
| 167 } | |
| 168 return b; | |
| 169 } | |
| 170 | |
| 171 bool OpenPrinter(LPCTSTR lpszPrinterName, const DEVMODE* pDevMode = NULL) | |
| 172 { | |
| 173 ClosePrinter(); | |
| 174 PRINTER_DEFAULTS pdefs = { NULL, (DEVMODE*)pDevMode, PRINTER_ACCESS_USE }; | |
| 175 ::OpenPrinter((LPTSTR) lpszPrinterName, &m_hPrinter, (pDevMode == NULL) ? NULL : &pdefs); | |
| 176 | |
| 177 return (m_hPrinter != NULL); | |
| 178 } | |
| 179 | |
| 180 bool OpenPrinter(LPCTSTR lpszPrinterName, PRINTER_DEFAULTS* pprintdefs) | |
| 181 { | |
| 182 ClosePrinter(); | |
| 183 ::OpenPrinter((LPTSTR) lpszPrinterName, &m_hPrinter, pprintdefs); | |
| 184 return (m_hPrinter != NULL); | |
| 185 } | |
| 186 | |
| 187 bool OpenDefaultPrinter(const DEVMODE* pDevMode = NULL) | |
| 188 { | |
| 189 ClosePrinter(); | |
| 190 | |
| 191 DWORD cchBuff = 0; | |
| 192 ::GetDefaultPrinter(NULL, &cchBuff); | |
| 193 TCHAR* pszBuff = new TCHAR[cchBuff]; | |
| 194 BOOL bRet = ::GetDefaultPrinter(pszBuff, &cchBuff); | |
| 195 if(bRet != FALSE) | |
| 196 { | |
| 197 PRINTER_DEFAULTS pdefs = { NULL, (DEVMODE*)pDevMode, PRINTER_ACCESS_USE }; | |
| 198 ::OpenPrinter(pszBuff, &m_hPrinter, (pDevMode == NULL) ? NULL : &pdefs); | |
| 199 } | |
| 200 delete [] pszBuff; | |
| 201 | |
| 202 return m_hPrinter != NULL; | |
| 203 } | |
| 204 | |
| 205 void ClosePrinter() | |
| 206 { | |
| 207 if (m_hPrinter != NULL) | |
| 208 { | |
| 209 if (t_bManaged) | |
| 210 ::ClosePrinter(m_hPrinter); | |
| 211 m_hPrinter = NULL; | |
| 212 } | |
| 213 } | |
| 214 | |
| 215 bool PrinterProperties(HWND hWnd = NULL) | |
| 216 { | |
| 217 if (hWnd == NULL) | |
| 218 hWnd = ::GetActiveWindow(); | |
| 219 return !!::PrinterProperties(hWnd, m_hPrinter); | |
| 220 } | |
| 221 | |
| 222 HANDLE CopyToHDEVNAMES() const | |
| 223 { | |
| 224 HANDLE hDevNames = NULL; | |
| 225 CPrinterInfo<5> pinfon5; | |
| 226 CPrinterInfo<2> pinfon2; | |
| 227 LPTSTR lpszPrinterName = NULL; | |
| 228 LPTSTR lpszPortName = NULL; | |
| 229 // Some printers fail for PRINTER_INFO_5 in some situations | |
| 230 if(pinfon5.GetPrinterInfo(m_hPrinter)) | |
| 231 { | |
| 232 lpszPrinterName = pinfon5.m_pi->pPrinterName; | |
| 233 lpszPortName = pinfon5.m_pi->pPortName; | |
| 234 } | |
| 235 else if(pinfon2.GetPrinterInfo(m_hPrinter)) | |
| 236 { | |
| 237 lpszPrinterName = pinfon2.m_pi->pPrinterName; | |
| 238 lpszPortName = pinfon2.m_pi->pPortName; | |
| 239 } | |
| 240 | |
| 241 if(lpszPrinterName != NULL) | |
| 242 { | |
| 243 int nLen = sizeof(DEVNAMES) + (lstrlen(lpszPrinterName) + 1 + lstrlen(lpszPortName) + 1) * sizeof(TCHAR); | |
| 244 hDevNames = ::GlobalAlloc(GMEM_MOVEABLE, nLen); | |
| 245 BYTE* pv = (BYTE*)::GlobalLock(hDevNames); | |
| 246 DEVNAMES* pdev = (DEVNAMES*)pv; | |
| 247 if(pv != NULL) | |
| 248 { | |
| 249 memset(pv, 0, nLen); | |
| 250 pdev->wDeviceOffset = sizeof(DEVNAMES); | |
| 251 pv = pv + sizeof(DEVNAMES); // now points to end | |
| 252 ATL::Checked::tcscpy_s((LPTSTR)pv, lstrlen(lpszPrinterName) + 1, lpszPrinterName); | |
| 253 pdev->wOutputOffset = (WORD)(sizeof(DEVNAMES) + (lstrlen(lpszPrinterName) + 1) * sizeof(TCHAR)); | |
| 254 pv = pv + (lstrlen(lpszPrinterName) + 1) * sizeof(TCHAR); | |
| 255 ATL::Checked::tcscpy_s((LPTSTR)pv, lstrlen(lpszPortName) + 1, lpszPortName); | |
| 256 ::GlobalUnlock(hDevNames); | |
| 257 } | |
| 258 } | |
| 259 | |
| 260 return hDevNames; | |
| 261 } | |
| 262 | |
| 263 HDC CreatePrinterDC(const DEVMODE* pdm = NULL) const | |
| 264 { | |
| 265 CPrinterInfo<5> pinfo5; | |
| 266 CPrinterInfo<2> pinfo2; | |
| 267 HDC hDC = NULL; | |
| 268 LPTSTR lpszPrinterName = NULL; | |
| 269 // Some printers fail for PRINTER_INFO_5 in some situations | |
| 270 if (pinfo5.GetPrinterInfo(m_hPrinter)) | |
| 271 lpszPrinterName = pinfo5.m_pi->pPrinterName; | |
| 272 else if (pinfo2.GetPrinterInfo(m_hPrinter)) | |
| 273 lpszPrinterName = pinfo2.m_pi->pPrinterName; | |
| 274 if (lpszPrinterName != NULL) | |
| 275 hDC = ::CreateDC(NULL, lpszPrinterName, NULL, pdm); | |
| 276 return hDC; | |
| 277 } | |
| 278 | |
| 279 HDC CreatePrinterIC(const DEVMODE* pdm = NULL) const | |
| 280 { | |
| 281 CPrinterInfo<5> pinfo5; | |
| 282 CPrinterInfo<2> pinfo2; | |
| 283 HDC hDC = NULL; | |
| 284 LPTSTR lpszPrinterName = NULL; | |
| 285 // Some printers fail for PRINTER_INFO_5 in some situations | |
| 286 if (pinfo5.GetPrinterInfo(m_hPrinter)) | |
| 287 lpszPrinterName = pinfo5.m_pi->pPrinterName; | |
| 288 else if (pinfo2.GetPrinterInfo(m_hPrinter)) | |
| 289 lpszPrinterName = pinfo2.m_pi->pPrinterName; | |
| 290 if (lpszPrinterName != NULL) | |
| 291 hDC = ::CreateIC(NULL, lpszPrinterName, NULL, pdm); | |
| 292 return hDC; | |
| 293 } | |
| 294 | |
| 295 void Attach(HANDLE hPrinter) | |
| 296 { | |
| 297 ClosePrinter(); | |
| 298 m_hPrinter = hPrinter; | |
| 299 } | |
| 300 | |
| 301 HANDLE Detach() | |
| 302 { | |
| 303 HANDLE hPrinter = m_hPrinter; | |
| 304 m_hPrinter = NULL; | |
| 305 return hPrinter; | |
| 306 } | |
| 307 | |
| 308 operator HANDLE() const { return m_hPrinter; } | |
| 309 }; | |
| 310 | |
| 311 typedef CPrinterT<false> CPrinterHandle; | |
| 312 typedef CPrinterT<true> CPrinter; | |
| 313 | |
| 314 | |
| 315 /////////////////////////////////////////////////////////////////////////////// | |
| 316 // CDevMode - Wrapper class for DEVMODE | |
| 317 | |
| 318 template <bool t_bManaged> | |
| 319 class CDevModeT | |
| 320 { | |
| 321 public: | |
| 322 // Data members | |
| 323 HANDLE m_hDevMode; | |
| 324 DEVMODE* m_pDevMode; | |
| 325 | |
| 326 // Constructor/destructor | |
| 327 CDevModeT(HANDLE hDevMode = NULL) : m_hDevMode(hDevMode) | |
| 328 { | |
| 329 m_pDevMode = (m_hDevMode != NULL) ? (DEVMODE*)::GlobalLock(m_hDevMode) : NULL; | |
| 330 } | |
| 331 | |
| 332 ~CDevModeT() | |
| 333 { | |
| 334 Cleanup(); | |
| 335 } | |
| 336 | |
| 337 // Operations | |
| 338 CDevModeT<t_bManaged>& operator =(HANDLE hDevMode) | |
| 339 { | |
| 340 Attach(hDevMode); | |
| 341 return *this; | |
| 342 } | |
| 343 | |
| 344 void Attach(HANDLE hDevModeNew) | |
| 345 { | |
| 346 Cleanup(); | |
| 347 m_hDevMode = hDevModeNew; | |
| 348 m_pDevMode = (m_hDevMode != NULL) ? (DEVMODE*)::GlobalLock(m_hDevMode) : NULL; | |
| 349 } | |
| 350 | |
| 351 HANDLE Detach() | |
| 352 { | |
| 353 if (m_hDevMode != NULL) | |
| 354 ::GlobalUnlock(m_hDevMode); | |
| 355 HANDLE hDevMode = m_hDevMode; | |
| 356 m_hDevMode = NULL; | |
| 357 return hDevMode; | |
| 358 } | |
| 359 | |
| 360 bool IsNull() const { return (m_hDevMode == NULL); } | |
| 361 | |
| 362 bool CopyFromPrinter(HANDLE hPrinter) | |
| 363 { | |
| 364 CPrinterInfo<2> pinfo; | |
| 365 bool b = pinfo.GetPrinterInfo(hPrinter); | |
| 366 if (b) | |
| 367 b = CopyFromDEVMODE(pinfo.m_pi->pDevMode); | |
| 368 return b; | |
| 369 } | |
| 370 | |
| 371 bool CopyFromDEVMODE(const DEVMODE* pdm) | |
| 372 { | |
| 373 if (pdm == NULL) | |
| 374 return false; | |
| 375 int nSize = pdm->dmSize + pdm->dmDriverExtra; | |
| 376 HANDLE h = ::GlobalAlloc(GMEM_MOVEABLE, nSize); | |
| 377 if (h != NULL) | |
| 378 { | |
| 379 void* p = ::GlobalLock(h); | |
| 380 ATL::Checked::memcpy_s(p, nSize, pdm, nSize); | |
| 381 ::GlobalUnlock(h); | |
| 382 } | |
| 383 Attach(h); | |
| 384 return (h != NULL); | |
| 385 } | |
| 386 | |
| 387 bool CopyFromHDEVMODE(HANDLE hdm) | |
| 388 { | |
| 389 bool b = false; | |
| 390 if (hdm != NULL) | |
| 391 { | |
| 392 DEVMODE* pdm = (DEVMODE*)::GlobalLock(hdm); | |
| 393 b = CopyFromDEVMODE(pdm); | |
| 394 ::GlobalUnlock(hdm); | |
| 395 } | |
| 396 return b; | |
| 397 } | |
| 398 | |
| 399 HANDLE CopyToHDEVMODE() | |
| 400 { | |
| 401 if ((m_hDevMode == NULL) || (m_pDevMode == NULL)) | |
| 402 return NULL; | |
| 403 int nSize = m_pDevMode->dmSize + m_pDevMode->dmDriverExtra; | |
| 404 HANDLE h = ::GlobalAlloc(GMEM_MOVEABLE, nSize); | |
| 405 if (h != NULL) | |
| 406 { | |
| 407 void* p = ::GlobalLock(h); | |
| 408 ATL::Checked::memcpy_s(p, nSize, m_pDevMode, nSize); | |
| 409 ::GlobalUnlock(h); | |
| 410 } | |
| 411 return h; | |
| 412 } | |
| 413 | |
| 414 // If this devmode was for another printer, this will create a new devmode | |
| 415 // based on the existing devmode, but retargeted at the new printer | |
| 416 bool UpdateForNewPrinter(HANDLE hPrinter) | |
| 417 { | |
| 418 bool bRet = false; | |
| 419 LONG nLen = ::DocumentProperties(NULL, hPrinter, NULL, NULL, NULL, 0); | |
| 420 ATL::CTempBuffer<DEVMODE, _WTL_STACK_ALLOC_THRESHOLD> buff; | |
| 421 DEVMODE* pdm = buff.AllocateBytes(nLen); | |
| 422 if(pdm != NULL) | |
| 423 { | |
| 424 memset(pdm, 0, nLen); | |
| 425 LONG l = ::DocumentProperties(NULL, hPrinter, NULL, pdm, m_pDevMode, DM_IN_BUFFER | DM_OUT_BUFFER); | |
| 426 if (l == IDOK) | |
| 427 bRet = CopyFromDEVMODE(pdm); | |
| 428 } | |
| 429 | |
| 430 return bRet; | |
| 431 } | |
| 432 | |
| 433 bool DocumentProperties(HANDLE hPrinter, HWND hWnd = NULL) | |
| 434 { | |
| 435 CPrinterInfo<1> pi; | |
| 436 pi.GetPrinterInfo(hPrinter); | |
| 437 if (hWnd == NULL) | |
| 438 hWnd = ::GetActiveWindow(); | |
| 439 | |
| 440 bool bRet = false; | |
| 441 LONG nLen = ::DocumentProperties(hWnd, hPrinter, pi.m_pi->pName, NULL, NULL, 0); | |
| 442 ATL::CTempBuffer<DEVMODE, _WTL_STACK_ALLOC_THRESHOLD> buff; | |
| 443 DEVMODE* pdm = buff.AllocateBytes(nLen); | |
| 444 if(pdm != NULL) | |
| 445 { | |
| 446 memset(pdm, 0, nLen); | |
| 447 LONG l = ::DocumentProperties(hWnd, hPrinter, pi.m_pi->pName, pdm, m_pDevMode, DM_IN_BUFFER | DM_OUT_BUFFER | DM_PROMPT); | |
| 448 if (l == IDOK) | |
| 449 bRet = CopyFromDEVMODE(pdm); | |
| 450 } | |
| 451 | |
| 452 return bRet; | |
| 453 } | |
| 454 | |
| 455 operator HANDLE() const { return m_hDevMode; } | |
| 456 | |
| 457 operator DEVMODE*() const { return m_pDevMode; } | |
| 458 | |
| 459 // Implementation | |
| 460 void Cleanup() | |
| 461 { | |
| 462 if (m_hDevMode != NULL) | |
| 463 { | |
| 464 ::GlobalUnlock(m_hDevMode); | |
| 465 if(t_bManaged) | |
| 466 ::GlobalFree(m_hDevMode); | |
| 467 m_hDevMode = NULL; | |
| 468 } | |
| 469 } | |
| 470 }; | |
| 471 | |
| 472 typedef CDevModeT<false> CDevModeHandle; | |
| 473 typedef CDevModeT<true> CDevMode; | |
| 474 | |
| 475 | |
| 476 /////////////////////////////////////////////////////////////////////////////// | |
| 477 // CPrinterDC | |
| 478 | |
| 479 class CPrinterDC : public CDC | |
| 480 { | |
| 481 public: | |
| 482 // Constructors/destructor | |
| 483 CPrinterDC() | |
| 484 { | |
| 485 CPrinter printer; | |
| 486 printer.OpenDefaultPrinter(); | |
| 487 Attach(printer.CreatePrinterDC()); | |
| 488 ATLASSERT(m_hDC != NULL); | |
| 489 } | |
| 490 | |
| 491 CPrinterDC(HANDLE hPrinter, const DEVMODE* pdm = NULL) | |
| 492 { | |
| 493 CPrinterHandle p; | |
| 494 p.Attach(hPrinter); | |
| 495 Attach(p.CreatePrinterDC(pdm)); | |
| 496 ATLASSERT(m_hDC != NULL); | |
| 497 } | |
| 498 | |
| 499 ~CPrinterDC() | |
| 500 { | |
| 501 DeleteDC(); | |
| 502 } | |
| 503 }; | |
| 504 | |
| 505 | |
| 506 /////////////////////////////////////////////////////////////////////////////// | |
| 507 // CPrintJob - Wraps a set of tasks for a specific printer (StartDoc/EndDoc) | |
| 508 // Handles aborting, background printing | |
| 509 | |
| 510 // Defines callbacks used by CPrintJob (not a COM interface) | |
| 511 class ATL_NO_VTABLE IPrintJobInfo | |
| 512 { | |
| 513 public: | |
| 514 virtual void BeginPrintJob(HDC hDC) = 0; // allocate handles needed, etc. | |
| 515 virtual void EndPrintJob(HDC hDC, bool bAborted) = 0; // free handles, etc. | |
| 516 virtual void PrePrintPage(UINT nPage, HDC hDC) = 0; | |
| 517 virtual bool PrintPage(UINT nPage, HDC hDC) = 0; | |
| 518 virtual void PostPrintPage(UINT nPage, HDC hDC) = 0; | |
| 519 // If you want per page devmodes, return the DEVMODE* to use for nPage. | |
| 520 // You can optimize by only returning a new DEVMODE* when it is different | |
| 521 // from the one for nLastPage, otherwise return NULL. | |
| 522 // When nLastPage==0, the current DEVMODE* will be the default passed to | |
| 523 // StartPrintJob. | |
| 524 // Note: During print preview, nLastPage will always be "0". | |
| 525 virtual DEVMODE* GetNewDevModeForPage(UINT nLastPage, UINT nPage) = 0; | |
| 526 virtual bool IsValidPage(UINT nPage) = 0; | |
| 527 }; | |
| 528 | |
| 529 // Provides a default implementatin for IPrintJobInfo | |
| 530 // Typically, MI'd into a document or view class | |
| 531 class ATL_NO_VTABLE CPrintJobInfo : public IPrintJobInfo | |
| 532 { | |
| 533 public: | |
| 534 virtual void BeginPrintJob(HDC /*hDC*/) // allocate handles needed, etc | |
| 535 { | |
| 536 } | |
| 537 | |
| 538 virtual void EndPrintJob(HDC /*hDC*/, bool /*bAborted*/) // free handles, etc | |
| 539 { | |
| 540 } | |
| 541 | |
| 542 virtual void PrePrintPage(UINT /*nPage*/, HDC hDC) | |
| 543 { | |
| 544 m_nPJState = ::SaveDC(hDC); | |
| 545 } | |
| 546 | |
| 547 virtual bool PrintPage(UINT /*nPage*/, HDC /*hDC*/) = 0; | |
| 548 | |
| 549 virtual void PostPrintPage(UINT /*nPage*/, HDC hDC) | |
| 550 { | |
| 551 RestoreDC(hDC, m_nPJState); | |
| 552 } | |
| 553 | |
| 554 virtual DEVMODE* GetNewDevModeForPage(UINT /*nLastPage*/, UINT /*nPage*/) | |
| 555 { | |
| 556 return NULL; | |
| 557 } | |
| 558 | |
| 559 virtual bool IsValidPage(UINT /*nPage*/) | |
| 560 { | |
| 561 return true; | |
| 562 } | |
| 563 | |
| 564 // Implementation - data | |
| 565 int m_nPJState; | |
| 566 }; | |
| 567 | |
| 568 | |
| 569 class CPrintJob | |
| 570 { | |
| 571 public: | |
| 572 // Data members | |
| 573 CPrinterHandle m_printer; | |
| 574 IPrintJobInfo* m_pInfo; | |
| 575 DEVMODE* m_pDefDevMode; | |
| 576 DOCINFO m_docinfo; | |
| 577 int m_nJobID; | |
| 578 bool m_bCancel; | |
| 579 bool m_bComplete; | |
| 580 unsigned long m_nStartPage; | |
| 581 unsigned long m_nEndPage; | |
| 582 | |
| 583 // Constructor/destructor | |
| 584 CPrintJob() : m_nJobID(0), m_bCancel(false), m_bComplete(true) | |
| 585 { } | |
| 586 | |
| 587 ~CPrintJob() | |
| 588 { | |
| 589 ATLASSERT(IsJobComplete()); // premature destruction? | |
| 590 } | |
| 591 | |
| 592 // Operations | |
| 593 bool IsJobComplete() const | |
| 594 { | |
| 595 return m_bComplete; | |
| 596 } | |
| 597 | |
| 598 bool StartPrintJob(bool bBackground, HANDLE hPrinter, DEVMODE* pDefaultDevMode, | |
| 599 IPrintJobInfo* pInfo, LPCTSTR lpszDocName, | |
| 600 unsigned long nStartPage, unsigned long nEndPage, | |
| 601 bool bPrintToFile = false, LPCTSTR lpstrOutputFile = NULL) | |
| 602 { | |
| 603 ATLASSERT(m_bComplete); // previous job not done yet? | |
| 604 if (pInfo == NULL) | |
| 605 return false; | |
| 606 | |
| 607 memset(&m_docinfo, 0, sizeof(m_docinfo)); | |
| 608 m_docinfo.cbSize = sizeof(m_docinfo); | |
| 609 m_docinfo.lpszDocName = lpszDocName; | |
| 610 m_pInfo = pInfo; | |
| 611 m_nStartPage = nStartPage; | |
| 612 m_nEndPage = nEndPage; | |
| 613 m_printer.Attach(hPrinter); | |
| 614 m_pDefDevMode = pDefaultDevMode; | |
| 615 m_bComplete = false; | |
| 616 | |
| 617 if(bPrintToFile) | |
| 618 m_docinfo.lpszOutput = (lpstrOutputFile != NULL) ? lpstrOutputFile : _T("FILE:"); | |
| 619 | |
| 620 if (!bBackground) | |
| 621 { | |
| 622 m_bComplete = true; | |
| 623 return StartHelper(); | |
| 624 } | |
| 625 | |
| 626 // Create a thread and return | |
| 627 DWORD dwThreadID = 0; | |
| 628 #ifdef _MT | |
| 629 HANDLE hThread = (HANDLE)_beginthreadex(NULL, 0, (UINT (WINAPI*)(void*))StartProc, this, 0, (UINT*)&dwThreadID); | |
| 630 #else | |
| 631 HANDLE hThread = ::CreateThread(NULL, 0, StartProc, (void*)this, 0, &dwThreadID); | |
| 632 #endif | |
| 633 if (hThread == NULL) | |
| 634 return false; | |
| 635 | |
| 636 ::CloseHandle(hThread); | |
| 637 | |
| 638 return true; | |
| 639 } | |
| 640 | |
| 641 // Implementation | |
| 642 static DWORD WINAPI StartProc(void* p) | |
| 643 { | |
| 644 CPrintJob* pThis = (CPrintJob*)p; | |
| 645 pThis->StartHelper(); | |
| 646 pThis->m_bComplete = true; | |
| 647 return 0; | |
| 648 } | |
| 649 | |
| 650 bool StartHelper() | |
| 651 { | |
| 652 CDC dcPrinter; | |
| 653 dcPrinter.Attach(m_printer.CreatePrinterDC(m_pDefDevMode)); | |
| 654 if (dcPrinter.IsNull()) | |
| 655 return false; | |
| 656 | |
| 657 m_nJobID = ::StartDoc(dcPrinter, &m_docinfo); | |
| 658 if (m_nJobID <= 0) | |
| 659 return false; | |
| 660 | |
| 661 m_pInfo->BeginPrintJob(dcPrinter); | |
| 662 | |
| 663 // print all the pages now | |
| 664 unsigned long nLastPage = 0; | |
| 665 for (unsigned long nPage = m_nStartPage; nPage <= m_nEndPage; nPage++) | |
| 666 { | |
| 667 if (!m_pInfo->IsValidPage(nPage)) | |
| 668 break; | |
| 669 DEVMODE* pdm = m_pInfo->GetNewDevModeForPage(nLastPage, nPage); | |
| 670 if (pdm != NULL) | |
| 671 dcPrinter.ResetDC(pdm); | |
| 672 dcPrinter.StartPage(); | |
| 673 m_pInfo->PrePrintPage(nPage, dcPrinter); | |
| 674 if (!m_pInfo->PrintPage(nPage, dcPrinter)) | |
| 675 m_bCancel = true; | |
| 676 m_pInfo->PostPrintPage(nPage, dcPrinter); | |
| 677 dcPrinter.EndPage(); | |
| 678 if (m_bCancel) | |
| 679 break; | |
| 680 nLastPage = nPage; | |
| 681 } | |
| 682 | |
| 683 m_pInfo->EndPrintJob(dcPrinter, m_bCancel); | |
| 684 if (m_bCancel) | |
| 685 ::AbortDoc(dcPrinter); | |
| 686 else | |
| 687 ::EndDoc(dcPrinter); | |
| 688 m_nJobID = 0; | |
| 689 return true; | |
| 690 } | |
| 691 | |
| 692 // Cancels a print job. Can be called asynchronously. | |
| 693 void CancelPrintJob() | |
| 694 { | |
| 695 m_bCancel = true; | |
| 696 } | |
| 697 }; | |
| 698 | |
| 699 | |
| 700 /////////////////////////////////////////////////////////////////////////////// | |
| 701 // CPrintPreview - Adds print preview support to an existing window | |
| 702 | |
| 703 class CPrintPreview | |
| 704 { | |
| 705 public: | |
| 706 // Data members | |
| 707 IPrintJobInfo* m_pInfo; | |
| 708 CPrinterHandle m_printer; | |
| 709 CEnhMetaFile m_meta; | |
| 710 DEVMODE* m_pDefDevMode; | |
| 711 DEVMODE* m_pCurDevMode; | |
| 712 SIZE m_sizeCurPhysOffset; | |
| 713 | |
| 714 // Constructor | |
| 715 CPrintPreview() : m_pInfo(NULL), m_pDefDevMode(NULL), m_pCurDevMode(NULL) | |
| 716 { | |
| 717 m_sizeCurPhysOffset.cx = 0; | |
| 718 m_sizeCurPhysOffset.cy = 0; | |
| 719 } | |
| 720 | |
| 721 // Operations | |
| 722 void SetPrintPreviewInfo(HANDLE hPrinter, DEVMODE* pDefaultDevMode, IPrintJobInfo* pji) | |
| 723 { | |
| 724 m_printer.Attach(hPrinter); | |
| 725 m_pDefDevMode = pDefaultDevMode; | |
| 726 m_pInfo = pji; | |
| 727 m_nCurPage = 0; | |
| 728 m_pCurDevMode = NULL; | |
| 729 } | |
| 730 | |
| 731 void SetEnhMetaFile(HENHMETAFILE hEMF) | |
| 732 { | |
| 733 m_meta = hEMF; | |
| 734 } | |
| 735 | |
| 736 void SetPage(int nPage) | |
| 737 { | |
| 738 if (!m_pInfo->IsValidPage(nPage)) | |
| 739 return; | |
| 740 m_nCurPage = nPage; | |
| 741 m_pCurDevMode = m_pInfo->GetNewDevModeForPage(0, nPage); | |
| 742 if (m_pCurDevMode == NULL) | |
| 743 m_pCurDevMode = m_pDefDevMode; | |
| 744 CDC dcPrinter = m_printer.CreatePrinterDC(m_pCurDevMode); | |
| 745 | |
| 746 int iWidth = dcPrinter.GetDeviceCaps(PHYSICALWIDTH); | |
| 747 int iHeight = dcPrinter.GetDeviceCaps(PHYSICALHEIGHT); | |
| 748 int nLogx = dcPrinter.GetDeviceCaps(LOGPIXELSX); | |
| 749 int nLogy = dcPrinter.GetDeviceCaps(LOGPIXELSY); | |
| 750 | |
| 751 RECT rcMM = { 0, 0, ::MulDiv(iWidth, 2540, nLogx), ::MulDiv(iHeight, 2540, nLogy) }; | |
| 752 | |
| 753 m_sizeCurPhysOffset.cx = dcPrinter.GetDeviceCaps(PHYSICALOFFSETX); | |
| 754 m_sizeCurPhysOffset.cy = dcPrinter.GetDeviceCaps(PHYSICALOFFSETY); | |
| 755 | |
| 756 CEnhMetaFileDC dcMeta(dcPrinter, &rcMM); | |
| 757 m_pInfo->PrePrintPage(nPage, dcMeta); | |
| 758 m_pInfo->PrintPage(nPage, dcMeta); | |
| 759 m_pInfo->PostPrintPage(nPage, dcMeta); | |
| 760 m_meta.Attach(dcMeta.Close()); | |
| 761 } | |
| 762 | |
| 763 void GetPageRect(RECT& rc, LPRECT prc) | |
| 764 { | |
| 765 int x1 = rc.right-rc.left; | |
| 766 int y1 = rc.bottom - rc.top; | |
| 767 if ((x1 < 0) || (y1 < 0)) | |
| 768 return; | |
| 769 | |
| 770 CEnhMetaFileInfo emfinfo(m_meta); | |
| 771 ENHMETAHEADER* pmh = emfinfo.GetEnhMetaFileHeader(); | |
| 772 | |
| 773 // Compute whether we are OK vertically or horizontally | |
| 774 int x2 = pmh->szlDevice.cx; | |
| 775 int y2 = pmh->szlDevice.cy; | |
| 776 int y1p = MulDiv(x1, y2, x2); | |
| 777 int x1p = MulDiv(y1, x2, y2); | |
| 778 ATLASSERT((x1p <= x1) || (y1p <= y1)); | |
| 779 if (x1p <= x1) | |
| 780 { | |
| 781 prc->left = rc.left + (x1 - x1p) / 2; | |
| 782 prc->right = prc->left + x1p; | |
| 783 prc->top = rc.top; | |
| 784 prc->bottom = rc.bottom; | |
| 785 } | |
| 786 else | |
| 787 { | |
| 788 prc->left = rc.left; | |
| 789 prc->right = rc.right; | |
| 790 prc->top = rc.top + (y1 - y1p) / 2; | |
| 791 prc->bottom = prc->top + y1p; | |
| 792 } | |
| 793 } | |
| 794 | |
| 795 // Painting helpers | |
| 796 void DoPaint(CDCHandle dc) | |
| 797 { | |
| 798 // this one is not used | |
| 799 } | |
| 800 | |
| 801 void DoPaint(CDCHandle dc, RECT& rc) | |
| 802 { | |
| 803 CEnhMetaFileInfo emfinfo(m_meta); | |
| 804 ENHMETAHEADER* pmh = emfinfo.GetEnhMetaFileHeader(); | |
| 805 int nOffsetX = MulDiv(m_sizeCurPhysOffset.cx, rc.right-rc.left, pmh->szlDevice.cx); | |
| 806 int nOffsetY = MulDiv(m_sizeCurPhysOffset.cy, rc.bottom-rc.top, pmh->szlDevice.cy); | |
| 807 | |
| 808 dc.OffsetWindowOrg(-nOffsetX, -nOffsetY); | |
| 809 dc.PlayMetaFile(m_meta, &rc); | |
| 810 } | |
| 811 | |
| 812 // Implementation - data | |
| 813 int m_nCurPage; | |
| 814 }; | |
| 815 | |
| 816 | |
| 817 /////////////////////////////////////////////////////////////////////////////// | |
| 818 // CPrintPreviewWindow - Implements a print preview window | |
| 819 | |
| 820 template <class T, class TBase = ATL::CWindow, class TWinTraits = ATL::CControlWinTraits> | |
| 821 class ATL_NO_VTABLE CPrintPreviewWindowImpl : public ATL::CWindowImpl<T, TBase, TWinTraits>, public CPrintPreview | |
| 822 { | |
| 823 public: | |
| 824 DECLARE_WND_CLASS_EX2(NULL, T, CS_VREDRAW | CS_HREDRAW, -1) | |
| 825 | |
| 826 enum { m_cxOffset = 10, m_cyOffset = 10 }; | |
| 827 | |
| 828 // Constructor | |
| 829 CPrintPreviewWindowImpl() : m_nMinPage(0), m_nMaxPage(0) | |
| 830 { } | |
| 831 | |
| 832 // Operations | |
| 833 void SetPrintPreviewInfo(HANDLE hPrinter, DEVMODE* pDefaultDevMode, | |
| 834 IPrintJobInfo* pji, int nMinPage, int nMaxPage) | |
| 835 { | |
| 836 CPrintPreview::SetPrintPreviewInfo(hPrinter, pDefaultDevMode, pji); | |
| 837 m_nMinPage = nMinPage; | |
| 838 m_nMaxPage = nMaxPage; | |
| 839 } | |
| 840 | |
| 841 bool NextPage() | |
| 842 { | |
| 843 if (m_nCurPage == m_nMaxPage) | |
| 844 return false; | |
| 845 SetPage(m_nCurPage + 1); | |
| 846 this->Invalidate(); | |
| 847 return true; | |
| 848 } | |
| 849 | |
| 850 bool PrevPage() | |
| 851 { | |
| 852 if (m_nCurPage == m_nMinPage) | |
| 853 return false; | |
| 854 if (m_nCurPage == 0) | |
| 855 return false; | |
| 856 SetPage(m_nCurPage - 1); | |
| 857 this->Invalidate(); | |
| 858 return true; | |
| 859 } | |
| 860 | |
| 861 // Message map and handlers | |
| 862 BEGIN_MSG_MAP(CPrintPreviewWindowImpl) | |
| 863 MESSAGE_HANDLER(WM_ERASEBKGND, OnEraseBkgnd) | |
| 864 MESSAGE_HANDLER(WM_PAINT, OnPaint) | |
| 865 MESSAGE_HANDLER(WM_PRINTCLIENT, OnPaint) | |
| 866 END_MSG_MAP() | |
| 867 | |
| 868 LRESULT OnEraseBkgnd(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& /*bHandled*/) | |
| 869 { | |
| 870 return 1; // no need for the background | |
| 871 } | |
| 872 | |
| 873 LRESULT OnPaint(UINT /*uMsg*/, WPARAM wParam, LPARAM /*lParam*/, BOOL& /*bHandled*/) | |
| 874 { | |
| 875 T* pT = static_cast<T*>(this); | |
| 876 RECT rc = {}; | |
| 877 | |
| 878 if(wParam != NULL) | |
| 879 { | |
| 880 pT->DoPrePaint((HDC)wParam, rc); | |
| 881 pT->DoPaint((HDC)wParam, rc); | |
| 882 } | |
| 883 else | |
| 884 { | |
| 885 CPaintDC dc(this->m_hWnd); | |
| 886 pT->DoPrePaint(dc.m_hDC, rc); | |
| 887 pT->DoPaint(dc.m_hDC, rc); | |
| 888 } | |
| 889 | |
| 890 return 0; | |
| 891 } | |
| 892 | |
| 893 // Painting helper | |
| 894 void DoPrePaint(CDCHandle dc, RECT& rc) | |
| 895 { | |
| 896 RECT rcClient = {}; | |
| 897 this->GetClientRect(&rcClient); | |
| 898 RECT rcArea = rcClient; | |
| 899 T* pT = static_cast<T*>(this); | |
| 900 (void)pT; // avoid level 4 warning | |
| 901 ::InflateRect(&rcArea, -pT->m_cxOffset, -pT->m_cyOffset); | |
| 902 if (rcArea.left > rcArea.right) | |
| 903 rcArea.right = rcArea.left; | |
| 904 if (rcArea.top > rcArea.bottom) | |
| 905 rcArea.bottom = rcArea.top; | |
| 906 GetPageRect(rcArea, &rc); | |
| 907 CRgn rgn1, rgn2; | |
| 908 rgn1.CreateRectRgnIndirect(&rc); | |
| 909 rgn2.CreateRectRgnIndirect(&rcClient); | |
| 910 rgn2.CombineRgn(rgn1, RGN_DIFF); | |
| 911 dc.SelectClipRgn(rgn2); | |
| 912 dc.FillRect(&rcClient, COLOR_BTNSHADOW); | |
| 913 dc.SelectClipRgn(NULL); | |
| 914 dc.FillRect(&rc, (HBRUSH)::GetStockObject(WHITE_BRUSH)); | |
| 915 } | |
| 916 | |
| 917 // Implementation - data | |
| 918 int m_nMinPage; | |
| 919 int m_nMaxPage; | |
| 920 }; | |
| 921 | |
| 922 | |
| 923 class CPrintPreviewWindow : public CPrintPreviewWindowImpl<CPrintPreviewWindow> | |
| 924 { | |
| 925 public: | |
| 926 DECLARE_WND_CLASS_EX(_T("WTL_PrintPreview"), CS_VREDRAW | CS_HREDRAW, -1) | |
| 927 }; | |
| 928 | |
| 929 | |
| 930 /////////////////////////////////////////////////////////////////////////////// | |
| 931 // CZoomPrintPreviewWindowImpl - Implements print preview window with zooming | |
| 932 | |
| 933 #ifdef __ATLSCRL_H__ | |
| 934 | |
| 935 template <class T, class TBase = ATL::CWindow, class TWinTraits = ATL::CControlWinTraits> | |
| 936 class ATL_NO_VTABLE CZoomPrintPreviewWindowImpl : public CPrintPreviewWindowImpl< T, TBase, TWinTraits >, public CZoomScrollImpl< T > | |
| 937 { | |
| 938 public: | |
| 939 bool m_bSized; | |
| 940 | |
| 941 CZoomPrintPreviewWindowImpl() | |
| 942 { | |
| 943 this->SetScrollExtendedStyle(SCRL_DISABLENOSCROLL); | |
| 944 InitZoom(); | |
| 945 } | |
| 946 | |
| 947 // should be called to reset data members before recreating window | |
| 948 void InitZoom() | |
| 949 { | |
| 950 m_bSized = false; | |
| 951 this->m_nZoomMode = ZOOMMODE_OFF; | |
| 952 this->m_fZoomScaleMin = 1.0; | |
| 953 this->m_fZoomScale = 1.0; | |
| 954 } | |
| 955 | |
| 956 BEGIN_MSG_MAP(CZoomPrintPreviewWindowImpl) | |
| 957 MESSAGE_HANDLER(WM_SETCURSOR, CZoomScrollImpl< T >::OnSetCursor) | |
| 958 MESSAGE_HANDLER(WM_VSCROLL, CScrollImpl< T >::OnVScroll) | |
| 959 MESSAGE_HANDLER(WM_HSCROLL, CScrollImpl< T >::OnHScroll) | |
| 960 MESSAGE_HANDLER(WM_MOUSEWHEEL, CScrollImpl< T >::OnMouseWheel) | |
| 961 MESSAGE_HANDLER(WM_MOUSEHWHEEL, CScrollImpl< T >::OnMouseHWheel) | |
| 962 MESSAGE_HANDLER(WM_SETTINGCHANGE, CScrollImpl< T >::OnSettingChange) | |
| 963 MESSAGE_HANDLER(WM_LBUTTONDOWN, CZoomScrollImpl< T >::OnLButtonDown) | |
| 964 MESSAGE_HANDLER(WM_MOUSEMOVE, CZoomScrollImpl< T >::OnMouseMove) | |
| 965 MESSAGE_HANDLER(WM_LBUTTONUP, CZoomScrollImpl< T >::OnLButtonUp) | |
| 966 MESSAGE_HANDLER(WM_CAPTURECHANGED, CZoomScrollImpl< T >::OnCaptureChanged) | |
| 967 MESSAGE_HANDLER(WM_SIZE, OnSize) | |
| 968 MESSAGE_HANDLER(WM_ERASEBKGND, OnEraseBkgnd) | |
| 969 MESSAGE_HANDLER(WM_PAINT, OnPaint) | |
| 970 MESSAGE_HANDLER(WM_PRINTCLIENT, OnPaint) | |
| 971 ALT_MSG_MAP(1) | |
| 972 COMMAND_ID_HANDLER(ID_SCROLL_UP, CScrollImpl< T >::OnScrollUp) | |
| 973 COMMAND_ID_HANDLER(ID_SCROLL_DOWN, CScrollImpl< T >::OnScrollDown) | |
| 974 COMMAND_ID_HANDLER(ID_SCROLL_PAGE_UP, CScrollImpl< T >::OnScrollPageUp) | |
| 975 COMMAND_ID_HANDLER(ID_SCROLL_PAGE_DOWN, CScrollImpl< T >::OnScrollPageDown) | |
| 976 COMMAND_ID_HANDLER(ID_SCROLL_TOP, CScrollImpl< T >::OnScrollTop) | |
| 977 COMMAND_ID_HANDLER(ID_SCROLL_BOTTOM, CScrollImpl< T >::OnScrollBottom) | |
| 978 COMMAND_ID_HANDLER(ID_SCROLL_LEFT, CScrollImpl< T >::OnScrollLeft) | |
| 979 COMMAND_ID_HANDLER(ID_SCROLL_RIGHT, CScrollImpl< T >::OnScrollRight) | |
| 980 COMMAND_ID_HANDLER(ID_SCROLL_PAGE_LEFT, CScrollImpl< T >::OnScrollPageLeft) | |
| 981 COMMAND_ID_HANDLER(ID_SCROLL_PAGE_RIGHT, CScrollImpl< T >::OnScrollPageRight) | |
| 982 COMMAND_ID_HANDLER(ID_SCROLL_ALL_LEFT, CScrollImpl< T >::OnScrollAllLeft) | |
| 983 COMMAND_ID_HANDLER(ID_SCROLL_ALL_RIGHT, CScrollImpl< T >::OnScrollAllRight) | |
| 984 END_MSG_MAP() | |
| 985 | |
| 986 LRESULT OnSize(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled) | |
| 987 { | |
| 988 SIZE sizeClient = {GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam)}; | |
| 989 POINT ptOffset = this->m_ptOffset; | |
| 990 SIZE sizeAll = this->m_sizeAll; | |
| 991 this->SetScrollSize(sizeClient); | |
| 992 if(sizeAll.cx > 0) | |
| 993 ptOffset.x = ::MulDiv(ptOffset.x, this->m_sizeAll.cx, sizeAll.cx); | |
| 994 if(sizeAll.cy > 0) | |
| 995 ptOffset.y = ::MulDiv(ptOffset.y, this->m_sizeAll.cy, sizeAll.cy); | |
| 996 this->SetScrollOffset(ptOffset); | |
| 997 CScrollImpl< T >::OnSize(uMsg, wParam, lParam, bHandled); | |
| 998 if(!m_bSized) | |
| 999 { | |
| 1000 m_bSized = true; | |
| 1001 T* pT = static_cast<T*>(this); | |
| 1002 pT->ShowScrollBar(SB_HORZ, TRUE); | |
| 1003 pT->ShowScrollBar(SB_VERT, TRUE); | |
| 1004 } | |
| 1005 return 0; | |
| 1006 } | |
| 1007 | |
| 1008 LRESULT OnEraseBkgnd(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& /*bHandled*/) | |
| 1009 { | |
| 1010 return 1; | |
| 1011 } | |
| 1012 | |
| 1013 LRESULT OnPaint(UINT /*uMsg*/, WPARAM wParam, LPARAM /*lParam*/, BOOL& /*bHandled*/) | |
| 1014 { | |
| 1015 T* pT = static_cast<T*>(this); | |
| 1016 RECT rc = {}; | |
| 1017 | |
| 1018 if(wParam != NULL) | |
| 1019 { | |
| 1020 CDCHandle dc = (HDC)wParam; | |
| 1021 int nMapModeSav = dc.GetMapMode(); | |
| 1022 dc.SetMapMode(MM_ANISOTROPIC); | |
| 1023 SIZE szWindowExt = { 0, 0 }; | |
| 1024 dc.SetWindowExt(this->m_sizeLogAll, &szWindowExt); | |
| 1025 SIZE szViewportExt = { 0, 0 }; | |
| 1026 dc.SetViewportExt(this->m_sizeAll, &szViewportExt); | |
| 1027 POINT ptViewportOrg = { 0, 0 }; | |
| 1028 dc.SetViewportOrg(-this->m_ptOffset.x, -this->m_ptOffset.y, &ptViewportOrg); | |
| 1029 | |
| 1030 pT->DoPrePaint(dc, rc); | |
| 1031 pT->DoPaint(dc, rc); | |
| 1032 | |
| 1033 dc.SetMapMode(nMapModeSav); | |
| 1034 dc.SetWindowExt(szWindowExt); | |
| 1035 dc.SetViewportExt(szViewportExt); | |
| 1036 dc.SetViewportOrg(ptViewportOrg); | |
| 1037 } | |
| 1038 else | |
| 1039 { | |
| 1040 CPaintDC dc(pT->m_hWnd); | |
| 1041 pT->PrepareDC(dc.m_hDC); | |
| 1042 pT->DoPrePaint(dc.m_hDC, rc); | |
| 1043 pT->DoPaint(dc.m_hDC, rc); | |
| 1044 } | |
| 1045 | |
| 1046 return 0; | |
| 1047 } | |
| 1048 | |
| 1049 // Painting helpers | |
| 1050 void DoPaint(CDCHandle dc) | |
| 1051 { | |
| 1052 // this one is not used | |
| 1053 } | |
| 1054 | |
| 1055 void DoPrePaint(CDCHandle dc, RECT& rc) | |
| 1056 { | |
| 1057 RECT rcClient = {}; | |
| 1058 this->GetClientRect(&rcClient); | |
| 1059 RECT rcArea = rcClient; | |
| 1060 T* pT = static_cast<T*>(this); | |
| 1061 (void)pT; // avoid level 4 warning | |
| 1062 ::InflateRect(&rcArea, -pT->m_cxOffset, -pT->m_cyOffset); | |
| 1063 if (rcArea.left > rcArea.right) | |
| 1064 rcArea.right = rcArea.left; | |
| 1065 if (rcArea.top > rcArea.bottom) | |
| 1066 rcArea.bottom = rcArea.top; | |
| 1067 this->GetPageRect(rcArea, &rc); | |
| 1068 HBRUSH hbrOld = dc.SelectBrush(::GetSysColorBrush(COLOR_BTNSHADOW)); | |
| 1069 dc.PatBlt(rcClient.left, rcClient.top, rc.left - rcClient.left, rcClient.bottom - rcClient.top, PATCOPY); | |
| 1070 dc.PatBlt(rc.left, rcClient.top, rc.right - rc.left, rc.top - rcClient.top, PATCOPY); | |
| 1071 dc.PatBlt(rc.right, rcClient.top, rcClient.right - rc.right, rcClient.bottom - rcClient.top, PATCOPY); | |
| 1072 dc.PatBlt(rc.left, rc.bottom, rc.right - rc.left, rcClient.bottom - rc.bottom, PATCOPY); | |
| 1073 dc.SelectBrush((HBRUSH)::GetStockObject(WHITE_BRUSH)); | |
| 1074 dc.PatBlt(rc.left, rc.top, rc.right - rc.left, rc.bottom - rc.top, PATCOPY); | |
| 1075 dc.SelectBrush(::GetSysColorBrush(COLOR_3DDKSHADOW)); | |
| 1076 dc.PatBlt(rc.right, rc.top + 4, 4, rc.bottom - rc.top, PATCOPY); | |
| 1077 dc.PatBlt(rc.left + 4, rc.bottom, rc.right - rc.left, 4, PATCOPY); | |
| 1078 dc.SelectBrush(hbrOld); | |
| 1079 } | |
| 1080 | |
| 1081 void DoPaint(CDCHandle dc, RECT& rc) | |
| 1082 { | |
| 1083 CEnhMetaFileInfo emfinfo(this->m_meta); | |
| 1084 ENHMETAHEADER* pmh = emfinfo.GetEnhMetaFileHeader(); | |
| 1085 int nOffsetX = MulDiv(this->m_sizeCurPhysOffset.cx, rc.right-rc.left, pmh->szlDevice.cx); | |
| 1086 int nOffsetY = MulDiv(this->m_sizeCurPhysOffset.cy, rc.bottom-rc.top, pmh->szlDevice.cy); | |
| 1087 | |
| 1088 dc.OffsetWindowOrg(-nOffsetX, -nOffsetY); | |
| 1089 dc.PlayMetaFile(this->m_meta, &rc); | |
| 1090 } | |
| 1091 }; | |
| 1092 | |
| 1093 class CZoomPrintPreviewWindow : public CZoomPrintPreviewWindowImpl<CZoomPrintPreviewWindow> | |
| 1094 { | |
| 1095 public: | |
| 1096 DECLARE_WND_CLASS_EX(_T("WTL_ZoomPrintPreview"), CS_VREDRAW | CS_HREDRAW, -1) | |
| 1097 }; | |
| 1098 | |
| 1099 #endif // __ATLSCRL_H__ | |
| 1100 | |
| 1101 } // namespace WTL | |
| 1102 | |
| 1103 #endif // __ATLPRINT_H__ |
