]>
git.saurik.com Git - wxWidgets.git/blob - src/msw/dcprint.cpp
1 /////////////////////////////////////////////////////////////////////////////
2 // Name: src/msw/dcprint.cpp
3 // Purpose: wxPrinterDC class
4 // Author: Julian Smart
8 // Copyright: (c) Julian Smart
9 // Licence: wxWindows licence
10 /////////////////////////////////////////////////////////////////////////////
12 // ============================================================================
14 // ============================================================================
16 // ----------------------------------------------------------------------------
18 // ----------------------------------------------------------------------------
20 // For compilers that support precompilation, includes "wx.h".
21 #include "wx/wxprec.h"
27 #if wxUSE_PRINTING_ARCHITECTURE
29 #include "wx/dcprint.h"
32 #include "wx/msw/wrapcdlg.h"
33 #include "wx/string.h"
35 #include "wx/window.h"
36 #include "wx/dcmemory.h"
40 #include "wx/msw/private.h"
43 #include "wx/msw/dib.h"
46 #include "wx/printdlg.h"
47 #include "wx/msw/printdlg.h"
53 // mingw32 defines GDI_ERROR incorrectly
54 #if defined(__GNUWIN32__) || !defined(GDI_ERROR)
56 #define GDI_ERROR ((int)-1)
59 #if defined(__WXUNIVERSAL__) && wxUSE_POSTSCRIPT_ARCHITECTURE_IN_MSW
60 #define wxUSE_PS_PRINTING 1
62 #define wxUSE_PS_PRINTING 0
65 // ----------------------------------------------------------------------------
67 // ----------------------------------------------------------------------------
69 IMPLEMENT_CLASS(wxPrinterDC
, wxDC
)
71 // ============================================================================
73 // ============================================================================
75 // ----------------------------------------------------------------------------
76 // wxPrinterDC construction
77 // ----------------------------------------------------------------------------
79 // This form is deprecated
80 wxPrinterDC::wxPrinterDC(const wxString
& driver_name
,
81 const wxString
& device_name
,
86 m_isInteractive
= interactive
;
89 m_printData
.SetFilename(file
);
91 #if wxUSE_COMMON_DIALOGS
96 pd
.lStructSize
= sizeof( PRINTDLG
);
97 pd
.hwndOwner
= (HWND
) NULL
;
98 pd
.hDevMode
= (HANDLE
)NULL
;
99 pd
.hDevNames
= (HANDLE
)NULL
;
100 pd
.Flags
= PD_RETURNDC
| PD_NOSELECTION
| PD_NOPAGENUMS
;
106 pd
.hInstance
= (HINSTANCE
)NULL
;
108 m_ok
= PrintDlg( &pd
) != 0;
111 m_hDC
= (WXHDC
) pd
.hDC
;
115 #endif // wxUSE_COMMON_DIALOGS
117 if ( !driver_name
.empty() && !device_name
.empty() && !file
.empty() )
119 m_hDC
= (WXHDC
) CreateDC(driver_name
, device_name
, file
, NULL
);
121 else // we don't have all parameters, ask the user
123 wxPrintData printData
;
124 printData
.SetOrientation(orientation
);
125 m_hDC
= wxGetPrinterDC(printData
);
128 m_ok
= m_hDC
? true: false;
130 // as we created it, we must delete it as well
137 wxPrinterDC::wxPrinterDC(const wxPrintData
& printData
)
139 m_printData
= printData
;
141 m_isInteractive
= false;
143 m_hDC
= wxGetPrinterDC(printData
);
151 wxPrinterDC::wxPrinterDC(WXHDC dc
)
153 m_isInteractive
= false;
160 void wxPrinterDC::Init()
164 // int width = GetDeviceCaps(m_hDC, VERTRES);
165 // int height = GetDeviceCaps(m_hDC, HORZRES);
166 SetMapMode(wxMM_TEXT
);
168 SetBrush(*wxBLACK_BRUSH
);
169 SetPen(*wxBLACK_PEN
);
173 // ----------------------------------------------------------------------------
174 // wxPrinterDC {Start/End}{Page/Doc} methods
175 // ----------------------------------------------------------------------------
177 bool wxPrinterDC::StartDoc(const wxString
& message
)
180 docinfo
.cbSize
= sizeof(DOCINFO
);
181 docinfo
.lpszDocName
= (const wxChar
*)message
;
183 wxString
filename(m_printData
.GetFilename());
185 if (filename
.empty())
186 docinfo
.lpszOutput
= NULL
;
188 docinfo
.lpszOutput
= (const wxChar
*) filename
;
190 docinfo
.lpszDatatype
= NULL
;
196 int ret
= ::StartDoc(GetHdc(), &docinfo
);
200 DWORD lastError
= GetLastError();
201 wxLogDebug(wxT("wxDC::StartDoc failed with error: %ld\n"), lastError
);
207 void wxPrinterDC::EndDoc()
209 if (m_hDC
) ::EndDoc((HDC
) m_hDC
);
212 void wxPrinterDC::StartPage()
215 ::StartPage((HDC
) m_hDC
);
218 void wxPrinterDC::EndPage()
221 ::EndPage((HDC
) m_hDC
);
224 #if !wxUSE_PS_PRINTING
226 // Returns default device and port names
227 static bool wxGetDefaultDeviceName(wxString
& deviceName
, wxString
& portName
)
231 LPDEVNAMES lpDevNames
;
232 LPTSTR lpszDeviceName
;
237 // Cygwin has trouble believing PRINTDLG is 66 bytes - thinks it is 68
240 pd
.lStructSize
= 66; // sizeof(PRINTDLG);
242 memset(&pd
, 0, sizeof(PRINTDLG
));
243 pd
.lStructSize
= sizeof(PRINTDLG
);
246 pd
.hwndOwner
= (HWND
)NULL
;
247 pd
.hDevMode
= NULL
; // Will be created by PrintDlg
248 pd
.hDevNames
= NULL
; // Ditto
249 pd
.Flags
= PD_RETURNDEFAULT
;
252 if (!PrintDlg((LPPRINTDLG
)&pd
))
255 GlobalFree(pd
.hDevMode
);
257 GlobalFree(pd
.hDevNames
);
264 lpDevNames
= (LPDEVNAMES
)GlobalLock(pd
.hDevNames
);
265 lpszDeviceName
= (LPTSTR
)lpDevNames
+ lpDevNames
->wDeviceOffset
;
266 lpszPortName
= (LPTSTR
)lpDevNames
+ lpDevNames
->wOutputOffset
;
268 deviceName
= lpszDeviceName
;
269 portName
= lpszPortName
;
271 GlobalUnlock(pd
.hDevNames
);
272 GlobalFree(pd
.hDevNames
);
278 GlobalFree(pd
.hDevMode
);
281 return ( !deviceName
.empty() );
284 #endif // !wxUSE_PS_PRINTING
286 // Gets an HDC for the specified printer configuration
287 WXHDC WXDLLEXPORT
wxGetPrinterDC(const wxPrintData
& printDataConst
)
289 #if wxUSE_PS_PRINTING
291 wxUnusedVar(printDataConst
);
293 #else // native Windows printing
294 wxWindowsPrintNativeData
*data
=
295 (wxWindowsPrintNativeData
*) printDataConst
.GetNativeData();
297 data
->TransferFrom( printDataConst
);
299 wxString deviceName
= printDataConst
.GetPrinterName();
300 if ( deviceName
.empty() )
302 // Retrieve the default device name
304 if ( !wxGetDefaultDeviceName(deviceName
, portName
) )
306 return 0; // Could not get default device name
311 HGLOBAL hDevMode
= (HGLOBAL
)(DWORD
) data
->GetDevMode();
313 DEVMODE
*lpDevMode
= hDevMode
? (DEVMODE
*)::GlobalLock(hDevMode
) : NULL
;
315 HDC hDC
= ::CreateDC(NULL
, deviceName
, NULL
, lpDevMode
);
317 wxLogLastError(_T("CreateDC(printer)"));
320 ::GlobalUnlock(hDevMode
);
323 #endif // PostScript/Windows printing
326 // ----------------------------------------------------------------------------
327 // wxPrinterDC bit blitting/bitmap drawing
328 // ----------------------------------------------------------------------------
330 // helper of DoDrawBitmap() and DoBlit()
332 bool DrawBitmapUsingStretchDIBits(HDC hdc
,
334 wxCoord x
, wxCoord y
)
338 bool ok
= dib
.IsOk();
343 if ( !::GetObject(dib
.GetHandle(), sizeof(ds
), &ds
) )
345 wxLogLastError(_T("GetObject(DIBSECTION)"));
350 // ok, we've got all data we need, do blit it
355 ds
.dsBmih
.biWidth
, ds
.dsBmih
.biHeight
,
357 ds
.dsBmih
.biWidth
, ds
.dsBmih
.biHeight
,
359 (LPBITMAPINFO
)&ds
.dsBmih
,
364 wxLogLastError(wxT("StretchDIBits"));
375 void wxPrinterDC::DoDrawBitmap(const wxBitmap
& bmp
,
376 wxCoord x
, wxCoord y
,
379 wxCHECK_RET( bmp
.Ok(), _T("invalid bitmap in wxPrinterDC::DrawBitmap") );
381 int width
= bmp
.GetWidth(),
382 height
= bmp
.GetHeight();
384 if ( !(::GetDeviceCaps(GetHdc(), RASTERCAPS
) & RC_STRETCHDIB
) ||
385 !DrawBitmapUsingStretchDIBits(GetHdc(), bmp
, x
, y
) )
387 // no support for StretchDIBits() or an error occurred if we got here
389 memDC
.SelectObject(bmp
);
391 Blit(x
, y
, width
, height
, &memDC
, 0, 0, wxCOPY
, useMask
);
393 memDC
.SelectObject(wxNullBitmap
);
397 bool wxPrinterDC::DoBlit(wxCoord xdest
, wxCoord ydest
,
398 wxCoord width
, wxCoord height
,
400 wxCoord
WXUNUSED(xsrc
), wxCoord
WXUNUSED(ysrc
),
401 int WXUNUSED(rop
), bool useMask
,
402 wxCoord
WXUNUSED(xsrcMask
), wxCoord
WXUNUSED(ysrcMask
))
404 wxBitmap
& bmp
= source
->GetSelectedBitmap();
405 wxMask
*mask
= useMask
? bmp
.GetMask() : NULL
;
408 // If we are printing source colours are screen colours not printer
409 // colours and so we need copy the bitmap pixel by pixel.
411 HDC dcSrc
= GetHdcOf(*source
);
412 MemoryHDC
dcMask(dcSrc
);
413 SelectInHDC
selectMask(dcMask
, (HBITMAP
)mask
->GetMaskBitmap());
415 for (int x
= 0; x
< width
; x
++)
417 for (int y
= 0; y
< height
; y
++)
419 COLORREF cref
= ::GetPixel(dcMask
, x
, y
);
422 HBRUSH brush
= ::CreateSolidBrush(::GetPixel(dcSrc
, x
, y
));
423 rect
.left
= xdest
+ x
;
424 rect
.right
= rect
.left
+ 1;
425 rect
.top
= ydest
+ y
;
426 rect
.bottom
= rect
.top
+ 1;
427 ::FillRect(GetHdc(), &rect
, brush
);
428 ::DeleteObject(brush
);
435 if ( !(::GetDeviceCaps(GetHdc(), RASTERCAPS
) & RC_STRETCHDIB
) ||
436 !DrawBitmapUsingStretchDIBits(GetHdc(), bmp
, xdest
, ydest
) )
438 // no support for StretchDIBits
440 // as we are printing, source colours are screen colours not
441 // printer colours and so we need copy the bitmap pixel by pixel.
442 HDC dcSrc
= GetHdcOf(*source
);
444 for (int y
= 0; y
< height
; y
++)
446 // optimization: draw identical adjacent pixels together.
447 for (int x
= 0; x
< width
; x
++)
449 COLORREF col
= ::GetPixel(dcSrc
, x
, y
);
450 HBRUSH brush
= ::CreateSolidBrush( col
);
452 rect
.left
= xdest
+ x
;
453 rect
.top
= ydest
+ y
;
454 while( (x
+ 1 < width
) &&
455 (::GetPixel(dcSrc
, x
+ 1, y
) == col
) )
459 rect
.right
= xdest
+ x
+ 1;
460 rect
.bottom
= rect
.top
+ 1;
461 ::FillRect((HDC
) m_hDC
, &rect
, brush
);
462 ::DeleteObject(brush
);
472 // wxUSE_PRINTING_ARCHITECTURE