diff --git a/include/wx/msw/private.h b/include/wx/msw/private.h index a96d9d2183..7b92082f5a 100644 --- a/include/wx/msw/private.h +++ b/include/wx/msw/private.h @@ -650,6 +650,52 @@ private: DECLARE_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 9206d115a9..f05f53bf48 100644 --- a/src/msw/printdlg.cpp +++ b/src/msw/printdlg.cpp @@ -352,6 +352,55 @@ bool wxWindowsPrintNativeData::TransferFrom( const wxPrintData &data ) { HGLOBAL hDevMode = (HGLOBAL)(DWORD) m_devMode; HGLOBAL hDevNames = (HGLOBAL)(DWORD) m_devNames; + 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 (!hDevMode) { // Use PRINTDLG as a way of creating a DEVMODE object @@ -476,7 +525,7 @@ bool wxWindowsPrintNativeData::TransferFrom( const wxPrintData &data ) devMode->dmPaperLength = (short)(paperSize.y * 10); devMode->dmFields |= DM_PAPERWIDTH; devMode->dmFields |= DM_PAPERLENGTH; - + // A printer driver may or may not also want DM_PAPERSIZE to // be specified. Also, if the printer driver doesn't implement the DMPAPER_USER // size, then this won't work, and even if you found the correct id by @@ -527,6 +576,8 @@ bool wxWindowsPrintNativeData::TransferFrom( const wxPrintData &data ) break; default: quality = (short)data.GetQuality(); + devMode->dmYResolution = quality; + devMode->dmFields |= DM_YRESOLUTION; break; } devMode->dmPrintQuality = quality; @@ -568,6 +619,20 @@ 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. + } GlobalUnlock(hDevMode); } @@ -879,17 +944,17 @@ int wxWindowsPageSetupDialog::ShowModal() pd->hwndOwner = (HWND) wxTheApp->GetTopWindow()->GetHWND(); else pd->hwndOwner = 0; - + BOOL retVal = PageSetupDlg( pd ) ; pd->hwndOwner = 0; - + if (retVal) { ConvertFromNative( m_pageSetupData ); - + return wxID_OK; } - + return wxID_CANCEL; } @@ -898,7 +963,7 @@ bool wxWindowsPageSetupDialog::ConvertToNative( wxPageSetupDialogData &data ) wxWindowsPrintNativeData *native_data = (wxWindowsPrintNativeData *) data.GetPrintData().GetNativeData(); data.GetPrintData().ConvertToNative(); - + PAGESETUPDLG *pd = (PAGESETUPDLG*) m_pageDlg; // Shouldn't have been defined anywhere