]> git.saurik.com Git - wxWidgets.git/blame - src/msw/printwin.cpp
Cured some Motif bugs
[wxWidgets.git] / src / msw / printwin.cpp
CommitLineData
2bda0e17
KB
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 and Markus Holzem
9// Licence: wxWindows license
10/////////////////////////////////////////////////////////////////////////////
11
12#ifdef __GNUG__
13#pragma implementation "printwin.h"
14#endif
15
16// For compilers that support precompilation, includes "wx.h".
17#include "wx/wxprec.h"
18
19#ifdef __BORLANDC__
20#pragma hdrstop
21#endif
22
23#include "wx/defs.h"
24
2bda0e17
KB
25#ifndef WX_PRECOMP
26#include "wx/utils.h"
27#include "wx/dc.h"
28#include "wx/app.h"
29#include "wx/msgdlg.h"
30#endif
31
32#include "wx/msw/printwin.h"
33#include "wx/dcprint.h"
34#include "wx/printdlg.h"
35#include "wx/msw/private.h"
36
37#include <stdlib.h>
38#include <windows.h>
39#include <commdlg.h>
40
41// Clash with Windows header files
42#ifdef StartDoc
43#undef StartDoc
44#endif
45
46#ifndef __WIN32__
47#include <print.h>
48#endif
49
50LONG APIENTRY _EXPORT wxAbortProc(HDC hPr, int Code);
51
52#if !USE_SHARED_LIBRARY
53IMPLEMENT_DYNAMIC_CLASS(wxWindowsPrinter, wxPrinterBase)
54IMPLEMENT_CLASS(wxWindowsPrintPreview, wxPrintPreviewBase)
55#endif
56
57/*
58 * Printer
59 */
60
61wxWindowsPrinter::wxWindowsPrinter(wxPrintData *data):
62 wxPrinterBase(data)
63{
34da0970 64 m_lpAbortProc = (WXFARPROC) MakeProcInstance((FARPROC) wxAbortProc, wxGetInstance());
2bda0e17
KB
65}
66
67wxWindowsPrinter::~wxWindowsPrinter(void)
68{
34da0970 69 FreeProcInstance((FARPROC) m_lpAbortProc);
2bda0e17
KB
70}
71
72bool wxWindowsPrinter::Print(wxWindow *parent, wxPrintout *printout, bool prompt)
73{
34da0970
JS
74 sm_abortIt = FALSE;
75 sm_abortWindow = NULL;
2bda0e17
KB
76
77 if (!printout)
78 return FALSE;
79
80 printout->SetIsPreview(FALSE);
81 printout->OnPreparePrinting();
82
83 // Get some parameters from the printout, if defined
84 int fromPage, toPage;
85 int minPage, maxPage;
86 printout->GetPageInfo(&minPage, &maxPage, &fromPage, &toPage);
87
88 if (maxPage == 0)
89 return FALSE;
90
34da0970
JS
91 m_printData.SetMinPage(minPage);
92 m_printData.SetMaxPage(maxPage);
2bda0e17 93 if (fromPage != 0)
34da0970 94 m_printData.SetFromPage(fromPage);
2bda0e17 95 if (toPage != 0)
34da0970 96 m_printData.SetToPage(toPage);
2bda0e17
KB
97
98 if (minPage != 0)
99 {
34da0970
JS
100 m_printData.EnablePageNumbers(TRUE);
101 if (m_printData.GetFromPage() < m_printData.GetMinPage())
102 m_printData.SetFromPage(m_printData.GetMinPage());
103 else if (m_printData.GetFromPage() > m_printData.GetMaxPage())
104 m_printData.SetFromPage(m_printData.GetMaxPage());
105 if (m_printData.GetToPage() > m_printData.GetMaxPage())
106 m_printData.SetToPage(m_printData.GetMaxPage());
107 else if (m_printData.GetToPage() < m_printData.GetMinPage())
108 m_printData.SetToPage(m_printData.GetMinPage());
2bda0e17
KB
109 }
110 else
34da0970
JS
111 m_printData.EnablePageNumbers(FALSE);
112
2bda0e17
KB
113 // Create a suitable device context
114 wxDC *dc = NULL;
115 if (prompt)
116 {
34da0970 117 wxPrintDialog dialog(parent, & m_printData);
2bda0e17
KB
118 if (dialog.ShowModal() == wxID_OK)
119 {
120 dc = dialog.GetPrintDC();
34da0970 121 m_printData = dialog.GetPrintData();
2bda0e17
KB
122 }
123 }
124 else
125 {
34da0970 126 dc = new wxPrinterDC("", "", "", FALSE, m_printData.GetOrientation());
2bda0e17
KB
127 }
128
129 // May have pressed cancel.
130 if (!dc || !dc->Ok())
131 {
132 if (dc) delete dc;
133 return FALSE;
134 }
135
136 int logPPIScreenX = 0;
137 int logPPIScreenY = 0;
138 int logPPIPrinterX = 0;
139 int logPPIPrinterY = 0;
140
141 HDC hdc = ::GetDC(NULL);
142 logPPIScreenX = ::GetDeviceCaps(hdc, LOGPIXELSX);
143 logPPIScreenY = ::GetDeviceCaps(hdc, LOGPIXELSY);
144 ::ReleaseDC(NULL, hdc);
145
146 logPPIPrinterX = ::GetDeviceCaps((HDC) dc->GetHDC(), LOGPIXELSX);
147 logPPIPrinterY = ::GetDeviceCaps((HDC) dc->GetHDC(), LOGPIXELSY);
148 if (logPPIPrinterX == 0 || logPPIPrinterY == 0)
149 {
150 delete dc;
151 return FALSE;
152 }
153
154 printout->SetPPIScreen(logPPIScreenX, logPPIScreenY);
155 printout->SetPPIPrinter(logPPIPrinterX, logPPIPrinterY);
156
157 // Set printout parameters
158 printout->SetDC(dc);
159
160 int w, h;
161 long ww, hh;
162 dc->GetSize(&w, &h);
163 printout->SetPageSizePixels((int)w, (int)h);
164 dc->GetSizeMM(&ww, &hh);
165 printout->SetPageSizeMM((int)ww, (int)hh);
166
167 // Create an abort window
168 wxBeginBusyCursor();
169
170 wxWindow *win = CreateAbortWindow(parent, printout);
171 wxYield();
d6a1743b 172
ce3ed50d 173#if defined(__BORLANDC__) || defined(__GNUWIN32__) || defined(__SALFORDC__) || !defined(__WIN32__)
34da0970 174 ::SetAbortProc((HDC) dc->GetHDC(), (FARPROC) m_lpAbortProc);
d6a1743b 175#else
c83d505a
VZ
176 ::SetAbortProc((HDC) dc->GetHDC(), (int (_stdcall *)
177 // cast it to right type only if required
178 // @@@ it's really cdecl and we're casting it to stdcall - either there is
179 // something I don't understand or it will crash at first usage
180 #ifdef STRICT
181 (HDC, int)
182 #else
183 ()
184 #endif
34da0970 185 )m_lpAbortProc);
d6a1743b 186#endif
2bda0e17
KB
187
188 if (!win)
189 {
190 wxEndBusyCursor();
191 wxMessageBox("Sorry, could not create an abort dialog.", "Print Error", wxOK, parent);
192 delete dc;
193 }
34da0970
JS
194 sm_abortWindow = win;
195 sm_abortWindow->Show(TRUE);
2bda0e17
KB
196 wxYield();
197
198 printout->OnBeginPrinting();
199
200 bool keepGoing = TRUE;
201
202 int copyCount;
34da0970 203 for (copyCount = 1; copyCount <= m_printData.GetNoCopies(); copyCount ++)
2bda0e17 204 {
34da0970 205 if (!printout->OnBeginDocument(m_printData.GetFromPage(), m_printData.GetToPage()))
2bda0e17
KB
206 {
207 wxEndBusyCursor();
208 wxMessageBox("Could not start printing.", "Print Error", wxOK, parent);
209 break;
210 }
34da0970 211 if (sm_abortIt)
2bda0e17
KB
212 break;
213
214 int pn;
34da0970 215 for (pn = m_printData.GetFromPage(); keepGoing && (pn <= m_printData.GetToPage()) && printout->HasPage(pn);
2bda0e17
KB
216 pn++)
217 {
34da0970 218 if (sm_abortIt)
2bda0e17
KB
219 {
220 keepGoing = FALSE;
221 break;
222 }
223 else
224 {
225// int dcID = ::SaveDC(dc->GetHDC());
226 dc->StartPage();
227 printout->OnPrintPage(pn);
228 dc->EndPage();
229// ::RestoreDC(dc->GetHDC(), dcID);
230 }
231 }
232 printout->OnEndDocument();
233 }
234
235 printout->OnEndPrinting();
236
34da0970 237 if (sm_abortWindow)
2bda0e17 238 {
34da0970
JS
239 sm_abortWindow->Show(FALSE);
240 delete sm_abortWindow;
241 sm_abortWindow = NULL;
2bda0e17
KB
242 }
243
244 wxEndBusyCursor();
245
246 delete dc;
247
248 return TRUE;
249}
250
251bool wxWindowsPrinter::PrintDialog(wxWindow *parent)
252{
34da0970 253 wxPrintDialog dialog(parent, & m_printData);
2bda0e17
KB
254 return (dialog.ShowModal() == wxID_OK);
255}
256
257bool wxWindowsPrinter::Setup(wxWindow *parent)
258{
34da0970 259 wxPrintDialog dialog(parent, & m_printData);
2bda0e17
KB
260 dialog.GetPrintData().SetSetupDialog(TRUE);
261 return (dialog.ShowModal() == wxID_OK);
262}
263
264/*
265 * Print preview
266 */
267
268wxWindowsPrintPreview::wxWindowsPrintPreview(wxPrintout *printout, wxPrintout *printoutForPrinting, wxPrintData *data):
269 wxPrintPreviewBase(printout, printoutForPrinting, data)
270{
271 DetermineScaling();
272}
273
274wxWindowsPrintPreview::~wxWindowsPrintPreview(void)
275{
276}
277
278bool wxWindowsPrintPreview::Print(bool interactive)
279{
34da0970 280 if (!m_printPrintout)
2bda0e17 281 return FALSE;
34da0970
JS
282 wxWindowsPrinter printer(&m_printData);
283 return printer.Print(m_previewFrame, m_printPrintout, interactive);
2bda0e17
KB
284}
285
286void wxWindowsPrintPreview::DetermineScaling(void)
287{
288 HDC dc = ::GetDC(NULL);
289 int screenWidth = ::GetDeviceCaps(dc, HORZSIZE);
290// int screenHeight = ::GetDeviceCaps(dc, VERTSIZE);
291 int screenXRes = ::GetDeviceCaps(dc, HORZRES);
292// int screenYRes = ::GetDeviceCaps(dc, VERTRES);
293 int logPPIScreenX = ::GetDeviceCaps(dc, LOGPIXELSX);
294 int logPPIScreenY = ::GetDeviceCaps(dc, LOGPIXELSY);
34da0970 295 m_previewPrintout->SetPPIScreen(logPPIScreenX, logPPIScreenY);
2bda0e17
KB
296
297 ::ReleaseDC(NULL, dc);
298
299 // Get a device context for the currently selected printer
34da0970 300 wxPrinterDC printerDC("", "", "", FALSE, m_printData.GetOrientation());
2bda0e17
KB
301
302 int printerWidth = 150;
303 int printerHeight = 250;
304 int printerXRes = 1500;
305 int printerYRes = 2500;
306
307 if (printerDC.GetHDC())
308 {
309 printerWidth = ::GetDeviceCaps((HDC) printerDC.GetHDC(), HORZSIZE);
310 printerHeight = ::GetDeviceCaps((HDC) printerDC.GetHDC(), VERTSIZE);
311 printerXRes = ::GetDeviceCaps((HDC) printerDC.GetHDC(), HORZRES);
312 printerYRes = ::GetDeviceCaps((HDC) printerDC.GetHDC(), VERTRES);
313
314 int logPPIPrinterX = ::GetDeviceCaps((HDC) printerDC.GetHDC(), LOGPIXELSX);
315 int logPPIPrinterY = ::GetDeviceCaps((HDC) printerDC.GetHDC(), LOGPIXELSY);
316
34da0970
JS
317 m_previewPrintout->SetPPIPrinter(logPPIPrinterX, logPPIPrinterY);
318 m_previewPrintout->SetPageSizeMM(printerWidth, printerHeight);
2bda0e17
KB
319
320 if (logPPIPrinterX == 0 || logPPIPrinterY == 0 || printerWidth == 0 || printerHeight == 0)
34da0970 321 m_isOk = FALSE;
2bda0e17
KB
322 }
323 else
34da0970 324 m_isOk = FALSE;
2bda0e17 325
34da0970
JS
326 m_pageWidth = printerXRes;
327 m_pageHeight = printerYRes;
2bda0e17
KB
328
329 // At 100%, the page should look about page-size on the screen.
34da0970
JS
330 m_previewScale = (float)((float)screenWidth/(float)printerWidth);
331 m_previewScale = m_previewScale * (float)((float)screenXRes/(float)printerYRes);
2bda0e17
KB
332}
333
334/****************************************************************************
335
336 FUNCTION: wxAbortProc()
337
338 PURPOSE: Processes messages for the Abort Dialog box
339
340****************************************************************************/
341
342LONG APIENTRY _EXPORT wxAbortProc(HDC WXUNUSED(hPr), int WXUNUSED(Code))
343{
344 MSG msg;
345
34da0970 346 if (!wxPrinterBase::sm_abortWindow) /* If the abort dialog isn't up yet */
2bda0e17
KB
347 return(TRUE);
348
349 /* Process messages intended for the abort dialog box */
350
34da0970
JS
351 while (!wxPrinterBase::sm_abortIt && PeekMessage(&msg, 0, 0, 0, TRUE))
352 if (!IsDialogMessage((HWND) wxPrinterBase::sm_abortWindow->GetHWND(), &msg)) {
2bda0e17
KB
353 TranslateMessage(&msg);
354 DispatchMessage(&msg);
355 }
356
357 /* bAbort is TRUE (return is FALSE) if the user has aborted */
358
34da0970 359 return (!wxPrinterBase::sm_abortIt);
2bda0e17
KB
360}
361