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