]>
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"
30 #include "wx/msw/dcprint.h"
33 #include "wx/msw/wrapcdlg.h"
34 #include "wx/string.h"
36 #include "wx/window.h"
37 #include "wx/dcmemory.h"
41 #include "wx/msw/private.h"
44 #include "wx/msw/dib.h"
47 #include "wx/printdlg.h"
48 #include "wx/msw/printdlg.h"
54 // mingw32 defines GDI_ERROR incorrectly
55 #if defined(__GNUWIN32__) || !defined(GDI_ERROR)
57 #define GDI_ERROR ((int)-1)
60 #if defined(__WXUNIVERSAL__) && wxUSE_POSTSCRIPT_ARCHITECTURE_IN_MSW
61 #define wxUSE_PS_PRINTING 1
63 #define wxUSE_PS_PRINTING 0
66 // ----------------------------------------------------------------------------
68 // ----------------------------------------------------------------------------
70 IMPLEMENT_ABSTRACT_CLASS(wxPrinterDCImpl
, wxMSWDCImpl
)
72 // ============================================================================
74 // ============================================================================
76 // ----------------------------------------------------------------------------
77 // wxPrinterDC construction
78 // ----------------------------------------------------------------------------
81 // This form is deprecated
82 wxPrinterDC::wxPrinterDC(const wxString
& driver_name
,
83 const wxString
& device_name
,
88 m_isInteractive
= interactive
;
91 m_printData
.SetFilename(file
);
93 #if wxUSE_COMMON_DIALOGS
98 pd
.lStructSize
= sizeof( PRINTDLG
);
99 pd
.hwndOwner
= (HWND
) NULL
;
100 pd
.hDevMode
= (HANDLE
)NULL
;
101 pd
.hDevNames
= (HANDLE
)NULL
;
102 pd
.Flags
= PD_RETURNDC
| PD_NOSELECTION
| PD_NOPAGENUMS
;
108 pd
.hInstance
= (HINSTANCE
)NULL
;
110 m_ok
= PrintDlg( &pd
) != 0;
113 m_hDC
= (WXHDC
) pd
.hDC
;
117 #endif // wxUSE_COMMON_DIALOGS
119 if ( !driver_name
.empty() && !device_name
.empty() && !file
.empty() )
121 m_hDC
= (WXHDC
) CreateDC(driver_name
.wx_str(),
122 device_name
.wx_str(),
126 else // we don't have all parameters, ask the user
128 wxPrintData printData
;
129 printData
.SetOrientation(orientation
);
130 m_hDC
= wxGetPrinterDC(printData
);
133 m_ok
= m_hDC
? true: false;
135 // as we created it, we must delete it as well
143 wxPrinterDCImpl::wxPrinterDCImpl( wxPrinterDC
*owner
, const wxPrintData
& printData
) :
146 m_printData
= printData
;
148 m_isInteractive
= false;
150 m_hDC
= wxGetPrinterDC(printData
);
158 wxPrinterDCImpl::wxPrinterDCImpl( wxPrinterDC
*owner
, WXHDC dc
) :
161 m_isInteractive
= false;
168 void wxPrinterDCImpl::Init()
172 // int width = GetDeviceCaps(m_hDC, VERTRES);
173 // int height = GetDeviceCaps(m_hDC, HORZRES);
174 SetMapMode(wxMM_TEXT
);
176 SetBrush(*wxBLACK_BRUSH
);
177 SetPen(*wxBLACK_PEN
);
181 // ----------------------------------------------------------------------------
182 // wxPrinterDCImpl {Start/End}{Page/Doc} methods
183 // ----------------------------------------------------------------------------
185 bool wxPrinterDCImpl::StartDoc(const wxString
& message
)
188 docinfo
.cbSize
= sizeof(DOCINFO
);
189 docinfo
.lpszDocName
= message
.wx_str();
191 wxString
filename(m_printData
.GetFilename());
193 if (filename
.empty())
194 docinfo
.lpszOutput
= NULL
;
196 docinfo
.lpszOutput
= filename
.wx_str();
198 docinfo
.lpszDatatype
= NULL
;
204 if ( ::StartDoc(GetHdc(), &docinfo
) <= 0 )
206 wxLogLastError(wxT("StartDoc"));
213 void wxPrinterDCImpl::EndDoc()
215 if (m_hDC
) ::EndDoc((HDC
) m_hDC
);
218 void wxPrinterDCImpl::StartPage()
221 ::StartPage((HDC
) m_hDC
);
224 void wxPrinterDCImpl::EndPage()
227 ::EndPage((HDC
) m_hDC
);
231 wxRect
wxPrinterDCImpl::GetPaperRect()
234 if (!IsOk()) return wxRect(0, 0, 0, 0);
235 int w
= ::GetDeviceCaps((HDC
) m_hDC
, PHYSICALWIDTH
);
236 int h
= ::GetDeviceCaps((HDC
) m_hDC
, PHYSICALHEIGHT
);
237 int x
= -::GetDeviceCaps((HDC
) m_hDC
, PHYSICALOFFSETX
);
238 int y
= -::GetDeviceCaps((HDC
) m_hDC
, PHYSICALOFFSETY
);
239 return wxRect(x
, y
, w
, h
);
243 #if !wxUSE_PS_PRINTING
245 // Returns default device and port names
246 static bool wxGetDefaultDeviceName(wxString
& deviceName
, wxString
& portName
)
250 LPDEVNAMES lpDevNames
;
251 LPTSTR lpszDeviceName
;
256 // Cygwin has trouble believing PRINTDLG is 66 bytes - thinks it is 68
259 pd
.lStructSize
= 66; // sizeof(PRINTDLG);
261 memset(&pd
, 0, sizeof(PRINTDLG
));
262 pd
.lStructSize
= sizeof(PRINTDLG
);
265 pd
.hwndOwner
= (HWND
)NULL
;
266 pd
.hDevMode
= NULL
; // Will be created by PrintDlg
267 pd
.hDevNames
= NULL
; // Ditto
268 pd
.Flags
= PD_RETURNDEFAULT
;
271 if (!PrintDlg((LPPRINTDLG
)&pd
))
274 GlobalFree(pd
.hDevMode
);
276 GlobalFree(pd
.hDevNames
);
283 lpDevNames
= (LPDEVNAMES
)GlobalLock(pd
.hDevNames
);
284 lpszDeviceName
= (LPTSTR
)lpDevNames
+ lpDevNames
->wDeviceOffset
;
285 lpszPortName
= (LPTSTR
)lpDevNames
+ lpDevNames
->wOutputOffset
;
287 deviceName
= lpszDeviceName
;
288 portName
= lpszPortName
;
290 GlobalUnlock(pd
.hDevNames
);
291 GlobalFree(pd
.hDevNames
);
297 GlobalFree(pd
.hDevMode
);
300 return ( !deviceName
.empty() );
303 #endif // !wxUSE_PS_PRINTING
305 // Gets an HDC for the specified printer configuration
306 WXHDC WXDLLEXPORT
wxGetPrinterDC(const wxPrintData
& printDataConst
)
308 #if wxUSE_PS_PRINTING
310 wxUnusedVar(printDataConst
);
312 #else // native Windows printing
313 wxWindowsPrintNativeData
*data
=
314 (wxWindowsPrintNativeData
*) printDataConst
.GetNativeData();
316 data
->TransferFrom( printDataConst
);
318 wxString deviceName
= printDataConst
.GetPrinterName();
319 if ( deviceName
.empty() )
321 // Retrieve the default device name
323 if ( !wxGetDefaultDeviceName(deviceName
, portName
) )
325 return 0; // Could not get default device name
330 HGLOBAL hDevMode
= (HGLOBAL
)(DWORD
) data
->GetDevMode();
332 DEVMODE
*lpDevMode
= hDevMode
? (DEVMODE
*)::GlobalLock(hDevMode
) : NULL
;
334 HDC hDC
= ::CreateDC(NULL
, deviceName
.wx_str(), NULL
, lpDevMode
);
336 wxLogLastError(_T("CreateDC(printer)"));
339 ::GlobalUnlock(hDevMode
);
342 #endif // PostScript/Windows printing
345 // ----------------------------------------------------------------------------
346 // wxPrinterDCImpl bit blitting/bitmap drawing
347 // ----------------------------------------------------------------------------
349 // helper of DoDrawBitmap() and DoBlit()
351 bool DrawBitmapUsingStretchDIBits(HDC hdc
,
353 wxCoord x
, wxCoord y
)
357 bool ok
= dib
.IsOk();
362 if ( !::GetObject(dib
.GetHandle(), sizeof(ds
), &ds
) )
364 wxLogLastError(_T("GetObject(DIBSECTION)"));
369 // ok, we've got all data we need, do blit it
374 ds
.dsBmih
.biWidth
, ds
.dsBmih
.biHeight
,
376 ds
.dsBmih
.biWidth
, ds
.dsBmih
.biHeight
,
378 (LPBITMAPINFO
)&ds
.dsBmih
,
383 wxLogLastError(wxT("StretchDIBits"));
394 void wxPrinterDCImpl::DoDrawBitmap(const wxBitmap
& bmp
,
395 wxCoord x
, wxCoord y
,
398 wxCHECK_RET( bmp
.Ok(), _T("invalid bitmap in wxPrinterDC::DrawBitmap") );
400 int width
= bmp
.GetWidth(),
401 height
= bmp
.GetHeight();
403 if ( !(::GetDeviceCaps(GetHdc(), RASTERCAPS
) & RC_STRETCHDIB
) ||
404 !DrawBitmapUsingStretchDIBits(GetHdc(), bmp
, x
, y
) )
406 // no support for StretchDIBits() or an error occurred if we got here
409 memDC
.SelectObjectAsSource(bmp
);
411 GetOwner()->Blit(x
, y
, width
, height
, &memDC
, 0, 0, wxCOPY
, useMask
);
413 memDC
.SelectObject(wxNullBitmap
);
417 bool wxPrinterDCImpl::DoBlit(wxCoord xdest
, wxCoord ydest
,
418 wxCoord width
, wxCoord height
,
420 wxCoord
WXUNUSED(xsrc
), wxCoord
WXUNUSED(ysrc
),
421 int WXUNUSED(rop
), bool useMask
,
422 wxCoord
WXUNUSED(xsrcMask
), wxCoord
WXUNUSED(ysrcMask
))
424 wxDCImpl
*impl
= source
->GetImpl();
425 wxMSWDCImpl
*msw_impl
= wxDynamicCast(impl
, wxMSWDCImpl
);
429 wxBitmap
& bmp
= msw_impl
->GetSelectedBitmap();
430 wxMask
*mask
= useMask
? bmp
.GetMask() : NULL
;
433 // If we are printing source colours are screen colours not printer
434 // colours and so we need copy the bitmap pixel by pixel.
436 HDC dcSrc
= GetHdcOf(*msw_impl
);
437 MemoryHDC
dcMask(dcSrc
);
438 SelectInHDC
selectMask(dcMask
, (HBITMAP
)mask
->GetMaskBitmap());
440 for (int x
= 0; x
< width
; x
++)
442 for (int y
= 0; y
< height
; y
++)
444 COLORREF cref
= ::GetPixel(dcMask
, x
, y
);
447 HBRUSH brush
= ::CreateSolidBrush(::GetPixel(dcSrc
, x
, y
));
448 rect
.left
= xdest
+ x
;
449 rect
.right
= rect
.left
+ 1;
450 rect
.top
= ydest
+ y
;
451 rect
.bottom
= rect
.top
+ 1;
452 ::FillRect(GetHdc(), &rect
, brush
);
453 ::DeleteObject(brush
);
460 if ( !(::GetDeviceCaps(GetHdc(), RASTERCAPS
) & RC_STRETCHDIB
) ||
461 !DrawBitmapUsingStretchDIBits(GetHdc(), bmp
, xdest
, ydest
) )
463 // no support for StretchDIBits
465 // as we are printing, source colours are screen colours not
466 // printer colours and so we need copy the bitmap pixel by pixel.
467 HDC dcSrc
= GetHdcOf(*msw_impl
);
469 for (int y
= 0; y
< height
; y
++)
471 // optimization: draw identical adjacent pixels together.
472 for (int x
= 0; x
< width
; x
++)
474 COLORREF col
= ::GetPixel(dcSrc
, x
, y
);
475 HBRUSH brush
= ::CreateSolidBrush( col
);
477 rect
.left
= xdest
+ x
;
478 rect
.top
= ydest
+ y
;
479 while( (x
+ 1 < width
) &&
480 (::GetPixel(dcSrc
, x
+ 1, y
) == col
) )
484 rect
.right
= xdest
+ x
+ 1;
485 rect
.bottom
= rect
.top
+ 1;
486 ::FillRect((HDC
) m_hDC
, &rect
, brush
);
487 ::DeleteObject(brush
);
497 // wxUSE_PRINTING_ARCHITECTURE