123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125 |
- // Windows Template Library - WTL version 10.0
- // Copyright (C) Microsoft Corporation, WTL Team. All rights reserved.
- //
- // This file is a part of the Windows Template Library.
- // The use and distribution terms for this software are covered by the
- // Microsoft Public License (http://opensource.org/licenses/MS-PL)
- // which can be found in the file MS-PL.txt at the root folder.
- #ifndef __ATLPRINT_H__
- #define __ATLPRINT_H__
- #pragma once
- #ifndef __ATLAPP_H__
- #error atlprint.h requires atlapp.h to be included first
- #endif
- #ifndef __ATLWIN_H__
- #error atlprint.h requires atlwin.h to be included first
- #endif
- #include <winspool.h>
- ///////////////////////////////////////////////////////////////////////////////
- // Classes in this file:
- //
- // CPrinterInfo<t_nInfo>
- // CPrinterT<t_bManaged>
- // CDevModeT<t_bManaged>
- // CPrinterDC
- // CPrintJobInfo
- // CPrintJob
- // CPrintPreview
- // CPrintPreviewWindowImpl<T, TBase, TWinTraits>
- // CPrintPreviewWindow
- // CZoomPrintPreviewWindowImpl<T, TBase, TWinTraits>
- // CZoomPrintPreviewWindow
- namespace WTL
- {
- ///////////////////////////////////////////////////////////////////////////////
- // CPrinterInfo - This class wraps all of the PRINTER_INFO_* structures
- // and provided by ::GetPrinter.
- template <unsigned int t_nInfo>
- class _printer_info
- {
- public:
- typedef void infotype;
- };
- template <> class _printer_info<1> { public: typedef PRINTER_INFO_1 infotype; };
- template <> class _printer_info<2> { public: typedef PRINTER_INFO_2 infotype; };
- template <> class _printer_info<3> { public: typedef PRINTER_INFO_3 infotype; };
- template <> class _printer_info<4> { public: typedef PRINTER_INFO_4 infotype; };
- template <> class _printer_info<5> { public: typedef PRINTER_INFO_5 infotype; };
- template <> class _printer_info<6> { public: typedef PRINTER_INFO_6 infotype; };
- template <> class _printer_info<7> { public: typedef PRINTER_INFO_7 infotype; };
- template <> class _printer_info<8> { public: typedef PRINTER_INFO_8 infotype; };
- template <> class _printer_info<9> { public: typedef PRINTER_INFO_9 infotype; };
- template <unsigned int t_nInfo>
- class CPrinterInfo
- {
- public:
- // Data members
- typename _printer_info<t_nInfo>::infotype* m_pi;
- // Constructor/destructor
- CPrinterInfo() : m_pi(NULL)
- { }
- CPrinterInfo(HANDLE hPrinter) : m_pi(NULL)
- {
- GetPrinterInfo(hPrinter);
- }
- ~CPrinterInfo()
- {
- Cleanup();
- }
- // Operations
- bool GetPrinterInfo(HANDLE hPrinter)
- {
- Cleanup();
- return GetPrinterInfoHelper(hPrinter, (BYTE**)&m_pi, t_nInfo);
- }
- // Implementation
- void Cleanup()
- {
- delete [] (BYTE*)m_pi;
- m_pi = NULL;
- }
- static bool GetPrinterInfoHelper(HANDLE hPrinter, BYTE** pi, int nIndex)
- {
- ATLASSERT(pi != NULL);
- DWORD dw = 0;
- BYTE* pb = NULL;
- ::GetPrinter(hPrinter, nIndex, NULL, 0, &dw);
- if (dw > 0)
- {
- ATLTRY(pb = new BYTE[dw]);
- if (pb != NULL)
- {
- memset(pb, 0, dw);
- DWORD dwNew;
- if (!::GetPrinter(hPrinter, nIndex, pb, dw, &dwNew))
- {
- delete [] pb;
- pb = NULL;
- }
- }
- }
- *pi = pb;
- return (pb != NULL);
- }
- };
- ///////////////////////////////////////////////////////////////////////////////
- // CPrinter - Wrapper class for a HANDLE to a printer
- template <bool t_bManaged>
- class CPrinterT
- {
- public:
- // Data members
- HANDLE m_hPrinter;
- // Constructor/destructor
- CPrinterT(HANDLE hPrinter = NULL) : m_hPrinter(hPrinter)
- { }
- ~CPrinterT()
- {
- ClosePrinter();
- }
- // Operations
- CPrinterT& operator =(HANDLE hPrinter)
- {
- if (hPrinter != m_hPrinter)
- {
- ClosePrinter();
- m_hPrinter = hPrinter;
- }
- return *this;
- }
- bool IsNull() const { return (m_hPrinter == NULL); }
- bool OpenPrinter(HANDLE hDevNames, const DEVMODE* pDevMode = NULL)
- {
- bool b = false;
- DEVNAMES* pdn = (DEVNAMES*)::GlobalLock(hDevNames);
- if (pdn != NULL)
- {
- LPTSTR lpszPrinterName = (LPTSTR)pdn + pdn->wDeviceOffset;
- b = OpenPrinter(lpszPrinterName, pDevMode);
- ::GlobalUnlock(hDevNames);
- }
- return b;
- }
- bool OpenPrinter(LPCTSTR lpszPrinterName, const DEVMODE* pDevMode = NULL)
- {
- ClosePrinter();
- PRINTER_DEFAULTS pdefs = { NULL, (DEVMODE*)pDevMode, PRINTER_ACCESS_USE };
- ::OpenPrinter((LPTSTR) lpszPrinterName, &m_hPrinter, (pDevMode == NULL) ? NULL : &pdefs);
- return (m_hPrinter != NULL);
- }
- bool OpenPrinter(LPCTSTR lpszPrinterName, PRINTER_DEFAULTS* pprintdefs)
- {
- ClosePrinter();
- ::OpenPrinter((LPTSTR) lpszPrinterName, &m_hPrinter, pprintdefs);
- return (m_hPrinter != NULL);
- }
- bool OpenDefaultPrinter(const DEVMODE* pDevMode = NULL)
- {
- ClosePrinter();
- DWORD cchBuff = 0;
- ::GetDefaultPrinter(NULL, &cchBuff);
- TCHAR* pszBuff = new TCHAR[cchBuff];
- BOOL bRet = ::GetDefaultPrinter(pszBuff, &cchBuff);
- if(bRet != FALSE)
- {
- PRINTER_DEFAULTS pdefs = { NULL, (DEVMODE*)pDevMode, PRINTER_ACCESS_USE };
- ::OpenPrinter(pszBuff, &m_hPrinter, (pDevMode == NULL) ? NULL : &pdefs);
- }
- delete [] pszBuff;
- return m_hPrinter != NULL;
- }
- void ClosePrinter()
- {
- if (m_hPrinter != NULL)
- {
- if (t_bManaged)
- ::ClosePrinter(m_hPrinter);
- m_hPrinter = NULL;
- }
- }
- bool PrinterProperties(HWND hWnd = NULL)
- {
- if (hWnd == NULL)
- hWnd = ::GetActiveWindow();
- return !!::PrinterProperties(hWnd, m_hPrinter);
- }
- HANDLE CopyToHDEVNAMES() const
- {
- HANDLE hDevNames = NULL;
- CPrinterInfo<5> pinfon5;
- CPrinterInfo<2> pinfon2;
- LPTSTR lpszPrinterName = NULL;
- LPTSTR lpszPortName = NULL;
- // Some printers fail for PRINTER_INFO_5 in some situations
- if(pinfon5.GetPrinterInfo(m_hPrinter))
- {
- lpszPrinterName = pinfon5.m_pi->pPrinterName;
- lpszPortName = pinfon5.m_pi->pPortName;
- }
- else if(pinfon2.GetPrinterInfo(m_hPrinter))
- {
- lpszPrinterName = pinfon2.m_pi->pPrinterName;
- lpszPortName = pinfon2.m_pi->pPortName;
- }
- if(lpszPrinterName != NULL)
- {
- int nLen = sizeof(DEVNAMES) + (lstrlen(lpszPrinterName) + 1 + lstrlen(lpszPortName) + 1) * sizeof(TCHAR);
- hDevNames = ::GlobalAlloc(GMEM_MOVEABLE, nLen);
- BYTE* pv = (BYTE*)::GlobalLock(hDevNames);
- DEVNAMES* pdev = (DEVNAMES*)pv;
- if(pv != NULL)
- {
- memset(pv, 0, nLen);
- pdev->wDeviceOffset = sizeof(DEVNAMES) / sizeof(TCHAR);
- pv = pv + sizeof(DEVNAMES); // now points to end
- ATL::Checked::tcscpy_s((LPTSTR)pv, lstrlen(lpszPrinterName) + 1, lpszPrinterName);
- pdev->wOutputOffset = (WORD)(sizeof(DEVNAMES) / sizeof(TCHAR) + lstrlen(lpszPrinterName) + 1);
- pv = pv + (lstrlen(lpszPrinterName) + 1) * sizeof(TCHAR);
- ATL::Checked::tcscpy_s((LPTSTR)pv, lstrlen(lpszPortName) + 1, lpszPortName);
- ::GlobalUnlock(hDevNames);
- }
- }
- return hDevNames;
- }
- HDC CreatePrinterDC(const DEVMODE* pdm = NULL) const
- {
- CPrinterInfo<5> pinfo5;
- CPrinterInfo<2> pinfo2;
- HDC hDC = NULL;
- LPTSTR lpszPrinterName = NULL;
- // Some printers fail for PRINTER_INFO_5 in some situations
- if (pinfo5.GetPrinterInfo(m_hPrinter))
- lpszPrinterName = pinfo5.m_pi->pPrinterName;
- else if (pinfo2.GetPrinterInfo(m_hPrinter))
- lpszPrinterName = pinfo2.m_pi->pPrinterName;
- if (lpszPrinterName != NULL)
- hDC = ::CreateDC(NULL, lpszPrinterName, NULL, pdm);
- return hDC;
- }
- HDC CreatePrinterIC(const DEVMODE* pdm = NULL) const
- {
- CPrinterInfo<5> pinfo5;
- CPrinterInfo<2> pinfo2;
- HDC hDC = NULL;
- LPTSTR lpszPrinterName = NULL;
- // Some printers fail for PRINTER_INFO_5 in some situations
- if (pinfo5.GetPrinterInfo(m_hPrinter))
- lpszPrinterName = pinfo5.m_pi->pPrinterName;
- else if (pinfo2.GetPrinterInfo(m_hPrinter))
- lpszPrinterName = pinfo2.m_pi->pPrinterName;
- if (lpszPrinterName != NULL)
- hDC = ::CreateIC(NULL, lpszPrinterName, NULL, pdm);
- return hDC;
- }
- void Attach(HANDLE hPrinter)
- {
- ClosePrinter();
- m_hPrinter = hPrinter;
- }
- HANDLE Detach()
- {
- HANDLE hPrinter = m_hPrinter;
- m_hPrinter = NULL;
- return hPrinter;
- }
- operator HANDLE() const { return m_hPrinter; }
- };
- typedef CPrinterT<false> CPrinterHandle;
- typedef CPrinterT<true> CPrinter;
- ///////////////////////////////////////////////////////////////////////////////
- // CDevMode - Wrapper class for DEVMODE
- template <bool t_bManaged>
- class CDevModeT
- {
- public:
- // Data members
- HANDLE m_hDevMode;
- DEVMODE* m_pDevMode;
- // Constructor/destructor
- CDevModeT(HANDLE hDevMode = NULL) : m_hDevMode(hDevMode)
- {
- m_pDevMode = (m_hDevMode != NULL) ? (DEVMODE*)::GlobalLock(m_hDevMode) : NULL;
- }
- ~CDevModeT()
- {
- Cleanup();
- }
- // Operations
- CDevModeT<t_bManaged>& operator =(HANDLE hDevMode)
- {
- Attach(hDevMode);
- return *this;
- }
- void Attach(HANDLE hDevModeNew)
- {
- Cleanup();
- m_hDevMode = hDevModeNew;
- m_pDevMode = (m_hDevMode != NULL) ? (DEVMODE*)::GlobalLock(m_hDevMode) : NULL;
- }
- HANDLE Detach()
- {
- if (m_hDevMode != NULL)
- ::GlobalUnlock(m_hDevMode);
- HANDLE hDevMode = m_hDevMode;
- m_hDevMode = NULL;
- return hDevMode;
- }
- bool IsNull() const { return (m_hDevMode == NULL); }
- bool CopyFromPrinter(HANDLE hPrinter)
- {
- CPrinterInfo<2> pinfo;
- bool b = pinfo.GetPrinterInfo(hPrinter);
- if (b)
- b = CopyFromDEVMODE(pinfo.m_pi->pDevMode);
- return b;
- }
- bool CopyFromDEVMODE(const DEVMODE* pdm)
- {
- if (pdm == NULL)
- return false;
- int nSize = pdm->dmSize + pdm->dmDriverExtra;
- HANDLE h = ::GlobalAlloc(GMEM_MOVEABLE, nSize);
- if (h != NULL)
- {
- void* p = ::GlobalLock(h);
- ATL::Checked::memcpy_s(p, nSize, pdm, nSize);
- ::GlobalUnlock(h);
- }
- Attach(h);
- return (h != NULL);
- }
- bool CopyFromHDEVMODE(HANDLE hdm)
- {
- bool b = false;
- if (hdm != NULL)
- {
- DEVMODE* pdm = (DEVMODE*)::GlobalLock(hdm);
- b = CopyFromDEVMODE(pdm);
- ::GlobalUnlock(hdm);
- }
- return b;
- }
- HANDLE CopyToHDEVMODE()
- {
- if ((m_hDevMode == NULL) || (m_pDevMode == NULL))
- return NULL;
- int nSize = m_pDevMode->dmSize + m_pDevMode->dmDriverExtra;
- HANDLE h = ::GlobalAlloc(GMEM_MOVEABLE, nSize);
- if (h != NULL)
- {
- void* p = ::GlobalLock(h);
- ATL::Checked::memcpy_s(p, nSize, m_pDevMode, nSize);
- ::GlobalUnlock(h);
- }
- return h;
- }
- // If this devmode was for another printer, this will create a new devmode
- // based on the existing devmode, but retargeted at the new printer
- bool UpdateForNewPrinter(HANDLE hPrinter)
- {
- bool bRet = false;
- LONG nLen = ::DocumentProperties(NULL, hPrinter, NULL, NULL, NULL, 0);
- ATL::CTempBuffer<DEVMODE, _WTL_STACK_ALLOC_THRESHOLD> buff;
- DEVMODE* pdm = buff.AllocateBytes(nLen);
- if(pdm != NULL)
- {
- memset(pdm, 0, nLen);
- LONG l = ::DocumentProperties(NULL, hPrinter, NULL, pdm, m_pDevMode, DM_IN_BUFFER | DM_OUT_BUFFER);
- if (l == IDOK)
- bRet = CopyFromDEVMODE(pdm);
- }
- return bRet;
- }
- bool DocumentProperties(HANDLE hPrinter, HWND hWnd = NULL)
- {
- CPrinterInfo<1> pi;
- pi.GetPrinterInfo(hPrinter);
- if (hWnd == NULL)
- hWnd = ::GetActiveWindow();
- bool bRet = false;
- LONG nLen = ::DocumentProperties(hWnd, hPrinter, pi.m_pi->pName, NULL, NULL, 0);
- ATL::CTempBuffer<DEVMODE, _WTL_STACK_ALLOC_THRESHOLD> buff;
- DEVMODE* pdm = buff.AllocateBytes(nLen);
- if(pdm != NULL)
- {
- memset(pdm, 0, nLen);
- LONG l = ::DocumentProperties(hWnd, hPrinter, pi.m_pi->pName, pdm, m_pDevMode, DM_IN_BUFFER | DM_OUT_BUFFER | DM_PROMPT);
- if (l == IDOK)
- bRet = CopyFromDEVMODE(pdm);
- }
- return bRet;
- }
- operator HANDLE() const { return m_hDevMode; }
- operator DEVMODE*() const { return m_pDevMode; }
- // Implementation
- void Cleanup()
- {
- if (m_hDevMode != NULL)
- {
- ::GlobalUnlock(m_hDevMode);
- if(t_bManaged)
- ::GlobalFree(m_hDevMode);
- m_hDevMode = NULL;
- }
- }
- };
- typedef CDevModeT<false> CDevModeHandle;
- typedef CDevModeT<true> CDevMode;
- ///////////////////////////////////////////////////////////////////////////////
- // CPrinterDC
- class CPrinterDC : public CDC
- {
- public:
- // Constructors/destructor
- CPrinterDC()
- {
- CPrinter printer;
- printer.OpenDefaultPrinter();
- Attach(printer.CreatePrinterDC());
- ATLASSERT(m_hDC != NULL);
- }
- CPrinterDC(HANDLE hPrinter, const DEVMODE* pdm = NULL)
- {
- CPrinterHandle p;
- p.Attach(hPrinter);
- Attach(p.CreatePrinterDC(pdm));
- ATLASSERT(m_hDC != NULL);
- }
- ~CPrinterDC()
- {
- DeleteDC();
- }
- };
- ///////////////////////////////////////////////////////////////////////////////
- // CPrintJob - Wraps a set of tasks for a specific printer (StartDoc/EndDoc)
- // Handles aborting, background printing
- // Defines callbacks used by CPrintJob (not a COM interface)
- class ATL_NO_VTABLE IPrintJobInfo
- {
- public:
- virtual void BeginPrintJob(HDC hDC) = 0; // allocate handles needed, etc.
- virtual void EndPrintJob(HDC hDC, bool bAborted) = 0; // free handles, etc.
- virtual void PrePrintPage(UINT nPage, HDC hDC) = 0;
- virtual bool PrintPage(UINT nPage, HDC hDC) = 0;
- virtual void PostPrintPage(UINT nPage, HDC hDC) = 0;
- // If you want per page devmodes, return the DEVMODE* to use for nPage.
- // You can optimize by only returning a new DEVMODE* when it is different
- // from the one for nLastPage, otherwise return NULL.
- // When nLastPage==0, the current DEVMODE* will be the default passed to
- // StartPrintJob.
- // Note: During print preview, nLastPage will always be "0".
- virtual DEVMODE* GetNewDevModeForPage(UINT nLastPage, UINT nPage) = 0;
- virtual bool IsValidPage(UINT nPage) = 0;
- };
- // Provides a default implementatin for IPrintJobInfo
- // Typically, MI'd into a document or view class
- class ATL_NO_VTABLE CPrintJobInfo : public IPrintJobInfo
- {
- public:
- CPrintJobInfo() : m_nPJState(0)
- { }
- virtual void BeginPrintJob(HDC /*hDC*/) // allocate handles needed, etc
- {
- }
- virtual void EndPrintJob(HDC /*hDC*/, bool /*bAborted*/) // free handles, etc
- {
- }
- virtual void PrePrintPage(UINT /*nPage*/, HDC hDC)
- {
- m_nPJState = ::SaveDC(hDC);
- }
- virtual bool PrintPage(UINT /*nPage*/, HDC /*hDC*/) = 0;
- virtual void PostPrintPage(UINT /*nPage*/, HDC hDC)
- {
- RestoreDC(hDC, m_nPJState);
- }
- virtual DEVMODE* GetNewDevModeForPage(UINT /*nLastPage*/, UINT /*nPage*/)
- {
- return NULL;
- }
- virtual bool IsValidPage(UINT /*nPage*/)
- {
- return true;
- }
- // Implementation - data
- int m_nPJState;
- };
- class CPrintJob
- {
- public:
- // Data members
- CPrinterHandle m_printer;
- IPrintJobInfo* m_pInfo;
- DEVMODE* m_pDefDevMode;
- DOCINFO m_docinfo;
- int m_nJobID;
- bool m_bCancel;
- bool m_bComplete;
- unsigned long m_nStartPage;
- unsigned long m_nEndPage;
- // Constructor/destructor
- CPrintJob() : m_pInfo(NULL), m_pDefDevMode(NULL), m_nJobID(0), m_bCancel(false), m_bComplete(true), m_nStartPage(0), m_nEndPage(0)
- {
- memset(&m_docinfo, 0, sizeof(m_docinfo));
- }
- ~CPrintJob()
- {
- ATLASSERT(IsJobComplete()); // premature destruction?
- }
- // Operations
- bool IsJobComplete() const
- {
- return m_bComplete;
- }
- bool StartPrintJob(bool bBackground, HANDLE hPrinter, DEVMODE* pDefaultDevMode,
- IPrintJobInfo* pInfo, LPCTSTR lpszDocName,
- unsigned long nStartPage, unsigned long nEndPage,
- bool bPrintToFile = false, LPCTSTR lpstrOutputFile = NULL)
- {
- ATLASSERT(m_bComplete); // previous job not done yet?
- if (pInfo == NULL)
- return false;
- memset(&m_docinfo, 0, sizeof(m_docinfo));
- m_docinfo.cbSize = sizeof(m_docinfo);
- m_docinfo.lpszDocName = lpszDocName;
- m_pInfo = pInfo;
- m_nStartPage = nStartPage;
- m_nEndPage = nEndPage;
- m_printer.Attach(hPrinter);
- m_pDefDevMode = pDefaultDevMode;
- m_bComplete = false;
- if(bPrintToFile)
- m_docinfo.lpszOutput = (lpstrOutputFile != NULL) ? lpstrOutputFile : _T("FILE:");
- if (!bBackground)
- {
- m_bComplete = true;
- return StartHelper();
- }
- // Create a thread and return
- DWORD dwThreadID = 0;
- #ifdef _MT
- HANDLE hThread = (HANDLE)_beginthreadex(NULL, 0, (UINT (WINAPI*)(void*))StartProc, this, 0, (UINT*)&dwThreadID);
- #else
- HANDLE hThread = ::CreateThread(NULL, 0, StartProc, (void*)this, 0, &dwThreadID);
- #endif
- if (hThread == NULL)
- return false;
- ::CloseHandle(hThread);
- return true;
- }
- // Implementation
- static DWORD WINAPI StartProc(void* p)
- {
- CPrintJob* pThis = (CPrintJob*)p;
- pThis->StartHelper();
- pThis->m_bComplete = true;
- return 0;
- }
- bool StartHelper()
- {
- CDC dcPrinter;
- dcPrinter.Attach(m_printer.CreatePrinterDC(m_pDefDevMode));
- if (dcPrinter.IsNull())
- return false;
-
- m_nJobID = ::StartDoc(dcPrinter, &m_docinfo);
- if (m_nJobID <= 0)
- return false;
- m_pInfo->BeginPrintJob(dcPrinter);
- // print all the pages now
- unsigned long nLastPage = 0;
- for (unsigned long nPage = m_nStartPage; nPage <= m_nEndPage; nPage++)
- {
- if (!m_pInfo->IsValidPage(nPage))
- break;
- DEVMODE* pdm = m_pInfo->GetNewDevModeForPage(nLastPage, nPage);
- if (pdm != NULL)
- dcPrinter.ResetDC(pdm);
- dcPrinter.StartPage();
- m_pInfo->PrePrintPage(nPage, dcPrinter);
- if (!m_pInfo->PrintPage(nPage, dcPrinter))
- m_bCancel = true;
- m_pInfo->PostPrintPage(nPage, dcPrinter);
- dcPrinter.EndPage();
- if (m_bCancel)
- break;
- nLastPage = nPage;
- }
- m_pInfo->EndPrintJob(dcPrinter, m_bCancel);
- if (m_bCancel)
- ::AbortDoc(dcPrinter);
- else
- ::EndDoc(dcPrinter);
- m_nJobID = 0;
- return true;
- }
- // Cancels a print job. Can be called asynchronously.
- void CancelPrintJob()
- {
- m_bCancel = true;
- }
- };
- ///////////////////////////////////////////////////////////////////////////////
- // CPrintPreview - Adds print preview support to an existing window
- class CPrintPreview
- {
- public:
- // Data members
- IPrintJobInfo* m_pInfo;
- CPrinterHandle m_printer;
- CEnhMetaFile m_meta;
- DEVMODE* m_pDefDevMode;
- DEVMODE* m_pCurDevMode;
- SIZE m_sizeCurPhysOffset;
- // Implementation - data
- int m_nCurPage;
- // Constructor
- CPrintPreview() : m_pInfo(NULL), m_pDefDevMode(NULL), m_pCurDevMode(NULL), m_nCurPage(0)
- {
- m_sizeCurPhysOffset.cx = 0;
- m_sizeCurPhysOffset.cy = 0;
- }
- // Operations
- void SetPrintPreviewInfo(HANDLE hPrinter, DEVMODE* pDefaultDevMode, IPrintJobInfo* pji)
- {
- m_printer.Attach(hPrinter);
- m_pDefDevMode = pDefaultDevMode;
- m_pInfo = pji;
- m_nCurPage = 0;
- m_pCurDevMode = NULL;
- }
- void SetEnhMetaFile(HENHMETAFILE hEMF)
- {
- m_meta = hEMF;
- }
- void SetPage(int nPage)
- {
- if (!m_pInfo->IsValidPage(nPage))
- return;
- m_nCurPage = nPage;
- m_pCurDevMode = m_pInfo->GetNewDevModeForPage(0, nPage);
- if (m_pCurDevMode == NULL)
- m_pCurDevMode = m_pDefDevMode;
- CDC dcPrinter = m_printer.CreatePrinterDC(m_pCurDevMode);
- int iWidth = dcPrinter.GetDeviceCaps(PHYSICALWIDTH);
- int iHeight = dcPrinter.GetDeviceCaps(PHYSICALHEIGHT);
- int nLogx = dcPrinter.GetDeviceCaps(LOGPIXELSX);
- int nLogy = dcPrinter.GetDeviceCaps(LOGPIXELSY);
- RECT rcMM = { 0, 0, ::MulDiv(iWidth, 2540, nLogx), ::MulDiv(iHeight, 2540, nLogy) };
- m_sizeCurPhysOffset.cx = dcPrinter.GetDeviceCaps(PHYSICALOFFSETX);
- m_sizeCurPhysOffset.cy = dcPrinter.GetDeviceCaps(PHYSICALOFFSETY);
-
- CEnhMetaFileDC dcMeta(dcPrinter, &rcMM);
- m_pInfo->PrePrintPage(nPage, dcMeta);
- m_pInfo->PrintPage(nPage, dcMeta);
- m_pInfo->PostPrintPage(nPage, dcMeta);
- m_meta.Attach(dcMeta.Close());
- }
- void GetPageRect(RECT& rc, LPRECT prc)
- {
- int x1 = rc.right-rc.left;
- int y1 = rc.bottom - rc.top;
- if ((x1 < 0) || (y1 < 0))
- return;
- CEnhMetaFileInfo emfinfo(m_meta);
- ENHMETAHEADER* pmh = emfinfo.GetEnhMetaFileHeader();
- if(pmh == NULL)
- {
- ATLASSERT(FALSE);
- return;
- }
- // Compute whether we are OK vertically or horizontally
- int x2 = pmh->szlDevice.cx;
- int y2 = pmh->szlDevice.cy;
- int y1p = MulDiv(x1, y2, x2);
- int x1p = MulDiv(y1, x2, y2);
- ATLASSERT((x1p <= x1) || (y1p <= y1));
- if (x1p <= x1)
- {
- prc->left = rc.left + (x1 - x1p) / 2;
- prc->right = prc->left + x1p;
- prc->top = rc.top;
- prc->bottom = rc.bottom;
- }
- else
- {
- prc->left = rc.left;
- prc->right = rc.right;
- prc->top = rc.top + (y1 - y1p) / 2;
- prc->bottom = prc->top + y1p;
- }
- }
- // Painting helpers
- void DoPaint(CDCHandle dc)
- {
- // this one is not used
- }
- void DoPaint(CDCHandle dc, RECT& rc)
- {
- CEnhMetaFileInfo emfinfo(m_meta);
- ENHMETAHEADER* pmh = emfinfo.GetEnhMetaFileHeader();
- if(pmh == NULL)
- {
- ATLASSERT(FALSE);
- return;
- }
- int nOffsetX = MulDiv(m_sizeCurPhysOffset.cx, rc.right-rc.left, pmh->szlDevice.cx);
- int nOffsetY = MulDiv(m_sizeCurPhysOffset.cy, rc.bottom-rc.top, pmh->szlDevice.cy);
- dc.OffsetWindowOrg(-nOffsetX, -nOffsetY);
- dc.PlayMetaFile(m_meta, &rc);
- }
- };
- ///////////////////////////////////////////////////////////////////////////////
- // CPrintPreviewWindow - Implements a print preview window
- template <class T, class TBase = ATL::CWindow, class TWinTraits = ATL::CControlWinTraits>
- class ATL_NO_VTABLE CPrintPreviewWindowImpl : public ATL::CWindowImpl<T, TBase, TWinTraits>, public CPrintPreview
- {
- public:
- DECLARE_WND_CLASS_EX2(NULL, T, CS_VREDRAW | CS_HREDRAW, -1)
- enum { m_cxOffset = 10, m_cyOffset = 10 };
- // Constructor
- CPrintPreviewWindowImpl() : m_nMinPage(0), m_nMaxPage(0)
- { }
- // Operations
- void SetPrintPreviewInfo(HANDLE hPrinter, DEVMODE* pDefaultDevMode,
- IPrintJobInfo* pji, int nMinPage, int nMaxPage)
- {
- CPrintPreview::SetPrintPreviewInfo(hPrinter, pDefaultDevMode, pji);
- m_nMinPage = nMinPage;
- m_nMaxPage = nMaxPage;
- }
- bool NextPage()
- {
- if (m_nCurPage == m_nMaxPage)
- return false;
- SetPage(m_nCurPage + 1);
- this->Invalidate();
- return true;
- }
- bool PrevPage()
- {
- if (m_nCurPage == m_nMinPage)
- return false;
- if (m_nCurPage == 0)
- return false;
- SetPage(m_nCurPage - 1);
- this->Invalidate();
- return true;
- }
- // Message map and handlers
- BEGIN_MSG_MAP(CPrintPreviewWindowImpl)
- MESSAGE_HANDLER(WM_ERASEBKGND, OnEraseBkgnd)
- MESSAGE_HANDLER(WM_PAINT, OnPaint)
- MESSAGE_HANDLER(WM_PRINTCLIENT, OnPaint)
- END_MSG_MAP()
- LRESULT OnEraseBkgnd(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& /*bHandled*/)
- {
- return 1; // no need for the background
- }
- LRESULT OnPaint(UINT /*uMsg*/, WPARAM wParam, LPARAM /*lParam*/, BOOL& /*bHandled*/)
- {
- T* pT = static_cast<T*>(this);
- RECT rc = {};
- if(wParam != NULL)
- {
- pT->DoPrePaint((HDC)wParam, rc);
- pT->DoPaint((HDC)wParam, rc);
- }
- else
- {
- CPaintDC dc(this->m_hWnd);
- pT->DoPrePaint(dc.m_hDC, rc);
- pT->DoPaint(dc.m_hDC, rc);
- }
- return 0;
- }
- // Painting helper
- void DoPrePaint(CDCHandle dc, RECT& rc)
- {
- RECT rcClient = {};
- this->GetClientRect(&rcClient);
- RECT rcArea = rcClient;
- T* pT = static_cast<T*>(this);
- (void)pT; // avoid level 4 warning
- ::InflateRect(&rcArea, -pT->m_cxOffset, -pT->m_cyOffset);
- if (rcArea.left > rcArea.right)
- rcArea.right = rcArea.left;
- if (rcArea.top > rcArea.bottom)
- rcArea.bottom = rcArea.top;
- GetPageRect(rcArea, &rc);
- CRgn rgn1, rgn2;
- rgn1.CreateRectRgnIndirect(&rc);
- rgn2.CreateRectRgnIndirect(&rcClient);
- rgn2.CombineRgn(rgn1, RGN_DIFF);
- dc.SelectClipRgn(rgn2);
- dc.FillRect(&rcClient, COLOR_BTNSHADOW);
- dc.SelectClipRgn(NULL);
- dc.FillRect(&rc, (HBRUSH)::GetStockObject(WHITE_BRUSH));
- }
- // Implementation - data
- int m_nMinPage;
- int m_nMaxPage;
- };
- class CPrintPreviewWindow : public CPrintPreviewWindowImpl<CPrintPreviewWindow>
- {
- public:
- DECLARE_WND_CLASS_EX(_T("WTL_PrintPreview"), CS_VREDRAW | CS_HREDRAW, -1)
- };
- ///////////////////////////////////////////////////////////////////////////////
- // CZoomPrintPreviewWindowImpl - Implements print preview window with zooming
- #ifdef __ATLSCRL_H__
- template <class T, class TBase = ATL::CWindow, class TWinTraits = ATL::CControlWinTraits>
- class ATL_NO_VTABLE CZoomPrintPreviewWindowImpl : public CPrintPreviewWindowImpl< T, TBase, TWinTraits >, public CZoomScrollImpl< T >
- {
- public:
- bool m_bSized;
- CZoomPrintPreviewWindowImpl()
- {
- this->SetScrollExtendedStyle(SCRL_DISABLENOSCROLL);
- InitZoom();
- }
- // should be called to reset data members before recreating window
- void InitZoom()
- {
- m_bSized = false;
- this->m_nZoomMode = ZOOMMODE_OFF;
- this->m_fZoomScaleMin = 1.0;
- this->m_fZoomScale = 1.0;
- }
- BEGIN_MSG_MAP(CZoomPrintPreviewWindowImpl)
- MESSAGE_HANDLER(WM_SETCURSOR, CZoomScrollImpl< T >::OnSetCursor)
- MESSAGE_HANDLER(WM_VSCROLL, CScrollImpl< T >::OnVScroll)
- MESSAGE_HANDLER(WM_HSCROLL, CScrollImpl< T >::OnHScroll)
- MESSAGE_HANDLER(WM_MOUSEWHEEL, CScrollImpl< T >::OnMouseWheel)
- MESSAGE_HANDLER(WM_MOUSEHWHEEL, CScrollImpl< T >::OnMouseHWheel)
- MESSAGE_HANDLER(WM_SETTINGCHANGE, CScrollImpl< T >::OnSettingChange)
- MESSAGE_HANDLER(WM_LBUTTONDOWN, CZoomScrollImpl< T >::OnLButtonDown)
- MESSAGE_HANDLER(WM_MOUSEMOVE, CZoomScrollImpl< T >::OnMouseMove)
- MESSAGE_HANDLER(WM_LBUTTONUP, CZoomScrollImpl< T >::OnLButtonUp)
- MESSAGE_HANDLER(WM_CAPTURECHANGED, CZoomScrollImpl< T >::OnCaptureChanged)
- MESSAGE_HANDLER(WM_SIZE, OnSize)
- MESSAGE_HANDLER(WM_ERASEBKGND, OnEraseBkgnd)
- MESSAGE_HANDLER(WM_PAINT, OnPaint)
- MESSAGE_HANDLER(WM_PRINTCLIENT, OnPaint)
- ALT_MSG_MAP(1)
- COMMAND_ID_HANDLER(ID_SCROLL_UP, CScrollImpl< T >::OnScrollUp)
- COMMAND_ID_HANDLER(ID_SCROLL_DOWN, CScrollImpl< T >::OnScrollDown)
- COMMAND_ID_HANDLER(ID_SCROLL_PAGE_UP, CScrollImpl< T >::OnScrollPageUp)
- COMMAND_ID_HANDLER(ID_SCROLL_PAGE_DOWN, CScrollImpl< T >::OnScrollPageDown)
- COMMAND_ID_HANDLER(ID_SCROLL_TOP, CScrollImpl< T >::OnScrollTop)
- COMMAND_ID_HANDLER(ID_SCROLL_BOTTOM, CScrollImpl< T >::OnScrollBottom)
- COMMAND_ID_HANDLER(ID_SCROLL_LEFT, CScrollImpl< T >::OnScrollLeft)
- COMMAND_ID_HANDLER(ID_SCROLL_RIGHT, CScrollImpl< T >::OnScrollRight)
- COMMAND_ID_HANDLER(ID_SCROLL_PAGE_LEFT, CScrollImpl< T >::OnScrollPageLeft)
- COMMAND_ID_HANDLER(ID_SCROLL_PAGE_RIGHT, CScrollImpl< T >::OnScrollPageRight)
- COMMAND_ID_HANDLER(ID_SCROLL_ALL_LEFT, CScrollImpl< T >::OnScrollAllLeft)
- COMMAND_ID_HANDLER(ID_SCROLL_ALL_RIGHT, CScrollImpl< T >::OnScrollAllRight)
- END_MSG_MAP()
-
- LRESULT OnSize(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
- {
- SIZE sizeClient = {GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam)};
- POINT ptOffset = this->m_ptOffset;
- SIZE sizeAll = this->m_sizeAll;
- this->SetScrollSize(sizeClient);
- if(sizeAll.cx > 0)
- ptOffset.x = ::MulDiv(ptOffset.x, this->m_sizeAll.cx, sizeAll.cx);
- if(sizeAll.cy > 0)
- ptOffset.y = ::MulDiv(ptOffset.y, this->m_sizeAll.cy, sizeAll.cy);
- this->SetScrollOffset(ptOffset);
- CScrollImpl< T >::OnSize(uMsg, wParam, lParam, bHandled);
- if(!m_bSized)
- {
- m_bSized = true;
- T* pT = static_cast<T*>(this);
- pT->ShowScrollBar(SB_HORZ, TRUE);
- pT->ShowScrollBar(SB_VERT, TRUE);
- }
- return 0;
- }
- LRESULT OnEraseBkgnd(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& /*bHandled*/)
- {
- return 1;
- }
- LRESULT OnPaint(UINT /*uMsg*/, WPARAM wParam, LPARAM /*lParam*/, BOOL& /*bHandled*/)
- {
- T* pT = static_cast<T*>(this);
- RECT rc = {};
- if(wParam != NULL)
- {
- CDCHandle dc = (HDC)wParam;
- int nMapModeSav = dc.GetMapMode();
- dc.SetMapMode(MM_ANISOTROPIC);
- SIZE szWindowExt = { 0, 0 };
- dc.SetWindowExt(this->m_sizeLogAll, &szWindowExt);
- SIZE szViewportExt = { 0, 0 };
- dc.SetViewportExt(this->m_sizeAll, &szViewportExt);
- POINT ptViewportOrg = { 0, 0 };
- dc.SetViewportOrg(-this->m_ptOffset.x, -this->m_ptOffset.y, &ptViewportOrg);
- pT->DoPrePaint(dc, rc);
- pT->DoPaint(dc, rc);
- dc.SetMapMode(nMapModeSav);
- dc.SetWindowExt(szWindowExt);
- dc.SetViewportExt(szViewportExt);
- dc.SetViewportOrg(ptViewportOrg);
- }
- else
- {
- CPaintDC dc(pT->m_hWnd);
- pT->PrepareDC(dc.m_hDC);
- pT->DoPrePaint(dc.m_hDC, rc);
- pT->DoPaint(dc.m_hDC, rc);
- }
- return 0;
- }
- // Painting helpers
- void DoPaint(CDCHandle dc)
- {
- // this one is not used
- }
- void DoPrePaint(CDCHandle dc, RECT& rc)
- {
- RECT rcClient = {};
- this->GetClientRect(&rcClient);
- RECT rcArea = rcClient;
- T* pT = static_cast<T*>(this);
- (void)pT; // avoid level 4 warning
- ::InflateRect(&rcArea, -pT->m_cxOffset, -pT->m_cyOffset);
- if (rcArea.left > rcArea.right)
- rcArea.right = rcArea.left;
- if (rcArea.top > rcArea.bottom)
- rcArea.bottom = rcArea.top;
- this->GetPageRect(rcArea, &rc);
- HBRUSH hbrOld = dc.SelectBrush(::GetSysColorBrush(COLOR_BTNSHADOW));
- dc.PatBlt(rcClient.left, rcClient.top, rc.left - rcClient.left, rcClient.bottom - rcClient.top, PATCOPY);
- dc.PatBlt(rc.left, rcClient.top, rc.right - rc.left, rc.top - rcClient.top, PATCOPY);
- dc.PatBlt(rc.right, rcClient.top, rcClient.right - rc.right, rcClient.bottom - rcClient.top, PATCOPY);
- dc.PatBlt(rc.left, rc.bottom, rc.right - rc.left, rcClient.bottom - rc.bottom, PATCOPY);
- dc.SelectBrush((HBRUSH)::GetStockObject(WHITE_BRUSH));
- dc.PatBlt(rc.left, rc.top, rc.right - rc.left, rc.bottom - rc.top, PATCOPY);
- dc.SelectBrush(::GetSysColorBrush(COLOR_3DDKSHADOW));
- dc.PatBlt(rc.right, rc.top + 4, 4, rc.bottom - rc.top, PATCOPY);
- dc.PatBlt(rc.left + 4, rc.bottom, rc.right - rc.left, 4, PATCOPY);
- dc.SelectBrush(hbrOld);
- }
- void DoPaint(CDCHandle dc, RECT& rc)
- {
- CEnhMetaFileInfo emfinfo(this->m_meta);
- ENHMETAHEADER* pmh = emfinfo.GetEnhMetaFileHeader();
- if(pmh == NULL)
- {
- ATLASSERT(FALSE);
- return;
- }
- int nOffsetX = MulDiv(this->m_sizeCurPhysOffset.cx, rc.right-rc.left, pmh->szlDevice.cx);
- int nOffsetY = MulDiv(this->m_sizeCurPhysOffset.cy, rc.bottom-rc.top, pmh->szlDevice.cy);
- dc.OffsetWindowOrg(-nOffsetX, -nOffsetY);
- dc.PlayMetaFile(this->m_meta, &rc);
- }
- };
- class CZoomPrintPreviewWindow : public CZoomPrintPreviewWindowImpl<CZoomPrintPreviewWindow>
- {
- public:
- DECLARE_WND_CLASS_EX(_T("WTL_ZoomPrintPreview"), CS_VREDRAW | CS_HREDRAW, -1)
- };
- #endif // __ATLSCRL_H__
- } // namespace WTL
- #endif // __ATLPRINT_H__
|