]>
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 // ----------------------------------------------------------------------------
21 #pragma implementation "dcprint.h"
24 // For compilers that support precompilation, includes "wx.h".
25 #include "wx/wxprec.h"
32 #include "wx/string.h"
34 #include "wx/window.h"
35 #include "wx/dcmemory.h"
38 #if wxUSE_PRINTING_ARCHITECTURE
40 #include "wx/msw/private.h"
41 #include "wx/msw/dib.h"
42 #include "wx/dcprint.h"
45 #if wxUSE_COMMON_DIALOGS
53 // mingw32 defines GDI_ERROR incorrectly
54 #if defined(__GNUWIN32__) || !defined(GDI_ERROR)
56 #define GDI_ERROR ((int)-1)
59 // ----------------------------------------------------------------------------
61 // ----------------------------------------------------------------------------
63 IMPLEMENT_CLASS(wxPrinterDC
, wxDC
)
65 // ============================================================================
67 // ============================================================================
69 // ----------------------------------------------------------------------------
70 // wxPrinterDC construction
71 // ----------------------------------------------------------------------------
73 // This form is deprecated
74 wxPrinterDC::wxPrinterDC(const wxString
& driver_name
,
75 const wxString
& device_name
,
80 m_isInteractive
= interactive
;
83 m_printData
.SetFilename(file
);
85 #if wxUSE_COMMON_DIALOGS
90 pd
.lStructSize
= sizeof( PRINTDLG
);
91 pd
.hwndOwner
= (HWND
) NULL
;
92 pd
.hDevMode
= (HANDLE
)NULL
;
93 pd
.hDevNames
= (HANDLE
)NULL
;
94 pd
.Flags
= PD_RETURNDC
| PD_NOSELECTION
| PD_NOPAGENUMS
;
100 pd
.hInstance
= (HINSTANCE
)NULL
;
102 m_ok
= PrintDlg( &pd
) != 0;
105 m_hDC
= (WXHDC
) pd
.hDC
;
109 #endif // wxUSE_COMMON_DIALOGS
111 if ( !driver_name
.empty() && !device_name
.empty() && !file
.empty() )
113 m_hDC
= (WXHDC
) CreateDC(driver_name
, device_name
, file
, NULL
);
115 else // we don't have all parameters, ask the user
117 wxPrintData printData
;
118 printData
.SetOrientation(orientation
);
119 m_hDC
= wxGetPrinterDC(printData
);
122 m_ok
= m_hDC
? TRUE
: FALSE
;
124 // as we created it, we must delete it as well
131 wxPrinterDC::wxPrinterDC(const wxPrintData
& printData
)
133 m_printData
= printData
;
135 m_isInteractive
= FALSE
;
137 m_hDC
= wxGetPrinterDC(printData
);
145 wxPrinterDC::wxPrinterDC(WXHDC dc
)
147 m_isInteractive
= FALSE
;
154 void wxPrinterDC::Init()
158 // int width = GetDeviceCaps(m_hDC, VERTRES);
159 // int height = GetDeviceCaps(m_hDC, HORZRES);
160 SetMapMode(wxMM_TEXT
);
162 SetBrush(*wxBLACK_BRUSH
);
163 SetPen(*wxBLACK_PEN
);
167 // ----------------------------------------------------------------------------
168 // wxPrinterDC {Start/End}{Page/Doc} methods
169 // ----------------------------------------------------------------------------
171 bool wxPrinterDC::StartDoc(const wxString
& message
)
174 docinfo
.cbSize
= sizeof(DOCINFO
);
175 docinfo
.lpszDocName
= (const wxChar
*)message
;
177 wxString
filename(m_printData
.GetFilename());
179 if (filename
.IsEmpty())
180 docinfo
.lpszOutput
= NULL
;
182 docinfo
.lpszOutput
= (const wxChar
*) filename
;
184 #if defined(__WIN95__)
185 docinfo
.lpszDatatype
= NULL
;
192 int ret
= ::StartDoc(GetHdc(), &docinfo
);
197 DWORD lastError
= GetLastError();
198 wxLogDebug(wxT("wxDC::StartDoc failed with error: %ld\n"), lastError
);
205 void wxPrinterDC::EndDoc()
207 if (m_hDC
) ::EndDoc((HDC
) m_hDC
);
210 void wxPrinterDC::StartPage()
213 ::StartPage((HDC
) m_hDC
);
216 void wxPrinterDC::EndPage()
219 ::EndPage((HDC
) m_hDC
);
222 // Returns default device and port names
223 static bool wxGetDefaultDeviceName(wxString
& deviceName
, wxString
& portName
)
227 LPDEVNAMES lpDevNames
;
228 LPTSTR lpszDriverName
;
229 LPTSTR lpszDeviceName
;
234 // Cygwin has trouble believing PRINTDLG is 66 bytes - thinks it is 68
237 pd
.lStructSize
= 66; // sizeof(PRINTDLG);
239 memset(&pd
, 0, sizeof(PRINTDLG
));
240 pd
.lStructSize
= sizeof(PRINTDLG
);
243 pd
.hwndOwner
= (HWND
)NULL
;
244 pd
.hDevMode
= NULL
; // Will be created by PrintDlg
245 pd
.hDevNames
= NULL
; // Ditto
246 pd
.Flags
= PD_RETURNDEFAULT
;
249 if (!PrintDlg((LPPRINTDLG
)&pd
))
252 GlobalFree(pd
.hDevMode
);
254 GlobalFree(pd
.hDevNames
);
261 lpDevNames
= (LPDEVNAMES
)GlobalLock(pd
.hDevNames
);
262 lpszDriverName
= (LPTSTR
)lpDevNames
+ lpDevNames
->wDriverOffset
;
263 lpszDeviceName
= (LPTSTR
)lpDevNames
+ lpDevNames
->wDeviceOffset
;
264 lpszPortName
= (LPTSTR
)lpDevNames
+ lpDevNames
->wOutputOffset
;
266 deviceName
= lpszDeviceName
;
267 portName
= lpszPortName
;
269 GlobalUnlock(pd
.hDevNames
);
270 GlobalFree(pd
.hDevNames
);
276 GlobalFree(pd
.hDevMode
);
279 return ( deviceName
!= wxT("") );
282 // Gets an HDC for the specified printer configuration
283 WXHDC WXDLLEXPORT
wxGetPrinterDC(const wxPrintData
& printDataConst
)
285 wxPrintData printData
= printDataConst
;
286 printData
.ConvertToNative();
288 wxChar
* driverName
= (wxChar
*) NULL
;
290 wxString devNameStr
= printData
.GetPrinterName();
291 wxChar
* portName
= (wxChar
*) NULL
; // Obsolete in WIN32
293 const wxChar
* deviceName
;
295 deviceName
= (wxChar
*) NULL
;
297 deviceName
= devNameStr
.c_str();
299 LPDEVMODE lpDevMode
= (LPDEVMODE
) NULL
;
301 HGLOBAL hDevMode
= (HGLOBAL
)(DWORD
) printData
.GetNativeData();
304 lpDevMode
= (DEVMODE
*) GlobalLock(hDevMode
);
308 // Retrieve the default device name
314 #endif // Debug/Release
315 wxGetDefaultDeviceName(devNameStr
, portName
);
317 wxASSERT_MSG( ret
, wxT("Could not get default device name.") );
319 deviceName
= devNameStr
.c_str();
323 HDC hDC
= CreateDC(driverName
, deviceName
, portName
, (DEVMODE
*) lpDevMode
);
325 HDC hDC
= CreateDC(driverName
, deviceName
, portName
, (LPSTR
) lpDevMode
);
328 if (hDevMode
&& lpDevMode
)
329 GlobalUnlock(hDevMode
);
334 // ----------------------------------------------------------------------------
335 // wxPrinterDC bit blitting/bitmap drawing
336 // ----------------------------------------------------------------------------
338 // helper of DoDrawBitmap() and DoBlit()
340 bool DrawBitmapUsingStretchDIBits(HDC hdc
,
342 wxCoord x
, wxCoord y
)
349 if ( !::GetObject(dib
.GetHandle(), sizeof(ds
), &ds
) )
351 wxLogLastError(_T("GetObject(DIBSECTION)"));
356 // ok, we've got all data we need, do blit it
361 ds
.dsBmih
.biWidth
, ds
.dsBmih
.biHeight
,
363 ds
.dsBmih
.biWidth
, ds
.dsBmih
.biHeight
,
365 (LPBITMAPINFO
)&ds
.dsBmih
,
370 wxLogLastError(wxT("StretchDIBits"));
378 void wxPrinterDC::DoDrawBitmap(const wxBitmap
& bmp
,
379 wxCoord x
, wxCoord y
,
382 wxCHECK_RET( bmp
.Ok(), _T("invalid bitmap in wxPrinterDC::DrawBitmap") );
384 int width
= bmp
.GetWidth(),
385 height
= bmp
.GetHeight();
387 if ( !(::GetDeviceCaps(GetHdc(), RASTERCAPS
) & RC_STRETCHDIB
) ||
388 !DrawBitmapUsingStretchDIBits(GetHdc(), bmp
, x
, y
) )
390 // no support for StretchDIBits() or an error occured if we got here
392 memDC
.SelectObject(bmp
);
394 Blit(x
, y
, width
, height
, &memDC
, 0, 0, wxCOPY
, useMask
);
396 memDC
.SelectObject(wxNullBitmap
);
400 bool wxPrinterDC::DoBlit(wxCoord xdest
, wxCoord ydest
,
401 wxCoord width
, wxCoord height
,
403 wxCoord xsrc
, wxCoord ysrc
,
404 int WXUNUSED(rop
), bool useMask
,
405 wxCoord
WXUNUSED(xsrcMask
), wxCoord
WXUNUSED(ysrcMask
))
407 wxBitmap
& bmp
= source
->GetSelectedBitmap();
408 wxMask
*mask
= useMask
? bmp
.GetMask() : NULL
;
411 // If we are printing source colours are screen colours not printer
412 // colours and so we need copy the bitmap pixel by pixel.
414 HDC dcSrc
= GetHdcOf(*source
);
415 MemoryHDC
dcMask(dcSrc
);
416 SelectInHDC
selectMask(dcMask
, (HBITMAP
)mask
->GetMaskBitmap());
418 for (int x
= 0; x
< width
; x
++)
420 for (int y
= 0; y
< height
; y
++)
422 COLORREF cref
= ::GetPixel(dcMask
, x
, y
);
425 HBRUSH brush
= ::CreateSolidBrush(::GetPixel(dcSrc
, x
, y
));
426 rect
.left
= xdest
+ x
;
427 rect
.right
= rect
.left
+ 1;
428 rect
.top
= ydest
+ y
;
429 rect
.bottom
= rect
.top
+ 1;
430 ::FillRect(GetHdc(), &rect
, brush
);
431 ::DeleteObject(brush
);
438 if ( !(::GetDeviceCaps(GetHdc(), RASTERCAPS
) & RC_STRETCHDIB
) ||
439 !DrawBitmapUsingStretchDIBits(GetHdc(), bmp
, xdest
, ydest
) )
441 // no support for StretchDIBits
443 // as we are printing, source colours are screen colours not
444 // printer colours and so we need copy the bitmap pixel by pixel.
445 HDC dcSrc
= GetHdcOf(*source
);
447 for (int y
= 0; y
< height
; y
++)
449 // optimization: draw identical adjacent pixels together.
450 for (int x
= 0; x
< width
; x
++)
452 COLORREF col
= ::GetPixel(dcSrc
, x
, y
);
453 HBRUSH brush
= ::CreateSolidBrush( col
);
455 rect
.left
= xdest
+ x
;
456 rect
.top
= ydest
+ y
;
457 while( (x
+ 1 < width
) &&
458 (::GetPixel(dcSrc
, x
+ 1, y
) == col
) )
462 rect
.right
= xdest
+ x
+ 1;
463 rect
.bottom
= rect
.top
+ 1;
464 ::FillRect((HDC
) m_hDC
, &rect
, brush
);
465 ::DeleteObject(brush
);
475 // wxUSE_PRINTING_ARCHITECTURE