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