Pin Chrome's shortcut to the Win10 Start menu on install and OS upgrade.
[chromium-blink-merge.git] / third_party / wtl / include / atlprint.h
blobdb30a06a5ed1123121e82eb74077afca912e994d
1 // Windows Template Library - WTL version 8.0
2 // Copyright (C) Microsoft Corporation. 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 Permissive License (Ms-PL) which can be found in the file
7 // Ms-PL.txt at the root of this distribution.
9 #ifndef __ATLPRINT_H__
10 #define __ATLPRINT_H__
12 #pragma once
14 #ifndef __cplusplus
15 #error ATL requires C++ compilation (use a .cpp suffix)
16 #endif
18 #ifdef _WIN32_WCE
19 #error atlprint.h is not supported on Windows CE
20 #endif
22 #ifndef __ATLAPP_H__
23 #error atlprint.h requires atlapp.h to be included first
24 #endif
26 #ifndef __ATLWIN_H__
27 #error atlprint.h requires atlwin.h to be included first
28 #endif
31 ///////////////////////////////////////////////////////////////////////////////
32 // Classes in this file:
34 // CPrinterInfo<t_nInfo>
35 // CPrinterT<t_bManaged>
36 // CDevModeT<t_bManaged>
37 // CPrinterDC
38 // CPrintJobInfo
39 // CPrintJob
40 // CPrintPreview
41 // CPrintPreviewWindowImpl<T, TBase, TWinTraits>
42 // CPrintPreviewWindow
43 // CZoomPrintPreviewWindowImpl<T, TBase, TWinTraits>
44 // CZoomPrintPreviewWindow
46 namespace WTL
49 ///////////////////////////////////////////////////////////////////////////////
50 // CPrinterInfo - This class wraps all of the PRINTER_INFO_* structures
51 // and provided by ::GetPrinter.
53 template <unsigned int t_nInfo>
54 class _printer_info
56 public:
57 typedef void infotype;
60 template <> class _printer_info<1> { public: typedef PRINTER_INFO_1 infotype; };
61 template <> class _printer_info<2> { public: typedef PRINTER_INFO_2 infotype; };
62 template <> class _printer_info<3> { public: typedef PRINTER_INFO_3 infotype; };
63 template <> class _printer_info<4> { public: typedef PRINTER_INFO_4 infotype; };
64 template <> class _printer_info<5> { public: typedef PRINTER_INFO_5 infotype; };
65 template <> class _printer_info<6> { public: typedef PRINTER_INFO_6 infotype; };
66 template <> class _printer_info<7> { public: typedef PRINTER_INFO_7 infotype; };
67 // these are not in the old (vc6.0) headers
68 #ifdef _ATL_USE_NEW_PRINTER_INFO
69 template <> class _printer_info<8> { public: typedef PRINTER_INFO_8 infotype; };
70 template <> class _printer_info<9> { public: typedef PRINTER_INFO_9 infotype; };
71 #endif // _ATL_USE_NEW_PRINTER_INFO
74 template <unsigned int t_nInfo>
75 class CPrinterInfo
77 public:
78 // Data members
79 typename _printer_info<t_nInfo>::infotype* m_pi;
81 // Constructor/destructor
82 CPrinterInfo() : m_pi(NULL)
83 { }
85 CPrinterInfo(HANDLE hPrinter) : m_pi(NULL)
87 GetPrinterInfo(hPrinter);
90 ~CPrinterInfo()
92 Cleanup();
95 // Operations
96 bool GetPrinterInfo(HANDLE hPrinter)
98 Cleanup();
99 return GetPrinterInfoHelper(hPrinter, (BYTE**)&m_pi, t_nInfo);
102 // Implementation
103 void Cleanup()
105 delete [] (BYTE*)m_pi;
106 m_pi = NULL;
109 static bool GetPrinterInfoHelper(HANDLE hPrinter, BYTE** pi, int nIndex)
111 ATLASSERT(pi != NULL);
112 DWORD dw = 0;
113 BYTE* pb = NULL;
114 ::GetPrinter(hPrinter, nIndex, NULL, 0, &dw);
115 if (dw > 0)
117 ATLTRY(pb = new BYTE[dw]);
118 if (pb != NULL)
120 memset(pb, 0, dw);
121 DWORD dwNew;
122 if (!::GetPrinter(hPrinter, nIndex, pb, dw, &dwNew))
124 delete [] pb;
125 pb = NULL;
129 *pi = pb;
130 return (pb != NULL);
135 ///////////////////////////////////////////////////////////////////////////////
136 // CPrinter - Wrapper class for a HANDLE to a printer
138 template <bool t_bManaged>
139 class CPrinterT
141 public:
142 // Data members
143 HANDLE m_hPrinter;
145 // Constructor/destructor
146 CPrinterT(HANDLE hPrinter = NULL) : m_hPrinter(hPrinter)
149 ~CPrinterT()
151 ClosePrinter();
154 // Operations
155 CPrinterT& operator =(HANDLE hPrinter)
157 if (hPrinter != m_hPrinter)
159 ClosePrinter();
160 m_hPrinter = hPrinter;
162 return *this;
165 bool IsNull() const { return (m_hPrinter == NULL); }
167 bool OpenPrinter(HANDLE hDevNames, const DEVMODE* pDevMode = NULL)
169 bool b = false;
170 DEVNAMES* pdn = (DEVNAMES*)::GlobalLock(hDevNames);
171 if (pdn != NULL)
173 LPTSTR lpszPrinterName = (LPTSTR)pdn + pdn->wDeviceOffset;
174 b = OpenPrinter(lpszPrinterName, pDevMode);
175 ::GlobalUnlock(hDevNames);
177 return b;
180 bool OpenPrinter(LPCTSTR lpszPrinterName, const DEVMODE* pDevMode = NULL)
182 ClosePrinter();
183 PRINTER_DEFAULTS pdefs = { NULL, (DEVMODE*)pDevMode, PRINTER_ACCESS_USE };
184 ::OpenPrinter((LPTSTR) lpszPrinterName, &m_hPrinter, (pDevMode == NULL) ? NULL : &pdefs);
186 return (m_hPrinter != NULL);
189 bool OpenPrinter(LPCTSTR lpszPrinterName, PRINTER_DEFAULTS* pprintdefs)
191 ClosePrinter();
192 ::OpenPrinter((LPTSTR) lpszPrinterName, &m_hPrinter, pprintdefs);
193 return (m_hPrinter != NULL);
196 bool OpenDefaultPrinter(const DEVMODE* pDevMode = NULL)
198 ClosePrinter();
199 const int cchBuff = 512;
200 TCHAR buffer[cchBuff];
201 buffer[0] = 0;
202 ::GetProfileString(_T("windows"), _T("device"), _T(",,,"), buffer, cchBuff);
203 int nLen = lstrlen(buffer);
204 if (nLen != 0)
206 LPTSTR lpsz = buffer;
207 while (*lpsz)
209 if (*lpsz == _T(','))
211 *lpsz = 0;
212 break;
214 lpsz = CharNext(lpsz);
216 PRINTER_DEFAULTS pdefs = { NULL, (DEVMODE*)pDevMode, PRINTER_ACCESS_USE };
217 ::OpenPrinter(buffer, &m_hPrinter, (pDevMode == NULL) ? NULL : &pdefs);
219 return m_hPrinter != NULL;
222 void ClosePrinter()
224 if (m_hPrinter != NULL)
226 if (t_bManaged)
227 ::ClosePrinter(m_hPrinter);
228 m_hPrinter = NULL;
232 bool PrinterProperties(HWND hWnd = NULL)
234 if (hWnd == NULL)
235 hWnd = ::GetActiveWindow();
236 return !!::PrinterProperties(hWnd, m_hPrinter);
239 HANDLE CopyToHDEVNAMES() const
241 HANDLE h = NULL;
242 CPrinterInfo<5> pinfon5;
243 CPrinterInfo<2> pinfon2;
244 LPTSTR lpszPrinterName = NULL;
245 // Some printers fail for PRINTER_INFO_5 in some situations
246 if (pinfon5.GetPrinterInfo(m_hPrinter))
247 lpszPrinterName = pinfon5.m_pi->pPrinterName;
248 else if (pinfon2.GetPrinterInfo(m_hPrinter))
249 lpszPrinterName = pinfon2.m_pi->pPrinterName;
250 if (lpszPrinterName != NULL)
252 int nLen = sizeof(DEVNAMES) + (lstrlen(lpszPrinterName) + 1) * sizeof(TCHAR);
253 h = ::GlobalAlloc(GMEM_MOVEABLE, nLen);
254 BYTE* pv = (BYTE*)::GlobalLock(h);
255 DEVNAMES* pdev = (DEVNAMES*)pv;
256 if (pv != NULL)
258 memset(pv, 0, nLen);
259 pdev->wDeviceOffset = sizeof(DEVNAMES) / sizeof(TCHAR);
260 pv = pv + sizeof(DEVNAMES); // now points to end
261 SecureHelper::strcpy_x((LPTSTR)pv, lstrlen(lpszPrinterName) + 1, lpszPrinterName);
262 ::GlobalUnlock(h);
265 return h;
268 HDC CreatePrinterDC(const DEVMODE* pdm = NULL) const
270 CPrinterInfo<5> pinfo5;
271 CPrinterInfo<2> pinfo2;
272 HDC hDC = NULL;
273 LPTSTR lpszPrinterName = NULL;
274 // Some printers fail for PRINTER_INFO_5 in some situations
275 if (pinfo5.GetPrinterInfo(m_hPrinter))
276 lpszPrinterName = pinfo5.m_pi->pPrinterName;
277 else if (pinfo2.GetPrinterInfo(m_hPrinter))
278 lpszPrinterName = pinfo2.m_pi->pPrinterName;
279 if (lpszPrinterName != NULL)
280 hDC = ::CreateDC(NULL, lpszPrinterName, NULL, pdm);
281 return hDC;
284 HDC CreatePrinterIC(const DEVMODE* pdm = NULL) const
286 CPrinterInfo<5> pinfo5;
287 CPrinterInfo<2> pinfo2;
288 HDC hDC = NULL;
289 LPTSTR lpszPrinterName = NULL;
290 // Some printers fail for PRINTER_INFO_5 in some situations
291 if (pinfo5.GetPrinterInfo(m_hPrinter))
292 lpszPrinterName = pinfo5.m_pi->pPrinterName;
293 else if (pinfo2.GetPrinterInfo(m_hPrinter))
294 lpszPrinterName = pinfo2.m_pi->pPrinterName;
295 if (lpszPrinterName != NULL)
296 hDC = ::CreateIC(NULL, lpszPrinterName, NULL, pdm);
297 return hDC;
300 void Attach(HANDLE hPrinter)
302 ClosePrinter();
303 m_hPrinter = hPrinter;
306 HANDLE Detach()
308 HANDLE hPrinter = m_hPrinter;
309 m_hPrinter = NULL;
310 return hPrinter;
313 operator HANDLE() const { return m_hPrinter; }
316 typedef CPrinterT<false> CPrinterHandle;
317 typedef CPrinterT<true> CPrinter;
320 ///////////////////////////////////////////////////////////////////////////////
321 // CDevMode - Wrapper class for DEVMODE
323 template <bool t_bManaged>
324 class CDevModeT
326 public:
327 // Data members
328 HANDLE m_hDevMode;
329 DEVMODE* m_pDevMode;
331 // Constructor/destructor
332 CDevModeT(HANDLE hDevMode = NULL) : m_hDevMode(hDevMode)
334 m_pDevMode = (m_hDevMode != NULL) ? (DEVMODE*)::GlobalLock(m_hDevMode) : NULL;
337 ~CDevModeT()
339 Cleanup();
342 // Operations
343 CDevModeT<t_bManaged>& operator =(HANDLE hDevMode)
345 Attach(hDevMode);
346 return *this;
349 void Attach(HANDLE hDevModeNew)
351 Cleanup();
352 m_hDevMode = hDevModeNew;
353 m_pDevMode = (m_hDevMode != NULL) ? (DEVMODE*)::GlobalLock(m_hDevMode) : NULL;
356 HANDLE Detach()
358 if (m_hDevMode != NULL)
359 ::GlobalUnlock(m_hDevMode);
360 HANDLE hDevMode = m_hDevMode;
361 m_hDevMode = NULL;
362 return hDevMode;
365 bool IsNull() const { return (m_hDevMode == NULL); }
367 bool CopyFromPrinter(HANDLE hPrinter)
369 CPrinterInfo<2> pinfo;
370 bool b = pinfo.GetPrinterInfo(hPrinter);
371 if (b)
372 b = CopyFromDEVMODE(pinfo.m_pi->pDevMode);
373 return b;
376 bool CopyFromDEVMODE(const DEVMODE* pdm)
378 if (pdm == NULL)
379 return false;
380 int nSize = pdm->dmSize + pdm->dmDriverExtra;
381 HANDLE h = ::GlobalAlloc(GMEM_MOVEABLE, nSize);
382 if (h != NULL)
384 void* p = ::GlobalLock(h);
385 SecureHelper::memcpy_x(p, nSize, pdm, nSize);
386 ::GlobalUnlock(h);
388 Attach(h);
389 return (h != NULL);
392 bool CopyFromHDEVMODE(HANDLE hdm)
394 bool b = false;
395 if (hdm != NULL)
397 DEVMODE* pdm = (DEVMODE*)::GlobalLock(hdm);
398 b = CopyFromDEVMODE(pdm);
399 ::GlobalUnlock(hdm);
401 return b;
404 HANDLE CopyToHDEVMODE()
406 if ((m_hDevMode == NULL) || (m_pDevMode == NULL))
407 return NULL;
408 int nSize = m_pDevMode->dmSize + m_pDevMode->dmDriverExtra;
409 HANDLE h = ::GlobalAlloc(GMEM_MOVEABLE, nSize);
410 if (h != NULL)
412 void* p = ::GlobalLock(h);
413 SecureHelper::memcpy_x(p, nSize, m_pDevMode, nSize);
414 ::GlobalUnlock(h);
416 return h;
419 // If this devmode was for another printer, this will create a new devmode
420 // based on the existing devmode, but retargeted at the new printer
421 bool UpdateForNewPrinter(HANDLE hPrinter)
423 bool bRet = false;
424 LONG nLen = ::DocumentProperties(NULL, hPrinter, NULL, NULL, NULL, 0);
425 CTempBuffer<DEVMODE, _WTL_STACK_ALLOC_THRESHOLD> buff;
426 DEVMODE* pdm = buff.AllocateBytes(nLen);
427 if(pdm != NULL)
429 memset(pdm, 0, nLen);
430 LONG l = ::DocumentProperties(NULL, hPrinter, NULL, pdm, m_pDevMode, DM_IN_BUFFER | DM_OUT_BUFFER);
431 if (l == IDOK)
432 bRet = CopyFromDEVMODE(pdm);
435 return bRet;
438 bool DocumentProperties(HANDLE hPrinter, HWND hWnd = NULL)
440 CPrinterInfo<1> pi;
441 pi.GetPrinterInfo(hPrinter);
442 if (hWnd == NULL)
443 hWnd = ::GetActiveWindow();
445 bool bRet = false;
446 LONG nLen = ::DocumentProperties(hWnd, hPrinter, pi.m_pi->pName, NULL, NULL, 0);
447 CTempBuffer<DEVMODE, _WTL_STACK_ALLOC_THRESHOLD> buff;
448 DEVMODE* pdm = buff.AllocateBytes(nLen);
449 if(pdm != NULL)
451 memset(pdm, 0, nLen);
452 LONG l = ::DocumentProperties(hWnd, hPrinter, pi.m_pi->pName, pdm, m_pDevMode, DM_IN_BUFFER | DM_OUT_BUFFER | DM_PROMPT);
453 if (l == IDOK)
454 bRet = CopyFromDEVMODE(pdm);
457 return bRet;
460 operator HANDLE() const { return m_hDevMode; }
462 operator DEVMODE*() const { return m_pDevMode; }
464 // Implementation
465 void Cleanup()
467 if (m_hDevMode != NULL)
469 ::GlobalUnlock(m_hDevMode);
470 if(t_bManaged)
471 ::GlobalFree(m_hDevMode);
472 m_hDevMode = NULL;
477 typedef CDevModeT<false> CDevModeHandle;
478 typedef CDevModeT<true> CDevMode;
481 ///////////////////////////////////////////////////////////////////////////////
482 // CPrinterDC
484 class CPrinterDC : public CDC
486 public:
487 // Constructors/destructor
488 CPrinterDC()
490 CPrinter printer;
491 printer.OpenDefaultPrinter();
492 Attach(printer.CreatePrinterDC());
493 ATLASSERT(m_hDC != NULL);
496 CPrinterDC(HANDLE hPrinter, const DEVMODE* pdm = NULL)
498 CPrinterHandle p;
499 p.Attach(hPrinter);
500 Attach(p.CreatePrinterDC(pdm));
501 ATLASSERT(m_hDC != NULL);
504 ~CPrinterDC()
506 DeleteDC();
511 ///////////////////////////////////////////////////////////////////////////////
512 // CPrintJob - Wraps a set of tasks for a specific printer (StartDoc/EndDoc)
513 // Handles aborting, background printing
515 // Defines callbacks used by CPrintJob (not a COM interface)
516 class ATL_NO_VTABLE IPrintJobInfo
518 public:
519 virtual void BeginPrintJob(HDC hDC) = 0; // allocate handles needed, etc.
520 virtual void EndPrintJob(HDC hDC, bool bAborted) = 0; // free handles, etc.
521 virtual void PrePrintPage(UINT nPage, HDC hDC) = 0;
522 virtual bool PrintPage(UINT nPage, HDC hDC) = 0;
523 virtual void PostPrintPage(UINT nPage, HDC hDC) = 0;
524 // If you want per page devmodes, return the DEVMODE* to use for nPage.
525 // You can optimize by only returning a new DEVMODE* when it is different
526 // from the one for nLastPage, otherwise return NULL.
527 // When nLastPage==0, the current DEVMODE* will be the default passed to
528 // StartPrintJob.
529 // Note: During print preview, nLastPage will always be "0".
530 virtual DEVMODE* GetNewDevModeForPage(UINT nLastPage, UINT nPage) = 0;
531 virtual bool IsValidPage(UINT nPage) = 0;
534 // Provides a default implementatin for IPrintJobInfo
535 // Typically, MI'd into a document or view class
536 class ATL_NO_VTABLE CPrintJobInfo : public IPrintJobInfo
538 public:
539 virtual void BeginPrintJob(HDC /*hDC*/) // allocate handles needed, etc
543 virtual void EndPrintJob(HDC /*hDC*/, bool /*bAborted*/) // free handles, etc
547 virtual void PrePrintPage(UINT /*nPage*/, HDC hDC)
549 m_nPJState = ::SaveDC(hDC);
552 virtual bool PrintPage(UINT /*nPage*/, HDC /*hDC*/) = 0;
554 virtual void PostPrintPage(UINT /*nPage*/, HDC hDC)
556 RestoreDC(hDC, m_nPJState);
559 virtual DEVMODE* GetNewDevModeForPage(UINT /*nLastPage*/, UINT /*nPage*/)
561 return NULL;
564 virtual bool IsValidPage(UINT /*nPage*/)
566 return true;
569 // Implementation - data
570 int m_nPJState;
574 class CPrintJob
576 public:
577 // Data members
578 CPrinterHandle m_printer;
579 IPrintJobInfo* m_pInfo;
580 DEVMODE* m_pDefDevMode;
581 DOCINFO m_docinfo;
582 int m_nJobID;
583 bool m_bCancel;
584 bool m_bComplete;
585 unsigned long m_nStartPage;
586 unsigned long m_nEndPage;
588 // Constructor/destructor
589 CPrintJob() : m_nJobID(0), m_bCancel(false), m_bComplete(true)
592 ~CPrintJob()
594 ATLASSERT(IsJobComplete()); // premature destruction?
597 // Operations
598 bool IsJobComplete() const
600 return m_bComplete;
603 bool StartPrintJob(bool bBackground, HANDLE hPrinter, DEVMODE* pDefaultDevMode,
604 IPrintJobInfo* pInfo, LPCTSTR lpszDocName,
605 unsigned long nStartPage, unsigned long nEndPage,
606 bool bPrintToFile = false, LPCTSTR lpstrOutputFile = NULL)
608 ATLASSERT(m_bComplete); // previous job not done yet?
609 if (pInfo == NULL)
610 return false;
612 memset(&m_docinfo, 0, sizeof(m_docinfo));
613 m_docinfo.cbSize = sizeof(m_docinfo);
614 m_docinfo.lpszDocName = lpszDocName;
615 m_pInfo = pInfo;
616 m_nStartPage = nStartPage;
617 m_nEndPage = nEndPage;
618 m_printer.Attach(hPrinter);
619 m_pDefDevMode = pDefaultDevMode;
620 m_bComplete = false;
622 if(bPrintToFile)
623 m_docinfo.lpszOutput = (lpstrOutputFile != NULL) ? lpstrOutputFile : _T("FILE:");
625 if (!bBackground)
627 m_bComplete = true;
628 return StartHelper();
631 // Create a thread and return
632 DWORD dwThreadID = 0;
633 #if !defined(_ATL_MIN_CRT) && defined(_MT)
634 HANDLE hThread = (HANDLE)_beginthreadex(NULL, 0, (UINT (WINAPI*)(void*))StartProc, this, 0, (UINT*)&dwThreadID);
635 #else
636 HANDLE hThread = ::CreateThread(NULL, 0, StartProc, (void*)this, 0, &dwThreadID);
637 #endif
638 if (hThread == NULL)
639 return false;
641 ::CloseHandle(hThread);
643 return true;
646 // Implementation
647 static DWORD WINAPI StartProc(void* p)
649 CPrintJob* pThis = (CPrintJob*)p;
650 pThis->StartHelper();
651 pThis->m_bComplete = true;
652 return 0;
655 bool StartHelper()
657 CDC dcPrinter;
658 dcPrinter.Attach(m_printer.CreatePrinterDC(m_pDefDevMode));
659 if (dcPrinter.IsNull())
660 return false;
662 m_nJobID = ::StartDoc(dcPrinter, &m_docinfo);
663 if (m_nJobID <= 0)
664 return false;
666 m_pInfo->BeginPrintJob(dcPrinter);
668 // print all the pages now
669 unsigned long nLastPage = 0;
670 for (unsigned long nPage = m_nStartPage; nPage <= m_nEndPage; nPage++)
672 if (!m_pInfo->IsValidPage(nPage))
673 break;
674 DEVMODE* pdm = m_pInfo->GetNewDevModeForPage(nLastPage, nPage);
675 if (pdm != NULL)
676 dcPrinter.ResetDC(pdm);
677 dcPrinter.StartPage();
678 m_pInfo->PrePrintPage(nPage, dcPrinter);
679 if (!m_pInfo->PrintPage(nPage, dcPrinter))
680 m_bCancel = true;
681 m_pInfo->PostPrintPage(nPage, dcPrinter);
682 dcPrinter.EndPage();
683 if (m_bCancel)
684 break;
685 nLastPage = nPage;
688 m_pInfo->EndPrintJob(dcPrinter, m_bCancel);
689 if (m_bCancel)
690 ::AbortDoc(dcPrinter);
691 else
692 ::EndDoc(dcPrinter);
693 m_nJobID = 0;
694 return true;
697 // Cancels a print job. Can be called asynchronously.
698 void CancelPrintJob()
700 m_bCancel = true;
705 ///////////////////////////////////////////////////////////////////////////////
706 // CPrintPreview - Adds print preview support to an existing window
708 class CPrintPreview
710 public:
711 // Data members
712 IPrintJobInfo* m_pInfo;
713 CPrinterHandle m_printer;
714 CEnhMetaFile m_meta;
715 DEVMODE* m_pDefDevMode;
716 DEVMODE* m_pCurDevMode;
717 SIZE m_sizeCurPhysOffset;
719 // Constructor
720 CPrintPreview() : m_pInfo(NULL), m_pDefDevMode(NULL), m_pCurDevMode(NULL)
722 m_sizeCurPhysOffset.cx = 0;
723 m_sizeCurPhysOffset.cy = 0;
726 // Operations
727 void SetPrintPreviewInfo(HANDLE hPrinter, DEVMODE* pDefaultDevMode, IPrintJobInfo* pji)
729 m_printer.Attach(hPrinter);
730 m_pDefDevMode = pDefaultDevMode;
731 m_pInfo = pji;
732 m_nCurPage = 0;
733 m_pCurDevMode = NULL;
736 void SetEnhMetaFile(HENHMETAFILE hEMF)
738 m_meta = hEMF;
741 void SetPage(int nPage)
743 if (!m_pInfo->IsValidPage(nPage))
744 return;
745 m_nCurPage = nPage;
746 m_pCurDevMode = m_pInfo->GetNewDevModeForPage(0, nPage);
747 if (m_pCurDevMode == NULL)
748 m_pCurDevMode = m_pDefDevMode;
749 CDC dcPrinter = m_printer.CreatePrinterDC(m_pCurDevMode);
751 int iWidth = dcPrinter.GetDeviceCaps(PHYSICALWIDTH);
752 int iHeight = dcPrinter.GetDeviceCaps(PHYSICALHEIGHT);
753 int nLogx = dcPrinter.GetDeviceCaps(LOGPIXELSX);
754 int nLogy = dcPrinter.GetDeviceCaps(LOGPIXELSY);
756 RECT rcMM = { 0, 0, ::MulDiv(iWidth, 2540, nLogx), ::MulDiv(iHeight, 2540, nLogy) };
758 m_sizeCurPhysOffset.cx = dcPrinter.GetDeviceCaps(PHYSICALOFFSETX);
759 m_sizeCurPhysOffset.cy = dcPrinter.GetDeviceCaps(PHYSICALOFFSETY);
761 CEnhMetaFileDC dcMeta(dcPrinter, &rcMM);
762 m_pInfo->PrePrintPage(nPage, dcMeta);
763 m_pInfo->PrintPage(nPage, dcMeta);
764 m_pInfo->PostPrintPage(nPage, dcMeta);
765 m_meta.Attach(dcMeta.Close());
768 void GetPageRect(RECT& rc, LPRECT prc)
770 int x1 = rc.right-rc.left;
771 int y1 = rc.bottom - rc.top;
772 if ((x1 < 0) || (y1 < 0))
773 return;
775 CEnhMetaFileInfo emfinfo(m_meta);
776 ENHMETAHEADER* pmh = emfinfo.GetEnhMetaFileHeader();
778 // Compute whether we are OK vertically or horizontally
779 int x2 = pmh->szlDevice.cx;
780 int y2 = pmh->szlDevice.cy;
781 int y1p = MulDiv(x1, y2, x2);
782 int x1p = MulDiv(y1, x2, y2);
783 ATLASSERT((x1p <= x1) || (y1p <= y1));
784 if (x1p <= x1)
786 prc->left = rc.left + (x1 - x1p) / 2;
787 prc->right = prc->left + x1p;
788 prc->top = rc.top;
789 prc->bottom = rc.bottom;
791 else
793 prc->left = rc.left;
794 prc->right = rc.right;
795 prc->top = rc.top + (y1 - y1p) / 2;
796 prc->bottom = prc->top + y1p;
800 // Painting helpers
801 void DoPaint(CDCHandle dc)
803 // this one is not used
806 void DoPaint(CDCHandle dc, RECT& rc)
808 CEnhMetaFileInfo emfinfo(m_meta);
809 ENHMETAHEADER* pmh = emfinfo.GetEnhMetaFileHeader();
810 int nOffsetX = MulDiv(m_sizeCurPhysOffset.cx, rc.right-rc.left, pmh->szlDevice.cx);
811 int nOffsetY = MulDiv(m_sizeCurPhysOffset.cy, rc.bottom-rc.top, pmh->szlDevice.cy);
813 dc.OffsetWindowOrg(-nOffsetX, -nOffsetY);
814 dc.PlayMetaFile(m_meta, &rc);
817 // Implementation - data
818 int m_nCurPage;
822 ///////////////////////////////////////////////////////////////////////////////
823 // CPrintPreviewWindow - Implements a print preview window
825 template <class T, class TBase = ATL::CWindow, class TWinTraits = ATL::CControlWinTraits>
826 class ATL_NO_VTABLE CPrintPreviewWindowImpl : public ATL::CWindowImpl<T, TBase, TWinTraits>, public CPrintPreview
828 public:
829 DECLARE_WND_CLASS_EX(NULL, CS_VREDRAW | CS_HREDRAW, -1)
831 enum { m_cxOffset = 10, m_cyOffset = 10 };
833 // Constructor
834 CPrintPreviewWindowImpl() : m_nMaxPage(0), m_nMinPage(0)
837 // Operations
838 void SetPrintPreviewInfo(HANDLE hPrinter, DEVMODE* pDefaultDevMode,
839 IPrintJobInfo* pji, int nMinPage, int nMaxPage)
841 CPrintPreview::SetPrintPreviewInfo(hPrinter, pDefaultDevMode, pji);
842 m_nMinPage = nMinPage;
843 m_nMaxPage = nMaxPage;
846 bool NextPage()
848 if (m_nCurPage == m_nMaxPage)
849 return false;
850 SetPage(m_nCurPage + 1);
851 Invalidate();
852 return true;
855 bool PrevPage()
857 if (m_nCurPage == m_nMinPage)
858 return false;
859 if (m_nCurPage == 0)
860 return false;
861 SetPage(m_nCurPage - 1);
862 Invalidate();
863 return true;
866 // Message map and handlers
867 BEGIN_MSG_MAP(CPrintPreviewWindowImpl)
868 MESSAGE_HANDLER(WM_ERASEBKGND, OnEraseBkgnd)
869 MESSAGE_HANDLER(WM_PAINT, OnPaint)
870 MESSAGE_HANDLER(WM_PRINTCLIENT, OnPaint)
871 END_MSG_MAP()
873 LRESULT OnEraseBkgnd(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& /*bHandled*/)
875 return 1; // no need for the background
878 LRESULT OnPaint(UINT /*uMsg*/, WPARAM wParam, LPARAM /*lParam*/, BOOL& /*bHandled*/)
880 T* pT = static_cast<T*>(this);
881 RECT rc = { 0 };
883 if(wParam != NULL)
885 pT->DoPrePaint((HDC)wParam, rc);
886 pT->DoPaint((HDC)wParam, rc);
888 else
890 CPaintDC dc(m_hWnd);
891 pT->DoPrePaint(dc.m_hDC, rc);
892 pT->DoPaint(dc.m_hDC, rc);
895 return 0;
898 // Painting helper
899 void DoPrePaint(CDCHandle dc, RECT& rc)
901 RECT rcClient = { 0 };
902 GetClientRect(&rcClient);
903 RECT rcArea = rcClient;
904 T* pT = static_cast<T*>(this);
905 pT; // avoid level 4 warning
906 ::InflateRect(&rcArea, -pT->m_cxOffset, -pT->m_cyOffset);
907 if (rcArea.left > rcArea.right)
908 rcArea.right = rcArea.left;
909 if (rcArea.top > rcArea.bottom)
910 rcArea.bottom = rcArea.top;
911 GetPageRect(rcArea, &rc);
912 CRgn rgn1, rgn2;
913 rgn1.CreateRectRgnIndirect(&rc);
914 rgn2.CreateRectRgnIndirect(&rcClient);
915 rgn2.CombineRgn(rgn1, RGN_DIFF);
916 dc.SelectClipRgn(rgn2);
917 dc.FillRect(&rcClient, COLOR_BTNSHADOW);
918 dc.SelectClipRgn(NULL);
919 dc.FillRect(&rc, (HBRUSH)::GetStockObject(WHITE_BRUSH));
922 // Implementation - data
923 int m_nMinPage;
924 int m_nMaxPage;
928 class CPrintPreviewWindow : public CPrintPreviewWindowImpl<CPrintPreviewWindow>
930 public:
931 DECLARE_WND_CLASS_EX(_T("WTL_PrintPreview"), CS_VREDRAW | CS_HREDRAW, -1)
935 ///////////////////////////////////////////////////////////////////////////////
936 // CZoomPrintPreviewWindowImpl - Implements print preview window with zooming
938 #ifdef __ATLSCRL_H__
940 template <class T, class TBase = ATL::CWindow, class TWinTraits = ATL::CControlWinTraits>
941 class ATL_NO_VTABLE CZoomPrintPreviewWindowImpl : public CPrintPreviewWindowImpl< T, TBase, TWinTraits >, public CZoomScrollImpl< T >
943 public:
944 bool m_bSized;
946 CZoomPrintPreviewWindowImpl()
948 SetScrollExtendedStyle(SCRL_DISABLENOSCROLL);
949 InitZoom();
952 // should be called to reset data members before recreating window
953 void InitZoom()
955 m_bSized = false;
956 m_nZoomMode = ZOOMMODE_OFF;
957 m_fZoomScaleMin = 1.0;
958 m_fZoomScale = 1.0;
961 BEGIN_MSG_MAP(CZoomPrintPreviewWindowImpl)
962 MESSAGE_HANDLER(WM_SETCURSOR, CZoomScrollImpl< T >::OnSetCursor)
963 MESSAGE_HANDLER(WM_VSCROLL, CScrollImpl< T >::OnVScroll)
964 MESSAGE_HANDLER(WM_HSCROLL, CScrollImpl< T >::OnHScroll)
965 MESSAGE_HANDLER(WM_MOUSEWHEEL, CScrollImpl< T >::OnMouseWheel)
966 #if !((_WIN32_WINNT >= 0x0400) || (_WIN32_WINDOWS > 0x0400))
967 MESSAGE_HANDLER(m_uMsgMouseWheel, CScrollImpl< T >::OnMouseWheel)
968 #endif // !((_WIN32_WINNT >= 0x0400) || (_WIN32_WINDOWS > 0x0400))
969 MESSAGE_HANDLER(WM_SETTINGCHANGE, CScrollImpl< T >::OnSettingChange)
970 MESSAGE_HANDLER(WM_LBUTTONDOWN, CZoomScrollImpl< T >::OnLButtonDown)
971 MESSAGE_HANDLER(WM_MOUSEMOVE, CZoomScrollImpl< T >::OnMouseMove)
972 MESSAGE_HANDLER(WM_LBUTTONUP, CZoomScrollImpl< T >::OnLButtonUp)
973 MESSAGE_HANDLER(WM_CAPTURECHANGED, CZoomScrollImpl< T >::OnCaptureChanged)
974 MESSAGE_HANDLER(WM_SIZE, OnSize)
975 MESSAGE_HANDLER(WM_ERASEBKGND, OnEraseBkgnd)
976 MESSAGE_HANDLER(WM_PAINT, OnPaint)
977 MESSAGE_HANDLER(WM_PRINTCLIENT, OnPaint)
978 ALT_MSG_MAP(1)
979 COMMAND_ID_HANDLER(ID_SCROLL_UP, CScrollImpl< T >::OnScrollUp)
980 COMMAND_ID_HANDLER(ID_SCROLL_DOWN, CScrollImpl< T >::OnScrollDown)
981 COMMAND_ID_HANDLER(ID_SCROLL_PAGE_UP, CScrollImpl< T >::OnScrollPageUp)
982 COMMAND_ID_HANDLER(ID_SCROLL_PAGE_DOWN, CScrollImpl< T >::OnScrollPageDown)
983 COMMAND_ID_HANDLER(ID_SCROLL_TOP, CScrollImpl< T >::OnScrollTop)
984 COMMAND_ID_HANDLER(ID_SCROLL_BOTTOM, CScrollImpl< T >::OnScrollBottom)
985 COMMAND_ID_HANDLER(ID_SCROLL_LEFT, CScrollImpl< T >::OnScrollLeft)
986 COMMAND_ID_HANDLER(ID_SCROLL_RIGHT, CScrollImpl< T >::OnScrollRight)
987 COMMAND_ID_HANDLER(ID_SCROLL_PAGE_LEFT, CScrollImpl< T >::OnScrollPageLeft)
988 COMMAND_ID_HANDLER(ID_SCROLL_PAGE_RIGHT, CScrollImpl< T >::OnScrollPageRight)
989 COMMAND_ID_HANDLER(ID_SCROLL_ALL_LEFT, CScrollImpl< T >::OnScrollAllLeft)
990 COMMAND_ID_HANDLER(ID_SCROLL_ALL_RIGHT, CScrollImpl< T >::OnScrollAllRight)
991 END_MSG_MAP()
993 LRESULT OnSize(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
995 SIZE sizeClient = {GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam)};
996 POINT ptOffset = m_ptOffset;
997 SIZE sizeAll = m_sizeAll;
998 SetScrollSize(sizeClient);
999 if(sizeAll.cx > 0)
1000 ptOffset.x = ::MulDiv(ptOffset.x, m_sizeAll.cx, sizeAll.cx);
1001 if(sizeAll.cy > 0)
1002 ptOffset.y = ::MulDiv(ptOffset.y, m_sizeAll.cy, sizeAll.cy);
1003 SetScrollOffset(ptOffset);
1004 CScrollImpl< T >::OnSize(uMsg, wParam, lParam, bHandled);
1005 if(!m_bSized)
1007 m_bSized = true;
1008 T* pT = static_cast<T*>(this);
1009 pT->ShowScrollBar(SB_HORZ, TRUE);
1010 pT->ShowScrollBar(SB_VERT, TRUE);
1012 return 0;
1015 LRESULT OnEraseBkgnd(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& /*bHandled*/)
1017 return 1;
1020 LRESULT OnPaint(UINT /*uMsg*/, WPARAM wParam, LPARAM /*lParam*/, BOOL& /*bHandled*/)
1022 T* pT = static_cast<T*>(this);
1023 RECT rc = { 0 };
1025 if(wParam != NULL)
1027 CDCHandle dc = (HDC)wParam;
1028 int nMapModeSav = dc.GetMapMode();
1029 dc.SetMapMode(MM_ANISOTROPIC);
1030 SIZE szWindowExt = { 0, 0 };
1031 dc.SetWindowExt(m_sizeLogAll, &szWindowExt);
1032 SIZE szViewportExt = { 0, 0 };
1033 dc.SetViewportExt(m_sizeAll, &szViewportExt);
1034 POINT ptViewportOrg = { 0, 0 };
1035 dc.SetViewportOrg(-m_ptOffset.x, -m_ptOffset.y, &ptViewportOrg);
1037 pT->DoPrePaint(dc, rc);
1038 pT->DoPaint(dc, rc);
1040 dc.SetMapMode(nMapModeSav);
1041 dc.SetWindowExt(szWindowExt);
1042 dc.SetViewportExt(szViewportExt);
1043 dc.SetViewportOrg(ptViewportOrg);
1045 else
1047 CPaintDC dc(pT->m_hWnd);
1048 pT->PrepareDC(dc.m_hDC);
1049 pT->DoPrePaint(dc.m_hDC, rc);
1050 pT->DoPaint(dc.m_hDC, rc);
1053 return 0;
1056 // Painting helpers
1057 void DoPaint(CDCHandle dc)
1059 // this one is not used
1062 void DoPrePaint(CDCHandle dc, RECT& rc)
1064 RECT rcClient;
1065 GetClientRect(&rcClient);
1066 RECT rcArea = rcClient;
1067 T* pT = static_cast<T*>(this);
1068 pT; // avoid level 4 warning
1069 ::InflateRect(&rcArea, -pT->m_cxOffset, -pT->m_cyOffset);
1070 if (rcArea.left > rcArea.right)
1071 rcArea.right = rcArea.left;
1072 if (rcArea.top > rcArea.bottom)
1073 rcArea.bottom = rcArea.top;
1074 GetPageRect(rcArea, &rc);
1075 HBRUSH hbrOld = dc.SelectBrush(::GetSysColorBrush(COLOR_BTNSHADOW));
1076 dc.PatBlt(rcClient.left, rcClient.top, rc.left - rcClient.left, rcClient.bottom - rcClient.top, PATCOPY);
1077 dc.PatBlt(rc.left, rcClient.top, rc.right - rc.left, rc.top - rcClient.top, PATCOPY);
1078 dc.PatBlt(rc.right, rcClient.top, rcClient.right - rc.right, rcClient.bottom - rcClient.top, PATCOPY);
1079 dc.PatBlt(rc.left, rc.bottom, rc.right - rc.left, rcClient.bottom - rc.bottom, PATCOPY);
1080 dc.SelectBrush((HBRUSH)::GetStockObject(WHITE_BRUSH));
1081 dc.PatBlt(rc.left, rc.top, rc.right - rc.left, rc.bottom - rc.top, PATCOPY);
1082 dc.SelectBrush(::GetSysColorBrush(COLOR_3DDKSHADOW));
1083 dc.PatBlt(rc.right, rc.top + 4, 4, rc.bottom - rc.top, PATCOPY);
1084 dc.PatBlt(rc.left + 4, rc.bottom, rc.right - rc.left, 4, PATCOPY);
1085 dc.SelectBrush(hbrOld);
1088 void DoPaint(CDCHandle dc, RECT& rc)
1090 CEnhMetaFileInfo emfinfo(m_meta);
1091 ENHMETAHEADER* pmh = emfinfo.GetEnhMetaFileHeader();
1092 int nOffsetX = MulDiv(m_sizeCurPhysOffset.cx, rc.right-rc.left, pmh->szlDevice.cx);
1093 int nOffsetY = MulDiv(m_sizeCurPhysOffset.cy, rc.bottom-rc.top, pmh->szlDevice.cy);
1095 dc.OffsetWindowOrg(-nOffsetX, -nOffsetY);
1096 dc.PlayMetaFile(m_meta, &rc);
1100 class CZoomPrintPreviewWindow : public CZoomPrintPreviewWindowImpl<CZoomPrintPreviewWindow>
1102 public:
1103 DECLARE_WND_CLASS_EX(_T("WTL_ZoomPrintPreview"), CS_VREDRAW | CS_HREDRAW, -1)
1106 #endif // __ATLSCRL_H__
1108 }; // namespace WTL
1110 #endif // __ATLPRINT_H__