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