1 // Windows Template Library - WTL version 8.0
2 // Copyright (C) Microsoft Corporation. All rights reserved.
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.
10 #define __ATLPRINT_H__
15 #error ATL requires C++ compilation (use a .cpp suffix)
19 #error atlprint.h is not supported on Windows CE
23 #error atlprint.h requires atlapp.h to be included first
27 #error atlprint.h requires atlwin.h to be included first
31 ///////////////////////////////////////////////////////////////////////////////
32 // Classes in this file:
34 // CPrinterInfo<t_nInfo>
35 // CPrinterT<t_bManaged>
36 // CDevModeT<t_bManaged>
41 // CPrintPreviewWindowImpl<T, TBase, TWinTraits>
42 // CPrintPreviewWindow
43 // CZoomPrintPreviewWindowImpl<T, TBase, TWinTraits>
44 // CZoomPrintPreviewWindow
49 ///////////////////////////////////////////////////////////////////////////////
50 // CPrinterInfo - This class wraps all of the PRINTER_INFO_* structures
51 // and provided by ::GetPrinter.
53 template <unsigned int t_nInfo
>
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
>
79 typename _printer_info
<t_nInfo
>::infotype
* m_pi
;
81 // Constructor/destructor
82 CPrinterInfo() : m_pi(NULL
)
85 CPrinterInfo(HANDLE hPrinter
) : m_pi(NULL
)
87 GetPrinterInfo(hPrinter
);
96 bool GetPrinterInfo(HANDLE hPrinter
)
99 return GetPrinterInfoHelper(hPrinter
, (BYTE
**)&m_pi
, t_nInfo
);
105 delete [] (BYTE
*)m_pi
;
109 static bool GetPrinterInfoHelper(HANDLE hPrinter
, BYTE
** pi
, int nIndex
)
111 ATLASSERT(pi
!= NULL
);
114 ::GetPrinter(hPrinter
, nIndex
, NULL
, 0, &dw
);
117 ATLTRY(pb
= new BYTE
[dw
]);
122 if (!::GetPrinter(hPrinter
, nIndex
, pb
, dw
, &dwNew
))
135 ///////////////////////////////////////////////////////////////////////////////
136 // CPrinter - Wrapper class for a HANDLE to a printer
138 template <bool t_bManaged
>
145 // Constructor/destructor
146 CPrinterT(HANDLE hPrinter
= NULL
) : m_hPrinter(hPrinter
)
155 CPrinterT
& operator =(HANDLE hPrinter
)
157 if (hPrinter
!= m_hPrinter
)
160 m_hPrinter
= hPrinter
;
165 bool IsNull() const { return (m_hPrinter
== NULL
); }
167 bool OpenPrinter(HANDLE hDevNames
, const DEVMODE
* pDevMode
= NULL
)
170 DEVNAMES
* pdn
= (DEVNAMES
*)::GlobalLock(hDevNames
);
173 LPTSTR lpszPrinterName
= (LPTSTR
)pdn
+ pdn
->wDeviceOffset
;
174 b
= OpenPrinter(lpszPrinterName
, pDevMode
);
175 ::GlobalUnlock(hDevNames
);
180 bool OpenPrinter(LPCTSTR lpszPrinterName
, const DEVMODE
* pDevMode
= NULL
)
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
)
192 ::OpenPrinter((LPTSTR
) lpszPrinterName
, &m_hPrinter
, pprintdefs
);
193 return (m_hPrinter
!= NULL
);
196 bool OpenDefaultPrinter(const DEVMODE
* pDevMode
= NULL
)
199 const int cchBuff
= 512;
200 TCHAR buffer
[cchBuff
];
202 ::GetProfileString(_T("windows"), _T("device"), _T(",,,"), buffer
, cchBuff
);
203 int nLen
= lstrlen(buffer
);
206 LPTSTR lpsz
= buffer
;
209 if (*lpsz
== _T(','))
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
;
224 if (m_hPrinter
!= NULL
)
227 ::ClosePrinter(m_hPrinter
);
232 bool PrinterProperties(HWND hWnd
= NULL
)
235 hWnd
= ::GetActiveWindow();
236 return !!::PrinterProperties(hWnd
, m_hPrinter
);
239 HANDLE
CopyToHDEVNAMES() const
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
;
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
);
268 HDC
CreatePrinterDC(const DEVMODE
* pdm
= NULL
) const
270 CPrinterInfo
<5> pinfo5
;
271 CPrinterInfo
<2> pinfo2
;
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
);
284 HDC
CreatePrinterIC(const DEVMODE
* pdm
= NULL
) const
286 CPrinterInfo
<5> pinfo5
;
287 CPrinterInfo
<2> pinfo2
;
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
);
300 void Attach(HANDLE hPrinter
)
303 m_hPrinter
= hPrinter
;
308 HANDLE hPrinter
= m_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
>
331 // Constructor/destructor
332 CDevModeT(HANDLE hDevMode
= NULL
) : m_hDevMode(hDevMode
)
334 m_pDevMode
= (m_hDevMode
!= NULL
) ? (DEVMODE
*)::GlobalLock(m_hDevMode
) : NULL
;
343 CDevModeT
<t_bManaged
>& operator =(HANDLE hDevMode
)
349 void Attach(HANDLE hDevModeNew
)
352 m_hDevMode
= hDevModeNew
;
353 m_pDevMode
= (m_hDevMode
!= NULL
) ? (DEVMODE
*)::GlobalLock(m_hDevMode
) : NULL
;
358 if (m_hDevMode
!= NULL
)
359 ::GlobalUnlock(m_hDevMode
);
360 HANDLE hDevMode
= m_hDevMode
;
365 bool IsNull() const { return (m_hDevMode
== NULL
); }
367 bool CopyFromPrinter(HANDLE hPrinter
)
369 CPrinterInfo
<2> pinfo
;
370 bool b
= pinfo
.GetPrinterInfo(hPrinter
);
372 b
= CopyFromDEVMODE(pinfo
.m_pi
->pDevMode
);
376 bool CopyFromDEVMODE(const DEVMODE
* pdm
)
380 int nSize
= pdm
->dmSize
+ pdm
->dmDriverExtra
;
381 HANDLE h
= ::GlobalAlloc(GMEM_MOVEABLE
, nSize
);
384 void* p
= ::GlobalLock(h
);
385 SecureHelper::memcpy_x(p
, nSize
, pdm
, nSize
);
392 bool CopyFromHDEVMODE(HANDLE hdm
)
397 DEVMODE
* pdm
= (DEVMODE
*)::GlobalLock(hdm
);
398 b
= CopyFromDEVMODE(pdm
);
404 HANDLE
CopyToHDEVMODE()
406 if ((m_hDevMode
== NULL
) || (m_pDevMode
== NULL
))
408 int nSize
= m_pDevMode
->dmSize
+ m_pDevMode
->dmDriverExtra
;
409 HANDLE h
= ::GlobalAlloc(GMEM_MOVEABLE
, nSize
);
412 void* p
= ::GlobalLock(h
);
413 SecureHelper::memcpy_x(p
, nSize
, m_pDevMode
, nSize
);
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
)
424 LONG nLen
= ::DocumentProperties(NULL
, hPrinter
, NULL
, NULL
, NULL
, 0);
425 CTempBuffer
<DEVMODE
, _WTL_STACK_ALLOC_THRESHOLD
> buff
;
426 DEVMODE
* pdm
= buff
.AllocateBytes(nLen
);
429 memset(pdm
, 0, nLen
);
430 LONG l
= ::DocumentProperties(NULL
, hPrinter
, NULL
, pdm
, m_pDevMode
, DM_IN_BUFFER
| DM_OUT_BUFFER
);
432 bRet
= CopyFromDEVMODE(pdm
);
438 bool DocumentProperties(HANDLE hPrinter
, HWND hWnd
= NULL
)
441 pi
.GetPrinterInfo(hPrinter
);
443 hWnd
= ::GetActiveWindow();
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
);
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
);
454 bRet
= CopyFromDEVMODE(pdm
);
460 operator HANDLE() const { return m_hDevMode
; }
462 operator DEVMODE
*() const { return m_pDevMode
; }
467 if (m_hDevMode
!= NULL
)
469 ::GlobalUnlock(m_hDevMode
);
471 ::GlobalFree(m_hDevMode
);
477 typedef CDevModeT
<false> CDevModeHandle
;
478 typedef CDevModeT
<true> CDevMode
;
481 ///////////////////////////////////////////////////////////////////////////////
484 class CPrinterDC
: public CDC
487 // Constructors/destructor
491 printer
.OpenDefaultPrinter();
492 Attach(printer
.CreatePrinterDC());
493 ATLASSERT(m_hDC
!= NULL
);
496 CPrinterDC(HANDLE hPrinter
, const DEVMODE
* pdm
= NULL
)
500 Attach(p
.CreatePrinterDC(pdm
));
501 ATLASSERT(m_hDC
!= NULL
);
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
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
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
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*/)
564 virtual bool IsValidPage(UINT
/*nPage*/)
569 // Implementation - data
578 CPrinterHandle m_printer
;
579 IPrintJobInfo
* m_pInfo
;
580 DEVMODE
* m_pDefDevMode
;
585 unsigned long m_nStartPage
;
586 unsigned long m_nEndPage
;
588 // Constructor/destructor
589 CPrintJob() : m_nJobID(0), m_bCancel(false), m_bComplete(true)
594 ATLASSERT(IsJobComplete()); // premature destruction?
598 bool IsJobComplete() const
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?
612 memset(&m_docinfo
, 0, sizeof(m_docinfo
));
613 m_docinfo
.cbSize
= sizeof(m_docinfo
);
614 m_docinfo
.lpszDocName
= lpszDocName
;
616 m_nStartPage
= nStartPage
;
617 m_nEndPage
= nEndPage
;
618 m_printer
.Attach(hPrinter
);
619 m_pDefDevMode
= pDefaultDevMode
;
623 m_docinfo
.lpszOutput
= (lpstrOutputFile
!= NULL
) ? lpstrOutputFile
: _T("FILE:");
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
);
636 HANDLE hThread
= ::CreateThread(NULL
, 0, StartProc
, (void*)this, 0, &dwThreadID
);
641 ::CloseHandle(hThread
);
647 static DWORD WINAPI
StartProc(void* p
)
649 CPrintJob
* pThis
= (CPrintJob
*)p
;
650 pThis
->StartHelper();
651 pThis
->m_bComplete
= true;
658 dcPrinter
.Attach(m_printer
.CreatePrinterDC(m_pDefDevMode
));
659 if (dcPrinter
.IsNull())
662 m_nJobID
= ::StartDoc(dcPrinter
, &m_docinfo
);
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
))
674 DEVMODE
* pdm
= m_pInfo
->GetNewDevModeForPage(nLastPage
, nPage
);
676 dcPrinter
.ResetDC(pdm
);
677 dcPrinter
.StartPage();
678 m_pInfo
->PrePrintPage(nPage
, dcPrinter
);
679 if (!m_pInfo
->PrintPage(nPage
, dcPrinter
))
681 m_pInfo
->PostPrintPage(nPage
, dcPrinter
);
688 m_pInfo
->EndPrintJob(dcPrinter
, m_bCancel
);
690 ::AbortDoc(dcPrinter
);
697 // Cancels a print job. Can be called asynchronously.
698 void CancelPrintJob()
705 ///////////////////////////////////////////////////////////////////////////////
706 // CPrintPreview - Adds print preview support to an existing window
712 IPrintJobInfo
* m_pInfo
;
713 CPrinterHandle m_printer
;
715 DEVMODE
* m_pDefDevMode
;
716 DEVMODE
* m_pCurDevMode
;
717 SIZE m_sizeCurPhysOffset
;
720 CPrintPreview() : m_pInfo(NULL
), m_pDefDevMode(NULL
), m_pCurDevMode(NULL
)
722 m_sizeCurPhysOffset
.cx
= 0;
723 m_sizeCurPhysOffset
.cy
= 0;
727 void SetPrintPreviewInfo(HANDLE hPrinter
, DEVMODE
* pDefaultDevMode
, IPrintJobInfo
* pji
)
729 m_printer
.Attach(hPrinter
);
730 m_pDefDevMode
= pDefaultDevMode
;
733 m_pCurDevMode
= NULL
;
736 void SetEnhMetaFile(HENHMETAFILE hEMF
)
741 void SetPage(int nPage
)
743 if (!m_pInfo
->IsValidPage(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))
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
));
786 prc
->left
= rc
.left
+ (x1
- x1p
) / 2;
787 prc
->right
= prc
->left
+ x1p
;
789 prc
->bottom
= rc
.bottom
;
794 prc
->right
= rc
.right
;
795 prc
->top
= rc
.top
+ (y1
- y1p
) / 2;
796 prc
->bottom
= prc
->top
+ y1p
;
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
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
829 DECLARE_WND_CLASS_EX(NULL
, CS_VREDRAW
| CS_HREDRAW
, -1)
831 enum { m_cxOffset
= 10, m_cyOffset
= 10 };
834 CPrintPreviewWindowImpl() : m_nMaxPage(0), m_nMinPage(0)
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
;
848 if (m_nCurPage
== m_nMaxPage
)
850 SetPage(m_nCurPage
+ 1);
857 if (m_nCurPage
== m_nMinPage
)
861 SetPage(m_nCurPage
- 1);
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
)
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);
885 pT
->DoPrePaint((HDC
)wParam
, rc
);
886 pT
->DoPaint((HDC
)wParam
, rc
);
891 pT
->DoPrePaint(dc
.m_hDC
, rc
);
892 pT
->DoPaint(dc
.m_hDC
, rc
);
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
);
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
928 class CPrintPreviewWindow
: public CPrintPreviewWindowImpl
<CPrintPreviewWindow
>
931 DECLARE_WND_CLASS_EX(_T("WTL_PrintPreview"), CS_VREDRAW
| CS_HREDRAW
, -1)
935 ///////////////////////////////////////////////////////////////////////////////
936 // CZoomPrintPreviewWindowImpl - Implements print preview window with zooming
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
>
946 CZoomPrintPreviewWindowImpl()
948 SetScrollExtendedStyle(SCRL_DISABLENOSCROLL
);
952 // should be called to reset data members before recreating window
956 m_nZoomMode
= ZOOMMODE_OFF
;
957 m_fZoomScaleMin
= 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
)
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
)
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
);
1000 ptOffset
.x
= ::MulDiv(ptOffset
.x
, m_sizeAll
.cx
, sizeAll
.cx
);
1002 ptOffset
.y
= ::MulDiv(ptOffset
.y
, m_sizeAll
.cy
, sizeAll
.cy
);
1003 SetScrollOffset(ptOffset
);
1004 CScrollImpl
< T
>::OnSize(uMsg
, wParam
, lParam
, bHandled
);
1008 T
* pT
= static_cast<T
*>(this);
1009 pT
->ShowScrollBar(SB_HORZ
, TRUE
);
1010 pT
->ShowScrollBar(SB_VERT
, TRUE
);
1015 LRESULT
OnEraseBkgnd(UINT
/*uMsg*/, WPARAM
/*wParam*/, LPARAM
/*lParam*/, BOOL
& /*bHandled*/)
1020 LRESULT
OnPaint(UINT
/*uMsg*/, WPARAM wParam
, LPARAM
/*lParam*/, BOOL
& /*bHandled*/)
1022 T
* pT
= static_cast<T
*>(this);
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
);
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
);
1057 void DoPaint(CDCHandle dc
)
1059 // this one is not used
1062 void DoPrePaint(CDCHandle dc
, RECT
& rc
)
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
>
1103 DECLARE_WND_CLASS_EX(_T("WTL_ZoomPrintPreview"), CS_VREDRAW
| CS_HREDRAW
, -1)
1106 #endif // __ATLSCRL_H__
1110 #endif // __ATLPRINT_H__