]>
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 and Markus Holzem
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 #include "wx/msw/private.h"
39 #include "wx/dcprint.h"
42 #if wxUSE_COMMON_DIALOGS || defined(__WXWINE__)
50 // mingw32 defines GDI_ERROR incorrectly
53 #define GDI_ERROR ((int)-1)
56 // ----------------------------------------------------------------------------
58 // ----------------------------------------------------------------------------
60 IMPLEMENT_CLASS(wxPrinterDC
, wxDC
)
62 // ============================================================================
64 // ============================================================================
66 // ----------------------------------------------------------------------------
67 // wxPrinterDC construction
68 // ----------------------------------------------------------------------------
70 // This form is deprecated
71 wxPrinterDC::wxPrinterDC(const wxString
& driver_name
, const wxString
& device_name
, const wxString
& file
, bool interactive
, int orientation
)
73 m_isInteractive
= interactive
;
76 m_printData
.SetFilename(file
);
78 #if wxUSE_COMMON_DIALOGS
83 pd
.lStructSize
= sizeof( PRINTDLG
);
84 pd
.hwndOwner
=(HWND
) NULL
;
85 pd
.hDevMode
=(HANDLE
)NULL
;
86 pd
.hDevNames
=(HANDLE
)NULL
;
87 pd
.Flags
=PD_RETURNDC
| PD_NOSELECTION
| PD_NOPAGENUMS
;
93 pd
.hInstance
=(HINSTANCE
)NULL
;
95 if ( PrintDlg( &pd
) != 0 )
97 m_hDC
= (WXHDC
) pd
.hDC
;
106 // m_dontDelete = TRUE;
109 #endif // wxUSE_COMMON_DIALOGS
110 if ((!driver_name
.IsNull() && driver_name
!= wxT("")) &&
111 (!device_name
.IsNull() && device_name
!= wxT("")) &&
112 (!file
.IsNull() && file
!= wxT("")))
114 m_hDC
= (WXHDC
) CreateDC(WXSTRINGCAST driver_name
, WXSTRINGCAST device_name
, WXSTRINGCAST file
, NULL
);
115 m_ok
= m_hDC
? TRUE
: FALSE
;
119 wxPrintData printData
;
120 printData
.SetOrientation(orientation
);
121 m_hDC
= wxGetPrinterDC(printData
);
122 m_ok
= m_hDC
? TRUE
: FALSE
;
127 // int width = GetDeviceCaps(m_hDC, VERTRES);
128 // int height = GetDeviceCaps(m_hDC, HORZRES);
129 SetMapMode(wxMM_TEXT
);
131 SetBrush(*wxBLACK_BRUSH
);
132 SetPen(*wxBLACK_PEN
);
135 wxPrinterDC::wxPrinterDC(const wxPrintData
& printData
)
137 m_printData
= printData
;
139 m_isInteractive
= FALSE
;
141 m_hDC
= wxGetPrinterDC(printData
);
145 SetMapMode(wxMM_TEXT
);
147 SetBrush(*wxBLACK_BRUSH
);
148 SetPen(*wxBLACK_PEN
);
152 wxPrinterDC::wxPrinterDC(WXHDC theDC
)
154 m_isInteractive
= FALSE
;
160 // int width = GetDeviceCaps(m_hDC, VERTRES);
161 // int height = GetDeviceCaps(m_hDC, HORZRES);
162 SetMapMode(wxMM_TEXT
);
164 SetBrush(*wxBLACK_BRUSH
);
165 SetPen(*wxBLACK_PEN
);
168 wxPrinterDC::~wxPrinterDC()
172 // ----------------------------------------------------------------------------
173 // wxPrinterDC {Start/End}{Page/Doc} methods
174 // ----------------------------------------------------------------------------
176 bool wxPrinterDC::StartDoc(const wxString
& message
)
179 docinfo
.cbSize
= sizeof(DOCINFO
);
180 docinfo
.lpszDocName
= (const wxChar
*)message
;
182 wxString
filename(m_printData
.GetFilename());
184 if (filename
.IsEmpty())
185 docinfo
.lpszOutput
= NULL
;
187 docinfo
.lpszOutput
= (const wxChar
*) filename
;
189 #if defined(__WIN95__)
190 docinfo
.lpszDatatype
= NULL
;
197 int ret
= ::StartDoc(GetHdc(), &docinfo
);
202 DWORD lastError
= GetLastError();
203 wxLogDebug(wxT("wxDC::StartDoc failed with error: %d\n"), lastError
);
210 void wxPrinterDC::EndDoc()
212 if (m_hDC
) ::EndDoc((HDC
) m_hDC
);
215 void wxPrinterDC::StartPage()
218 ::StartPage((HDC
) m_hDC
);
221 void wxPrinterDC::EndPage()
224 ::EndPage((HDC
) m_hDC
);
227 // Returns default device and port names
228 static bool wxGetDefaultDeviceName(wxString
& deviceName
, wxString
& portName
)
232 LPDEVNAMES lpDevNames
;
233 LPSTR lpszDriverName
;
234 LPSTR lpszDeviceName
;
239 // Cygwin has trouble believing PRINTDLG is 66 bytes - thinks it is 68
241 pd
.lStructSize
= 66; // 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 lpszDriverName
= (LPSTR
)lpDevNames
+ lpDevNames
->wDriverOffset
;
266 lpszDeviceName
= (LPSTR
)lpDevNames
+ lpDevNames
->wDeviceOffset
;
267 lpszPortName
= (LPSTR
)lpDevNames
+ lpDevNames
->wOutputOffset
;
269 deviceName
= lpszDeviceName
;
270 portName
= lpszPortName
;
272 GlobalUnlock(pd
.hDevNames
);
273 GlobalFree(pd
.hDevNames
);
279 GlobalFree(pd
.hDevMode
);
282 return ( deviceName
!= wxT("") );
286 // This uses defaults, except for orientation, so we should eliminate this function
287 // and use the 2nd form (passing wxPrintData) instead.
288 WXHDC
wxGetPrinterDC(int orientation
)
291 LPDEVMODE lpDevMode
= NULL
;
292 LPDEVNAMES lpDevNames
;
293 LPSTR lpszDriverName
;
294 LPSTR lpszDeviceName
;
298 // __GNUWIN32__ has trouble believing PRINTDLG is 66 bytes - thinks it is 68
300 pd
.lStructSize
= 66; // sizeof(PRINTDLG);
302 pd
.lStructSize
= sizeof(PRINTDLG
);
304 pd
.hwndOwner
= (HWND
)NULL
;
305 pd
.hDevMode
= NULL
; // Will be created by PrintDlg
306 pd
.hDevNames
= NULL
; // Ditto
307 pd
.Flags
= PD_RETURNDEFAULT
;
310 if (!PrintDlg((LPPRINTDLG
)&pd
))
313 GlobalFree(pd
.hDevMode
);
315 GlobalFree(pd
.hDevNames
);
323 GlobalFree(pd
.hDevMode
);
326 lpDevNames
= (LPDEVNAMES
)GlobalLock(pd
.hDevNames
);
327 lpszDriverName
= (LPSTR
)lpDevNames
+ lpDevNames
->wDriverOffset
;
328 lpszDeviceName
= (LPSTR
)lpDevNames
+ lpDevNames
->wDeviceOffset
;
329 lpszPortName
= (LPSTR
)lpDevNames
+ lpDevNames
->wOutputOffset
;
330 GlobalUnlock(pd
.hDevNames
);
334 lpDevMode
= (DEVMODE
*) GlobalLock(pd
.hDevMode
);
335 lpDevMode
->dmOrientation
= orientation
;
336 lpDevMode
->dmFields
|= DM_ORIENTATION
;
340 hDC
= CreateDC(lpszDriverName
, lpszDeviceName
, lpszPortName
, (DEVMODE
*)lpDevMode
);
342 hDC
= CreateDC(lpszDriverName
, lpszDeviceName
, lpszPortName
, (LPSTR
)lpDevMode
);
345 if (pd
.hDevMode
&& lpDevMode
)
346 GlobalUnlock(pd
.hDevMode
);
350 GlobalFree(pd
.hDevNames
);
355 GlobalFree(pd
.hDevMode
);
362 // Gets an HDC for the specified printer configuration
363 WXHDC WXDLLEXPORT
wxGetPrinterDC(const wxPrintData
& printDataConst
)
365 wxPrintData printData
= printDataConst
;
366 printData
.ConvertToNative();
368 wxChar
* driverName
= (wxChar
*) NULL
;
370 wxString devNameStr
= printData
.GetPrinterName();
371 wxChar
* portName
= (wxChar
*) NULL
; // Obsolete in WIN32
373 const wxChar
* deviceName
;
375 deviceName
= (wxChar
*) NULL
;
377 deviceName
= devNameStr
.c_str();
379 LPDEVMODE lpDevMode
= (LPDEVMODE
) NULL
;
381 HGLOBAL hDevMode
= (HGLOBAL
)(DWORD
) printData
.GetNativeData();
384 lpDevMode
= (DEVMODE
*) GlobalLock(hDevMode
);
388 // Retrieve the default device name
394 #endif // Debug/Release
395 wxGetDefaultDeviceName(devNameStr
, portName
);
397 wxASSERT_MSG( ret
, wxT("Could not get default device name.") );
399 deviceName
= devNameStr
.c_str();
403 HDC hDC
= CreateDC(driverName
, deviceName
, portName
, (DEVMODE
*) lpDevMode
);
405 HDC hDC
= CreateDC(driverName
, deviceName
, portName
, (LPSTR
) lpDevMode
);
408 if (hDevMode
&& lpDevMode
)
409 GlobalUnlock(hDevMode
);
414 // ----------------------------------------------------------------------------
415 // wxPrinterDC bit blitting/bitmap drawing
416 // ----------------------------------------------------------------------------
418 // Win16 doesn't define GDI_ERROR.
423 void wxPrinterDC::DoDrawBitmap(const wxBitmap
&bmp
,
424 wxCoord x
, wxCoord y
,
427 wxCHECK_RET( bmp
.Ok(), _T("invalid bitmap in wxPrinterDC::DrawBitmap") );
429 int width
= bmp
.GetWidth(),
430 height
= bmp
.GetHeight();
432 if ( ::GetDeviceCaps(GetHdc(), RASTERCAPS
) & RC_STRETCHDIB
)
434 BITMAPINFO
*info
= (BITMAPINFO
*) malloc( sizeof( BITMAPINFOHEADER
) + 256 * sizeof(RGBQUAD
) );
435 memset( info
, 0, sizeof( BITMAPINFOHEADER
) );
437 int iBitsSize
= ((width
+ 3 ) & ~3 ) * height
;
439 void* bits
= malloc( iBitsSize
);
441 info
->bmiHeader
.biSize
= sizeof( BITMAPINFOHEADER
);
442 info
->bmiHeader
.biWidth
= width
;
443 info
->bmiHeader
.biHeight
= height
;
444 info
->bmiHeader
.biPlanes
= 1;
445 info
->bmiHeader
.biBitCount
= 8;
446 info
->bmiHeader
.biCompression
= BI_RGB
;
449 if ( GetDIBits(display
, GetHbitmapOf(bmp
), 0,
450 bmp
.GetHeight(), bits
, info
,
453 if ( ::StretchDIBits(GetHdc(), x
, y
,
455 0 , 0, width
, height
,
457 DIB_RGB_COLORS
, SRCCOPY
) == GDI_ERROR
)
459 wxLogLastError("StretchDIBits");
466 else // no support for StretchDIBits()
469 memDC
.SelectObject(bmp
);
471 Blit(x
, y
, width
, height
, &memDC
, 0, 0, wxCOPY
, useMask
);
473 memDC
.SelectObject(wxNullBitmap
);
477 bool wxPrinterDC::DoBlit(wxCoord xdest
, wxCoord ydest
,
478 wxCoord width
, wxCoord height
,
480 wxCoord xsrc
, wxCoord ysrc
,
481 int rop
, bool useMask
)
487 // If we are printing source colours are screen colours
488 // not printer colours and so we need copy the bitmap
491 HDC dc_src
= GetHdcOf(*source
);
492 HDC dc_mask
= ::CreateCompatibleDC(dc_src
);
494 ::SelectObject(dc_mask
, (HBITMAP
) source
->GetSelectedBitmap().GetMask()->GetMaskBitmap());
495 for (int x
= 0; x
< width
; x
++)
497 for (int y
= 0; y
< height
; y
++)
499 COLORREF cref
= ::GetPixel(dc_mask
, x
, y
);
502 HBRUSH brush
= ::CreateSolidBrush(::GetPixel(dc_src
, x
, y
));
503 rect
.left
= xdest
+ x
;
504 rect
.right
= rect
.left
+ 1;
505 rect
.top
= ydest
+ y
;
506 rect
.bottom
= rect
.top
+ 1;
507 ::FillRect(GetHdc(), &rect
, brush
);
508 ::DeleteObject(brush
);
512 ::SelectObject(dc_mask
, 0);
517 if ( ::GetDeviceCaps(GetHdc(), RASTERCAPS
) & RC_STRETCHDIB
)
519 wxBitmap
& bmp
= source
->GetSelectedBitmap();
520 int width
= bmp
.GetWidth(),
521 height
= bmp
.GetHeight();
523 BITMAPINFO
*info
= (BITMAPINFO
*) malloc( sizeof( BITMAPINFOHEADER
) + 256 * sizeof(RGBQUAD
) );
524 int iBitsSize
= ((width
+ 3 ) & ~3 ) * height
;
526 void* bits
= malloc( iBitsSize
);
528 memset( info
, 0 , sizeof( BITMAPINFOHEADER
) );
530 info
->bmiHeader
.biSize
= sizeof( BITMAPINFOHEADER
);
531 info
->bmiHeader
.biWidth
= width
;
532 info
->bmiHeader
.biHeight
= height
;
533 info
->bmiHeader
.biPlanes
= 1;
534 info
->bmiHeader
.biBitCount
= 8;
535 info
->bmiHeader
.biCompression
= BI_RGB
;
538 if ( !::GetDIBits(display
, GetHbitmapOf(bmp
), 0,
539 height
, bits
, info
, DIB_RGB_COLORS
) )
541 wxLogLastError("GetDIBits");
548 success
= ::StretchDIBits(GetHdc(), xdest
, ydest
,
554 SRCCOPY
) != GDI_ERROR
;
557 wxLogLastError("StretchDIBits");
564 else // no support for StretchDIBits
566 // as we are printing, source colours are screen colours not printer
567 // colours and so we need copy the bitmap pixel by pixel.
568 HDC dc_src
= GetHdcOf(*source
);
570 for (int y
= 0; y
< height
; y
++)
572 // This is Stefan Csomor's optimisation, where identical adjacent
573 // pixels are drawn together.
574 for (int x
= 0; x
< width
; x
++)
576 COLORREF col
= ::GetPixel(dc_src
, x
, y
);
577 HBRUSH brush
= ::CreateSolidBrush( col
);
579 rect
.left
= xdest
+ x
;
580 rect
.top
= ydest
+ y
;
581 while( (x
+ 1 < width
) && (::GetPixel(dc_src
, x
+ 1, y
) == col
) )
585 rect
.right
= xdest
+ x
+ 1;
586 rect
.bottom
= rect
.top
+ 1;
587 ::FillRect((HDC
) m_hDC
, &rect
, brush
);
588 ::DeleteObject(brush
);