diff --git a/include/wx/msw/private.h b/include/wx/msw/private.h index 9e40732a37..fa95062dc0 100644 --- a/include/wx/msw/private.h +++ b/include/wx/msw/private.h @@ -727,6 +727,52 @@ private: wxDECLARE_NO_COPY_CLASS(GlobalPtrLock); }; +// smart pointer like class using OpenPrinter and ClosePrinter +class WinPrinter +{ +public: + // default ctor + WinPrinter() + { + m_hPrinter = (HANDLE)NULL; + } + + WinPrinter( const wxString& printerName ) + { + Open( printerName ); + } + + ~WinPrinter() + { + Close(); + } + + BOOL Open( const wxString& printerName, LPPRINTER_DEFAULTS pDefault=(LPPRINTER_DEFAULTS)NULL ) + { + Close(); + return OpenPrinter( (LPTSTR)printerName.wx_str(), &m_hPrinter, pDefault ); + } + + BOOL Close() + { + BOOL result = TRUE; + if( m_hPrinter ) + { + result = ClosePrinter( m_hPrinter ); + m_hPrinter = (HANDLE)NULL; + } + return result; + } + + operator HANDLE() { return m_hPrinter; } + operator bool() { return m_hPrinter != (HANDLE)NULL; } + +private: + HANDLE m_hPrinter; + + wxDECLARE_NO_COPY_CLASS(WinPrinter); +}; + // register the class when it is first needed and unregister it in dtor class ClassRegistrar { diff --git a/src/msw/printdlg.cpp b/src/msw/printdlg.cpp index 37bdfd3aba..b9b89b6210 100644 --- a/src/msw/printdlg.cpp +++ b/src/msw/printdlg.cpp @@ -339,6 +339,55 @@ bool wxWindowsPrintNativeData::TransferTo( wxPrintData &data ) bool wxWindowsPrintNativeData::TransferFrom( const wxPrintData &data ) { HGLOBAL hDevMode = static_cast(m_devMode); + WinPrinter printer; + LPTSTR szPrinterName = (LPTSTR)data.GetPrinterName().wx_str(); + + // From MSDN: How To Modify Printer Settings with the DocumentProperties() Function + // The purpose of this is to fill the DEVMODE with privdata from printer driver. + // If we have a printer name and OpenPrinter sucessfully returns + // this replaces the PrintDlg function which creates the DEVMODE filled only with data from default printer. + if ( !m_devMode && !data.GetPrinterName().IsEmpty() ) + { + // Open printer + if ( printer.Open( data.GetPrinterName() ) == TRUE ) + { + DWORD dwNeeded, dwRet; + + // Step 1: + // Allocate a buffer of the correct size. + dwNeeded = DocumentProperties( NULL, + printer, // Handle to our printer. + szPrinterName, // Name of the printer. + NULL, // Asking for size, so + NULL, // these are not used. + 0 ); // Zero returns buffer size. + + LPDEVMODE tempDevMode = static_cast( GlobalAlloc( GMEM_FIXED | GMEM_ZEROINIT, dwNeeded ) ); + + // Step 2: + // Get the default DevMode for the printer + dwRet = DocumentProperties( NULL, + printer, + szPrinterName, + tempDevMode, // The address of the buffer to fill. + NULL, // Not using the input buffer. + DM_OUT_BUFFER ); // Have the output buffer filled. + + if ( dwRet != IDOK ) + { + // If failure, cleanup + GlobalFree( tempDevMode ); + printer.Close(); + } + else + { + hDevMode = tempDevMode; + m_devMode = hDevMode; + tempDevMode = NULL; + } + } + } + if ( !m_devMode ) { // Use PRINTDLG as a way of creating a DEVMODE object @@ -508,6 +557,8 @@ bool wxWindowsPrintNativeData::TransferFrom( const wxPrintData &data ) break; default: quality = (short)data.GetQuality(); + devMode->dmYResolution = quality; + devMode->dmFields |= DM_YRESOLUTION; break; } devMode->dmPrintQuality = quality; @@ -549,6 +600,21 @@ bool wxWindowsPrintNativeData::TransferFrom( const wxPrintData &data ) devMode->dmMediaType = data.GetMedia(); devMode->dmFields |= DM_MEDIATYPE; } + + if( printer ) + { + // Step 3: + // Merge the new settings with the old. + // This gives the driver an opportunity to update any private + // portions of the DevMode structure. + DocumentProperties( NULL, + printer, + szPrinterName, + (LPDEVMODE)hDevMode, // Reuse our buffer for output. + (LPDEVMODE)hDevMode, // Pass the driver our changes + DM_IN_BUFFER | // Commands to Merge our changes and + DM_OUT_BUFFER ); // write the result. + } } if ( m_devNames )