]> git.saurik.com Git - wxWidgets.git/blame - src/msw/printwin.cpp
Fixed wxAtomicInc/Dec() to not use asm/atomic.h header on Linux - it's kernel interna...
[wxWidgets.git] / src / msw / printwin.cpp
CommitLineData
2bda0e17 1/////////////////////////////////////////////////////////////////////////////
7520f3da 2// Name: src/msw/printwin.cpp
2bda0e17
KB
3// Purpose: wxWindowsPrinter framework
4// Author: Julian Smart
5// Modified by:
6// Created: 04/01/98
7// RCS-ID: $Id$
6c9a19aa 8// Copyright: (c) Julian Smart
65571936 9// Licence: wxWindows licence
2bda0e17
KB
10/////////////////////////////////////////////////////////////////////////////
11
103aec29
VZ
12// ===========================================================================
13// declarations
14// ===========================================================================
15
16// ---------------------------------------------------------------------------
17// headers
18// ---------------------------------------------------------------------------
19
2bda0e17
KB
20// For compilers that support precompilation, includes "wx.h".
21#include "wx/wxprec.h"
22
23#ifdef __BORLANDC__
103aec29 24 #pragma hdrstop
2bda0e17
KB
25#endif
26
12bdd77c
JS
27// Don't use the Windows printer if we're in wxUniv mode and using
28// the PostScript architecture
29#if wxUSE_PRINTING_ARCHITECTURE && (!defined(__WXUNIVERSAL__) || !wxUSE_POSTSCRIPT_ARCHITECTURE_IN_MSW)
f6bcfd97 30
2bda0e17 31#ifndef WX_PRECOMP
57bd4c60 32 #include "wx/msw/wrapcdlg.h"
0c589ad0
BM
33 #include "wx/window.h"
34 #include "wx/msw/private.h"
103aec29
VZ
35 #include "wx/utils.h"
36 #include "wx/dc.h"
37 #include "wx/app.h"
38 #include "wx/msgdlg.h"
0c589ad0 39 #include "wx/intl.h"
e4db172a 40 #include "wx/log.h"
6d50343d 41 #include "wx/dcprint.h"
2bda0e17
KB
42#endif
43
44#include "wx/msw/printwin.h"
f4322df6 45#include "wx/msw/printdlg.h"
2bda0e17
KB
46#include "wx/msw/private.h"
47
48#include <stdlib.h>
2bda0e17 49
2bda0e17 50#ifndef __WIN32__
103aec29 51 #include <print.h>
2bda0e17
KB
52#endif
53
103aec29
VZ
54// ---------------------------------------------------------------------------
55// private functions
56// ---------------------------------------------------------------------------
57
2bda0e17
KB
58LONG APIENTRY _EXPORT wxAbortProc(HDC hPr, int Code);
59
103aec29
VZ
60// ---------------------------------------------------------------------------
61// wxWin macros
62// ---------------------------------------------------------------------------
63
103aec29
VZ
64 IMPLEMENT_DYNAMIC_CLASS(wxWindowsPrinter, wxPrinterBase)
65 IMPLEMENT_CLASS(wxWindowsPrintPreview, wxPrintPreviewBase)
2bda0e17 66
103aec29
VZ
67// ===========================================================================
68// implementation
69// ===========================================================================
70
71// ---------------------------------------------------------------------------
72// Printer
73// ---------------------------------------------------------------------------
7bcb11d3 74
103aec29
VZ
75wxWindowsPrinter::wxWindowsPrinter(wxPrintDialogData *data)
76 : wxPrinterBase(data)
2bda0e17 77{
d6f2a891 78 m_lpAbortProc = (WXFARPROC)wxAbortProc;
2bda0e17
KB
79}
80
103aec29 81wxWindowsPrinter::~wxWindowsPrinter()
2bda0e17 82{
33ac7e6f 83 // avoids warning about statement with no effect (FreeProcInstance
e41e579f 84 // doesn't do anything under Win32)
d66dcb60 85#if !defined(__WIN32__) && !defined(__NT__)
34da0970 86 FreeProcInstance((FARPROC) m_lpAbortProc);
a17e237f 87#endif
2bda0e17
KB
88}
89
90bool wxWindowsPrinter::Print(wxWindow *parent, wxPrintout *printout, bool prompt)
91{
e41e579f 92 sm_abortIt = false;
7bcb11d3 93 sm_abortWindow = NULL;
103aec29 94
7bcb11d3 95 if (!printout)
f6bcfd97
BP
96 {
97 sm_lastError = wxPRINTER_ERROR;
e41e579f 98 return false;
f6bcfd97 99 }
103aec29 100
e41e579f 101 printout->SetIsPreview(false);
1044a386 102
d2b354f9
JS
103 if (m_printDialogData.GetMinPage() < 1)
104 m_printDialogData.SetMinPage(1);
105 if (m_printDialogData.GetMaxPage() < 1)
106 m_printDialogData.SetMaxPage(9999);
2bda0e17 107
103aec29 108 // Create a suitable device context
f415cab9 109 wxPrinterDC *dc wxDUMMY_INITIALIZE(NULL);
7bcb11d3
JS
110 if (prompt)
111 {
f415cab9 112 dc = wxDynamicCast(PrintDialog(parent), wxPrinterDC);
7bcb11d3 113 if (!dc)
e41e579f 114 return false;
7bcb11d3
JS
115 }
116 else
117 {
7bcb11d3
JS
118 dc = new wxPrinterDC(m_printDialogData.GetPrintData());
119 }
103aec29 120
7bcb11d3
JS
121 // May have pressed cancel.
122 if (!dc || !dc->Ok())
123 {
124 if (dc) delete dc;
e41e579f 125 return false;
7bcb11d3 126 }
103aec29 127
7bcb11d3 128 HDC hdc = ::GetDC(NULL);
5cb598ae
WS
129 int logPPIScreenX = ::GetDeviceCaps(hdc, LOGPIXELSX);
130 int logPPIScreenY = ::GetDeviceCaps(hdc, LOGPIXELSY);
7bcb11d3 131 ::ReleaseDC(NULL, hdc);
103aec29 132
5cb598ae
WS
133 int logPPIPrinterX = ::GetDeviceCaps((HDC) dc->GetHDC(), LOGPIXELSX);
134 int logPPIPrinterY = ::GetDeviceCaps((HDC) dc->GetHDC(), LOGPIXELSY);
7bcb11d3
JS
135 if (logPPIPrinterX == 0 || logPPIPrinterY == 0)
136 {
137 delete dc;
f6bcfd97 138 sm_lastError = wxPRINTER_ERROR;
e41e579f 139 return false;
7bcb11d3 140 }
103aec29 141
7bcb11d3
JS
142 printout->SetPPIScreen(logPPIScreenX, logPPIScreenY);
143 printout->SetPPIPrinter(logPPIPrinterX, logPPIPrinterY);
103aec29
VZ
144
145 // Set printout parameters
7bcb11d3 146 printout->SetDC(dc);
103aec29 147
7bcb11d3
JS
148 int w, h;
149 dc->GetSize(&w, &h);
150 printout->SetPageSizePixels((int)w, (int)h);
f415cab9 151 printout->SetPaperRectPixels(dc->GetPaperRect());
d6a1743b 152
7bcb11d3
JS
153 dc->GetSizeMM(&w, &h);
154 printout->SetPageSizeMM((int)w, (int)h);
103aec29 155
7bcb11d3 156 // Create an abort window
0f07e3dc 157 wxBusyCursor busyCursor;
103aec29 158
1044a386
JS
159 printout->OnPreparePrinting();
160
d2b354f9
JS
161 // Get some parameters from the printout, if defined
162 int fromPage, toPage;
163 int minPage, maxPage;
164 printout->GetPageInfo(&minPage, &maxPage, &fromPage, &toPage);
165
166 if (maxPage == 0)
167 {
168 sm_lastError = wxPRINTER_ERROR;
e41e579f 169 return false;
d2b354f9
JS
170 }
171
172 // Only set min and max, because from and to have been
173 // set by the user
174 m_printDialogData.SetMinPage(minPage);
175 m_printDialogData.SetMaxPage(maxPage);
176
7bcb11d3
JS
177 wxWindow *win = CreateAbortWindow(parent, printout);
178 wxYield();
103aec29 179
c34924f7 180#if defined(__WATCOMC__) || defined(__BORLANDC__) || defined(__GNUWIN32__) || defined(__SALFORDC__) || !defined(__WIN32__)
27a9bd48
PA
181#ifdef STRICT
182 ::SetAbortProc((HDC) dc->GetHDC(), (ABORTPROC) m_lpAbortProc);
183#else
7bcb11d3 184 ::SetAbortProc((HDC) dc->GetHDC(), (FARPROC) m_lpAbortProc);
27a9bd48 185#endif
7bcb11d3
JS
186#else
187 ::SetAbortProc((HDC) dc->GetHDC(), (int (_stdcall *)
188 // cast it to right type only if required
103aec29
VZ
189 // FIXME it's really cdecl and we're casting it to stdcall - either there is
190 // something I don't understand or it will crash at first usage
7bcb11d3
JS
191#ifdef STRICT
192 (HDC, int)
d6a1743b 193#else
7bcb11d3 194 ()
d6a1743b 195#endif
7bcb11d3
JS
196 )m_lpAbortProc);
197#endif
103aec29 198
7bcb11d3 199 if (!win)
2bda0e17 200 {
223d09f6 201 wxLogDebug(wxT("Could not create an abort dialog."));
f6bcfd97 202 sm_lastError = wxPRINTER_ERROR;
103aec29 203
7bcb11d3 204 delete dc;
e71693c3 205 return false;
2bda0e17 206 }
7bcb11d3 207 sm_abortWindow = win;
e41e579f 208 sm_abortWindow->Show();
103aec29
VZ
209 wxSafeYield();
210
7bcb11d3 211 printout->OnBeginPrinting();
103aec29 212
f6bcfd97
BP
213 sm_lastError = wxPRINTER_NO_ERROR;
214
e41e579f
DS
215 int minPageNum = minPage, maxPageNum = maxPage;
216
217 if ( !m_printDialogData.GetAllPages() )
e41e579f
DS
218 {
219 minPageNum = m_printDialogData.GetFromPage();
220 maxPageNum = m_printDialogData.GetToPage();
221 }
222
7bcb11d3 223 int copyCount;
70846f0a
VZ
224 for ( copyCount = 1;
225 copyCount <= m_printDialogData.GetNoCopies();
226 copyCount++ )
7bcb11d3 227 {
e41e579f 228 if ( !printout->OnBeginDocument(minPageNum, maxPageNum) )
7bcb11d3 229 {
103aec29 230 wxLogError(_("Could not start printing."));
f6bcfd97 231 sm_lastError = wxPRINTER_ERROR;
7bcb11d3
JS
232 break;
233 }
234 if (sm_abortIt)
f6bcfd97
BP
235 {
236 sm_lastError = wxPRINTER_CANCELLED;
7bcb11d3 237 break;
f6bcfd97 238 }
103aec29 239
7bcb11d3 240 int pn;
e41e579f
DS
241
242 for ( pn = minPageNum;
243 pn <= maxPageNum && printout->HasPage(pn);
70846f0a 244 pn++ )
7bcb11d3 245 {
70846f0a 246 if ( sm_abortIt )
7bcb11d3 247 {
f6bcfd97 248 sm_lastError = wxPRINTER_CANCELLED;
7bcb11d3
JS
249 break;
250 }
70846f0a
VZ
251
252 dc->StartPage();
253 bool cont = printout->OnPrintPage(pn);
254 dc->EndPage();
255
256 if ( !cont )
f6bcfd97
BP
257 {
258 sm_lastError = wxPRINTER_CANCELLED;
70846f0a 259 break;
f6bcfd97 260 }
7bcb11d3 261 }
70846f0a 262
7bcb11d3
JS
263 printout->OnEndDocument();
264 }
103aec29 265
7bcb11d3 266 printout->OnEndPrinting();
103aec29 267
7bcb11d3 268 if (sm_abortWindow)
2bda0e17 269 {
e41e579f 270 sm_abortWindow->Show(false);
7bcb11d3
JS
271 delete sm_abortWindow;
272 sm_abortWindow = NULL;
2bda0e17 273 }
103aec29 274
7bcb11d3 275 delete dc;
103aec29 276
e71693c3 277 return sm_lastError == wxPRINTER_NO_ERROR;
7bcb11d3 278}
2bda0e17 279
f415cab9 280wxDC *wxWindowsPrinter::PrintDialog(wxWindow *parent)
7bcb11d3 281{
f415cab9 282 wxDC *dc = (wxPrinterDC*) NULL;
2bda0e17 283
f415cab9 284 wxWindowsPrintDialog dialog(parent, & m_printDialogData);
7bcb11d3 285 int ret = dialog.ShowModal();
2bda0e17 286
7bcb11d3
JS
287 if (ret == wxID_OK)
288 {
289 dc = dialog.GetPrintDC();
290 m_printDialogData = dialog.GetPrintDialogData();
33ac7e6f 291 if (dc == NULL)
f6bcfd97
BP
292 sm_lastError = wxPRINTER_ERROR;
293 else
294 sm_lastError = wxPRINTER_NO_ERROR;
7bcb11d3 295 }
f6bcfd97
BP
296 else
297 sm_lastError = wxPRINTER_CANCELLED;
2bda0e17 298
7bcb11d3 299 return dc;
2bda0e17
KB
300}
301
a12f001e 302bool wxWindowsPrinter::Setup(wxWindow *WXUNUSED(parent))
2bda0e17 303{
b45dfd0a
RR
304#if 0
305 // We no longer expose that dialog
7bcb11d3 306 wxPrintDialog dialog(parent, & m_printDialogData);
e41e579f 307 dialog.GetPrintDialogData().SetSetupDialog(true);
7bcb11d3
JS
308
309 int ret = dialog.ShowModal();
310
311 if (ret == wxID_OK)
312 {
313 m_printDialogData = dialog.GetPrintDialogData();
314 }
315
316 return (ret == wxID_OK);
b45dfd0a 317#else
3950f9e1 318 return false;
b45dfd0a 319#endif
2bda0e17
KB
320}
321
322/*
7bcb11d3
JS
323* Print preview
324*/
2bda0e17 325
103aec29
VZ
326wxWindowsPrintPreview::wxWindowsPrintPreview(wxPrintout *printout,
327 wxPrintout *printoutForPrinting,
328 wxPrintDialogData *data)
329 : wxPrintPreviewBase(printout, printoutForPrinting, data)
2bda0e17 330{
7bcb11d3 331 DetermineScaling();
2bda0e17
KB
332}
333
103aec29
VZ
334wxWindowsPrintPreview::wxWindowsPrintPreview(wxPrintout *printout,
335 wxPrintout *printoutForPrinting,
336 wxPrintData *data)
337 : wxPrintPreviewBase(printout, printoutForPrinting, data)
338{
339 DetermineScaling();
340}
341
342wxWindowsPrintPreview::~wxWindowsPrintPreview()
2bda0e17
KB
343{
344}
345
346bool wxWindowsPrintPreview::Print(bool interactive)
347{
7bcb11d3 348 if (!m_printPrintout)
e41e579f 349 return false;
7bcb11d3
JS
350 wxWindowsPrinter printer(&m_printDialogData);
351 return printer.Print(m_previewFrame, m_printPrintout, interactive);
2bda0e17
KB
352}
353
103aec29 354void wxWindowsPrintPreview::DetermineScaling()
2bda0e17 355{
f2a59080 356 ScreenHDC dc;
2bda0e17
KB
357 int logPPIScreenX = ::GetDeviceCaps(dc, LOGPIXELSX);
358 int logPPIScreenY = ::GetDeviceCaps(dc, LOGPIXELSY);
34da0970 359 m_previewPrintout->SetPPIScreen(logPPIScreenX, logPPIScreenY);
103aec29 360
2bda0e17 361 // Get a device context for the currently selected printer
7bcb11d3 362 wxPrinterDC printerDC(m_printDialogData.GetPrintData());
103aec29 363
f415cab9
JS
364 int printerWidthMM;
365 int printerHeightMM;
366 int printerXRes;
367 int printerYRes;
368 int logPPIPrinterX;
369 int logPPIPrinterY;
370
f4322df6 371 wxRect paperRect;
103aec29 372
f2a59080 373 if ( printerDC.Ok() )
2bda0e17 374 {
f2a59080 375 HDC dc = GetHdcOf(printerDC);
f415cab9
JS
376 printerWidthMM = ::GetDeviceCaps(dc, HORZSIZE);
377 printerHeightMM = ::GetDeviceCaps(dc, VERTSIZE);
f4fefc23
VZ
378 printerXRes = ::GetDeviceCaps(dc, HORZRES);
379 printerYRes = ::GetDeviceCaps(dc, VERTRES);
f415cab9
JS
380 logPPIPrinterX = ::GetDeviceCaps(dc, LOGPIXELSX);
381 logPPIPrinterY = ::GetDeviceCaps(dc, LOGPIXELSY);
103aec29 382
f4322df6 383 paperRect = printerDC.GetPaperRect();
103aec29 384
f2a59080
VZ
385 if ( logPPIPrinterX == 0 ||
386 logPPIPrinterY == 0 ||
f415cab9
JS
387 printerWidthMM == 0 ||
388 printerHeightMM == 0 )
f2a59080 389 {
e41e579f 390 m_isOk = false;
f2a59080 391 }
2bda0e17
KB
392 }
393 else
f2a59080 394 {
f415cab9
JS
395 // use some defaults
396 printerWidthMM = 150;
397 printerHeightMM = 250;
398 printerXRes = 1500;
399 printerYRes = 2500;
400 logPPIPrinterX = 600;
401 logPPIPrinterY = 600;
402
f4322df6 403 paperRect = wxRect(0, 0, printerXRes, printerYRes);
e41e579f 404 m_isOk = false;
f2a59080 405 }
34da0970
JS
406 m_pageWidth = printerXRes;
407 m_pageHeight = printerYRes;
f415cab9
JS
408 m_previewPrintout->SetPageSizePixels(printerXRes, printerYRes);
409 m_previewPrintout->SetPageSizeMM(printerWidthMM, printerHeightMM);
410 m_previewPrintout->SetPaperRectPixels(paperRect);
411 m_previewPrintout->SetPPIPrinter(logPPIPrinterX, logPPIPrinterY);
103aec29 412
2bda0e17 413 // At 100%, the page should look about page-size on the screen.
f415cab9
JS
414 m_previewScaleX = float(logPPIScreenX) / logPPIPrinterX;
415 m_previewScaleY = float(logPPIScreenY) / logPPIPrinterY;
2bda0e17
KB
416}
417
418/****************************************************************************
419
7bcb11d3 420 FUNCTION: wxAbortProc()
103aec29 421
2bda0e17 422 PURPOSE: Processes messages for the Abort Dialog box
103aec29 423
2bda0e17
KB
424****************************************************************************/
425
426LONG APIENTRY _EXPORT wxAbortProc(HDC WXUNUSED(hPr), int WXUNUSED(Code))
427{
428 MSG msg;
103aec29 429
34da0970 430 if (!wxPrinterBase::sm_abortWindow) /* If the abort dialog isn't up yet */
2bda0e17 431 return(TRUE);
103aec29 432
2bda0e17 433 /* Process messages intended for the abort dialog box */
103aec29 434
078cf5cb 435 while (!wxPrinterBase::sm_abortIt && ::PeekMessage(&msg, 0, 0, 0, TRUE))
34da0970 436 if (!IsDialogMessage((HWND) wxPrinterBase::sm_abortWindow->GetHWND(), &msg)) {
2bda0e17
KB
437 TranslateMessage(&msg);
438 DispatchMessage(&msg);
439 }
103aec29 440
e71693c3 441 /* bAbort is TRUE (return is FALSE) if the user has aborted */
103aec29 442
e71693c3 443 return !wxPrinterBase::sm_abortIt;
2bda0e17
KB
444}
445
f6bcfd97
BP
446#endif
447 // wxUSE_PRINTING_ARCHITECTURE