]> git.saurik.com Git - wxWidgets.git/blame - src/msw/printwin.cpp
Fixed the "Can't open file" message in ReadDIB so that it actually
[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/*
7bcb11d3
JS
58* Printer
59*/
60
61wxWindowsPrinter::wxWindowsPrinter(wxPrintDialogData *data):
62wxPrinterBase(data)
2bda0e17 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{
7bcb11d3
JS
74 sm_abortIt = FALSE;
75 sm_abortWindow = NULL;
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
91 m_printDialogData.SetMinPage(minPage);
92 m_printDialogData.SetMaxPage(maxPage);
93 if (fromPage != 0)
94 m_printDialogData.SetFromPage(fromPage);
95 if (toPage != 0)
96 m_printDialogData.SetToPage(toPage);
97
98 if (minPage != 0)
99 {
100 m_printDialogData.EnablePageNumbers(TRUE);
101 if (m_printDialogData.GetFromPage() < m_printDialogData.GetMinPage())
102 m_printDialogData.SetFromPage(m_printDialogData.GetMinPage());
103 else if (m_printDialogData.GetFromPage() > m_printDialogData.GetMaxPage())
104 m_printDialogData.SetFromPage(m_printDialogData.GetMaxPage());
105 if (m_printDialogData.GetToPage() > m_printDialogData.GetMaxPage())
106 m_printDialogData.SetToPage(m_printDialogData.GetMaxPage());
107 else if (m_printDialogData.GetToPage() < m_printDialogData.GetMinPage())
108 m_printDialogData.SetToPage(m_printDialogData.GetMinPage());
109 }
110 else
111 m_printDialogData.EnablePageNumbers(FALSE);
2bda0e17 112
7bcb11d3
JS
113 // Create a suitable device context
114 wxDC *dc = NULL;
115 if (prompt)
116 {
117 dc = PrintDialog(parent);
118 if (!dc)
119 return FALSE;
120 }
121 else
122 {
123 // dc = new wxPrinterDC("", "", "", FALSE, m_printData.GetOrientation());
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 int logPPIScreenX = 0;
135 int logPPIScreenY = 0;
136 int logPPIPrinterX = 0;
137 int logPPIPrinterY = 0;
138
139 HDC hdc = ::GetDC(NULL);
140 logPPIScreenX = ::GetDeviceCaps(hdc, LOGPIXELSX);
141 logPPIScreenY = ::GetDeviceCaps(hdc, LOGPIXELSY);
142 ::ReleaseDC(NULL, hdc);
143
144 logPPIPrinterX = ::GetDeviceCaps((HDC) dc->GetHDC(), LOGPIXELSX);
145 logPPIPrinterY = ::GetDeviceCaps((HDC) dc->GetHDC(), LOGPIXELSY);
146 if (logPPIPrinterX == 0 || logPPIPrinterY == 0)
147 {
148 delete dc;
149 return FALSE;
150 }
151
152 printout->SetPPIScreen(logPPIScreenX, logPPIScreenY);
153 printout->SetPPIPrinter(logPPIPrinterX, logPPIPrinterY);
154
155 // Set printout parameters
156 printout->SetDC(dc);
157
158 int w, h;
159 dc->GetSize(&w, &h);
160 printout->SetPageSizePixels((int)w, (int)h);
d6a1743b 161
7bcb11d3
JS
162 dc->GetSizeMM(&w, &h);
163 printout->SetPageSizeMM((int)w, (int)h);
164
165 // Create an abort window
166 wxBeginBusyCursor();
167
168 wxWindow *win = CreateAbortWindow(parent, printout);
169 wxYield();
170
ce3ed50d 171#if defined(__BORLANDC__) || defined(__GNUWIN32__) || defined(__SALFORDC__) || !defined(__WIN32__)
7bcb11d3
JS
172 ::SetAbortProc((HDC) dc->GetHDC(), (FARPROC) m_lpAbortProc);
173#else
174 ::SetAbortProc((HDC) dc->GetHDC(), (int (_stdcall *)
175 // cast it to right type only if required
176 // @@@ it's really cdecl and we're casting it to stdcall - either there is
177 // something I don't understand or it will crash at first usage
178#ifdef STRICT
179 (HDC, int)
d6a1743b 180#else
7bcb11d3 181 ()
d6a1743b 182#endif
7bcb11d3
JS
183 )m_lpAbortProc);
184#endif
185
186 if (!win)
2bda0e17 187 {
7bcb11d3
JS
188 wxEndBusyCursor();
189 wxMessageBox("Sorry, could not create an abort dialog.", "Print Error", wxOK, parent);
190 delete dc;
2bda0e17 191 }
7bcb11d3
JS
192 sm_abortWindow = win;
193 sm_abortWindow->Show(TRUE);
194 wxYield();
195
196 printout->OnBeginPrinting();
197
198 bool keepGoing = TRUE;
199
200 int copyCount;
201 for (copyCount = 1; copyCount <= m_printDialogData.GetNoCopies(); copyCount ++)
202 {
203 if (!printout->OnBeginDocument(m_printDialogData.GetFromPage(), m_printDialogData.GetToPage()))
204 {
205 wxEndBusyCursor();
206 wxMessageBox("Could not start printing.", "Print Error", wxOK, parent);
207 break;
208 }
209 if (sm_abortIt)
210 break;
211
212 int pn;
213 for (pn = m_printDialogData.GetFromPage(); keepGoing && (pn <= m_printDialogData.GetToPage()) && printout->HasPage(pn);
214 pn++)
215 {
216 if (sm_abortIt)
217 {
218 keepGoing = FALSE;
219 break;
220 }
221 else
222 {
223 dc->StartPage();
224 printout->OnPrintPage(pn);
225 dc->EndPage();
226 }
227 }
228 printout->OnEndDocument();
229 }
230
231 printout->OnEndPrinting();
232
233 if (sm_abortWindow)
2bda0e17 234 {
7bcb11d3
JS
235 sm_abortWindow->Show(FALSE);
236 delete sm_abortWindow;
237 sm_abortWindow = NULL;
2bda0e17 238 }
7bcb11d3
JS
239
240 wxEndBusyCursor();
241
242 delete dc;
243
244 return TRUE;
245}
2bda0e17 246
7bcb11d3
JS
247wxDC* wxWindowsPrinter::PrintDialog(wxWindow *parent)
248{
249 wxDC* dc = (wxDC*) NULL;
2bda0e17 250
7bcb11d3
JS
251 wxPrintDialog dialog(parent, & m_printDialogData);
252 int ret = dialog.ShowModal();
2bda0e17 253
7bcb11d3
JS
254 if (ret == wxID_OK)
255 {
256 dc = dialog.GetPrintDC();
257 m_printDialogData = dialog.GetPrintDialogData();
258 }
2bda0e17 259
7bcb11d3 260 return dc;
2bda0e17
KB
261}
262
263bool wxWindowsPrinter::Setup(wxWindow *parent)
264{
7bcb11d3
JS
265 wxPrintDialog dialog(parent, & m_printDialogData);
266 dialog.GetPrintDialogData().SetSetupDialog(TRUE);
267
268 int ret = dialog.ShowModal();
269
270 if (ret == wxID_OK)
271 {
272 m_printDialogData = dialog.GetPrintDialogData();
273 }
274
275 return (ret == wxID_OK);
2bda0e17
KB
276}
277
278/*
7bcb11d3
JS
279* Print preview
280*/
2bda0e17 281
7bcb11d3
JS
282wxWindowsPrintPreview::wxWindowsPrintPreview(wxPrintout *printout, wxPrintout *printoutForPrinting, wxPrintDialogData *data):
283wxPrintPreviewBase(printout, printoutForPrinting, data)
2bda0e17 284{
7bcb11d3 285 DetermineScaling();
2bda0e17
KB
286}
287
288wxWindowsPrintPreview::~wxWindowsPrintPreview(void)
289{
290}
291
292bool wxWindowsPrintPreview::Print(bool interactive)
293{
7bcb11d3
JS
294 if (!m_printPrintout)
295 return FALSE;
296 wxWindowsPrinter printer(&m_printDialogData);
297 return printer.Print(m_previewFrame, m_printPrintout, interactive);
2bda0e17
KB
298}
299
300void wxWindowsPrintPreview::DetermineScaling(void)
301{
302 HDC dc = ::GetDC(NULL);
303 int screenWidth = ::GetDeviceCaps(dc, HORZSIZE);
7bcb11d3 304 // int screenHeight = ::GetDeviceCaps(dc, VERTSIZE);
2bda0e17 305 int screenXRes = ::GetDeviceCaps(dc, HORZRES);
7bcb11d3 306 // int screenYRes = ::GetDeviceCaps(dc, VERTRES);
2bda0e17
KB
307 int logPPIScreenX = ::GetDeviceCaps(dc, LOGPIXELSX);
308 int logPPIScreenY = ::GetDeviceCaps(dc, LOGPIXELSY);
34da0970 309 m_previewPrintout->SetPPIScreen(logPPIScreenX, logPPIScreenY);
7bcb11d3 310
2bda0e17 311 ::ReleaseDC(NULL, dc);
7bcb11d3 312
2bda0e17 313 // Get a device context for the currently selected printer
7bcb11d3
JS
314 wxPrinterDC printerDC(m_printDialogData.GetPrintData());
315
2bda0e17
KB
316 int printerWidth = 150;
317 int printerHeight = 250;
318 int printerXRes = 1500;
319 int printerYRes = 2500;
7bcb11d3 320
2bda0e17
KB
321 if (printerDC.GetHDC())
322 {
7bcb11d3
JS
323 printerWidth = ::GetDeviceCaps((HDC) printerDC.GetHDC(), HORZSIZE);
324 printerHeight = ::GetDeviceCaps((HDC) printerDC.GetHDC(), VERTSIZE);
325 printerXRes = ::GetDeviceCaps((HDC) printerDC.GetHDC(), HORZRES);
326 printerYRes = ::GetDeviceCaps((HDC) printerDC.GetHDC(), VERTRES);
327
328 int logPPIPrinterX = ::GetDeviceCaps((HDC) printerDC.GetHDC(), LOGPIXELSX);
329 int logPPIPrinterY = ::GetDeviceCaps((HDC) printerDC.GetHDC(), LOGPIXELSY);
330
331 m_previewPrintout->SetPPIPrinter(logPPIPrinterX, logPPIPrinterY);
332 m_previewPrintout->SetPageSizeMM(printerWidth, printerHeight);
333
334 if (logPPIPrinterX == 0 || logPPIPrinterY == 0 || printerWidth == 0 || printerHeight == 0)
335 m_isOk = FALSE;
2bda0e17
KB
336 }
337 else
7bcb11d3
JS
338 m_isOk = FALSE;
339
34da0970
JS
340 m_pageWidth = printerXRes;
341 m_pageHeight = printerYRes;
7bcb11d3 342
2bda0e17 343 // At 100%, the page should look about page-size on the screen.
34da0970
JS
344 m_previewScale = (float)((float)screenWidth/(float)printerWidth);
345 m_previewScale = m_previewScale * (float)((float)screenXRes/(float)printerYRes);
2bda0e17
KB
346}
347
348/****************************************************************************
349
7bcb11d3
JS
350 FUNCTION: wxAbortProc()
351
2bda0e17 352 PURPOSE: Processes messages for the Abort Dialog box
7bcb11d3 353
2bda0e17
KB
354****************************************************************************/
355
356LONG APIENTRY _EXPORT wxAbortProc(HDC WXUNUSED(hPr), int WXUNUSED(Code))
357{
358 MSG msg;
7bcb11d3 359
34da0970 360 if (!wxPrinterBase::sm_abortWindow) /* If the abort dialog isn't up yet */
2bda0e17 361 return(TRUE);
7bcb11d3 362
2bda0e17 363 /* Process messages intended for the abort dialog box */
7bcb11d3 364
34da0970
JS
365 while (!wxPrinterBase::sm_abortIt && PeekMessage(&msg, 0, 0, 0, TRUE))
366 if (!IsDialogMessage((HWND) wxPrinterBase::sm_abortWindow->GetHWND(), &msg)) {
2bda0e17
KB
367 TranslateMessage(&msg);
368 DispatchMessage(&msg);
369 }
7bcb11d3
JS
370
371 /* bAbort is TRUE (return is FALSE) if the user has aborted */
372
373 return (!wxPrinterBase::sm_abortIt);
2bda0e17
KB
374}
375