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