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