]>
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 #if defined(__GNUG__) && !defined(NO_GCC_PRAGMA) 
  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" 
  43 #include "wx/msw/dib.h" 
  46 #include "wx/dcprint.h" 
  49 #if wxUSE_COMMON_DIALOGS 
  57 // mingw32 defines GDI_ERROR incorrectly 
  58 #if defined(__GNUWIN32__) || !defined(GDI_ERROR) 
  60     #define GDI_ERROR ((int)-1) 
  63 // ---------------------------------------------------------------------------- 
  65 // ---------------------------------------------------------------------------- 
  67 IMPLEMENT_CLASS(wxPrinterDC
, wxDC
) 
  69 // ============================================================================ 
  71 // ============================================================================ 
  73 // ---------------------------------------------------------------------------- 
  74 // wxPrinterDC construction 
  75 // ---------------------------------------------------------------------------- 
  77 // This form is deprecated 
  78 wxPrinterDC::wxPrinterDC(const wxString
& driver_name
, 
  79                          const wxString
& device_name
, 
  84     m_isInteractive 
= interactive
; 
  87         m_printData
.SetFilename(file
); 
  89 #if wxUSE_COMMON_DIALOGS 
  94         pd
.lStructSize 
= sizeof( PRINTDLG 
); 
  95         pd
.hwndOwner 
= (HWND
) NULL
; 
  96         pd
.hDevMode 
= (HANDLE
)NULL
; 
  97         pd
.hDevNames 
= (HANDLE
)NULL
; 
  98         pd
.Flags 
= PD_RETURNDC 
| PD_NOSELECTION 
| PD_NOPAGENUMS
; 
 104         pd
.hInstance 
= (HINSTANCE
)NULL
; 
 106         m_ok 
= PrintDlg( &pd 
) != 0; 
 109             m_hDC 
= (WXHDC
) pd
.hDC
; 
 113 #endif // wxUSE_COMMON_DIALOGS 
 115         if ( !driver_name
.empty() && !device_name
.empty() && !file
.empty() ) 
 117             m_hDC 
= (WXHDC
) CreateDC(driver_name
, device_name
, file
, NULL
); 
 119         else // we don't have all parameters, ask the user 
 121             wxPrintData printData
; 
 122             printData
.SetOrientation(orientation
); 
 123             m_hDC 
= wxGetPrinterDC(printData
); 
 126         m_ok 
= m_hDC 
? TRUE
: FALSE
; 
 128         // as we created it, we must delete it as well 
 135 wxPrinterDC::wxPrinterDC(const wxPrintData
& printData
) 
 137     m_printData 
= printData
; 
 139     m_isInteractive 
= FALSE
; 
 141     m_hDC 
= wxGetPrinterDC(printData
); 
 149 wxPrinterDC::wxPrinterDC(WXHDC dc
) 
 151     m_isInteractive 
= FALSE
; 
 158 void wxPrinterDC::Init() 
 162         //     int width = GetDeviceCaps(m_hDC, VERTRES); 
 163         //     int height = GetDeviceCaps(m_hDC, HORZRES); 
 164         SetMapMode(wxMM_TEXT
); 
 166         SetBrush(*wxBLACK_BRUSH
); 
 167         SetPen(*wxBLACK_PEN
); 
 171 // ---------------------------------------------------------------------------- 
 172 // wxPrinterDC {Start/End}{Page/Doc} methods 
 173 // ---------------------------------------------------------------------------- 
 175 bool wxPrinterDC::StartDoc(const wxString
& message
) 
 178     docinfo
.cbSize 
= sizeof(DOCINFO
); 
 179     docinfo
.lpszDocName 
= (const wxChar
*)message
; 
 181     wxString 
filename(m_printData
.GetFilename()); 
 183     if (filename
.IsEmpty()) 
 184         docinfo
.lpszOutput 
= NULL
; 
 186         docinfo
.lpszOutput 
= (const wxChar 
*) filename
; 
 188 #if defined(__WIN95__) 
 189     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 // Returns default device and port names 
 225 static bool wxGetDefaultDeviceName(wxString
& deviceName
, wxString
& portName
) 
 229     LPDEVNAMES  lpDevNames
; 
 230     LPTSTR      lpszDeviceName
; 
 235     // Cygwin has trouble believing PRINTDLG is 66 bytes - thinks it is 68 
 238     pd
.lStructSize    
= 66; // sizeof(PRINTDLG); 
 240     memset(&pd
, 0, sizeof(PRINTDLG
)); 
 241     pd
.lStructSize    
= sizeof(PRINTDLG
); 
 244     pd
.hwndOwner      
= (HWND
)NULL
; 
 245     pd
.hDevMode       
= NULL
; // Will be created by PrintDlg 
 246     pd
.hDevNames      
= NULL
; // Ditto 
 247     pd
.Flags          
= PD_RETURNDEFAULT
; 
 250     if (!PrintDlg((LPPRINTDLG
)&pd
)) 
 253             GlobalFree(pd
.hDevMode
); 
 255             GlobalFree(pd
.hDevNames
); 
 262         lpDevNames 
= (LPDEVNAMES
)GlobalLock(pd
.hDevNames
); 
 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 
!= wxEmptyString 
); 
 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 
 310         if ( !wxGetDefaultDeviceName(devNameStr
, portName
) ) 
 312             return 0; // Could not get default device name 
 314         deviceName 
= devNameStr
.c_str(); 
 318     HDC hDC 
= CreateDC(driverName
, deviceName
, portName
, (DEVMODE 
*) lpDevMode
); 
 320     HDC hDC 
= CreateDC(driverName
, deviceName
, portName
, (LPSTR
) lpDevMode
); 
 323     if (hDevMode 
&& lpDevMode
) 
 324         GlobalUnlock(hDevMode
); 
 329 // ---------------------------------------------------------------------------- 
 330 // wxPrinterDC bit blitting/bitmap drawing 
 331 // ---------------------------------------------------------------------------- 
 333 // helper of DoDrawBitmap() and DoBlit() 
 335 bool DrawBitmapUsingStretchDIBits(HDC hdc
, 
 337                                   wxCoord x
, wxCoord y
) 
 341     bool ok 
= dib
.IsOk(); 
 346     if ( !::GetObject(dib
.GetHandle(), sizeof(ds
), &ds
) ) 
 348         wxLogLastError(_T("GetObject(DIBSECTION)")); 
 353     // ok, we've got all data we need, do blit it 
 358                 ds
.dsBmih
.biWidth
, ds
.dsBmih
.biHeight
, 
 360                 ds
.dsBmih
.biWidth
, ds
.dsBmih
.biHeight
, 
 362                 (LPBITMAPINFO
)&ds
.dsBmih
, 
 367         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 
WXUNUSED(xsrc
), wxCoord 
WXUNUSED(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