|
1
|
1 // Windows Template Library - WTL version 10.0
|
|
|
2 // Copyright (C) Microsoft Corporation, WTL Team. All rights reserved.
|
|
|
3 //
|
|
|
4 // This file is a part of the Windows Template Library.
|
|
|
5 // The use and distribution terms for this software are covered by the
|
|
|
6 // Microsoft Public License (http://opensource.org/licenses/MS-PL)
|
|
|
7 // which can be found in the file MS-PL.txt at the root folder.
|
|
|
8
|
|
|
9 #ifndef __ATLPRINT_H__
|
|
|
10 #define __ATLPRINT_H__
|
|
|
11
|
|
|
12 #pragma once
|
|
|
13
|
|
|
14 #ifndef __ATLAPP_H__
|
|
|
15 #error atlprint.h requires atlapp.h to be included first
|
|
|
16 #endif
|
|
|
17
|
|
|
18 #ifndef __ATLWIN_H__
|
|
|
19 #error atlprint.h requires atlwin.h to be included first
|
|
|
20 #endif
|
|
|
21
|
|
|
22 #include <winspool.h>
|
|
|
23
|
|
|
24
|
|
|
25 ///////////////////////////////////////////////////////////////////////////////
|
|
|
26 // Classes in this file:
|
|
|
27 //
|
|
|
28 // CPrinterInfo<t_nInfo>
|
|
|
29 // CPrinterT<t_bManaged>
|
|
|
30 // CDevModeT<t_bManaged>
|
|
|
31 // CPrinterDC
|
|
|
32 // CPrintJobInfo
|
|
|
33 // CPrintJob
|
|
|
34 // CPrintPreview
|
|
|
35 // CPrintPreviewWindowImpl<T, TBase, TWinTraits>
|
|
|
36 // CPrintPreviewWindow
|
|
|
37 // CZoomPrintPreviewWindowImpl<T, TBase, TWinTraits>
|
|
|
38 // CZoomPrintPreviewWindow
|
|
|
39
|
|
|
40 namespace WTL
|
|
|
41 {
|
|
|
42
|
|
|
43 ///////////////////////////////////////////////////////////////////////////////
|
|
|
44 // CPrinterInfo - This class wraps all of the PRINTER_INFO_* structures
|
|
|
45 // and provided by ::GetPrinter.
|
|
|
46
|
|
|
47 template <unsigned int t_nInfo>
|
|
|
48 class _printer_info
|
|
|
49 {
|
|
|
50 public:
|
|
|
51 typedef void infotype;
|
|
|
52 };
|
|
|
53
|
|
|
54 template <> class _printer_info<1> { public: typedef PRINTER_INFO_1 infotype; };
|
|
|
55 template <> class _printer_info<2> { public: typedef PRINTER_INFO_2 infotype; };
|
|
|
56 template <> class _printer_info<3> { public: typedef PRINTER_INFO_3 infotype; };
|
|
|
57 template <> class _printer_info<4> { public: typedef PRINTER_INFO_4 infotype; };
|
|
|
58 template <> class _printer_info<5> { public: typedef PRINTER_INFO_5 infotype; };
|
|
|
59 template <> class _printer_info<6> { public: typedef PRINTER_INFO_6 infotype; };
|
|
|
60 template <> class _printer_info<7> { public: typedef PRINTER_INFO_7 infotype; };
|
|
|
61 template <> class _printer_info<8> { public: typedef PRINTER_INFO_8 infotype; };
|
|
|
62 template <> class _printer_info<9> { public: typedef PRINTER_INFO_9 infotype; };
|
|
|
63
|
|
|
64
|
|
|
65 template <unsigned int t_nInfo>
|
|
|
66 class CPrinterInfo
|
|
|
67 {
|
|
|
68 public:
|
|
|
69 // Data members
|
|
|
70 typename _printer_info<t_nInfo>::infotype* m_pi;
|
|
|
71
|
|
|
72 // Constructor/destructor
|
|
|
73 CPrinterInfo() : m_pi(NULL)
|
|
|
74 { }
|
|
|
75
|
|
|
76 CPrinterInfo(HANDLE hPrinter) : m_pi(NULL)
|
|
|
77 {
|
|
|
78 GetPrinterInfo(hPrinter);
|
|
|
79 }
|
|
|
80
|
|
|
81 ~CPrinterInfo()
|
|
|
82 {
|
|
|
83 Cleanup();
|
|
|
84 }
|
|
|
85
|
|
|
86 // Operations
|
|
|
87 bool GetPrinterInfo(HANDLE hPrinter)
|
|
|
88 {
|
|
|
89 Cleanup();
|
|
|
90 return GetPrinterInfoHelper(hPrinter, (BYTE**)&m_pi, t_nInfo);
|
|
|
91 }
|
|
|
92
|
|
|
93 // Implementation
|
|
|
94 void Cleanup()
|
|
|
95 {
|
|
|
96 delete [] (BYTE*)m_pi;
|
|
|
97 m_pi = NULL;
|
|
|
98 }
|
|
|
99
|
|
|
100 static bool GetPrinterInfoHelper(HANDLE hPrinter, BYTE** pi, int nIndex)
|
|
|
101 {
|
|
|
102 ATLASSERT(pi != NULL);
|
|
|
103 DWORD dw = 0;
|
|
|
104 BYTE* pb = NULL;
|
|
|
105 ::GetPrinter(hPrinter, nIndex, NULL, 0, &dw);
|
|
|
106 if (dw > 0)
|
|
|
107 {
|
|
|
108 ATLTRY(pb = new BYTE[dw]);
|
|
|
109 if (pb != NULL)
|
|
|
110 {
|
|
|
111 memset(pb, 0, dw);
|
|
|
112 DWORD dwNew;
|
|
|
113 if (!::GetPrinter(hPrinter, nIndex, pb, dw, &dwNew))
|
|
|
114 {
|
|
|
115 delete [] pb;
|
|
|
116 pb = NULL;
|
|
|
117 }
|
|
|
118 }
|
|
|
119 }
|
|
|
120 *pi = pb;
|
|
|
121 return (pb != NULL);
|
|
|
122 }
|
|
|
123 };
|
|
|
124
|
|
|
125
|
|
|
126 ///////////////////////////////////////////////////////////////////////////////
|
|
|
127 // CPrinter - Wrapper class for a HANDLE to a printer
|
|
|
128
|
|
|
129 template <bool t_bManaged>
|
|
|
130 class CPrinterT
|
|
|
131 {
|
|
|
132 public:
|
|
|
133 // Data members
|
|
|
134 HANDLE m_hPrinter;
|
|
|
135
|
|
|
136 // Constructor/destructor
|
|
|
137 CPrinterT(HANDLE hPrinter = NULL) : m_hPrinter(hPrinter)
|
|
|
138 { }
|
|
|
139
|
|
|
140 ~CPrinterT()
|
|
|
141 {
|
|
|
142 ClosePrinter();
|
|
|
143 }
|
|
|
144
|
|
|
145 // Operations
|
|
|
146 CPrinterT& operator =(HANDLE hPrinter)
|
|
|
147 {
|
|
|
148 if (hPrinter != m_hPrinter)
|
|
|
149 {
|
|
|
150 ClosePrinter();
|
|
|
151 m_hPrinter = hPrinter;
|
|
|
152 }
|
|
|
153 return *this;
|
|
|
154 }
|
|
|
155
|
|
|
156 bool IsNull() const { return (m_hPrinter == NULL); }
|
|
|
157
|
|
|
158 bool OpenPrinter(HANDLE hDevNames, const DEVMODE* pDevMode = NULL)
|
|
|
159 {
|
|
|
160 bool b = false;
|
|
|
161 DEVNAMES* pdn = (DEVNAMES*)::GlobalLock(hDevNames);
|
|
|
162 if (pdn != NULL)
|
|
|
163 {
|
|
|
164 LPTSTR lpszPrinterName = (LPTSTR)pdn + pdn->wDeviceOffset;
|
|
|
165 b = OpenPrinter(lpszPrinterName, pDevMode);
|
|
|
166 ::GlobalUnlock(hDevNames);
|
|
|
167 }
|
|
|
168 return b;
|
|
|
169 }
|
|
|
170
|
|
|
171 bool OpenPrinter(LPCTSTR lpszPrinterName, const DEVMODE* pDevMode = NULL)
|
|
|
172 {
|
|
|
173 ClosePrinter();
|
|
|
174 PRINTER_DEFAULTS pdefs = { NULL, (DEVMODE*)pDevMode, PRINTER_ACCESS_USE };
|
|
|
175 ::OpenPrinter((LPTSTR) lpszPrinterName, &m_hPrinter, (pDevMode == NULL) ? NULL : &pdefs);
|
|
|
176
|
|
|
177 return (m_hPrinter != NULL);
|
|
|
178 }
|
|
|
179
|
|
|
180 bool OpenPrinter(LPCTSTR lpszPrinterName, PRINTER_DEFAULTS* pprintdefs)
|
|
|
181 {
|
|
|
182 ClosePrinter();
|
|
|
183 ::OpenPrinter((LPTSTR) lpszPrinterName, &m_hPrinter, pprintdefs);
|
|
|
184 return (m_hPrinter != NULL);
|
|
|
185 }
|
|
|
186
|
|
|
187 bool OpenDefaultPrinter(const DEVMODE* pDevMode = NULL)
|
|
|
188 {
|
|
|
189 ClosePrinter();
|
|
|
190
|
|
|
191 DWORD cchBuff = 0;
|
|
|
192 ::GetDefaultPrinter(NULL, &cchBuff);
|
|
|
193 TCHAR* pszBuff = new TCHAR[cchBuff];
|
|
|
194 BOOL bRet = ::GetDefaultPrinter(pszBuff, &cchBuff);
|
|
|
195 if(bRet != FALSE)
|
|
|
196 {
|
|
|
197 PRINTER_DEFAULTS pdefs = { NULL, (DEVMODE*)pDevMode, PRINTER_ACCESS_USE };
|
|
|
198 ::OpenPrinter(pszBuff, &m_hPrinter, (pDevMode == NULL) ? NULL : &pdefs);
|
|
|
199 }
|
|
|
200 delete [] pszBuff;
|
|
|
201
|
|
|
202 return m_hPrinter != NULL;
|
|
|
203 }
|
|
|
204
|
|
|
205 void ClosePrinter()
|
|
|
206 {
|
|
|
207 if (m_hPrinter != NULL)
|
|
|
208 {
|
|
|
209 if (t_bManaged)
|
|
|
210 ::ClosePrinter(m_hPrinter);
|
|
|
211 m_hPrinter = NULL;
|
|
|
212 }
|
|
|
213 }
|
|
|
214
|
|
|
215 bool PrinterProperties(HWND hWnd = NULL)
|
|
|
216 {
|
|
|
217 if (hWnd == NULL)
|
|
|
218 hWnd = ::GetActiveWindow();
|
|
|
219 return !!::PrinterProperties(hWnd, m_hPrinter);
|
|
|
220 }
|
|
|
221
|
|
|
222 HANDLE CopyToHDEVNAMES() const
|
|
|
223 {
|
|
|
224 HANDLE hDevNames = NULL;
|
|
|
225 CPrinterInfo<5> pinfon5;
|
|
|
226 CPrinterInfo<2> pinfon2;
|
|
|
227 LPTSTR lpszPrinterName = NULL;
|
|
|
228 LPTSTR lpszPortName = NULL;
|
|
|
229 // Some printers fail for PRINTER_INFO_5 in some situations
|
|
|
230 if(pinfon5.GetPrinterInfo(m_hPrinter))
|
|
|
231 {
|
|
|
232 lpszPrinterName = pinfon5.m_pi->pPrinterName;
|
|
|
233 lpszPortName = pinfon5.m_pi->pPortName;
|
|
|
234 }
|
|
|
235 else if(pinfon2.GetPrinterInfo(m_hPrinter))
|
|
|
236 {
|
|
|
237 lpszPrinterName = pinfon2.m_pi->pPrinterName;
|
|
|
238 lpszPortName = pinfon2.m_pi->pPortName;
|
|
|
239 }
|
|
|
240
|
|
|
241 if(lpszPrinterName != NULL)
|
|
|
242 {
|
|
|
243 int nLen = sizeof(DEVNAMES) + (lstrlen(lpszPrinterName) + 1 + lstrlen(lpszPortName) + 1) * sizeof(TCHAR);
|
|
|
244 hDevNames = ::GlobalAlloc(GMEM_MOVEABLE, nLen);
|
|
|
245 BYTE* pv = (BYTE*)::GlobalLock(hDevNames);
|
|
|
246 DEVNAMES* pdev = (DEVNAMES*)pv;
|
|
|
247 if(pv != NULL)
|
|
|
248 {
|
|
|
249 memset(pv, 0, nLen);
|
|
|
250 pdev->wDeviceOffset = sizeof(DEVNAMES);
|
|
|
251 pv = pv + sizeof(DEVNAMES); // now points to end
|
|
|
252 ATL::Checked::tcscpy_s((LPTSTR)pv, lstrlen(lpszPrinterName) + 1, lpszPrinterName);
|
|
|
253 pdev->wOutputOffset = (WORD)(sizeof(DEVNAMES) + (lstrlen(lpszPrinterName) + 1) * sizeof(TCHAR));
|
|
|
254 pv = pv + (lstrlen(lpszPrinterName) + 1) * sizeof(TCHAR);
|
|
|
255 ATL::Checked::tcscpy_s((LPTSTR)pv, lstrlen(lpszPortName) + 1, lpszPortName);
|
|
|
256 ::GlobalUnlock(hDevNames);
|
|
|
257 }
|
|
|
258 }
|
|
|
259
|
|
|
260 return hDevNames;
|
|
|
261 }
|
|
|
262
|
|
|
263 HDC CreatePrinterDC(const DEVMODE* pdm = NULL) const
|
|
|
264 {
|
|
|
265 CPrinterInfo<5> pinfo5;
|
|
|
266 CPrinterInfo<2> pinfo2;
|
|
|
267 HDC hDC = NULL;
|
|
|
268 LPTSTR lpszPrinterName = NULL;
|
|
|
269 // Some printers fail for PRINTER_INFO_5 in some situations
|
|
|
270 if (pinfo5.GetPrinterInfo(m_hPrinter))
|
|
|
271 lpszPrinterName = pinfo5.m_pi->pPrinterName;
|
|
|
272 else if (pinfo2.GetPrinterInfo(m_hPrinter))
|
|
|
273 lpszPrinterName = pinfo2.m_pi->pPrinterName;
|
|
|
274 if (lpszPrinterName != NULL)
|
|
|
275 hDC = ::CreateDC(NULL, lpszPrinterName, NULL, pdm);
|
|
|
276 return hDC;
|
|
|
277 }
|
|
|
278
|
|
|
279 HDC CreatePrinterIC(const DEVMODE* pdm = NULL) const
|
|
|
280 {
|
|
|
281 CPrinterInfo<5> pinfo5;
|
|
|
282 CPrinterInfo<2> pinfo2;
|
|
|
283 HDC hDC = NULL;
|
|
|
284 LPTSTR lpszPrinterName = NULL;
|
|
|
285 // Some printers fail for PRINTER_INFO_5 in some situations
|
|
|
286 if (pinfo5.GetPrinterInfo(m_hPrinter))
|
|
|
287 lpszPrinterName = pinfo5.m_pi->pPrinterName;
|
|
|
288 else if (pinfo2.GetPrinterInfo(m_hPrinter))
|
|
|
289 lpszPrinterName = pinfo2.m_pi->pPrinterName;
|
|
|
290 if (lpszPrinterName != NULL)
|
|
|
291 hDC = ::CreateIC(NULL, lpszPrinterName, NULL, pdm);
|
|
|
292 return hDC;
|
|
|
293 }
|
|
|
294
|
|
|
295 void Attach(HANDLE hPrinter)
|
|
|
296 {
|
|
|
297 ClosePrinter();
|
|
|
298 m_hPrinter = hPrinter;
|
|
|
299 }
|
|
|
300
|
|
|
301 HANDLE Detach()
|
|
|
302 {
|
|
|
303 HANDLE hPrinter = m_hPrinter;
|
|
|
304 m_hPrinter = NULL;
|
|
|
305 return hPrinter;
|
|
|
306 }
|
|
|
307
|
|
|
308 operator HANDLE() const { return m_hPrinter; }
|
|
|
309 };
|
|
|
310
|
|
|
311 typedef CPrinterT<false> CPrinterHandle;
|
|
|
312 typedef CPrinterT<true> CPrinter;
|
|
|
313
|
|
|
314
|
|
|
315 ///////////////////////////////////////////////////////////////////////////////
|
|
|
316 // CDevMode - Wrapper class for DEVMODE
|
|
|
317
|
|
|
318 template <bool t_bManaged>
|
|
|
319 class CDevModeT
|
|
|
320 {
|
|
|
321 public:
|
|
|
322 // Data members
|
|
|
323 HANDLE m_hDevMode;
|
|
|
324 DEVMODE* m_pDevMode;
|
|
|
325
|
|
|
326 // Constructor/destructor
|
|
|
327 CDevModeT(HANDLE hDevMode = NULL) : m_hDevMode(hDevMode)
|
|
|
328 {
|
|
|
329 m_pDevMode = (m_hDevMode != NULL) ? (DEVMODE*)::GlobalLock(m_hDevMode) : NULL;
|
|
|
330 }
|
|
|
331
|
|
|
332 ~CDevModeT()
|
|
|
333 {
|
|
|
334 Cleanup();
|
|
|
335 }
|
|
|
336
|
|
|
337 // Operations
|
|
|
338 CDevModeT<t_bManaged>& operator =(HANDLE hDevMode)
|
|
|
339 {
|
|
|
340 Attach(hDevMode);
|
|
|
341 return *this;
|
|
|
342 }
|
|
|
343
|
|
|
344 void Attach(HANDLE hDevModeNew)
|
|
|
345 {
|
|
|
346 Cleanup();
|
|
|
347 m_hDevMode = hDevModeNew;
|
|
|
348 m_pDevMode = (m_hDevMode != NULL) ? (DEVMODE*)::GlobalLock(m_hDevMode) : NULL;
|
|
|
349 }
|
|
|
350
|
|
|
351 HANDLE Detach()
|
|
|
352 {
|
|
|
353 if (m_hDevMode != NULL)
|
|
|
354 ::GlobalUnlock(m_hDevMode);
|
|
|
355 HANDLE hDevMode = m_hDevMode;
|
|
|
356 m_hDevMode = NULL;
|
|
|
357 return hDevMode;
|
|
|
358 }
|
|
|
359
|
|
|
360 bool IsNull() const { return (m_hDevMode == NULL); }
|
|
|
361
|
|
|
362 bool CopyFromPrinter(HANDLE hPrinter)
|
|
|
363 {
|
|
|
364 CPrinterInfo<2> pinfo;
|
|
|
365 bool b = pinfo.GetPrinterInfo(hPrinter);
|
|
|
366 if (b)
|
|
|
367 b = CopyFromDEVMODE(pinfo.m_pi->pDevMode);
|
|
|
368 return b;
|
|
|
369 }
|
|
|
370
|
|
|
371 bool CopyFromDEVMODE(const DEVMODE* pdm)
|
|
|
372 {
|
|
|
373 if (pdm == NULL)
|
|
|
374 return false;
|
|
|
375 int nSize = pdm->dmSize + pdm->dmDriverExtra;
|
|
|
376 HANDLE h = ::GlobalAlloc(GMEM_MOVEABLE, nSize);
|
|
|
377 if (h != NULL)
|
|
|
378 {
|
|
|
379 void* p = ::GlobalLock(h);
|
|
|
380 ATL::Checked::memcpy_s(p, nSize, pdm, nSize);
|
|
|
381 ::GlobalUnlock(h);
|
|
|
382 }
|
|
|
383 Attach(h);
|
|
|
384 return (h != NULL);
|
|
|
385 }
|
|
|
386
|
|
|
387 bool CopyFromHDEVMODE(HANDLE hdm)
|
|
|
388 {
|
|
|
389 bool b = false;
|
|
|
390 if (hdm != NULL)
|
|
|
391 {
|
|
|
392 DEVMODE* pdm = (DEVMODE*)::GlobalLock(hdm);
|
|
|
393 b = CopyFromDEVMODE(pdm);
|
|
|
394 ::GlobalUnlock(hdm);
|
|
|
395 }
|
|
|
396 return b;
|
|
|
397 }
|
|
|
398
|
|
|
399 HANDLE CopyToHDEVMODE()
|
|
|
400 {
|
|
|
401 if ((m_hDevMode == NULL) || (m_pDevMode == NULL))
|
|
|
402 return NULL;
|
|
|
403 int nSize = m_pDevMode->dmSize + m_pDevMode->dmDriverExtra;
|
|
|
404 HANDLE h = ::GlobalAlloc(GMEM_MOVEABLE, nSize);
|
|
|
405 if (h != NULL)
|
|
|
406 {
|
|
|
407 void* p = ::GlobalLock(h);
|
|
|
408 ATL::Checked::memcpy_s(p, nSize, m_pDevMode, nSize);
|
|
|
409 ::GlobalUnlock(h);
|
|
|
410 }
|
|
|
411 return h;
|
|
|
412 }
|
|
|
413
|
|
|
414 // If this devmode was for another printer, this will create a new devmode
|
|
|
415 // based on the existing devmode, but retargeted at the new printer
|
|
|
416 bool UpdateForNewPrinter(HANDLE hPrinter)
|
|
|
417 {
|
|
|
418 bool bRet = false;
|
|
|
419 LONG nLen = ::DocumentProperties(NULL, hPrinter, NULL, NULL, NULL, 0);
|
|
|
420 ATL::CTempBuffer<DEVMODE, _WTL_STACK_ALLOC_THRESHOLD> buff;
|
|
|
421 DEVMODE* pdm = buff.AllocateBytes(nLen);
|
|
|
422 if(pdm != NULL)
|
|
|
423 {
|
|
|
424 memset(pdm, 0, nLen);
|
|
|
425 LONG l = ::DocumentProperties(NULL, hPrinter, NULL, pdm, m_pDevMode, DM_IN_BUFFER | DM_OUT_BUFFER);
|
|
|
426 if (l == IDOK)
|
|
|
427 bRet = CopyFromDEVMODE(pdm);
|
|
|
428 }
|
|
|
429
|
|
|
430 return bRet;
|
|
|
431 }
|
|
|
432
|
|
|
433 bool DocumentProperties(HANDLE hPrinter, HWND hWnd = NULL)
|
|
|
434 {
|
|
|
435 CPrinterInfo<1> pi;
|
|
|
436 pi.GetPrinterInfo(hPrinter);
|
|
|
437 if (hWnd == NULL)
|
|
|
438 hWnd = ::GetActiveWindow();
|
|
|
439
|
|
|
440 bool bRet = false;
|
|
|
441 LONG nLen = ::DocumentProperties(hWnd, hPrinter, pi.m_pi->pName, NULL, NULL, 0);
|
|
|
442 ATL::CTempBuffer<DEVMODE, _WTL_STACK_ALLOC_THRESHOLD> buff;
|
|
|
443 DEVMODE* pdm = buff.AllocateBytes(nLen);
|
|
|
444 if(pdm != NULL)
|
|
|
445 {
|
|
|
446 memset(pdm, 0, nLen);
|
|
|
447 LONG l = ::DocumentProperties(hWnd, hPrinter, pi.m_pi->pName, pdm, m_pDevMode, DM_IN_BUFFER | DM_OUT_BUFFER | DM_PROMPT);
|
|
|
448 if (l == IDOK)
|
|
|
449 bRet = CopyFromDEVMODE(pdm);
|
|
|
450 }
|
|
|
451
|
|
|
452 return bRet;
|
|
|
453 }
|
|
|
454
|
|
|
455 operator HANDLE() const { return m_hDevMode; }
|
|
|
456
|
|
|
457 operator DEVMODE*() const { return m_pDevMode; }
|
|
|
458
|
|
|
459 // Implementation
|
|
|
460 void Cleanup()
|
|
|
461 {
|
|
|
462 if (m_hDevMode != NULL)
|
|
|
463 {
|
|
|
464 ::GlobalUnlock(m_hDevMode);
|
|
|
465 if(t_bManaged)
|
|
|
466 ::GlobalFree(m_hDevMode);
|
|
|
467 m_hDevMode = NULL;
|
|
|
468 }
|
|
|
469 }
|
|
|
470 };
|
|
|
471
|
|
|
472 typedef CDevModeT<false> CDevModeHandle;
|
|
|
473 typedef CDevModeT<true> CDevMode;
|
|
|
474
|
|
|
475
|
|
|
476 ///////////////////////////////////////////////////////////////////////////////
|
|
|
477 // CPrinterDC
|
|
|
478
|
|
|
479 class CPrinterDC : public CDC
|
|
|
480 {
|
|
|
481 public:
|
|
|
482 // Constructors/destructor
|
|
|
483 CPrinterDC()
|
|
|
484 {
|
|
|
485 CPrinter printer;
|
|
|
486 printer.OpenDefaultPrinter();
|
|
|
487 Attach(printer.CreatePrinterDC());
|
|
|
488 ATLASSERT(m_hDC != NULL);
|
|
|
489 }
|
|
|
490
|
|
|
491 CPrinterDC(HANDLE hPrinter, const DEVMODE* pdm = NULL)
|
|
|
492 {
|
|
|
493 CPrinterHandle p;
|
|
|
494 p.Attach(hPrinter);
|
|
|
495 Attach(p.CreatePrinterDC(pdm));
|
|
|
496 ATLASSERT(m_hDC != NULL);
|
|
|
497 }
|
|
|
498
|
|
|
499 ~CPrinterDC()
|
|
|
500 {
|
|
|
501 DeleteDC();
|
|
|
502 }
|
|
|
503 };
|
|
|
504
|
|
|
505
|
|
|
506 ///////////////////////////////////////////////////////////////////////////////
|
|
|
507 // CPrintJob - Wraps a set of tasks for a specific printer (StartDoc/EndDoc)
|
|
|
508 // Handles aborting, background printing
|
|
|
509
|
|
|
510 // Defines callbacks used by CPrintJob (not a COM interface)
|
|
|
511 class ATL_NO_VTABLE IPrintJobInfo
|
|
|
512 {
|
|
|
513 public:
|
|
|
514 virtual void BeginPrintJob(HDC hDC) = 0; // allocate handles needed, etc.
|
|
|
515 virtual void EndPrintJob(HDC hDC, bool bAborted) = 0; // free handles, etc.
|
|
|
516 virtual void PrePrintPage(UINT nPage, HDC hDC) = 0;
|
|
|
517 virtual bool PrintPage(UINT nPage, HDC hDC) = 0;
|
|
|
518 virtual void PostPrintPage(UINT nPage, HDC hDC) = 0;
|
|
|
519 // If you want per page devmodes, return the DEVMODE* to use for nPage.
|
|
|
520 // You can optimize by only returning a new DEVMODE* when it is different
|
|
|
521 // from the one for nLastPage, otherwise return NULL.
|
|
|
522 // When nLastPage==0, the current DEVMODE* will be the default passed to
|
|
|
523 // StartPrintJob.
|
|
|
524 // Note: During print preview, nLastPage will always be "0".
|
|
|
525 virtual DEVMODE* GetNewDevModeForPage(UINT nLastPage, UINT nPage) = 0;
|
|
|
526 virtual bool IsValidPage(UINT nPage) = 0;
|
|
|
527 };
|
|
|
528
|
|
|
529 // Provides a default implementatin for IPrintJobInfo
|
|
|
530 // Typically, MI'd into a document or view class
|
|
|
531 class ATL_NO_VTABLE CPrintJobInfo : public IPrintJobInfo
|
|
|
532 {
|
|
|
533 public:
|
|
|
534 virtual void BeginPrintJob(HDC /*hDC*/) // allocate handles needed, etc
|
|
|
535 {
|
|
|
536 }
|
|
|
537
|
|
|
538 virtual void EndPrintJob(HDC /*hDC*/, bool /*bAborted*/) // free handles, etc
|
|
|
539 {
|
|
|
540 }
|
|
|
541
|
|
|
542 virtual void PrePrintPage(UINT /*nPage*/, HDC hDC)
|
|
|
543 {
|
|
|
544 m_nPJState = ::SaveDC(hDC);
|
|
|
545 }
|
|
|
546
|
|
|
547 virtual bool PrintPage(UINT /*nPage*/, HDC /*hDC*/) = 0;
|
|
|
548
|
|
|
549 virtual void PostPrintPage(UINT /*nPage*/, HDC hDC)
|
|
|
550 {
|
|
|
551 RestoreDC(hDC, m_nPJState);
|
|
|
552 }
|
|
|
553
|
|
|
554 virtual DEVMODE* GetNewDevModeForPage(UINT /*nLastPage*/, UINT /*nPage*/)
|
|
|
555 {
|
|
|
556 return NULL;
|
|
|
557 }
|
|
|
558
|
|
|
559 virtual bool IsValidPage(UINT /*nPage*/)
|
|
|
560 {
|
|
|
561 return true;
|
|
|
562 }
|
|
|
563
|
|
|
564 // Implementation - data
|
|
|
565 int m_nPJState;
|
|
|
566 };
|
|
|
567
|
|
|
568
|
|
|
569 class CPrintJob
|
|
|
570 {
|
|
|
571 public:
|
|
|
572 // Data members
|
|
|
573 CPrinterHandle m_printer;
|
|
|
574 IPrintJobInfo* m_pInfo;
|
|
|
575 DEVMODE* m_pDefDevMode;
|
|
|
576 DOCINFO m_docinfo;
|
|
|
577 int m_nJobID;
|
|
|
578 bool m_bCancel;
|
|
|
579 bool m_bComplete;
|
|
|
580 unsigned long m_nStartPage;
|
|
|
581 unsigned long m_nEndPage;
|
|
|
582
|
|
|
583 // Constructor/destructor
|
|
|
584 CPrintJob() : m_nJobID(0), m_bCancel(false), m_bComplete(true)
|
|
|
585 { }
|
|
|
586
|
|
|
587 ~CPrintJob()
|
|
|
588 {
|
|
|
589 ATLASSERT(IsJobComplete()); // premature destruction?
|
|
|
590 }
|
|
|
591
|
|
|
592 // Operations
|
|
|
593 bool IsJobComplete() const
|
|
|
594 {
|
|
|
595 return m_bComplete;
|
|
|
596 }
|
|
|
597
|
|
|
598 bool StartPrintJob(bool bBackground, HANDLE hPrinter, DEVMODE* pDefaultDevMode,
|
|
|
599 IPrintJobInfo* pInfo, LPCTSTR lpszDocName,
|
|
|
600 unsigned long nStartPage, unsigned long nEndPage,
|
|
|
601 bool bPrintToFile = false, LPCTSTR lpstrOutputFile = NULL)
|
|
|
602 {
|
|
|
603 ATLASSERT(m_bComplete); // previous job not done yet?
|
|
|
604 if (pInfo == NULL)
|
|
|
605 return false;
|
|
|
606
|
|
|
607 memset(&m_docinfo, 0, sizeof(m_docinfo));
|
|
|
608 m_docinfo.cbSize = sizeof(m_docinfo);
|
|
|
609 m_docinfo.lpszDocName = lpszDocName;
|
|
|
610 m_pInfo = pInfo;
|
|
|
611 m_nStartPage = nStartPage;
|
|
|
612 m_nEndPage = nEndPage;
|
|
|
613 m_printer.Attach(hPrinter);
|
|
|
614 m_pDefDevMode = pDefaultDevMode;
|
|
|
615 m_bComplete = false;
|
|
|
616
|
|
|
617 if(bPrintToFile)
|
|
|
618 m_docinfo.lpszOutput = (lpstrOutputFile != NULL) ? lpstrOutputFile : _T("FILE:");
|
|
|
619
|
|
|
620 if (!bBackground)
|
|
|
621 {
|
|
|
622 m_bComplete = true;
|
|
|
623 return StartHelper();
|
|
|
624 }
|
|
|
625
|
|
|
626 // Create a thread and return
|
|
|
627 DWORD dwThreadID = 0;
|
|
|
628 #ifdef _MT
|
|
|
629 HANDLE hThread = (HANDLE)_beginthreadex(NULL, 0, (UINT (WINAPI*)(void*))StartProc, this, 0, (UINT*)&dwThreadID);
|
|
|
630 #else
|
|
|
631 HANDLE hThread = ::CreateThread(NULL, 0, StartProc, (void*)this, 0, &dwThreadID);
|
|
|
632 #endif
|
|
|
633 if (hThread == NULL)
|
|
|
634 return false;
|
|
|
635
|
|
|
636 ::CloseHandle(hThread);
|
|
|
637
|
|
|
638 return true;
|
|
|
639 }
|
|
|
640
|
|
|
641 // Implementation
|
|
|
642 static DWORD WINAPI StartProc(void* p)
|
|
|
643 {
|
|
|
644 CPrintJob* pThis = (CPrintJob*)p;
|
|
|
645 pThis->StartHelper();
|
|
|
646 pThis->m_bComplete = true;
|
|
|
647 return 0;
|
|
|
648 }
|
|
|
649
|
|
|
650 bool StartHelper()
|
|
|
651 {
|
|
|
652 CDC dcPrinter;
|
|
|
653 dcPrinter.Attach(m_printer.CreatePrinterDC(m_pDefDevMode));
|
|
|
654 if (dcPrinter.IsNull())
|
|
|
655 return false;
|
|
|
656
|
|
|
657 m_nJobID = ::StartDoc(dcPrinter, &m_docinfo);
|
|
|
658 if (m_nJobID <= 0)
|
|
|
659 return false;
|
|
|
660
|
|
|
661 m_pInfo->BeginPrintJob(dcPrinter);
|
|
|
662
|
|
|
663 // print all the pages now
|
|
|
664 unsigned long nLastPage = 0;
|
|
|
665 for (unsigned long nPage = m_nStartPage; nPage <= m_nEndPage; nPage++)
|
|
|
666 {
|
|
|
667 if (!m_pInfo->IsValidPage(nPage))
|
|
|
668 break;
|
|
|
669 DEVMODE* pdm = m_pInfo->GetNewDevModeForPage(nLastPage, nPage);
|
|
|
670 if (pdm != NULL)
|
|
|
671 dcPrinter.ResetDC(pdm);
|
|
|
672 dcPrinter.StartPage();
|
|
|
673 m_pInfo->PrePrintPage(nPage, dcPrinter);
|
|
|
674 if (!m_pInfo->PrintPage(nPage, dcPrinter))
|
|
|
675 m_bCancel = true;
|
|
|
676 m_pInfo->PostPrintPage(nPage, dcPrinter);
|
|
|
677 dcPrinter.EndPage();
|
|
|
678 if (m_bCancel)
|
|
|
679 break;
|
|
|
680 nLastPage = nPage;
|
|
|
681 }
|
|
|
682
|
|
|
683 m_pInfo->EndPrintJob(dcPrinter, m_bCancel);
|
|
|
684 if (m_bCancel)
|
|
|
685 ::AbortDoc(dcPrinter);
|
|
|
686 else
|
|
|
687 ::EndDoc(dcPrinter);
|
|
|
688 m_nJobID = 0;
|
|
|
689 return true;
|
|
|
690 }
|
|
|
691
|
|
|
692 // Cancels a print job. Can be called asynchronously.
|
|
|
693 void CancelPrintJob()
|
|
|
694 {
|
|
|
695 m_bCancel = true;
|
|
|
696 }
|
|
|
697 };
|
|
|
698
|
|
|
699
|
|
|
700 ///////////////////////////////////////////////////////////////////////////////
|
|
|
701 // CPrintPreview - Adds print preview support to an existing window
|
|
|
702
|
|
|
703 class CPrintPreview
|
|
|
704 {
|
|
|
705 public:
|
|
|
706 // Data members
|
|
|
707 IPrintJobInfo* m_pInfo;
|
|
|
708 CPrinterHandle m_printer;
|
|
|
709 CEnhMetaFile m_meta;
|
|
|
710 DEVMODE* m_pDefDevMode;
|
|
|
711 DEVMODE* m_pCurDevMode;
|
|
|
712 SIZE m_sizeCurPhysOffset;
|
|
|
713
|
|
|
714 // Constructor
|
|
|
715 CPrintPreview() : m_pInfo(NULL), m_pDefDevMode(NULL), m_pCurDevMode(NULL)
|
|
|
716 {
|
|
|
717 m_sizeCurPhysOffset.cx = 0;
|
|
|
718 m_sizeCurPhysOffset.cy = 0;
|
|
|
719 }
|
|
|
720
|
|
|
721 // Operations
|
|
|
722 void SetPrintPreviewInfo(HANDLE hPrinter, DEVMODE* pDefaultDevMode, IPrintJobInfo* pji)
|
|
|
723 {
|
|
|
724 m_printer.Attach(hPrinter);
|
|
|
725 m_pDefDevMode = pDefaultDevMode;
|
|
|
726 m_pInfo = pji;
|
|
|
727 m_nCurPage = 0;
|
|
|
728 m_pCurDevMode = NULL;
|
|
|
729 }
|
|
|
730
|
|
|
731 void SetEnhMetaFile(HENHMETAFILE hEMF)
|
|
|
732 {
|
|
|
733 m_meta = hEMF;
|
|
|
734 }
|
|
|
735
|
|
|
736 void SetPage(int nPage)
|
|
|
737 {
|
|
|
738 if (!m_pInfo->IsValidPage(nPage))
|
|
|
739 return;
|
|
|
740 m_nCurPage = nPage;
|
|
|
741 m_pCurDevMode = m_pInfo->GetNewDevModeForPage(0, nPage);
|
|
|
742 if (m_pCurDevMode == NULL)
|
|
|
743 m_pCurDevMode = m_pDefDevMode;
|
|
|
744 CDC dcPrinter = m_printer.CreatePrinterDC(m_pCurDevMode);
|
|
|
745
|
|
|
746 int iWidth = dcPrinter.GetDeviceCaps(PHYSICALWIDTH);
|
|
|
747 int iHeight = dcPrinter.GetDeviceCaps(PHYSICALHEIGHT);
|
|
|
748 int nLogx = dcPrinter.GetDeviceCaps(LOGPIXELSX);
|
|
|
749 int nLogy = dcPrinter.GetDeviceCaps(LOGPIXELSY);
|
|
|
750
|
|
|
751 RECT rcMM = { 0, 0, ::MulDiv(iWidth, 2540, nLogx), ::MulDiv(iHeight, 2540, nLogy) };
|
|
|
752
|
|
|
753 m_sizeCurPhysOffset.cx = dcPrinter.GetDeviceCaps(PHYSICALOFFSETX);
|
|
|
754 m_sizeCurPhysOffset.cy = dcPrinter.GetDeviceCaps(PHYSICALOFFSETY);
|
|
|
755
|
|
|
756 CEnhMetaFileDC dcMeta(dcPrinter, &rcMM);
|
|
|
757 m_pInfo->PrePrintPage(nPage, dcMeta);
|
|
|
758 m_pInfo->PrintPage(nPage, dcMeta);
|
|
|
759 m_pInfo->PostPrintPage(nPage, dcMeta);
|
|
|
760 m_meta.Attach(dcMeta.Close());
|
|
|
761 }
|
|
|
762
|
|
|
763 void GetPageRect(RECT& rc, LPRECT prc)
|
|
|
764 {
|
|
|
765 int x1 = rc.right-rc.left;
|
|
|
766 int y1 = rc.bottom - rc.top;
|
|
|
767 if ((x1 < 0) || (y1 < 0))
|
|
|
768 return;
|
|
|
769
|
|
|
770 CEnhMetaFileInfo emfinfo(m_meta);
|
|
|
771 ENHMETAHEADER* pmh = emfinfo.GetEnhMetaFileHeader();
|
|
|
772
|
|
|
773 // Compute whether we are OK vertically or horizontally
|
|
|
774 int x2 = pmh->szlDevice.cx;
|
|
|
775 int y2 = pmh->szlDevice.cy;
|
|
|
776 int y1p = MulDiv(x1, y2, x2);
|
|
|
777 int x1p = MulDiv(y1, x2, y2);
|
|
|
778 ATLASSERT((x1p <= x1) || (y1p <= y1));
|
|
|
779 if (x1p <= x1)
|
|
|
780 {
|
|
|
781 prc->left = rc.left + (x1 - x1p) / 2;
|
|
|
782 prc->right = prc->left + x1p;
|
|
|
783 prc->top = rc.top;
|
|
|
784 prc->bottom = rc.bottom;
|
|
|
785 }
|
|
|
786 else
|
|
|
787 {
|
|
|
788 prc->left = rc.left;
|
|
|
789 prc->right = rc.right;
|
|
|
790 prc->top = rc.top + (y1 - y1p) / 2;
|
|
|
791 prc->bottom = prc->top + y1p;
|
|
|
792 }
|
|
|
793 }
|
|
|
794
|
|
|
795 // Painting helpers
|
|
|
796 void DoPaint(CDCHandle dc)
|
|
|
797 {
|
|
|
798 // this one is not used
|
|
|
799 }
|
|
|
800
|
|
|
801 void DoPaint(CDCHandle dc, RECT& rc)
|
|
|
802 {
|
|
|
803 CEnhMetaFileInfo emfinfo(m_meta);
|
|
|
804 ENHMETAHEADER* pmh = emfinfo.GetEnhMetaFileHeader();
|
|
|
805 int nOffsetX = MulDiv(m_sizeCurPhysOffset.cx, rc.right-rc.left, pmh->szlDevice.cx);
|
|
|
806 int nOffsetY = MulDiv(m_sizeCurPhysOffset.cy, rc.bottom-rc.top, pmh->szlDevice.cy);
|
|
|
807
|
|
|
808 dc.OffsetWindowOrg(-nOffsetX, -nOffsetY);
|
|
|
809 dc.PlayMetaFile(m_meta, &rc);
|
|
|
810 }
|
|
|
811
|
|
|
812 // Implementation - data
|
|
|
813 int m_nCurPage;
|
|
|
814 };
|
|
|
815
|
|
|
816
|
|
|
817 ///////////////////////////////////////////////////////////////////////////////
|
|
|
818 // CPrintPreviewWindow - Implements a print preview window
|
|
|
819
|
|
|
820 template <class T, class TBase = ATL::CWindow, class TWinTraits = ATL::CControlWinTraits>
|
|
|
821 class ATL_NO_VTABLE CPrintPreviewWindowImpl : public ATL::CWindowImpl<T, TBase, TWinTraits>, public CPrintPreview
|
|
|
822 {
|
|
|
823 public:
|
|
|
824 DECLARE_WND_CLASS_EX2(NULL, T, CS_VREDRAW | CS_HREDRAW, -1)
|
|
|
825
|
|
|
826 enum { m_cxOffset = 10, m_cyOffset = 10 };
|
|
|
827
|
|
|
828 // Constructor
|
|
|
829 CPrintPreviewWindowImpl() : m_nMinPage(0), m_nMaxPage(0)
|
|
|
830 { }
|
|
|
831
|
|
|
832 // Operations
|
|
|
833 void SetPrintPreviewInfo(HANDLE hPrinter, DEVMODE* pDefaultDevMode,
|
|
|
834 IPrintJobInfo* pji, int nMinPage, int nMaxPage)
|
|
|
835 {
|
|
|
836 CPrintPreview::SetPrintPreviewInfo(hPrinter, pDefaultDevMode, pji);
|
|
|
837 m_nMinPage = nMinPage;
|
|
|
838 m_nMaxPage = nMaxPage;
|
|
|
839 }
|
|
|
840
|
|
|
841 bool NextPage()
|
|
|
842 {
|
|
|
843 if (m_nCurPage == m_nMaxPage)
|
|
|
844 return false;
|
|
|
845 SetPage(m_nCurPage + 1);
|
|
|
846 this->Invalidate();
|
|
|
847 return true;
|
|
|
848 }
|
|
|
849
|
|
|
850 bool PrevPage()
|
|
|
851 {
|
|
|
852 if (m_nCurPage == m_nMinPage)
|
|
|
853 return false;
|
|
|
854 if (m_nCurPage == 0)
|
|
|
855 return false;
|
|
|
856 SetPage(m_nCurPage - 1);
|
|
|
857 this->Invalidate();
|
|
|
858 return true;
|
|
|
859 }
|
|
|
860
|
|
|
861 // Message map and handlers
|
|
|
862 BEGIN_MSG_MAP(CPrintPreviewWindowImpl)
|
|
|
863 MESSAGE_HANDLER(WM_ERASEBKGND, OnEraseBkgnd)
|
|
|
864 MESSAGE_HANDLER(WM_PAINT, OnPaint)
|
|
|
865 MESSAGE_HANDLER(WM_PRINTCLIENT, OnPaint)
|
|
|
866 END_MSG_MAP()
|
|
|
867
|
|
|
868 LRESULT OnEraseBkgnd(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& /*bHandled*/)
|
|
|
869 {
|
|
|
870 return 1; // no need for the background
|
|
|
871 }
|
|
|
872
|
|
|
873 LRESULT OnPaint(UINT /*uMsg*/, WPARAM wParam, LPARAM /*lParam*/, BOOL& /*bHandled*/)
|
|
|
874 {
|
|
|
875 T* pT = static_cast<T*>(this);
|
|
|
876 RECT rc = {};
|
|
|
877
|
|
|
878 if(wParam != NULL)
|
|
|
879 {
|
|
|
880 pT->DoPrePaint((HDC)wParam, rc);
|
|
|
881 pT->DoPaint((HDC)wParam, rc);
|
|
|
882 }
|
|
|
883 else
|
|
|
884 {
|
|
|
885 CPaintDC dc(this->m_hWnd);
|
|
|
886 pT->DoPrePaint(dc.m_hDC, rc);
|
|
|
887 pT->DoPaint(dc.m_hDC, rc);
|
|
|
888 }
|
|
|
889
|
|
|
890 return 0;
|
|
|
891 }
|
|
|
892
|
|
|
893 // Painting helper
|
|
|
894 void DoPrePaint(CDCHandle dc, RECT& rc)
|
|
|
895 {
|
|
|
896 RECT rcClient = {};
|
|
|
897 this->GetClientRect(&rcClient);
|
|
|
898 RECT rcArea = rcClient;
|
|
|
899 T* pT = static_cast<T*>(this);
|
|
|
900 (void)pT; // avoid level 4 warning
|
|
|
901 ::InflateRect(&rcArea, -pT->m_cxOffset, -pT->m_cyOffset);
|
|
|
902 if (rcArea.left > rcArea.right)
|
|
|
903 rcArea.right = rcArea.left;
|
|
|
904 if (rcArea.top > rcArea.bottom)
|
|
|
905 rcArea.bottom = rcArea.top;
|
|
|
906 GetPageRect(rcArea, &rc);
|
|
|
907 CRgn rgn1, rgn2;
|
|
|
908 rgn1.CreateRectRgnIndirect(&rc);
|
|
|
909 rgn2.CreateRectRgnIndirect(&rcClient);
|
|
|
910 rgn2.CombineRgn(rgn1, RGN_DIFF);
|
|
|
911 dc.SelectClipRgn(rgn2);
|
|
|
912 dc.FillRect(&rcClient, COLOR_BTNSHADOW);
|
|
|
913 dc.SelectClipRgn(NULL);
|
|
|
914 dc.FillRect(&rc, (HBRUSH)::GetStockObject(WHITE_BRUSH));
|
|
|
915 }
|
|
|
916
|
|
|
917 // Implementation - data
|
|
|
918 int m_nMinPage;
|
|
|
919 int m_nMaxPage;
|
|
|
920 };
|
|
|
921
|
|
|
922
|
|
|
923 class CPrintPreviewWindow : public CPrintPreviewWindowImpl<CPrintPreviewWindow>
|
|
|
924 {
|
|
|
925 public:
|
|
|
926 DECLARE_WND_CLASS_EX(_T("WTL_PrintPreview"), CS_VREDRAW | CS_HREDRAW, -1)
|
|
|
927 };
|
|
|
928
|
|
|
929
|
|
|
930 ///////////////////////////////////////////////////////////////////////////////
|
|
|
931 // CZoomPrintPreviewWindowImpl - Implements print preview window with zooming
|
|
|
932
|
|
|
933 #ifdef __ATLSCRL_H__
|
|
|
934
|
|
|
935 template <class T, class TBase = ATL::CWindow, class TWinTraits = ATL::CControlWinTraits>
|
|
|
936 class ATL_NO_VTABLE CZoomPrintPreviewWindowImpl : public CPrintPreviewWindowImpl< T, TBase, TWinTraits >, public CZoomScrollImpl< T >
|
|
|
937 {
|
|
|
938 public:
|
|
|
939 bool m_bSized;
|
|
|
940
|
|
|
941 CZoomPrintPreviewWindowImpl()
|
|
|
942 {
|
|
|
943 this->SetScrollExtendedStyle(SCRL_DISABLENOSCROLL);
|
|
|
944 InitZoom();
|
|
|
945 }
|
|
|
946
|
|
|
947 // should be called to reset data members before recreating window
|
|
|
948 void InitZoom()
|
|
|
949 {
|
|
|
950 m_bSized = false;
|
|
|
951 this->m_nZoomMode = ZOOMMODE_OFF;
|
|
|
952 this->m_fZoomScaleMin = 1.0;
|
|
|
953 this->m_fZoomScale = 1.0;
|
|
|
954 }
|
|
|
955
|
|
|
956 BEGIN_MSG_MAP(CZoomPrintPreviewWindowImpl)
|
|
|
957 MESSAGE_HANDLER(WM_SETCURSOR, CZoomScrollImpl< T >::OnSetCursor)
|
|
|
958 MESSAGE_HANDLER(WM_VSCROLL, CScrollImpl< T >::OnVScroll)
|
|
|
959 MESSAGE_HANDLER(WM_HSCROLL, CScrollImpl< T >::OnHScroll)
|
|
|
960 MESSAGE_HANDLER(WM_MOUSEWHEEL, CScrollImpl< T >::OnMouseWheel)
|
|
|
961 MESSAGE_HANDLER(WM_MOUSEHWHEEL, CScrollImpl< T >::OnMouseHWheel)
|
|
|
962 MESSAGE_HANDLER(WM_SETTINGCHANGE, CScrollImpl< T >::OnSettingChange)
|
|
|
963 MESSAGE_HANDLER(WM_LBUTTONDOWN, CZoomScrollImpl< T >::OnLButtonDown)
|
|
|
964 MESSAGE_HANDLER(WM_MOUSEMOVE, CZoomScrollImpl< T >::OnMouseMove)
|
|
|
965 MESSAGE_HANDLER(WM_LBUTTONUP, CZoomScrollImpl< T >::OnLButtonUp)
|
|
|
966 MESSAGE_HANDLER(WM_CAPTURECHANGED, CZoomScrollImpl< T >::OnCaptureChanged)
|
|
|
967 MESSAGE_HANDLER(WM_SIZE, OnSize)
|
|
|
968 MESSAGE_HANDLER(WM_ERASEBKGND, OnEraseBkgnd)
|
|
|
969 MESSAGE_HANDLER(WM_PAINT, OnPaint)
|
|
|
970 MESSAGE_HANDLER(WM_PRINTCLIENT, OnPaint)
|
|
|
971 ALT_MSG_MAP(1)
|
|
|
972 COMMAND_ID_HANDLER(ID_SCROLL_UP, CScrollImpl< T >::OnScrollUp)
|
|
|
973 COMMAND_ID_HANDLER(ID_SCROLL_DOWN, CScrollImpl< T >::OnScrollDown)
|
|
|
974 COMMAND_ID_HANDLER(ID_SCROLL_PAGE_UP, CScrollImpl< T >::OnScrollPageUp)
|
|
|
975 COMMAND_ID_HANDLER(ID_SCROLL_PAGE_DOWN, CScrollImpl< T >::OnScrollPageDown)
|
|
|
976 COMMAND_ID_HANDLER(ID_SCROLL_TOP, CScrollImpl< T >::OnScrollTop)
|
|
|
977 COMMAND_ID_HANDLER(ID_SCROLL_BOTTOM, CScrollImpl< T >::OnScrollBottom)
|
|
|
978 COMMAND_ID_HANDLER(ID_SCROLL_LEFT, CScrollImpl< T >::OnScrollLeft)
|
|
|
979 COMMAND_ID_HANDLER(ID_SCROLL_RIGHT, CScrollImpl< T >::OnScrollRight)
|
|
|
980 COMMAND_ID_HANDLER(ID_SCROLL_PAGE_LEFT, CScrollImpl< T >::OnScrollPageLeft)
|
|
|
981 COMMAND_ID_HANDLER(ID_SCROLL_PAGE_RIGHT, CScrollImpl< T >::OnScrollPageRight)
|
|
|
982 COMMAND_ID_HANDLER(ID_SCROLL_ALL_LEFT, CScrollImpl< T >::OnScrollAllLeft)
|
|
|
983 COMMAND_ID_HANDLER(ID_SCROLL_ALL_RIGHT, CScrollImpl< T >::OnScrollAllRight)
|
|
|
984 END_MSG_MAP()
|
|
|
985
|
|
|
986 LRESULT OnSize(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
|
|
|
987 {
|
|
|
988 SIZE sizeClient = {GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam)};
|
|
|
989 POINT ptOffset = this->m_ptOffset;
|
|
|
990 SIZE sizeAll = this->m_sizeAll;
|
|
|
991 this->SetScrollSize(sizeClient);
|
|
|
992 if(sizeAll.cx > 0)
|
|
|
993 ptOffset.x = ::MulDiv(ptOffset.x, this->m_sizeAll.cx, sizeAll.cx);
|
|
|
994 if(sizeAll.cy > 0)
|
|
|
995 ptOffset.y = ::MulDiv(ptOffset.y, this->m_sizeAll.cy, sizeAll.cy);
|
|
|
996 this->SetScrollOffset(ptOffset);
|
|
|
997 CScrollImpl< T >::OnSize(uMsg, wParam, lParam, bHandled);
|
|
|
998 if(!m_bSized)
|
|
|
999 {
|
|
|
1000 m_bSized = true;
|
|
|
1001 T* pT = static_cast<T*>(this);
|
|
|
1002 pT->ShowScrollBar(SB_HORZ, TRUE);
|
|
|
1003 pT->ShowScrollBar(SB_VERT, TRUE);
|
|
|
1004 }
|
|
|
1005 return 0;
|
|
|
1006 }
|
|
|
1007
|
|
|
1008 LRESULT OnEraseBkgnd(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& /*bHandled*/)
|
|
|
1009 {
|
|
|
1010 return 1;
|
|
|
1011 }
|
|
|
1012
|
|
|
1013 LRESULT OnPaint(UINT /*uMsg*/, WPARAM wParam, LPARAM /*lParam*/, BOOL& /*bHandled*/)
|
|
|
1014 {
|
|
|
1015 T* pT = static_cast<T*>(this);
|
|
|
1016 RECT rc = {};
|
|
|
1017
|
|
|
1018 if(wParam != NULL)
|
|
|
1019 {
|
|
|
1020 CDCHandle dc = (HDC)wParam;
|
|
|
1021 int nMapModeSav = dc.GetMapMode();
|
|
|
1022 dc.SetMapMode(MM_ANISOTROPIC);
|
|
|
1023 SIZE szWindowExt = { 0, 0 };
|
|
|
1024 dc.SetWindowExt(this->m_sizeLogAll, &szWindowExt);
|
|
|
1025 SIZE szViewportExt = { 0, 0 };
|
|
|
1026 dc.SetViewportExt(this->m_sizeAll, &szViewportExt);
|
|
|
1027 POINT ptViewportOrg = { 0, 0 };
|
|
|
1028 dc.SetViewportOrg(-this->m_ptOffset.x, -this->m_ptOffset.y, &ptViewportOrg);
|
|
|
1029
|
|
|
1030 pT->DoPrePaint(dc, rc);
|
|
|
1031 pT->DoPaint(dc, rc);
|
|
|
1032
|
|
|
1033 dc.SetMapMode(nMapModeSav);
|
|
|
1034 dc.SetWindowExt(szWindowExt);
|
|
|
1035 dc.SetViewportExt(szViewportExt);
|
|
|
1036 dc.SetViewportOrg(ptViewportOrg);
|
|
|
1037 }
|
|
|
1038 else
|
|
|
1039 {
|
|
|
1040 CPaintDC dc(pT->m_hWnd);
|
|
|
1041 pT->PrepareDC(dc.m_hDC);
|
|
|
1042 pT->DoPrePaint(dc.m_hDC, rc);
|
|
|
1043 pT->DoPaint(dc.m_hDC, rc);
|
|
|
1044 }
|
|
|
1045
|
|
|
1046 return 0;
|
|
|
1047 }
|
|
|
1048
|
|
|
1049 // Painting helpers
|
|
|
1050 void DoPaint(CDCHandle dc)
|
|
|
1051 {
|
|
|
1052 // this one is not used
|
|
|
1053 }
|
|
|
1054
|
|
|
1055 void DoPrePaint(CDCHandle dc, RECT& rc)
|
|
|
1056 {
|
|
|
1057 RECT rcClient = {};
|
|
|
1058 this->GetClientRect(&rcClient);
|
|
|
1059 RECT rcArea = rcClient;
|
|
|
1060 T* pT = static_cast<T*>(this);
|
|
|
1061 (void)pT; // avoid level 4 warning
|
|
|
1062 ::InflateRect(&rcArea, -pT->m_cxOffset, -pT->m_cyOffset);
|
|
|
1063 if (rcArea.left > rcArea.right)
|
|
|
1064 rcArea.right = rcArea.left;
|
|
|
1065 if (rcArea.top > rcArea.bottom)
|
|
|
1066 rcArea.bottom = rcArea.top;
|
|
|
1067 this->GetPageRect(rcArea, &rc);
|
|
|
1068 HBRUSH hbrOld = dc.SelectBrush(::GetSysColorBrush(COLOR_BTNSHADOW));
|
|
|
1069 dc.PatBlt(rcClient.left, rcClient.top, rc.left - rcClient.left, rcClient.bottom - rcClient.top, PATCOPY);
|
|
|
1070 dc.PatBlt(rc.left, rcClient.top, rc.right - rc.left, rc.top - rcClient.top, PATCOPY);
|
|
|
1071 dc.PatBlt(rc.right, rcClient.top, rcClient.right - rc.right, rcClient.bottom - rcClient.top, PATCOPY);
|
|
|
1072 dc.PatBlt(rc.left, rc.bottom, rc.right - rc.left, rcClient.bottom - rc.bottom, PATCOPY);
|
|
|
1073 dc.SelectBrush((HBRUSH)::GetStockObject(WHITE_BRUSH));
|
|
|
1074 dc.PatBlt(rc.left, rc.top, rc.right - rc.left, rc.bottom - rc.top, PATCOPY);
|
|
|
1075 dc.SelectBrush(::GetSysColorBrush(COLOR_3DDKSHADOW));
|
|
|
1076 dc.PatBlt(rc.right, rc.top + 4, 4, rc.bottom - rc.top, PATCOPY);
|
|
|
1077 dc.PatBlt(rc.left + 4, rc.bottom, rc.right - rc.left, 4, PATCOPY);
|
|
|
1078 dc.SelectBrush(hbrOld);
|
|
|
1079 }
|
|
|
1080
|
|
|
1081 void DoPaint(CDCHandle dc, RECT& rc)
|
|
|
1082 {
|
|
|
1083 CEnhMetaFileInfo emfinfo(this->m_meta);
|
|
|
1084 ENHMETAHEADER* pmh = emfinfo.GetEnhMetaFileHeader();
|
|
|
1085 int nOffsetX = MulDiv(this->m_sizeCurPhysOffset.cx, rc.right-rc.left, pmh->szlDevice.cx);
|
|
|
1086 int nOffsetY = MulDiv(this->m_sizeCurPhysOffset.cy, rc.bottom-rc.top, pmh->szlDevice.cy);
|
|
|
1087
|
|
|
1088 dc.OffsetWindowOrg(-nOffsetX, -nOffsetY);
|
|
|
1089 dc.PlayMetaFile(this->m_meta, &rc);
|
|
|
1090 }
|
|
|
1091 };
|
|
|
1092
|
|
|
1093 class CZoomPrintPreviewWindow : public CZoomPrintPreviewWindowImpl<CZoomPrintPreviewWindow>
|
|
|
1094 {
|
|
|
1095 public:
|
|
|
1096 DECLARE_WND_CLASS_EX(_T("WTL_ZoomPrintPreview"), CS_VREDRAW | CS_HREDRAW, -1)
|
|
|
1097 };
|
|
|
1098
|
|
|
1099 #endif // __ATLSCRL_H__
|
|
|
1100
|
|
|
1101 } // namespace WTL
|
|
|
1102
|
|
|
1103 #endif // __ATLPRINT_H__
|