]> git.saurik.com Git - wxWidgets.git/blame - src/msw/printwin.cpp
allow changing the page from keyboard in property sheet like controls even when the...
[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
0c589ad0
BM
32 #include "wx/window.h"
33 #include "wx/msw/private.h"
103aec29
VZ
34 #include "wx/utils.h"
35 #include "wx/dc.h"
36 #include "wx/app.h"
37 #include "wx/msgdlg.h"
0c589ad0 38 #include "wx/intl.h"
e4db172a 39 #include "wx/log.h"
6d50343d 40 #include "wx/dcprint.h"
2bda0e17
KB
41#endif
42
43#include "wx/msw/printwin.h"
2bda0e17
KB
44#include "wx/printdlg.h"
45#include "wx/msw/private.h"
46
47#include <stdlib.h>
2bda0e17 48
660296aa 49#include "wx/msw/wrapcdlg.h"
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{
34da0970 78 m_lpAbortProc = (WXFARPROC) MakeProcInstance((FARPROC) wxAbortProc, wxGetInstance());
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
5cb598ae 109 wxDC *dc wxDUMMY_INITIALIZE(NULL);
7bcb11d3
JS
110 if (prompt)
111 {
112 dc = PrintDialog(parent);
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);
d6a1743b 151
7bcb11d3
JS
152 dc->GetSizeMM(&w, &h);
153 printout->SetPageSizeMM((int)w, (int)h);
103aec29 154
7bcb11d3 155 // Create an abort window
0f07e3dc 156 wxBusyCursor busyCursor;
103aec29 157
1044a386
JS
158 printout->OnPreparePrinting();
159
d2b354f9
JS
160 // Get some parameters from the printout, if defined
161 int fromPage, toPage;
162 int minPage, maxPage;
163 printout->GetPageInfo(&minPage, &maxPage, &fromPage, &toPage);
164
165 if (maxPage == 0)
166 {
167 sm_lastError = wxPRINTER_ERROR;
e41e579f 168 return false;
d2b354f9
JS
169 }
170
171 // Only set min and max, because from and to have been
172 // set by the user
173 m_printDialogData.SetMinPage(minPage);
174 m_printDialogData.SetMaxPage(maxPage);
175
7bcb11d3
JS
176 wxWindow *win = CreateAbortWindow(parent, printout);
177 wxYield();
103aec29 178
c34924f7 179#if defined(__WATCOMC__) || defined(__BORLANDC__) || defined(__GNUWIN32__) || defined(__SALFORDC__) || !defined(__WIN32__)
27a9bd48
PA
180#ifdef STRICT
181 ::SetAbortProc((HDC) dc->GetHDC(), (ABORTPROC) m_lpAbortProc);
182#else
7bcb11d3 183 ::SetAbortProc((HDC) dc->GetHDC(), (FARPROC) m_lpAbortProc);
27a9bd48 184#endif
7bcb11d3
JS
185#else
186 ::SetAbortProc((HDC) dc->GetHDC(), (int (_stdcall *)
187 // cast it to right type only if required
103aec29
VZ
188 // FIXME it's really cdecl and we're casting it to stdcall - either there is
189 // something I don't understand or it will crash at first usage
7bcb11d3
JS
190#ifdef STRICT
191 (HDC, int)
d6a1743b 192#else
7bcb11d3 193 ()
d6a1743b 194#endif
7bcb11d3
JS
195 )m_lpAbortProc);
196#endif
103aec29 197
7bcb11d3 198 if (!win)
2bda0e17 199 {
223d09f6 200 wxLogDebug(wxT("Could not create an abort dialog."));
f6bcfd97 201 sm_lastError = wxPRINTER_ERROR;
103aec29 202
7bcb11d3 203 delete dc;
e71693c3 204 return false;
2bda0e17 205 }
7bcb11d3 206 sm_abortWindow = win;
e41e579f 207 sm_abortWindow->Show();
103aec29
VZ
208 wxSafeYield();
209
7bcb11d3 210 printout->OnBeginPrinting();
103aec29 211
f6bcfd97
BP
212 sm_lastError = wxPRINTER_NO_ERROR;
213
e41e579f
DS
214 int minPageNum = minPage, maxPageNum = maxPage;
215
216 if ( !m_printDialogData.GetAllPages() )
e41e579f
DS
217 {
218 minPageNum = m_printDialogData.GetFromPage();
219 maxPageNum = m_printDialogData.GetToPage();
220 }
221
7bcb11d3 222 int copyCount;
70846f0a
VZ
223 for ( copyCount = 1;
224 copyCount <= m_printDialogData.GetNoCopies();
225 copyCount++ )
7bcb11d3 226 {
e41e579f 227 if ( !printout->OnBeginDocument(minPageNum, maxPageNum) )
7bcb11d3 228 {
103aec29 229 wxLogError(_("Could not start printing."));
f6bcfd97 230 sm_lastError = wxPRINTER_ERROR;
7bcb11d3
JS
231 break;
232 }
233 if (sm_abortIt)
f6bcfd97
BP
234 {
235 sm_lastError = wxPRINTER_CANCELLED;
7bcb11d3 236 break;
f6bcfd97 237 }
103aec29 238
7bcb11d3 239 int pn;
e41e579f
DS
240
241 for ( pn = minPageNum;
242 pn <= maxPageNum && printout->HasPage(pn);
70846f0a 243 pn++ )
7bcb11d3 244 {
70846f0a 245 if ( sm_abortIt )
7bcb11d3 246 {
f6bcfd97 247 sm_lastError = wxPRINTER_CANCELLED;
7bcb11d3
JS
248 break;
249 }
70846f0a
VZ
250
251 dc->StartPage();
252 bool cont = printout->OnPrintPage(pn);
253 dc->EndPage();
254
255 if ( !cont )
f6bcfd97
BP
256 {
257 sm_lastError = wxPRINTER_CANCELLED;
70846f0a 258 break;
f6bcfd97 259 }
7bcb11d3 260 }
70846f0a 261
7bcb11d3
JS
262 printout->OnEndDocument();
263 }
103aec29 264
7bcb11d3 265 printout->OnEndPrinting();
103aec29 266
7bcb11d3 267 if (sm_abortWindow)
2bda0e17 268 {
e41e579f 269 sm_abortWindow->Show(false);
7bcb11d3
JS
270 delete sm_abortWindow;
271 sm_abortWindow = NULL;
2bda0e17 272 }
103aec29 273
7bcb11d3 274 delete dc;
103aec29 275
e71693c3 276 return sm_lastError == wxPRINTER_NO_ERROR;
7bcb11d3 277}
2bda0e17 278
7bcb11d3
JS
279wxDC* wxWindowsPrinter::PrintDialog(wxWindow *parent)
280{
281 wxDC* dc = (wxDC*) NULL;
2bda0e17 282
7bcb11d3
JS
283 wxPrintDialog dialog(parent, & m_printDialogData);
284 int ret = dialog.ShowModal();
2bda0e17 285
7bcb11d3
JS
286 if (ret == wxID_OK)
287 {
288 dc = dialog.GetPrintDC();
289 m_printDialogData = dialog.GetPrintDialogData();
33ac7e6f 290 if (dc == NULL)
f6bcfd97
BP
291 sm_lastError = wxPRINTER_ERROR;
292 else
293 sm_lastError = wxPRINTER_NO_ERROR;
7bcb11d3 294 }
f6bcfd97
BP
295 else
296 sm_lastError = wxPRINTER_CANCELLED;
2bda0e17 297
7bcb11d3 298 return dc;
2bda0e17
KB
299}
300
a12f001e 301bool wxWindowsPrinter::Setup(wxWindow *WXUNUSED(parent))
2bda0e17 302{
b45dfd0a
RR
303#if 0
304 // We no longer expose that dialog
7bcb11d3 305 wxPrintDialog dialog(parent, & m_printDialogData);
e41e579f 306 dialog.GetPrintDialogData().SetSetupDialog(true);
7bcb11d3
JS
307
308 int ret = dialog.ShowModal();
309
310 if (ret == wxID_OK)
311 {
312 m_printDialogData = dialog.GetPrintDialogData();
313 }
314
315 return (ret == wxID_OK);
b45dfd0a 316#else
3950f9e1 317 return false;
b45dfd0a 318#endif
2bda0e17
KB
319}
320
321/*
7bcb11d3
JS
322* Print preview
323*/
2bda0e17 324
103aec29
VZ
325wxWindowsPrintPreview::wxWindowsPrintPreview(wxPrintout *printout,
326 wxPrintout *printoutForPrinting,
327 wxPrintDialogData *data)
328 : wxPrintPreviewBase(printout, printoutForPrinting, data)
2bda0e17 329{
7bcb11d3 330 DetermineScaling();
2bda0e17
KB
331}
332
103aec29
VZ
333wxWindowsPrintPreview::wxWindowsPrintPreview(wxPrintout *printout,
334 wxPrintout *printoutForPrinting,
335 wxPrintData *data)
336 : wxPrintPreviewBase(printout, printoutForPrinting, data)
337{
338 DetermineScaling();
339}
340
341wxWindowsPrintPreview::~wxWindowsPrintPreview()
2bda0e17
KB
342{
343}
344
345bool wxWindowsPrintPreview::Print(bool interactive)
346{
7bcb11d3 347 if (!m_printPrintout)
e41e579f 348 return false;
7bcb11d3
JS
349 wxWindowsPrinter printer(&m_printDialogData);
350 return printer.Print(m_previewFrame, m_printPrintout, interactive);
2bda0e17
KB
351}
352
103aec29 353void wxWindowsPrintPreview::DetermineScaling()
2bda0e17 354{
f2a59080 355 ScreenHDC dc;
2bda0e17 356 int screenWidth = ::GetDeviceCaps(dc, HORZSIZE);
f2a59080 357 int screenXRes = ::GetDeviceCaps(dc, HORZRES);
2bda0e17
KB
358 int logPPIScreenX = ::GetDeviceCaps(dc, LOGPIXELSX);
359 int logPPIScreenY = ::GetDeviceCaps(dc, LOGPIXELSY);
34da0970 360 m_previewPrintout->SetPPIScreen(logPPIScreenX, logPPIScreenY);
103aec29 361
103aec29 362
2bda0e17 363 // Get a device context for the currently selected printer
7bcb11d3 364 wxPrinterDC printerDC(m_printDialogData.GetPrintData());
103aec29 365
2bda0e17 366 int printerWidth = 150;
2bda0e17
KB
367 int printerXRes = 1500;
368 int printerYRes = 2500;
103aec29 369
f2a59080 370 if ( printerDC.Ok() )
2bda0e17 371 {
f2a59080
VZ
372 HDC dc = GetHdcOf(printerDC);
373
f4fefc23 374 printerWidth = ::GetDeviceCaps(dc, HORZSIZE);
f2a59080 375 int printerHeight = ::GetDeviceCaps(dc, VERTSIZE);
f4fefc23
VZ
376 printerXRes = ::GetDeviceCaps(dc, HORZRES);
377 printerYRes = ::GetDeviceCaps(dc, VERTRES);
103aec29 378
f4fefc23
VZ
379 int logPPIPrinterX = ::GetDeviceCaps(dc, LOGPIXELSX);
380 int logPPIPrinterY = ::GetDeviceCaps(dc, LOGPIXELSY);
103aec29 381
7bcb11d3
JS
382 m_previewPrintout->SetPPIPrinter(logPPIPrinterX, logPPIPrinterY);
383 m_previewPrintout->SetPageSizeMM(printerWidth, printerHeight);
103aec29 384
f2a59080
VZ
385 if ( logPPIPrinterX == 0 ||
386 logPPIPrinterY == 0 ||
387 printerWidth == 0 ||
388 printerHeight == 0 )
389 {
e41e579f 390 m_isOk = false;
f2a59080 391 }
2bda0e17
KB
392 }
393 else
f2a59080 394 {
e41e579f 395 m_isOk = false;
f2a59080 396 }
103aec29 397
34da0970
JS
398 m_pageWidth = printerXRes;
399 m_pageHeight = printerYRes;
103aec29 400
2bda0e17 401 // At 100%, the page should look about page-size on the screen.
f2a59080
VZ
402 //
403 // TODO: the scale could be different in vertical and horizontal directions
404 float screenDPI = (float)screenXRes / screenWidth;
405 float printerDPI = (float)printerXRes / printerWidth;
406
407 m_previewScale = screenDPI / printerDPI;
2bda0e17
KB
408}
409
410/****************************************************************************
411
7bcb11d3 412 FUNCTION: wxAbortProc()
103aec29 413
2bda0e17 414 PURPOSE: Processes messages for the Abort Dialog box
103aec29 415
2bda0e17
KB
416****************************************************************************/
417
418LONG APIENTRY _EXPORT wxAbortProc(HDC WXUNUSED(hPr), int WXUNUSED(Code))
419{
420 MSG msg;
103aec29 421
34da0970 422 if (!wxPrinterBase::sm_abortWindow) /* If the abort dialog isn't up yet */
2bda0e17 423 return(TRUE);
103aec29 424
2bda0e17 425 /* Process messages intended for the abort dialog box */
103aec29 426
078cf5cb 427 while (!wxPrinterBase::sm_abortIt && ::PeekMessage(&msg, 0, 0, 0, TRUE))
34da0970 428 if (!IsDialogMessage((HWND) wxPrinterBase::sm_abortWindow->GetHWND(), &msg)) {
2bda0e17
KB
429 TranslateMessage(&msg);
430 DispatchMessage(&msg);
431 }
103aec29 432
e71693c3 433 /* bAbort is TRUE (return is FALSE) if the user has aborted */
103aec29 434
e71693c3 435 return !wxPrinterBase::sm_abortIt;
2bda0e17
KB
436}
437
f6bcfd97
BP
438#endif
439 // wxUSE_PRINTING_ARCHITECTURE