]> git.sesse.net Git - casparcg/blob - WTL80/include/atlprint.h
2.0.2: INFO TEMPLATE works on both compressed and uncompressed templates.
[casparcg] / WTL80 / include / atlprint.h
1 // Windows Template Library - WTL version 8.0\r
2 // Copyright (C) Microsoft Corporation. All rights reserved.\r
3 //\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
11 \r
12 #ifndef __ATLPRINT_H__\r
13 #define __ATLPRINT_H__\r
14 \r
15 #pragma once\r
16 \r
17 #ifndef __cplusplus\r
18         #error ATL requires C++ compilation (use a .cpp suffix)\r
19 #endif\r
20 \r
21 #ifdef _WIN32_WCE\r
22         #error atlprint.h is not supported on Windows CE\r
23 #endif\r
24 \r
25 #ifndef __ATLAPP_H__\r
26         #error atlprint.h requires atlapp.h to be included first\r
27 #endif\r
28 \r
29 #ifndef __ATLWIN_H__\r
30         #error atlprint.h requires atlwin.h to be included first\r
31 #endif\r
32 \r
33 \r
34 ///////////////////////////////////////////////////////////////////////////////\r
35 // Classes in this file:\r
36 //\r
37 // CPrinterInfo<t_nInfo>\r
38 // CPrinterT<t_bManaged>\r
39 // CDevModeT<t_bManaged>\r
40 // CPrinterDC\r
41 // CPrintJobInfo\r
42 // CPrintJob\r
43 // CPrintPreview\r
44 // CPrintPreviewWindowImpl<T, TBase, TWinTraits>\r
45 // CPrintPreviewWindow\r
46 // CZoomPrintPreviewWindowImpl<T, TBase, TWinTraits>\r
47 // CZoomPrintPreviewWindow\r
48 \r
49 namespace WTL\r
50 {\r
51 \r
52 ///////////////////////////////////////////////////////////////////////////////\r
53 // CPrinterInfo - This class wraps all of the PRINTER_INFO_* structures\r
54 //                and provided by ::GetPrinter.\r
55 \r
56 template <unsigned int t_nInfo>\r
57 class _printer_info\r
58 {\r
59 public:\r
60         typedef void infotype;\r
61 };\r
62 \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
75 \r
76 \r
77 template <unsigned int t_nInfo>\r
78 class CPrinterInfo\r
79 {\r
80 public:\r
81 // Data members\r
82         typename _printer_info<t_nInfo>::infotype* m_pi;\r
83 \r
84 // Constructor/destructor\r
85         CPrinterInfo() : m_pi(NULL)\r
86         { }\r
87 \r
88         CPrinterInfo(HANDLE hPrinter) : m_pi(NULL)\r
89         {\r
90                 GetPrinterInfo(hPrinter);\r
91         }\r
92 \r
93         ~CPrinterInfo()\r
94         {\r
95                 Cleanup();\r
96         }\r
97 \r
98 // Operations\r
99         bool GetPrinterInfo(HANDLE hPrinter)\r
100         {\r
101                 Cleanup();\r
102                 return GetPrinterInfoHelper(hPrinter, (BYTE**)&m_pi, t_nInfo);\r
103         }\r
104 \r
105 // Implementation\r
106         void Cleanup()\r
107         {\r
108                 delete [] (BYTE*)m_pi;\r
109                 m_pi = NULL;\r
110         }\r
111 \r
112         static bool GetPrinterInfoHelper(HANDLE hPrinter, BYTE** pi, int nIndex)\r
113         {\r
114                 ATLASSERT(pi != NULL);\r
115                 DWORD dw = 0;\r
116                 BYTE* pb = NULL;\r
117                 ::GetPrinter(hPrinter, nIndex, NULL, 0, &dw);\r
118                 if (dw > 0)\r
119                 {\r
120                         ATLTRY(pb = new BYTE[dw]);\r
121                         if (pb != NULL)\r
122                         {\r
123                                 memset(pb, 0, dw);\r
124                                 DWORD dwNew;\r
125                                 if (!::GetPrinter(hPrinter, nIndex, pb, dw, &dwNew))\r
126                                 {\r
127                                         delete [] pb;\r
128                                         pb = NULL;\r
129                                 }\r
130                         }\r
131                 }\r
132                 *pi = pb;\r
133                 return (pb != NULL);\r
134         }\r
135 };\r
136 \r
137 \r
138 ///////////////////////////////////////////////////////////////////////////////\r
139 // CPrinter - Wrapper class for a HANDLE to a printer\r
140 \r
141 template <bool t_bManaged>\r
142 class CPrinterT\r
143 {\r
144 public:\r
145 // Data members\r
146         HANDLE m_hPrinter;\r
147 \r
148 // Constructor/destructor\r
149         CPrinterT(HANDLE hPrinter = NULL) : m_hPrinter(hPrinter)\r
150         { }\r
151 \r
152         ~CPrinterT()\r
153         {\r
154                 ClosePrinter();\r
155         }\r
156 \r
157 // Operations\r
158         CPrinterT& operator =(HANDLE hPrinter)\r
159         {\r
160                 if (hPrinter != m_hPrinter)\r
161                 {\r
162                         ClosePrinter();\r
163                         m_hPrinter = hPrinter;\r
164                 }\r
165                 return *this;\r
166         }\r
167 \r
168         bool IsNull() const { return (m_hPrinter == NULL); }\r
169 \r
170         bool OpenPrinter(HANDLE hDevNames, const DEVMODE* pDevMode = NULL)\r
171         {\r
172                 bool b = false;\r
173                 DEVNAMES* pdn = (DEVNAMES*)::GlobalLock(hDevNames);\r
174                 if (pdn != NULL)\r
175                 {\r
176                         LPTSTR lpszPrinterName = (LPTSTR)pdn + pdn->wDeviceOffset;\r
177                         b = OpenPrinter(lpszPrinterName, pDevMode);\r
178                         ::GlobalUnlock(hDevNames);\r
179                 }\r
180                 return b;\r
181         }\r
182 \r
183         bool OpenPrinter(LPCTSTR lpszPrinterName, const DEVMODE* pDevMode = NULL)\r
184         {\r
185                 ClosePrinter();\r
186                 PRINTER_DEFAULTS pdefs = { NULL, (DEVMODE*)pDevMode, PRINTER_ACCESS_USE };\r
187                 ::OpenPrinter((LPTSTR) lpszPrinterName, &m_hPrinter, (pDevMode == NULL) ? NULL : &pdefs);\r
188 \r
189                 return (m_hPrinter != NULL);\r
190         }\r
191 \r
192         bool OpenPrinter(LPCTSTR lpszPrinterName, PRINTER_DEFAULTS* pprintdefs)\r
193         {\r
194                 ClosePrinter();\r
195                 ::OpenPrinter((LPTSTR) lpszPrinterName, &m_hPrinter, pprintdefs);\r
196                 return (m_hPrinter != NULL);\r
197         }\r
198 \r
199         bool OpenDefaultPrinter(const DEVMODE* pDevMode = NULL)\r
200         {\r
201                 ClosePrinter();\r
202                 const int cchBuff = 512;\r
203                 TCHAR buffer[cchBuff];\r
204                 buffer[0] = 0;\r
205                 ::GetProfileString(_T("windows"), _T("device"), _T(",,,"), buffer, cchBuff);\r
206                 int nLen = lstrlen(buffer);\r
207                 if (nLen != 0)\r
208                 {\r
209                         LPTSTR lpsz = buffer;\r
210                         while (*lpsz)\r
211                         {\r
212                                 if (*lpsz == _T(','))\r
213                                 {\r
214                                         *lpsz = 0;\r
215                                         break;\r
216                                 }\r
217                                 lpsz = CharNext(lpsz);\r
218                         }\r
219                         PRINTER_DEFAULTS pdefs = { NULL, (DEVMODE*)pDevMode, PRINTER_ACCESS_USE };\r
220                         ::OpenPrinter(buffer, &m_hPrinter, (pDevMode == NULL) ? NULL : &pdefs);\r
221                 }\r
222                 return m_hPrinter != NULL;\r
223         }\r
224 \r
225         void ClosePrinter()\r
226         {\r
227                 if (m_hPrinter != NULL)\r
228                 {\r
229                         if (t_bManaged)\r
230                                 ::ClosePrinter(m_hPrinter);\r
231                         m_hPrinter = NULL;\r
232                 }\r
233         }\r
234 \r
235         bool PrinterProperties(HWND hWnd = NULL)\r
236         {\r
237                 if (hWnd == NULL)\r
238                         hWnd = ::GetActiveWindow();\r
239                 return !!::PrinterProperties(hWnd, m_hPrinter);\r
240         }\r
241 \r
242         HANDLE CopyToHDEVNAMES() const\r
243         {\r
244                 HANDLE h = NULL;\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
254                 {\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
259                         if (pv != NULL)\r
260                         {\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
265                                 ::GlobalUnlock(h);\r
266                         }\r
267                 }\r
268                 return h;\r
269         }\r
270 \r
271         HDC CreatePrinterDC(const DEVMODE* pdm = NULL) const\r
272         {\r
273                 CPrinterInfo<5> pinfo5;\r
274                 CPrinterInfo<2> pinfo2;\r
275                 HDC hDC = NULL;\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
284                 return hDC;\r
285         }\r
286 \r
287         HDC CreatePrinterIC(const DEVMODE* pdm = NULL) const\r
288         {\r
289                 CPrinterInfo<5> pinfo5;\r
290                 CPrinterInfo<2> pinfo2;\r
291                 HDC hDC = NULL;\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
300                 return hDC;\r
301         }\r
302 \r
303         void Attach(HANDLE hPrinter)\r
304         {\r
305                 ClosePrinter();\r
306                 m_hPrinter = hPrinter;\r
307         }\r
308 \r
309         HANDLE Detach()\r
310         {\r
311                 HANDLE hPrinter = m_hPrinter;\r
312                 m_hPrinter = NULL;\r
313                 return hPrinter;\r
314         }\r
315 \r
316         operator HANDLE() const { return m_hPrinter; }\r
317 };\r
318 \r
319 typedef CPrinterT<false>   CPrinterHandle;\r
320 typedef CPrinterT<true>    CPrinter;\r
321 \r
322 \r
323 ///////////////////////////////////////////////////////////////////////////////\r
324 // CDevMode - Wrapper class for DEVMODE\r
325 \r
326 template <bool t_bManaged>\r
327 class CDevModeT\r
328 {\r
329 public:\r
330 // Data members\r
331         HANDLE m_hDevMode;\r
332         DEVMODE* m_pDevMode;\r
333 \r
334 // Constructor/destructor\r
335         CDevModeT(HANDLE hDevMode = NULL) : m_hDevMode(hDevMode)\r
336         {\r
337                 m_pDevMode = (m_hDevMode != NULL) ? (DEVMODE*)::GlobalLock(m_hDevMode) : NULL;\r
338         }\r
339 \r
340         ~CDevModeT()\r
341         {\r
342                 Cleanup();\r
343         }\r
344 \r
345 // Operations\r
346         CDevModeT<t_bManaged>& operator =(HANDLE hDevMode)\r
347         {\r
348                 Attach(hDevMode);\r
349                 return *this;\r
350         }\r
351 \r
352         void Attach(HANDLE hDevModeNew)\r
353         {\r
354                 Cleanup();\r
355                 m_hDevMode = hDevModeNew;\r
356                 m_pDevMode = (m_hDevMode != NULL) ? (DEVMODE*)::GlobalLock(m_hDevMode) : NULL;\r
357         }\r
358 \r
359         HANDLE Detach()\r
360         {\r
361                 if (m_hDevMode != NULL)\r
362                         ::GlobalUnlock(m_hDevMode);\r
363                 HANDLE hDevMode = m_hDevMode;\r
364                 m_hDevMode = NULL;\r
365                 return hDevMode;\r
366         }\r
367 \r
368         bool IsNull() const { return (m_hDevMode == NULL); }\r
369 \r
370         bool CopyFromPrinter(HANDLE hPrinter)\r
371         {\r
372                 CPrinterInfo<2> pinfo;\r
373                 bool b = pinfo.GetPrinterInfo(hPrinter);\r
374                 if (b)\r
375                  b = CopyFromDEVMODE(pinfo.m_pi->pDevMode);\r
376                 return b;\r
377         }\r
378 \r
379         bool CopyFromDEVMODE(const DEVMODE* pdm)\r
380         {\r
381                 if (pdm == NULL)\r
382                         return false;\r
383                 int nSize = pdm->dmSize + pdm->dmDriverExtra;\r
384                 HANDLE h = ::GlobalAlloc(GMEM_MOVEABLE, nSize);\r
385                 if (h != NULL)\r
386                 {\r
387                         void* p = ::GlobalLock(h);\r
388                         SecureHelper::memcpy_x(p, nSize, pdm, nSize);\r
389                         ::GlobalUnlock(h);\r
390                 }\r
391                 Attach(h);\r
392                 return (h != NULL);\r
393         }\r
394 \r
395         bool CopyFromHDEVMODE(HANDLE hdm)\r
396         {\r
397                 bool b = false;\r
398                 if (hdm != NULL)\r
399                 {\r
400                         DEVMODE* pdm = (DEVMODE*)::GlobalLock(hdm);\r
401                         b = CopyFromDEVMODE(pdm);\r
402                         ::GlobalUnlock(hdm);\r
403                 }\r
404                 return b;\r
405         }\r
406 \r
407         HANDLE CopyToHDEVMODE()\r
408         {\r
409                 if ((m_hDevMode == NULL) || (m_pDevMode == NULL))\r
410                         return NULL;\r
411                 int nSize = m_pDevMode->dmSize + m_pDevMode->dmDriverExtra;\r
412                 HANDLE h = ::GlobalAlloc(GMEM_MOVEABLE, nSize);\r
413                 if (h != NULL)\r
414                 {\r
415                         void* p = ::GlobalLock(h);\r
416                         SecureHelper::memcpy_x(p, nSize, m_pDevMode, nSize);\r
417                         ::GlobalUnlock(h);\r
418                 }\r
419                 return h;\r
420         }\r
421 \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
425         {\r
426                 bool bRet = false;\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
430                 if(pdm != NULL)\r
431                 {\r
432                         memset(pdm, 0, nLen);\r
433                         LONG l = ::DocumentProperties(NULL, hPrinter, NULL, pdm, m_pDevMode, DM_IN_BUFFER | DM_OUT_BUFFER);\r
434                         if (l == IDOK)\r
435                                 bRet = CopyFromDEVMODE(pdm);\r
436                 }\r
437 \r
438                 return bRet;\r
439         }\r
440 \r
441         bool DocumentProperties(HANDLE hPrinter, HWND hWnd = NULL)\r
442         {\r
443                 CPrinterInfo<1> pi;\r
444                 pi.GetPrinterInfo(hPrinter);\r
445                 if (hWnd == NULL)\r
446                         hWnd = ::GetActiveWindow();\r
447 \r
448                 bool bRet = false;\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
452                 if(pdm != NULL)\r
453                 {\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
456                         if (l == IDOK)\r
457                                 bRet = CopyFromDEVMODE(pdm);\r
458                 }\r
459 \r
460                 return bRet;\r
461         }\r
462 \r
463         operator HANDLE() const { return m_hDevMode; }\r
464 \r
465         operator DEVMODE*() const { return m_pDevMode; }\r
466 \r
467 // Implementation\r
468         void Cleanup()\r
469         {\r
470                 if (m_hDevMode != NULL)\r
471                 {\r
472                         ::GlobalUnlock(m_hDevMode);\r
473                         if(t_bManaged)\r
474                                 ::GlobalFree(m_hDevMode);\r
475                         m_hDevMode = NULL;\r
476                 }\r
477         }\r
478 };\r
479 \r
480 typedef CDevModeT<false>   CDevModeHandle;\r
481 typedef CDevModeT<true>    CDevMode;\r
482 \r
483 \r
484 ///////////////////////////////////////////////////////////////////////////////\r
485 // CPrinterDC\r
486 \r
487 class CPrinterDC : public CDC\r
488 {\r
489 public:\r
490 // Constructors/destructor\r
491         CPrinterDC()\r
492         {\r
493                 CPrinter printer;\r
494                 printer.OpenDefaultPrinter();\r
495                 Attach(printer.CreatePrinterDC());\r
496                 ATLASSERT(m_hDC != NULL);\r
497         }\r
498 \r
499         CPrinterDC(HANDLE hPrinter, const DEVMODE* pdm = NULL)\r
500         {\r
501                 CPrinterHandle p;\r
502                 p.Attach(hPrinter);\r
503                 Attach(p.CreatePrinterDC(pdm));\r
504                 ATLASSERT(m_hDC != NULL);\r
505         }\r
506 \r
507         ~CPrinterDC()\r
508         {\r
509                 DeleteDC();\r
510         }\r
511 };\r
512 \r
513 \r
514 ///////////////////////////////////////////////////////////////////////////////\r
515 // CPrintJob - Wraps a set of tasks for a specific printer (StartDoc/EndDoc)\r
516 //             Handles aborting, background printing\r
517 \r
518 // Defines callbacks used by CPrintJob (not a COM interface)\r
519 class ATL_NO_VTABLE IPrintJobInfo\r
520 {\r
521 public:\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
531         // StartPrintJob.\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
535 };\r
536 \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
540 {\r
541 public:\r
542         virtual void BeginPrintJob(HDC /*hDC*/)   // allocate handles needed, etc\r
543         {\r
544         }\r
545 \r
546         virtual void EndPrintJob(HDC /*hDC*/, bool /*bAborted*/)   // free handles, etc\r
547         {\r
548         }\r
549 \r
550         virtual void PrePrintPage(UINT /*nPage*/, HDC hDC)\r
551         {\r
552                 m_nPJState = ::SaveDC(hDC);\r
553         }\r
554 \r
555         virtual bool PrintPage(UINT /*nPage*/, HDC /*hDC*/) = 0;\r
556 \r
557         virtual void PostPrintPage(UINT /*nPage*/, HDC hDC)\r
558         {\r
559                 RestoreDC(hDC, m_nPJState);\r
560         }\r
561 \r
562         virtual DEVMODE* GetNewDevModeForPage(UINT /*nLastPage*/, UINT /*nPage*/)\r
563         {\r
564                 return NULL;\r
565         }\r
566 \r
567         virtual bool IsValidPage(UINT /*nPage*/)\r
568         {\r
569                 return true;\r
570         }\r
571 \r
572 // Implementation - data\r
573         int m_nPJState;\r
574 };\r
575 \r
576 \r
577 class CPrintJob\r
578 {\r
579 public:\r
580 // Data members\r
581         CPrinterHandle m_printer;\r
582         IPrintJobInfo* m_pInfo;\r
583         DEVMODE* m_pDefDevMode;\r
584         DOCINFO m_docinfo;\r
585         int m_nJobID;\r
586         bool m_bCancel;\r
587         bool m_bComplete;\r
588         unsigned long m_nStartPage;\r
589         unsigned long m_nEndPage;\r
590 \r
591 // Constructor/destructor\r
592         CPrintJob() : m_nJobID(0), m_bCancel(false), m_bComplete(true)\r
593         { }\r
594 \r
595         ~CPrintJob()\r
596         {\r
597                 ATLASSERT(IsJobComplete()); // premature destruction?\r
598         }\r
599 \r
600 // Operations\r
601         bool IsJobComplete() const\r
602         {\r
603                 return m_bComplete;\r
604         }\r
605 \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
610         {\r
611                 ATLASSERT(m_bComplete); // previous job not done yet?\r
612                 if (pInfo == NULL)\r
613                         return false;\r
614 \r
615                 memset(&m_docinfo, 0, sizeof(m_docinfo));\r
616                 m_docinfo.cbSize = sizeof(m_docinfo);\r
617                 m_docinfo.lpszDocName = lpszDocName;\r
618                 m_pInfo = pInfo;\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
624 \r
625                 if(bPrintToFile)\r
626                         m_docinfo.lpszOutput = (lpstrOutputFile != NULL) ? lpstrOutputFile : _T("FILE:");\r
627 \r
628                 if (!bBackground)\r
629                 {\r
630                         m_bComplete = true;\r
631                         return StartHelper();\r
632                 }\r
633 \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
638 #else\r
639                 HANDLE hThread = ::CreateThread(NULL, 0, StartProc, (void*)this, 0, &dwThreadID);\r
640 #endif\r
641                 if (hThread == NULL)\r
642                         return false;\r
643 \r
644                 ::CloseHandle(hThread);\r
645 \r
646                 return true;\r
647         }\r
648 \r
649 // Implementation\r
650         static DWORD WINAPI StartProc(void* p)\r
651         {\r
652                 CPrintJob* pThis = (CPrintJob*)p;\r
653                 pThis->StartHelper();\r
654                 pThis->m_bComplete = true;\r
655                 return 0;\r
656         }\r
657 \r
658         bool StartHelper()\r
659         {\r
660                 CDC dcPrinter;\r
661                 dcPrinter.Attach(m_printer.CreatePrinterDC(m_pDefDevMode));\r
662                 if (dcPrinter.IsNull())\r
663                         return false;\r
664                         \r
665                 m_nJobID = ::StartDoc(dcPrinter, &m_docinfo);\r
666                 if (m_nJobID <= 0)\r
667                         return false;\r
668 \r
669                 m_pInfo->BeginPrintJob(dcPrinter);\r
670 \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
674                 {\r
675                         if (!m_pInfo->IsValidPage(nPage))\r
676                                 break;\r
677                         DEVMODE* pdm = m_pInfo->GetNewDevModeForPage(nLastPage, nPage);\r
678                         if (pdm != NULL)\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
683                                 m_bCancel = true;\r
684                         m_pInfo->PostPrintPage(nPage, dcPrinter);\r
685                         dcPrinter.EndPage();\r
686                         if (m_bCancel)\r
687                                 break;\r
688                         nLastPage = nPage;\r
689                 }\r
690 \r
691                 m_pInfo->EndPrintJob(dcPrinter, m_bCancel);\r
692                 if (m_bCancel)\r
693                         ::AbortDoc(dcPrinter);\r
694                 else\r
695                         ::EndDoc(dcPrinter);\r
696                 m_nJobID = 0;\r
697                 return true;\r
698         }\r
699 \r
700         // Cancels a print job. Can be called asynchronously.\r
701         void CancelPrintJob()\r
702         {\r
703                 m_bCancel = true;\r
704         }\r
705 };\r
706 \r
707 \r
708 ///////////////////////////////////////////////////////////////////////////////\r
709 // CPrintPreview - Adds print preview support to an existing window\r
710 \r
711 class CPrintPreview\r
712 {\r
713 public:\r
714 // Data members\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
721 \r
722 // Constructor\r
723         CPrintPreview() : m_pInfo(NULL), m_pDefDevMode(NULL), m_pCurDevMode(NULL)\r
724         {\r
725                 m_sizeCurPhysOffset.cx = 0;\r
726                 m_sizeCurPhysOffset.cy = 0;\r
727         }\r
728 \r
729 // Operations\r
730         void SetPrintPreviewInfo(HANDLE hPrinter, DEVMODE* pDefaultDevMode, IPrintJobInfo* pji)\r
731         {\r
732                 m_printer.Attach(hPrinter);\r
733                 m_pDefDevMode = pDefaultDevMode;\r
734                 m_pInfo = pji;\r
735                 m_nCurPage = 0;\r
736                 m_pCurDevMode = NULL;\r
737         }\r
738 \r
739         void SetEnhMetaFile(HENHMETAFILE hEMF)\r
740         {\r
741                 m_meta = hEMF;\r
742         }\r
743 \r
744         void SetPage(int nPage)\r
745         {\r
746                 if (!m_pInfo->IsValidPage(nPage))\r
747                         return;\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
753 \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
758 \r
759                 RECT rcMM = { 0, 0, ::MulDiv(iWidth, 2540, nLogx), ::MulDiv(iHeight, 2540, nLogy) };\r
760 \r
761                 m_sizeCurPhysOffset.cx = dcPrinter.GetDeviceCaps(PHYSICALOFFSETX);\r
762                 m_sizeCurPhysOffset.cy = dcPrinter.GetDeviceCaps(PHYSICALOFFSETY);\r
763                 \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
769         }\r
770 \r
771         void GetPageRect(RECT& rc, LPRECT prc)\r
772         {\r
773                 int x1 = rc.right-rc.left;\r
774                 int y1 = rc.bottom - rc.top;\r
775                 if ((x1 < 0) || (y1 < 0))\r
776                         return;\r
777 \r
778                 CEnhMetaFileInfo emfinfo(m_meta);\r
779                 ENHMETAHEADER* pmh = emfinfo.GetEnhMetaFileHeader();\r
780 \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
787                 if (x1p <= x1)\r
788                 {\r
789                         prc->left = rc.left + (x1 - x1p) / 2;\r
790                         prc->right = prc->left + x1p;\r
791                         prc->top = rc.top;\r
792                         prc->bottom = rc.bottom;\r
793                 }\r
794                 else\r
795                 {\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
800                 }\r
801         }\r
802 \r
803 // Painting helpers\r
804         void DoPaint(CDCHandle dc)\r
805         {\r
806                 // this one is not used\r
807         }\r
808 \r
809         void DoPaint(CDCHandle dc, RECT& rc)\r
810         {\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
815 \r
816                 dc.OffsetWindowOrg(-nOffsetX, -nOffsetY);\r
817                 dc.PlayMetaFile(m_meta, &rc);\r
818         }\r
819 \r
820 // Implementation - data\r
821         int m_nCurPage;\r
822 };\r
823 \r
824 \r
825 ///////////////////////////////////////////////////////////////////////////////\r
826 // CPrintPreviewWindow - Implements a print preview window\r
827 \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
830 {\r
831 public:\r
832         DECLARE_WND_CLASS_EX(NULL, CS_VREDRAW | CS_HREDRAW, -1)\r
833 \r
834         enum { m_cxOffset = 10, m_cyOffset = 10 };\r
835 \r
836 // Constructor\r
837         CPrintPreviewWindowImpl() : m_nMaxPage(0), m_nMinPage(0)\r
838         { }\r
839 \r
840 // Operations\r
841         void SetPrintPreviewInfo(HANDLE hPrinter, DEVMODE* pDefaultDevMode, \r
842                 IPrintJobInfo* pji, int nMinPage, int nMaxPage)\r
843         {\r
844                 CPrintPreview::SetPrintPreviewInfo(hPrinter, pDefaultDevMode, pji);\r
845                 m_nMinPage = nMinPage;\r
846                 m_nMaxPage = nMaxPage;\r
847         }\r
848 \r
849         bool NextPage()\r
850         {\r
851                 if (m_nCurPage == m_nMaxPage)\r
852                         return false;\r
853                 SetPage(m_nCurPage + 1);\r
854                 Invalidate();\r
855                 return true;\r
856         }\r
857 \r
858         bool PrevPage()\r
859         {\r
860                 if (m_nCurPage == m_nMinPage)\r
861                         return false;\r
862                 if (m_nCurPage == 0)\r
863                         return false;\r
864                 SetPage(m_nCurPage - 1);\r
865                 Invalidate();\r
866                 return true;\r
867         }\r
868 \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
874         END_MSG_MAP()\r
875 \r
876         LRESULT OnEraseBkgnd(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& /*bHandled*/)\r
877         {\r
878                 return 1;   // no need for the background\r
879         }\r
880 \r
881         LRESULT OnPaint(UINT /*uMsg*/, WPARAM wParam, LPARAM /*lParam*/, BOOL& /*bHandled*/)\r
882         {\r
883                 T* pT = static_cast<T*>(this);\r
884                 RECT rc = { 0 };\r
885 \r
886                 if(wParam != NULL)\r
887                 {\r
888                         pT->DoPrePaint((HDC)wParam, rc);\r
889                         pT->DoPaint((HDC)wParam, rc);\r
890                 }\r
891                 else\r
892                 {\r
893                         CPaintDC dc(m_hWnd);\r
894                         pT->DoPrePaint(dc.m_hDC, rc);\r
895                         pT->DoPaint(dc.m_hDC, rc);\r
896                 }\r
897 \r
898                 return 0;\r
899         }\r
900 \r
901 // Painting helper\r
902         void DoPrePaint(CDCHandle dc, RECT& rc)\r
903         {\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
915                 CRgn rgn1, rgn2;\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
923         }\r
924 \r
925 // Implementation - data\r
926         int m_nMinPage;\r
927         int m_nMaxPage;\r
928 };\r
929 \r
930 \r
931 class CPrintPreviewWindow : public CPrintPreviewWindowImpl<CPrintPreviewWindow>\r
932 {\r
933 public:\r
934         DECLARE_WND_CLASS_EX(_T("WTL_PrintPreview"), CS_VREDRAW | CS_HREDRAW, -1)\r
935 };\r
936 \r
937 \r
938 ///////////////////////////////////////////////////////////////////////////////\r
939 // CZoomPrintPreviewWindowImpl - Implements print preview window with zooming\r
940 \r
941 #ifdef __ATLSCRL_H__\r
942 \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
945 {\r
946 public:\r
947         bool m_bSized;\r
948 \r
949         CZoomPrintPreviewWindowImpl()  \r
950         {\r
951                 SetScrollExtendedStyle(SCRL_DISABLENOSCROLL);\r
952                 InitZoom();\r
953         }\r
954 \r
955         // should be called to reset data members before recreating window \r
956         void InitZoom()\r
957         {\r
958                 m_bSized = false;       \r
959                 m_nZoomMode = ZOOMMODE_OFF;\r
960                 m_fZoomScaleMin = 1.0;\r
961                 m_fZoomScale = 1.0;\r
962         }\r
963 \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
981         ALT_MSG_MAP(1)\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
994         END_MSG_MAP()\r
995         \r
996         LRESULT OnSize(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled)\r
997         {\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
1008                 if(!m_bSized)\r
1009                 {\r
1010                         m_bSized = true;\r
1011                         T* pT = static_cast<T*>(this);\r
1012                         pT->ShowScrollBar(SB_HORZ, TRUE);\r
1013                         pT->ShowScrollBar(SB_VERT, TRUE);\r
1014                 }\r
1015                 return 0;\r
1016         }\r
1017 \r
1018         LRESULT OnEraseBkgnd(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& /*bHandled*/)\r
1019         {\r
1020                 return 1;\r
1021         }\r
1022 \r
1023         LRESULT OnPaint(UINT /*uMsg*/, WPARAM wParam, LPARAM /*lParam*/, BOOL& /*bHandled*/)\r
1024         {\r
1025                 T* pT = static_cast<T*>(this);\r
1026                 RECT rc = { 0 };\r
1027 \r
1028                 if(wParam != NULL)\r
1029                 {\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
1039 \r
1040                         pT->DoPrePaint(dc, rc);\r
1041                         pT->DoPaint(dc, rc);\r
1042 \r
1043                         dc.SetMapMode(nMapModeSav);\r
1044                         dc.SetWindowExt(szWindowExt);\r
1045                         dc.SetViewportExt(szViewportExt);\r
1046                         dc.SetViewportOrg(ptViewportOrg);\r
1047                 }\r
1048                 else\r
1049                 {\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
1054                 }\r
1055 \r
1056                 return 0;\r
1057         }\r
1058 \r
1059         // Painting helpers\r
1060         void DoPaint(CDCHandle dc)\r
1061         {\r
1062                 // this one is not used\r
1063         }\r
1064 \r
1065         void DoPrePaint(CDCHandle dc, RECT& rc)\r
1066         {\r
1067                 RECT rcClient;\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
1089         }\r
1090 \r
1091         void DoPaint(CDCHandle dc, RECT& rc)\r
1092         {\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
1097 \r
1098                 dc.OffsetWindowOrg(-nOffsetX, -nOffsetY);\r
1099                 dc.PlayMetaFile(m_meta, &rc);\r
1100         }\r
1101 };\r
1102 \r
1103 class CZoomPrintPreviewWindow : public CZoomPrintPreviewWindowImpl<CZoomPrintPreviewWindow>\r
1104 {\r
1105 public:\r
1106         DECLARE_WND_CLASS_EX(_T("WTL_ZoomPrintPreview"), CS_VREDRAW | CS_HREDRAW, -1)\r
1107 };\r
1108 \r
1109 #endif // __ATLSCRL_H__\r
1110 \r
1111 }; // namespace WTL\r
1112 \r
1113 #endif // __ATLPRINT_H__\r