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"
28 #include "wx/string.h"
30 #include "wx/window.h"
31 #include "wx/dcmemory.h"
34 #if wxUSE_PRINTING_ARCHITECTURE
36 #include "wx/msw/private.h"
39 #include "wx/msw/dib.h"
42 #include "wx/dcprint.h"
43 #include "wx/printdlg.h"
44 #include "wx/msw/printdlg.h"
47 #include "wx/msw/wrapcdlg.h"
52 // mingw32 defines GDI_ERROR incorrectly
53 #if defined(__GNUWIN32__) || !defined(GDI_ERROR)
55 #define GDI_ERROR ((int)-1)
58 // ----------------------------------------------------------------------------
60 // ----------------------------------------------------------------------------
62 IMPLEMENT_CLASS(wxPrinterDC
, wxDC
)
64 // ============================================================================
66 // ============================================================================
68 // ----------------------------------------------------------------------------
69 // wxPrinterDC construction
70 // ----------------------------------------------------------------------------
72 // This form is deprecated
73 wxPrinterDC::wxPrinterDC(const wxString
& driver_name
,
74 const wxString
& device_name
,
79 m_isInteractive
= interactive
;
82 m_printData
.SetFilename(file
);
84 #if wxUSE_COMMON_DIALOGS
89 pd
.lStructSize
= sizeof( PRINTDLG
);
90 pd
.hwndOwner
= (HWND
) NULL
;
91 pd
.hDevMode
= (HANDLE
)NULL
;
92 pd
.hDevNames
= (HANDLE
)NULL
;
93 pd
.Flags
= PD_RETURNDC
| PD_NOSELECTION
| PD_NOPAGENUMS
;
99 pd
.hInstance
= (HINSTANCE
)NULL
;
101 m_ok
= PrintDlg( &pd
) != 0;
104 m_hDC
= (WXHDC
) pd
.hDC
;
108 #endif // wxUSE_COMMON_DIALOGS
110 if ( !driver_name
.empty() && !device_name
.empty() && !file
.empty() )
112 m_hDC
= (WXHDC
) CreateDC(driver_name
, device_name
, file
, NULL
);
114 else // we don't have all parameters, ask the user
116 wxPrintData printData
;
117 printData
.SetOrientation(orientation
);
118 m_hDC
= wxGetPrinterDC(printData
);
121 m_ok
= m_hDC
? true: false;
123 // as we created it, we must delete it as well
130 wxPrinterDC::wxPrinterDC(const wxPrintData
& printData
)
132 m_printData
= printData
;
134 m_isInteractive
= false;
136 m_hDC
= wxGetPrinterDC(printData
);
144 wxPrinterDC::wxPrinterDC(WXHDC dc
)
146 m_isInteractive
= false;
153 void wxPrinterDC::Init()
157 // int width = GetDeviceCaps(m_hDC, VERTRES);
158 // int height = GetDeviceCaps(m_hDC, HORZRES);
159 SetMapMode(wxMM_TEXT
);
161 SetBrush(*wxBLACK_BRUSH
);
162 SetPen(*wxBLACK_PEN
);
166 // ----------------------------------------------------------------------------
167 // wxPrinterDC {Start/End}{Page/Doc} methods
168 // ----------------------------------------------------------------------------
170 bool wxPrinterDC::StartDoc(const wxString
& message
)
173 docinfo
.cbSize
= sizeof(DOCINFO
);
174 docinfo
.lpszDocName
= (const wxChar
*)message
;
176 wxString
filename(m_printData
.GetFilename());
178 if (filename
.empty())
179 docinfo
.lpszOutput
= NULL
;
181 docinfo
.lpszOutput
= (const wxChar
*) filename
;
183 #if defined(__WIN95__)
184 docinfo
.lpszDatatype
= NULL
;
191 int ret
= ::StartDoc(GetHdc(), &docinfo
);
195 DWORD lastError
= GetLastError();
196 wxLogDebug(wxT("wxDC::StartDoc failed with error: %ld\n"), lastError
);
202 void wxPrinterDC::EndDoc()
204 if (m_hDC
) ::EndDoc((HDC
) m_hDC
);
207 void wxPrinterDC::StartPage()
210 ::StartPage((HDC
) m_hDC
);
213 void wxPrinterDC::EndPage()
216 ::EndPage((HDC
) m_hDC
);
219 // Returns default device and port names
220 static bool wxGetDefaultDeviceName(wxString
& deviceName
, wxString
& portName
)
224 LPDEVNAMES lpDevNames
;
225 LPTSTR lpszDeviceName
;
230 // Cygwin has trouble believing PRINTDLG is 66 bytes - thinks it is 68
233 pd
.lStructSize
= 66; // sizeof(PRINTDLG);
235 memset(&pd
, 0, sizeof(PRINTDLG
));
236 pd
.lStructSize
= sizeof(PRINTDLG
);
239 pd
.hwndOwner
= (HWND
)NULL
;
240 pd
.hDevMode
= NULL
; // Will be created by PrintDlg
241 pd
.hDevNames
= NULL
; // Ditto
242 pd
.Flags
= PD_RETURNDEFAULT
;
245 if (!PrintDlg((LPPRINTDLG
)&pd
))
248 GlobalFree(pd
.hDevMode
);
250 GlobalFree(pd
.hDevNames
);
257 lpDevNames
= (LPDEVNAMES
)GlobalLock(pd
.hDevNames
);
258 lpszDeviceName
= (LPTSTR
)lpDevNames
+ lpDevNames
->wDeviceOffset
;
259 lpszPortName
= (LPTSTR
)lpDevNames
+ lpDevNames
->wOutputOffset
;
261 deviceName
= lpszDeviceName
;
262 portName
= lpszPortName
;
264 GlobalUnlock(pd
.hDevNames
);
265 GlobalFree(pd
.hDevNames
);
271 GlobalFree(pd
.hDevMode
);
274 return ( !deviceName
.empty() );
277 // Gets an HDC for the specified printer configuration
278 WXHDC WXDLLEXPORT
wxGetPrinterDC(const wxPrintData
& printDataConst
)
280 #if defined(__WXUNIVERSAL__) && (!defined(__WXMSW__) || wxUSE_POSTSCRIPT_ARCHITECTURE_IN_MSW)
283 wxPostScriptPrintNativeData
*data
=
284 (wxPostScriptPrintNativeData
*) printDataConst
.GetNativeData();
285 // FIXME: how further ???
290 #else // Postscript vs. native Windows
292 wxWindowsPrintNativeData
*data
=
293 (wxWindowsPrintNativeData
*) printDataConst
.GetNativeData();
295 data
->TransferFrom( printDataConst
);
297 wxChar
* driverName
= (wxChar
*) NULL
;
299 wxString devNameStr
= printDataConst
.GetPrinterName();
300 wxChar
* portName
= (wxChar
*) NULL
; // Obsolete in WIN32
302 const wxChar
* deviceName
;
304 deviceName
= (wxChar
*) NULL
;
306 deviceName
= devNameStr
.c_str();
308 LPDEVMODE lpDevMode
= (LPDEVMODE
) NULL
;
310 HGLOBAL hDevMode
= (HGLOBAL
)(DWORD
) data
->GetDevMode();
313 lpDevMode
= (DEVMODE
*) GlobalLock(hDevMode
);
317 // Retrieve the default device name
319 if ( !wxGetDefaultDeviceName(devNameStr
, portName
) )
321 return 0; // Could not get default device name
323 deviceName
= devNameStr
.c_str();
327 HDC hDC
= CreateDC(driverName
, deviceName
, portName
, (DEVMODE
*) lpDevMode
);
329 HDC hDC
= CreateDC(driverName
, deviceName
, portName
, (LPSTR
) lpDevMode
);
332 if (hDevMode
&& lpDevMode
)
333 GlobalUnlock(hDevMode
);
339 // ----------------------------------------------------------------------------
340 // wxPrinterDC bit blitting/bitmap drawing
341 // ----------------------------------------------------------------------------
343 // helper of DoDrawBitmap() and DoBlit()
345 bool DrawBitmapUsingStretchDIBits(HDC hdc
,
347 wxCoord x
, wxCoord y
)
351 bool ok
= dib
.IsOk();
356 if ( !::GetObject(dib
.GetHandle(), sizeof(ds
), &ds
) )
358 wxLogLastError(_T("GetObject(DIBSECTION)"));
363 // ok, we've got all data we need, do blit it
368 ds
.dsBmih
.biWidth
, ds
.dsBmih
.biHeight
,
370 ds
.dsBmih
.biWidth
, ds
.dsBmih
.biHeight
,
372 (LPBITMAPINFO
)&ds
.dsBmih
,
377 wxLogLastError(wxT("StretchDIBits"));
388 void wxPrinterDC::DoDrawBitmap(const wxBitmap
& bmp
,
389 wxCoord x
, wxCoord y
,
392 wxCHECK_RET( bmp
.Ok(), _T("invalid bitmap in wxPrinterDC::DrawBitmap") );
394 int width
= bmp
.GetWidth(),
395 height
= bmp
.GetHeight();
397 if ( !(::GetDeviceCaps(GetHdc(), RASTERCAPS
) & RC_STRETCHDIB
) ||
398 !DrawBitmapUsingStretchDIBits(GetHdc(), bmp
, x
, y
) )
400 // no support for StretchDIBits() or an error occurred if we got here
402 memDC
.SelectObject(bmp
);
404 Blit(x
, y
, width
, height
, &memDC
, 0, 0, wxCOPY
, useMask
);
406 memDC
.SelectObject(wxNullBitmap
);
410 bool wxPrinterDC::DoBlit(wxCoord xdest
, wxCoord ydest
,
411 wxCoord width
, wxCoord height
,
413 wxCoord
WXUNUSED(xsrc
), wxCoord
WXUNUSED(ysrc
),
414 int WXUNUSED(rop
), bool useMask
,
415 wxCoord
WXUNUSED(xsrcMask
), wxCoord
WXUNUSED(ysrcMask
))
417 wxBitmap
& bmp
= source
->GetSelectedBitmap();
418 wxMask
*mask
= useMask
? bmp
.GetMask() : NULL
;
421 // If we are printing source colours are screen colours not printer
422 // colours and so we need copy the bitmap pixel by pixel.
424 HDC dcSrc
= GetHdcOf(*source
);
425 MemoryHDC
dcMask(dcSrc
);
426 SelectInHDC
selectMask(dcMask
, (HBITMAP
)mask
->GetMaskBitmap());
428 for (int x
= 0; x
< width
; x
++)
430 for (int y
= 0; y
< height
; y
++)
432 COLORREF cref
= ::GetPixel(dcMask
, x
, y
);
435 HBRUSH brush
= ::CreateSolidBrush(::GetPixel(dcSrc
, x
, y
));
436 rect
.left
= xdest
+ x
;
437 rect
.right
= rect
.left
+ 1;
438 rect
.top
= ydest
+ y
;
439 rect
.bottom
= rect
.top
+ 1;
440 ::FillRect(GetHdc(), &rect
, brush
);
441 ::DeleteObject(brush
);
448 if ( !(::GetDeviceCaps(GetHdc(), RASTERCAPS
) & RC_STRETCHDIB
) ||
449 !DrawBitmapUsingStretchDIBits(GetHdc(), bmp
, xdest
, ydest
) )
451 // no support for StretchDIBits
453 // as we are printing, source colours are screen colours not
454 // printer colours and so we need copy the bitmap pixel by pixel.
455 HDC dcSrc
= GetHdcOf(*source
);
457 for (int y
= 0; y
< height
; y
++)
459 // optimization: draw identical adjacent pixels together.
460 for (int x
= 0; x
< width
; x
++)
462 COLORREF col
= ::GetPixel(dcSrc
, x
, y
);
463 HBRUSH brush
= ::CreateSolidBrush( col
);
465 rect
.left
= xdest
+ x
;
466 rect
.top
= ydest
+ y
;
467 while( (x
+ 1 < width
) &&
468 (::GetPixel(dcSrc
, x
+ 1, y
) == col
) )
472 rect
.right
= xdest
+ x
+ 1;
473 rect
.bottom
= rect
.top
+ 1;
474 ::FillRect((HDC
) m_hDC
, &rect
, brush
);
475 ::DeleteObject(brush
);
485 // wxUSE_PRINTING_ARCHITECTURE