1 // Windows Template Library - WTL version 8.0
\r
2 // Copyright (C) Microsoft Corporation. All rights reserved.
\r
4 // This file is a part of the Windows Template Library.
\r
5 // The use and distribution terms for this software are covered by the
\r
6 // Common Public License 1.0 (http://opensource.org/osi3.0/licenses/cpl1.0.php)
\r
7 // which can be found in the file CPL.TXT at the root of this distribution.
\r
8 // By using this software in any fashion, you are agreeing to be bound by
\r
9 // the terms of this license. You must not remove this notice, or
\r
10 // any other, from this software.
\r
12 #ifndef __ATLPRINT_H__
\r
13 #define __ATLPRINT_H__
\r
18 #error ATL requires C++ compilation (use a .cpp suffix)
\r
22 #error atlprint.h is not supported on Windows CE
\r
25 #ifndef __ATLAPP_H__
\r
26 #error atlprint.h requires atlapp.h to be included first
\r
29 #ifndef __ATLWIN_H__
\r
30 #error atlprint.h requires atlwin.h to be included first
\r
34 ///////////////////////////////////////////////////////////////////////////////
\r
35 // Classes in this file:
\r
37 // CPrinterInfo<t_nInfo>
\r
38 // CPrinterT<t_bManaged>
\r
39 // CDevModeT<t_bManaged>
\r
44 // CPrintPreviewWindowImpl<T, TBase, TWinTraits>
\r
45 // CPrintPreviewWindow
\r
46 // CZoomPrintPreviewWindowImpl<T, TBase, TWinTraits>
\r
47 // CZoomPrintPreviewWindow
\r
52 ///////////////////////////////////////////////////////////////////////////////
\r
53 // CPrinterInfo - This class wraps all of the PRINTER_INFO_* structures
\r
54 // and provided by ::GetPrinter.
\r
56 template <unsigned int t_nInfo>
\r
60 typedef void infotype;
\r
63 template <> class _printer_info<1> { public: typedef PRINTER_INFO_1 infotype; };
\r
64 template <> class _printer_info<2> { public: typedef PRINTER_INFO_2 infotype; };
\r
65 template <> class _printer_info<3> { public: typedef PRINTER_INFO_3 infotype; };
\r
66 template <> class _printer_info<4> { public: typedef PRINTER_INFO_4 infotype; };
\r
67 template <> class _printer_info<5> { public: typedef PRINTER_INFO_5 infotype; };
\r
68 template <> class _printer_info<6> { public: typedef PRINTER_INFO_6 infotype; };
\r
69 template <> class _printer_info<7> { public: typedef PRINTER_INFO_7 infotype; };
\r
70 // these are not in the old (vc6.0) headers
\r
71 #ifdef _ATL_USE_NEW_PRINTER_INFO
\r
72 template <> class _printer_info<8> { public: typedef PRINTER_INFO_8 infotype; };
\r
73 template <> class _printer_info<9> { public: typedef PRINTER_INFO_9 infotype; };
\r
74 #endif // _ATL_USE_NEW_PRINTER_INFO
\r
77 template <unsigned int t_nInfo>
\r
82 typename _printer_info<t_nInfo>::infotype* m_pi;
\r
84 // Constructor/destructor
\r
85 CPrinterInfo() : m_pi(NULL)
\r
88 CPrinterInfo(HANDLE hPrinter) : m_pi(NULL)
\r
90 GetPrinterInfo(hPrinter);
\r
99 bool GetPrinterInfo(HANDLE hPrinter)
\r
102 return GetPrinterInfoHelper(hPrinter, (BYTE**)&m_pi, t_nInfo);
\r
108 delete [] (BYTE*)m_pi;
\r
112 static bool GetPrinterInfoHelper(HANDLE hPrinter, BYTE** pi, int nIndex)
\r
114 ATLASSERT(pi != NULL);
\r
117 ::GetPrinter(hPrinter, nIndex, NULL, 0, &dw);
\r
120 ATLTRY(pb = new BYTE[dw]);
\r
125 if (!::GetPrinter(hPrinter, nIndex, pb, dw, &dwNew))
\r
133 return (pb != NULL);
\r
138 ///////////////////////////////////////////////////////////////////////////////
\r
139 // CPrinter - Wrapper class for a HANDLE to a printer
\r
141 template <bool t_bManaged>
\r
148 // Constructor/destructor
\r
149 CPrinterT(HANDLE hPrinter = NULL) : m_hPrinter(hPrinter)
\r
158 CPrinterT& operator =(HANDLE hPrinter)
\r
160 if (hPrinter != m_hPrinter)
\r
163 m_hPrinter = hPrinter;
\r
168 bool IsNull() const { return (m_hPrinter == NULL); }
\r
170 bool OpenPrinter(HANDLE hDevNames, const DEVMODE* pDevMode = NULL)
\r
173 DEVNAMES* pdn = (DEVNAMES*)::GlobalLock(hDevNames);
\r
176 LPTSTR lpszPrinterName = (LPTSTR)pdn + pdn->wDeviceOffset;
\r
177 b = OpenPrinter(lpszPrinterName, pDevMode);
\r
178 ::GlobalUnlock(hDevNames);
\r
183 bool OpenPrinter(LPCTSTR lpszPrinterName, const DEVMODE* pDevMode = NULL)
\r
186 PRINTER_DEFAULTS pdefs = { NULL, (DEVMODE*)pDevMode, PRINTER_ACCESS_USE };
\r
187 ::OpenPrinter((LPTSTR) lpszPrinterName, &m_hPrinter, (pDevMode == NULL) ? NULL : &pdefs);
\r
189 return (m_hPrinter != NULL);
\r
192 bool OpenPrinter(LPCTSTR lpszPrinterName, PRINTER_DEFAULTS* pprintdefs)
\r
195 ::OpenPrinter((LPTSTR) lpszPrinterName, &m_hPrinter, pprintdefs);
\r
196 return (m_hPrinter != NULL);
\r
199 bool OpenDefaultPrinter(const DEVMODE* pDevMode = NULL)
\r
202 const int cchBuff = 512;
\r
203 TCHAR buffer[cchBuff];
\r
205 ::GetProfileString(_T("windows"), _T("device"), _T(",,,"), buffer, cchBuff);
\r
206 int nLen = lstrlen(buffer);
\r
209 LPTSTR lpsz = buffer;
\r
212 if (*lpsz == _T(','))
\r
217 lpsz = CharNext(lpsz);
\r
219 PRINTER_DEFAULTS pdefs = { NULL, (DEVMODE*)pDevMode, PRINTER_ACCESS_USE };
\r
220 ::OpenPrinter(buffer, &m_hPrinter, (pDevMode == NULL) ? NULL : &pdefs);
\r
222 return m_hPrinter != NULL;
\r
225 void ClosePrinter()
\r
227 if (m_hPrinter != NULL)
\r
230 ::ClosePrinter(m_hPrinter);
\r
235 bool PrinterProperties(HWND hWnd = NULL)
\r
238 hWnd = ::GetActiveWindow();
\r
239 return !!::PrinterProperties(hWnd, m_hPrinter);
\r
242 HANDLE CopyToHDEVNAMES() const
\r
245 CPrinterInfo<5> pinfon5;
\r
246 CPrinterInfo<2> pinfon2;
\r
247 LPTSTR lpszPrinterName = NULL;
\r
248 // Some printers fail for PRINTER_INFO_5 in some situations
\r
249 if (pinfon5.GetPrinterInfo(m_hPrinter))
\r
250 lpszPrinterName = pinfon5.m_pi->pPrinterName;
\r
251 else if (pinfon2.GetPrinterInfo(m_hPrinter))
\r
252 lpszPrinterName = pinfon2.m_pi->pPrinterName;
\r
253 if (lpszPrinterName != NULL)
\r
255 int nLen = sizeof(DEVNAMES) + (lstrlen(lpszPrinterName) + 1) * sizeof(TCHAR);
\r
256 h = ::GlobalAlloc(GMEM_MOVEABLE, nLen);
\r
257 BYTE* pv = (BYTE*)::GlobalLock(h);
\r
258 DEVNAMES* pdev = (DEVNAMES*)pv;
\r
261 memset(pv, 0, nLen);
\r
262 pdev->wDeviceOffset = sizeof(DEVNAMES) / sizeof(TCHAR);
\r
263 pv = pv + sizeof(DEVNAMES); // now points to end
\r
264 SecureHelper::strcpy_x((LPTSTR)pv, lstrlen(lpszPrinterName) + 1, lpszPrinterName);
\r
271 HDC CreatePrinterDC(const DEVMODE* pdm = NULL) const
\r
273 CPrinterInfo<5> pinfo5;
\r
274 CPrinterInfo<2> pinfo2;
\r
276 LPTSTR lpszPrinterName = NULL;
\r
277 // Some printers fail for PRINTER_INFO_5 in some situations
\r
278 if (pinfo5.GetPrinterInfo(m_hPrinter))
\r
279 lpszPrinterName = pinfo5.m_pi->pPrinterName;
\r
280 else if (pinfo2.GetPrinterInfo(m_hPrinter))
\r
281 lpszPrinterName = pinfo2.m_pi->pPrinterName;
\r
282 if (lpszPrinterName != NULL)
\r
283 hDC = ::CreateDC(NULL, lpszPrinterName, NULL, pdm);
\r
287 HDC CreatePrinterIC(const DEVMODE* pdm = NULL) const
\r
289 CPrinterInfo<5> pinfo5;
\r
290 CPrinterInfo<2> pinfo2;
\r
292 LPTSTR lpszPrinterName = NULL;
\r
293 // Some printers fail for PRINTER_INFO_5 in some situations
\r
294 if (pinfo5.GetPrinterInfo(m_hPrinter))
\r
295 lpszPrinterName = pinfo5.m_pi->pPrinterName;
\r
296 else if (pinfo2.GetPrinterInfo(m_hPrinter))
\r
297 lpszPrinterName = pinfo2.m_pi->pPrinterName;
\r
298 if (lpszPrinterName != NULL)
\r
299 hDC = ::CreateIC(NULL, lpszPrinterName, NULL, pdm);
\r
303 void Attach(HANDLE hPrinter)
\r
306 m_hPrinter = hPrinter;
\r
311 HANDLE hPrinter = m_hPrinter;
\r
316 operator HANDLE() const { return m_hPrinter; }
\r
319 typedef CPrinterT<false> CPrinterHandle;
\r
320 typedef CPrinterT<true> CPrinter;
\r
323 ///////////////////////////////////////////////////////////////////////////////
\r
324 // CDevMode - Wrapper class for DEVMODE
\r
326 template <bool t_bManaged>
\r
332 DEVMODE* m_pDevMode;
\r
334 // Constructor/destructor
\r
335 CDevModeT(HANDLE hDevMode = NULL) : m_hDevMode(hDevMode)
\r
337 m_pDevMode = (m_hDevMode != NULL) ? (DEVMODE*)::GlobalLock(m_hDevMode) : NULL;
\r
346 CDevModeT<t_bManaged>& operator =(HANDLE hDevMode)
\r
352 void Attach(HANDLE hDevModeNew)
\r
355 m_hDevMode = hDevModeNew;
\r
356 m_pDevMode = (m_hDevMode != NULL) ? (DEVMODE*)::GlobalLock(m_hDevMode) : NULL;
\r
361 if (m_hDevMode != NULL)
\r
362 ::GlobalUnlock(m_hDevMode);
\r
363 HANDLE hDevMode = m_hDevMode;
\r
368 bool IsNull() const { return (m_hDevMode == NULL); }
\r
370 bool CopyFromPrinter(HANDLE hPrinter)
\r
372 CPrinterInfo<2> pinfo;
\r
373 bool b = pinfo.GetPrinterInfo(hPrinter);
\r
375 b = CopyFromDEVMODE(pinfo.m_pi->pDevMode);
\r
379 bool CopyFromDEVMODE(const DEVMODE* pdm)
\r
383 int nSize = pdm->dmSize + pdm->dmDriverExtra;
\r
384 HANDLE h = ::GlobalAlloc(GMEM_MOVEABLE, nSize);
\r
387 void* p = ::GlobalLock(h);
\r
388 SecureHelper::memcpy_x(p, nSize, pdm, nSize);
\r
392 return (h != NULL);
\r
395 bool CopyFromHDEVMODE(HANDLE hdm)
\r
400 DEVMODE* pdm = (DEVMODE*)::GlobalLock(hdm);
\r
401 b = CopyFromDEVMODE(pdm);
\r
402 ::GlobalUnlock(hdm);
\r
407 HANDLE CopyToHDEVMODE()
\r
409 if ((m_hDevMode == NULL) || (m_pDevMode == NULL))
\r
411 int nSize = m_pDevMode->dmSize + m_pDevMode->dmDriverExtra;
\r
412 HANDLE h = ::GlobalAlloc(GMEM_MOVEABLE, nSize);
\r
415 void* p = ::GlobalLock(h);
\r
416 SecureHelper::memcpy_x(p, nSize, m_pDevMode, nSize);
\r
422 // If this devmode was for another printer, this will create a new devmode
\r
423 // based on the existing devmode, but retargeted at the new printer
\r
424 bool UpdateForNewPrinter(HANDLE hPrinter)
\r
427 LONG nLen = ::DocumentProperties(NULL, hPrinter, NULL, NULL, NULL, 0);
\r
428 CTempBuffer<DEVMODE, _WTL_STACK_ALLOC_THRESHOLD> buff;
\r
429 DEVMODE* pdm = buff.AllocateBytes(nLen);
\r
432 memset(pdm, 0, nLen);
\r
433 LONG l = ::DocumentProperties(NULL, hPrinter, NULL, pdm, m_pDevMode, DM_IN_BUFFER | DM_OUT_BUFFER);
\r
435 bRet = CopyFromDEVMODE(pdm);
\r
441 bool DocumentProperties(HANDLE hPrinter, HWND hWnd = NULL)
\r
443 CPrinterInfo<1> pi;
\r
444 pi.GetPrinterInfo(hPrinter);
\r
446 hWnd = ::GetActiveWindow();
\r
449 LONG nLen = ::DocumentProperties(hWnd, hPrinter, pi.m_pi->pName, NULL, NULL, 0);
\r
450 CTempBuffer<DEVMODE, _WTL_STACK_ALLOC_THRESHOLD> buff;
\r
451 DEVMODE* pdm = buff.AllocateBytes(nLen);
\r
454 memset(pdm, 0, nLen);
\r
455 LONG l = ::DocumentProperties(hWnd, hPrinter, pi.m_pi->pName, pdm, m_pDevMode, DM_IN_BUFFER | DM_OUT_BUFFER | DM_PROMPT);
\r
457 bRet = CopyFromDEVMODE(pdm);
\r
463 operator HANDLE() const { return m_hDevMode; }
\r
465 operator DEVMODE*() const { return m_pDevMode; }
\r
470 if (m_hDevMode != NULL)
\r
472 ::GlobalUnlock(m_hDevMode);
\r
474 ::GlobalFree(m_hDevMode);
\r
480 typedef CDevModeT<false> CDevModeHandle;
\r
481 typedef CDevModeT<true> CDevMode;
\r
484 ///////////////////////////////////////////////////////////////////////////////
\r
487 class CPrinterDC : public CDC
\r
490 // Constructors/destructor
\r
494 printer.OpenDefaultPrinter();
\r
495 Attach(printer.CreatePrinterDC());
\r
496 ATLASSERT(m_hDC != NULL);
\r
499 CPrinterDC(HANDLE hPrinter, const DEVMODE* pdm = NULL)
\r
502 p.Attach(hPrinter);
\r
503 Attach(p.CreatePrinterDC(pdm));
\r
504 ATLASSERT(m_hDC != NULL);
\r
514 ///////////////////////////////////////////////////////////////////////////////
\r
515 // CPrintJob - Wraps a set of tasks for a specific printer (StartDoc/EndDoc)
\r
516 // Handles aborting, background printing
\r
518 // Defines callbacks used by CPrintJob (not a COM interface)
\r
519 class ATL_NO_VTABLE IPrintJobInfo
\r
522 virtual void BeginPrintJob(HDC hDC) = 0; // allocate handles needed, etc.
\r
523 virtual void EndPrintJob(HDC hDC, bool bAborted) = 0; // free handles, etc.
\r
524 virtual void PrePrintPage(UINT nPage, HDC hDC) = 0;
\r
525 virtual bool PrintPage(UINT nPage, HDC hDC) = 0;
\r
526 virtual void PostPrintPage(UINT nPage, HDC hDC) = 0;
\r
527 // If you want per page devmodes, return the DEVMODE* to use for nPage.
\r
528 // You can optimize by only returning a new DEVMODE* when it is different
\r
529 // from the one for nLastPage, otherwise return NULL.
\r
530 // When nLastPage==0, the current DEVMODE* will be the default passed to
\r
532 // Note: During print preview, nLastPage will always be "0".
\r
533 virtual DEVMODE* GetNewDevModeForPage(UINT nLastPage, UINT nPage) = 0;
\r
534 virtual bool IsValidPage(UINT nPage) = 0;
\r
537 // Provides a default implementatin for IPrintJobInfo
\r
538 // Typically, MI'd into a document or view class
\r
539 class ATL_NO_VTABLE CPrintJobInfo : public IPrintJobInfo
\r
542 virtual void BeginPrintJob(HDC /*hDC*/) // allocate handles needed, etc
\r
546 virtual void EndPrintJob(HDC /*hDC*/, bool /*bAborted*/) // free handles, etc
\r
550 virtual void PrePrintPage(UINT /*nPage*/, HDC hDC)
\r
552 m_nPJState = ::SaveDC(hDC);
\r
555 virtual bool PrintPage(UINT /*nPage*/, HDC /*hDC*/) = 0;
\r
557 virtual void PostPrintPage(UINT /*nPage*/, HDC hDC)
\r
559 RestoreDC(hDC, m_nPJState);
\r
562 virtual DEVMODE* GetNewDevModeForPage(UINT /*nLastPage*/, UINT /*nPage*/)
\r
567 virtual bool IsValidPage(UINT /*nPage*/)
\r
572 // Implementation - data
\r
581 CPrinterHandle m_printer;
\r
582 IPrintJobInfo* m_pInfo;
\r
583 DEVMODE* m_pDefDevMode;
\r
588 unsigned long m_nStartPage;
\r
589 unsigned long m_nEndPage;
\r
591 // Constructor/destructor
\r
592 CPrintJob() : m_nJobID(0), m_bCancel(false), m_bComplete(true)
\r
597 ATLASSERT(IsJobComplete()); // premature destruction?
\r
601 bool IsJobComplete() const
\r
603 return m_bComplete;
\r
606 bool StartPrintJob(bool bBackground, HANDLE hPrinter, DEVMODE* pDefaultDevMode,
\r
607 IPrintJobInfo* pInfo, LPCTSTR lpszDocName,
\r
608 unsigned long nStartPage, unsigned long nEndPage,
\r
609 bool bPrintToFile = false, LPCTSTR lpstrOutputFile = NULL)
\r
611 ATLASSERT(m_bComplete); // previous job not done yet?
\r
615 memset(&m_docinfo, 0, sizeof(m_docinfo));
\r
616 m_docinfo.cbSize = sizeof(m_docinfo);
\r
617 m_docinfo.lpszDocName = lpszDocName;
\r
619 m_nStartPage = nStartPage;
\r
620 m_nEndPage = nEndPage;
\r
621 m_printer.Attach(hPrinter);
\r
622 m_pDefDevMode = pDefaultDevMode;
\r
623 m_bComplete = false;
\r
626 m_docinfo.lpszOutput = (lpstrOutputFile != NULL) ? lpstrOutputFile : _T("FILE:");
\r
630 m_bComplete = true;
\r
631 return StartHelper();
\r
634 // Create a thread and return
\r
635 DWORD dwThreadID = 0;
\r
636 #if !defined(_ATL_MIN_CRT) && defined(_MT)
\r
637 HANDLE hThread = (HANDLE)_beginthreadex(NULL, 0, (UINT (WINAPI*)(void*))StartProc, this, 0, (UINT*)&dwThreadID);
\r
639 HANDLE hThread = ::CreateThread(NULL, 0, StartProc, (void*)this, 0, &dwThreadID);
\r
641 if (hThread == NULL)
\r
644 ::CloseHandle(hThread);
\r
650 static DWORD WINAPI StartProc(void* p)
\r
652 CPrintJob* pThis = (CPrintJob*)p;
\r
653 pThis->StartHelper();
\r
654 pThis->m_bComplete = true;
\r
661 dcPrinter.Attach(m_printer.CreatePrinterDC(m_pDefDevMode));
\r
662 if (dcPrinter.IsNull())
\r
665 m_nJobID = ::StartDoc(dcPrinter, &m_docinfo);
\r
669 m_pInfo->BeginPrintJob(dcPrinter);
\r
671 // print all the pages now
\r
672 unsigned long nLastPage = 0;
\r
673 for (unsigned long nPage = m_nStartPage; nPage <= m_nEndPage; nPage++)
\r
675 if (!m_pInfo->IsValidPage(nPage))
\r
677 DEVMODE* pdm = m_pInfo->GetNewDevModeForPage(nLastPage, nPage);
\r
679 dcPrinter.ResetDC(pdm);
\r
680 dcPrinter.StartPage();
\r
681 m_pInfo->PrePrintPage(nPage, dcPrinter);
\r
682 if (!m_pInfo->PrintPage(nPage, dcPrinter))
\r
684 m_pInfo->PostPrintPage(nPage, dcPrinter);
\r
685 dcPrinter.EndPage();
\r
691 m_pInfo->EndPrintJob(dcPrinter, m_bCancel);
\r
693 ::AbortDoc(dcPrinter);
\r
695 ::EndDoc(dcPrinter);
\r
700 // Cancels a print job. Can be called asynchronously.
\r
701 void CancelPrintJob()
\r
708 ///////////////////////////////////////////////////////////////////////////////
\r
709 // CPrintPreview - Adds print preview support to an existing window
\r
711 class CPrintPreview
\r
715 IPrintJobInfo* m_pInfo;
\r
716 CPrinterHandle m_printer;
\r
717 CEnhMetaFile m_meta;
\r
718 DEVMODE* m_pDefDevMode;
\r
719 DEVMODE* m_pCurDevMode;
\r
720 SIZE m_sizeCurPhysOffset;
\r
723 CPrintPreview() : m_pInfo(NULL), m_pDefDevMode(NULL), m_pCurDevMode(NULL)
\r
725 m_sizeCurPhysOffset.cx = 0;
\r
726 m_sizeCurPhysOffset.cy = 0;
\r
730 void SetPrintPreviewInfo(HANDLE hPrinter, DEVMODE* pDefaultDevMode, IPrintJobInfo* pji)
\r
732 m_printer.Attach(hPrinter);
\r
733 m_pDefDevMode = pDefaultDevMode;
\r
736 m_pCurDevMode = NULL;
\r
739 void SetEnhMetaFile(HENHMETAFILE hEMF)
\r
744 void SetPage(int nPage)
\r
746 if (!m_pInfo->IsValidPage(nPage))
\r
748 m_nCurPage = nPage;
\r
749 m_pCurDevMode = m_pInfo->GetNewDevModeForPage(0, nPage);
\r
750 if (m_pCurDevMode == NULL)
\r
751 m_pCurDevMode = m_pDefDevMode;
\r
752 CDC dcPrinter = m_printer.CreatePrinterDC(m_pCurDevMode);
\r
754 int iWidth = dcPrinter.GetDeviceCaps(PHYSICALWIDTH);
\r
755 int iHeight = dcPrinter.GetDeviceCaps(PHYSICALHEIGHT);
\r
756 int nLogx = dcPrinter.GetDeviceCaps(LOGPIXELSX);
\r
757 int nLogy = dcPrinter.GetDeviceCaps(LOGPIXELSY);
\r
759 RECT rcMM = { 0, 0, ::MulDiv(iWidth, 2540, nLogx), ::MulDiv(iHeight, 2540, nLogy) };
\r
761 m_sizeCurPhysOffset.cx = dcPrinter.GetDeviceCaps(PHYSICALOFFSETX);
\r
762 m_sizeCurPhysOffset.cy = dcPrinter.GetDeviceCaps(PHYSICALOFFSETY);
\r
764 CEnhMetaFileDC dcMeta(dcPrinter, &rcMM);
\r
765 m_pInfo->PrePrintPage(nPage, dcMeta);
\r
766 m_pInfo->PrintPage(nPage, dcMeta);
\r
767 m_pInfo->PostPrintPage(nPage, dcMeta);
\r
768 m_meta.Attach(dcMeta.Close());
\r
771 void GetPageRect(RECT& rc, LPRECT prc)
\r
773 int x1 = rc.right-rc.left;
\r
774 int y1 = rc.bottom - rc.top;
\r
775 if ((x1 < 0) || (y1 < 0))
\r
778 CEnhMetaFileInfo emfinfo(m_meta);
\r
779 ENHMETAHEADER* pmh = emfinfo.GetEnhMetaFileHeader();
\r
781 // Compute whether we are OK vertically or horizontally
\r
782 int x2 = pmh->szlDevice.cx;
\r
783 int y2 = pmh->szlDevice.cy;
\r
784 int y1p = MulDiv(x1, y2, x2);
\r
785 int x1p = MulDiv(y1, x2, y2);
\r
786 ATLASSERT((x1p <= x1) || (y1p <= y1));
\r
789 prc->left = rc.left + (x1 - x1p) / 2;
\r
790 prc->right = prc->left + x1p;
\r
792 prc->bottom = rc.bottom;
\r
796 prc->left = rc.left;
\r
797 prc->right = rc.right;
\r
798 prc->top = rc.top + (y1 - y1p) / 2;
\r
799 prc->bottom = prc->top + y1p;
\r
803 // Painting helpers
\r
804 void DoPaint(CDCHandle dc)
\r
806 // this one is not used
\r
809 void DoPaint(CDCHandle dc, RECT& rc)
\r
811 CEnhMetaFileInfo emfinfo(m_meta);
\r
812 ENHMETAHEADER* pmh = emfinfo.GetEnhMetaFileHeader();
\r
813 int nOffsetX = MulDiv(m_sizeCurPhysOffset.cx, rc.right-rc.left, pmh->szlDevice.cx);
\r
814 int nOffsetY = MulDiv(m_sizeCurPhysOffset.cy, rc.bottom-rc.top, pmh->szlDevice.cy);
\r
816 dc.OffsetWindowOrg(-nOffsetX, -nOffsetY);
\r
817 dc.PlayMetaFile(m_meta, &rc);
\r
820 // Implementation - data
\r
825 ///////////////////////////////////////////////////////////////////////////////
\r
826 // CPrintPreviewWindow - Implements a print preview window
\r
828 template <class T, class TBase = ATL::CWindow, class TWinTraits = ATL::CControlWinTraits>
\r
829 class ATL_NO_VTABLE CPrintPreviewWindowImpl : public ATL::CWindowImpl<T, TBase, TWinTraits>, public CPrintPreview
\r
832 DECLARE_WND_CLASS_EX(NULL, CS_VREDRAW | CS_HREDRAW, -1)
\r
834 enum { m_cxOffset = 10, m_cyOffset = 10 };
\r
837 CPrintPreviewWindowImpl() : m_nMaxPage(0), m_nMinPage(0)
\r
841 void SetPrintPreviewInfo(HANDLE hPrinter, DEVMODE* pDefaultDevMode,
\r
842 IPrintJobInfo* pji, int nMinPage, int nMaxPage)
\r
844 CPrintPreview::SetPrintPreviewInfo(hPrinter, pDefaultDevMode, pji);
\r
845 m_nMinPage = nMinPage;
\r
846 m_nMaxPage = nMaxPage;
\r
851 if (m_nCurPage == m_nMaxPage)
\r
853 SetPage(m_nCurPage + 1);
\r
860 if (m_nCurPage == m_nMinPage)
\r
862 if (m_nCurPage == 0)
\r
864 SetPage(m_nCurPage - 1);
\r
869 // Message map and handlers
\r
870 BEGIN_MSG_MAP(CPrintPreviewWindowImpl)
\r
871 MESSAGE_HANDLER(WM_ERASEBKGND, OnEraseBkgnd)
\r
872 MESSAGE_HANDLER(WM_PAINT, OnPaint)
\r
873 MESSAGE_HANDLER(WM_PRINTCLIENT, OnPaint)
\r
876 LRESULT OnEraseBkgnd(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& /*bHandled*/)
\r
878 return 1; // no need for the background
\r
881 LRESULT OnPaint(UINT /*uMsg*/, WPARAM wParam, LPARAM /*lParam*/, BOOL& /*bHandled*/)
\r
883 T* pT = static_cast<T*>(this);
\r
888 pT->DoPrePaint((HDC)wParam, rc);
\r
889 pT->DoPaint((HDC)wParam, rc);
\r
893 CPaintDC dc(m_hWnd);
\r
894 pT->DoPrePaint(dc.m_hDC, rc);
\r
895 pT->DoPaint(dc.m_hDC, rc);
\r
902 void DoPrePaint(CDCHandle dc, RECT& rc)
\r
904 RECT rcClient = { 0 };
\r
905 GetClientRect(&rcClient);
\r
906 RECT rcArea = rcClient;
\r
907 T* pT = static_cast<T*>(this);
\r
908 pT; // avoid level 4 warning
\r
909 ::InflateRect(&rcArea, -pT->m_cxOffset, -pT->m_cyOffset);
\r
910 if (rcArea.left > rcArea.right)
\r
911 rcArea.right = rcArea.left;
\r
912 if (rcArea.top > rcArea.bottom)
\r
913 rcArea.bottom = rcArea.top;
\r
914 GetPageRect(rcArea, &rc);
\r
916 rgn1.CreateRectRgnIndirect(&rc);
\r
917 rgn2.CreateRectRgnIndirect(&rcClient);
\r
918 rgn2.CombineRgn(rgn1, RGN_DIFF);
\r
919 dc.SelectClipRgn(rgn2);
\r
920 dc.FillRect(&rcClient, COLOR_BTNSHADOW);
\r
921 dc.SelectClipRgn(NULL);
\r
922 dc.FillRect(&rc, (HBRUSH)::GetStockObject(WHITE_BRUSH));
\r
925 // Implementation - data
\r
931 class CPrintPreviewWindow : public CPrintPreviewWindowImpl<CPrintPreviewWindow>
\r
934 DECLARE_WND_CLASS_EX(_T("WTL_PrintPreview"), CS_VREDRAW | CS_HREDRAW, -1)
\r
938 ///////////////////////////////////////////////////////////////////////////////
\r
939 // CZoomPrintPreviewWindowImpl - Implements print preview window with zooming
\r
941 #ifdef __ATLSCRL_H__
\r
943 template <class T, class TBase = ATL::CWindow, class TWinTraits = ATL::CControlWinTraits>
\r
944 class ATL_NO_VTABLE CZoomPrintPreviewWindowImpl : public CPrintPreviewWindowImpl< T, TBase, TWinTraits >, public CZoomScrollImpl< T >
\r
949 CZoomPrintPreviewWindowImpl()
\r
951 SetScrollExtendedStyle(SCRL_DISABLENOSCROLL);
\r
955 // should be called to reset data members before recreating window
\r
959 m_nZoomMode = ZOOMMODE_OFF;
\r
960 m_fZoomScaleMin = 1.0;
\r
961 m_fZoomScale = 1.0;
\r
964 BEGIN_MSG_MAP(CZoomPrintPreviewWindowImpl)
\r
965 MESSAGE_HANDLER(WM_SETCURSOR, CZoomScrollImpl< T >::OnSetCursor)
\r
966 MESSAGE_HANDLER(WM_VSCROLL, CScrollImpl< T >::OnVScroll)
\r
967 MESSAGE_HANDLER(WM_HSCROLL, CScrollImpl< T >::OnHScroll)
\r
968 MESSAGE_HANDLER(WM_MOUSEWHEEL, CScrollImpl< T >::OnMouseWheel)
\r
969 #if !((_WIN32_WINNT >= 0x0400) || (_WIN32_WINDOWS > 0x0400))
\r
970 MESSAGE_HANDLER(m_uMsgMouseWheel, CScrollImpl< T >::OnMouseWheel)
\r
971 #endif // !((_WIN32_WINNT >= 0x0400) || (_WIN32_WINDOWS > 0x0400))
\r
972 MESSAGE_HANDLER(WM_SETTINGCHANGE, CScrollImpl< T >::OnSettingChange)
\r
973 MESSAGE_HANDLER(WM_LBUTTONDOWN, CZoomScrollImpl< T >::OnLButtonDown)
\r
974 MESSAGE_HANDLER(WM_MOUSEMOVE, CZoomScrollImpl< T >::OnMouseMove)
\r
975 MESSAGE_HANDLER(WM_LBUTTONUP, CZoomScrollImpl< T >::OnLButtonUp)
\r
976 MESSAGE_HANDLER(WM_CAPTURECHANGED, CZoomScrollImpl< T >::OnCaptureChanged)
\r
977 MESSAGE_HANDLER(WM_SIZE, OnSize)
\r
978 MESSAGE_HANDLER(WM_ERASEBKGND, OnEraseBkgnd)
\r
979 MESSAGE_HANDLER(WM_PAINT, OnPaint)
\r
980 MESSAGE_HANDLER(WM_PRINTCLIENT, OnPaint)
\r
982 COMMAND_ID_HANDLER(ID_SCROLL_UP, CScrollImpl< T >::OnScrollUp)
\r
983 COMMAND_ID_HANDLER(ID_SCROLL_DOWN, CScrollImpl< T >::OnScrollDown)
\r
984 COMMAND_ID_HANDLER(ID_SCROLL_PAGE_UP, CScrollImpl< T >::OnScrollPageUp)
\r
985 COMMAND_ID_HANDLER(ID_SCROLL_PAGE_DOWN, CScrollImpl< T >::OnScrollPageDown)
\r
986 COMMAND_ID_HANDLER(ID_SCROLL_TOP, CScrollImpl< T >::OnScrollTop)
\r
987 COMMAND_ID_HANDLER(ID_SCROLL_BOTTOM, CScrollImpl< T >::OnScrollBottom)
\r
988 COMMAND_ID_HANDLER(ID_SCROLL_LEFT, CScrollImpl< T >::OnScrollLeft)
\r
989 COMMAND_ID_HANDLER(ID_SCROLL_RIGHT, CScrollImpl< T >::OnScrollRight)
\r
990 COMMAND_ID_HANDLER(ID_SCROLL_PAGE_LEFT, CScrollImpl< T >::OnScrollPageLeft)
\r
991 COMMAND_ID_HANDLER(ID_SCROLL_PAGE_RIGHT, CScrollImpl< T >::OnScrollPageRight)
\r
992 COMMAND_ID_HANDLER(ID_SCROLL_ALL_LEFT, CScrollImpl< T >::OnScrollAllLeft)
\r
993 COMMAND_ID_HANDLER(ID_SCROLL_ALL_RIGHT, CScrollImpl< T >::OnScrollAllRight)
\r
996 LRESULT OnSize(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
\r
998 SIZE sizeClient = {GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam)};
\r
999 POINT ptOffset = m_ptOffset;
\r
1000 SIZE sizeAll = m_sizeAll;
\r
1001 SetScrollSize(sizeClient);
\r
1002 if(sizeAll.cx > 0)
\r
1003 ptOffset.x = ::MulDiv(ptOffset.x, m_sizeAll.cx, sizeAll.cx);
\r
1004 if(sizeAll.cy > 0)
\r
1005 ptOffset.y = ::MulDiv(ptOffset.y, m_sizeAll.cy, sizeAll.cy);
\r
1006 SetScrollOffset(ptOffset);
\r
1007 CScrollImpl< T >::OnSize(uMsg, wParam, lParam, bHandled);
\r
1011 T* pT = static_cast<T*>(this);
\r
1012 pT->ShowScrollBar(SB_HORZ, TRUE);
\r
1013 pT->ShowScrollBar(SB_VERT, TRUE);
\r
1018 LRESULT OnEraseBkgnd(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& /*bHandled*/)
\r
1023 LRESULT OnPaint(UINT /*uMsg*/, WPARAM wParam, LPARAM /*lParam*/, BOOL& /*bHandled*/)
\r
1025 T* pT = static_cast<T*>(this);
\r
1028 if(wParam != NULL)
\r
1030 CDCHandle dc = (HDC)wParam;
\r
1031 int nMapModeSav = dc.GetMapMode();
\r
1032 dc.SetMapMode(MM_ANISOTROPIC);
\r
1033 SIZE szWindowExt = { 0, 0 };
\r
1034 dc.SetWindowExt(m_sizeLogAll, &szWindowExt);
\r
1035 SIZE szViewportExt = { 0, 0 };
\r
1036 dc.SetViewportExt(m_sizeAll, &szViewportExt);
\r
1037 POINT ptViewportOrg = { 0, 0 };
\r
1038 dc.SetViewportOrg(-m_ptOffset.x, -m_ptOffset.y, &ptViewportOrg);
\r
1040 pT->DoPrePaint(dc, rc);
\r
1041 pT->DoPaint(dc, rc);
\r
1043 dc.SetMapMode(nMapModeSav);
\r
1044 dc.SetWindowExt(szWindowExt);
\r
1045 dc.SetViewportExt(szViewportExt);
\r
1046 dc.SetViewportOrg(ptViewportOrg);
\r
1050 CPaintDC dc(pT->m_hWnd);
\r
1051 pT->PrepareDC(dc.m_hDC);
\r
1052 pT->DoPrePaint(dc.m_hDC, rc);
\r
1053 pT->DoPaint(dc.m_hDC, rc);
\r
1059 // Painting helpers
\r
1060 void DoPaint(CDCHandle dc)
\r
1062 // this one is not used
\r
1065 void DoPrePaint(CDCHandle dc, RECT& rc)
\r
1068 GetClientRect(&rcClient);
\r
1069 RECT rcArea = rcClient;
\r
1070 T* pT = static_cast<T*>(this);
\r
1071 pT; // avoid level 4 warning
\r
1072 ::InflateRect(&rcArea, -pT->m_cxOffset, -pT->m_cyOffset);
\r
1073 if (rcArea.left > rcArea.right)
\r
1074 rcArea.right = rcArea.left;
\r
1075 if (rcArea.top > rcArea.bottom)
\r
1076 rcArea.bottom = rcArea.top;
\r
1077 GetPageRect(rcArea, &rc);
\r
1078 HBRUSH hbrOld = dc.SelectBrush(::GetSysColorBrush(COLOR_BTNSHADOW));
\r
1079 dc.PatBlt(rcClient.left, rcClient.top, rc.left - rcClient.left, rcClient.bottom - rcClient.top, PATCOPY);
\r
1080 dc.PatBlt(rc.left, rcClient.top, rc.right - rc.left, rc.top - rcClient.top, PATCOPY);
\r
1081 dc.PatBlt(rc.right, rcClient.top, rcClient.right - rc.right, rcClient.bottom - rcClient.top, PATCOPY);
\r
1082 dc.PatBlt(rc.left, rc.bottom, rc.right - rc.left, rcClient.bottom - rc.bottom, PATCOPY);
\r
1083 dc.SelectBrush((HBRUSH)::GetStockObject(WHITE_BRUSH));
\r
1084 dc.PatBlt(rc.left, rc.top, rc.right - rc.left, rc.bottom - rc.top, PATCOPY);
\r
1085 dc.SelectBrush(::GetSysColorBrush(COLOR_3DDKSHADOW));
\r
1086 dc.PatBlt(rc.right, rc.top + 4, 4, rc.bottom - rc.top, PATCOPY);
\r
1087 dc.PatBlt(rc.left + 4, rc.bottom, rc.right - rc.left, 4, PATCOPY);
\r
1088 dc.SelectBrush(hbrOld);
\r
1091 void DoPaint(CDCHandle dc, RECT& rc)
\r
1093 CEnhMetaFileInfo emfinfo(m_meta);
\r
1094 ENHMETAHEADER* pmh = emfinfo.GetEnhMetaFileHeader();
\r
1095 int nOffsetX = MulDiv(m_sizeCurPhysOffset.cx, rc.right-rc.left, pmh->szlDevice.cx);
\r
1096 int nOffsetY = MulDiv(m_sizeCurPhysOffset.cy, rc.bottom-rc.top, pmh->szlDevice.cy);
\r
1098 dc.OffsetWindowOrg(-nOffsetX, -nOffsetY);
\r
1099 dc.PlayMetaFile(m_meta, &rc);
\r
1103 class CZoomPrintPreviewWindow : public CZoomPrintPreviewWindowImpl<CZoomPrintPreviewWindow>
\r
1106 DECLARE_WND_CLASS_EX(_T("WTL_ZoomPrintPreview"), CS_VREDRAW | CS_HREDRAW, -1)
\r
1109 #endif // __ATLSCRL_H__
\r
1111 }; // namespace WTL
\r
1113 #endif // __ATLPRINT_H__
\r