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