X-Git-Url: https://git.saurik.com/wxWidgets.git/blobdiff_plain/5c33522fca7cddc441a316f5b9fb50d7685435ba..1ce077e25b52782f7823b7372664db76a9aa96c9:/src/msw/printdlg.cpp diff --git a/src/msw/printdlg.cpp b/src/msw/printdlg.cpp index 46d877613e..fac6fdf743 100644 --- a/src/msw/printdlg.cpp +++ b/src/msw/printdlg.cpp @@ -42,11 +42,59 @@ #include +// 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); +}; + + //---------------------------------------------------------------------------- // wxWindowsPrintNativeData //---------------------------------------------------------------------------- -#ifdef __WXDEBUG__ +#if wxDEBUG_LEVEL + static wxString wxGetPrintDlgError() { DWORD err = CommDlgExtendedError(); @@ -79,7 +127,9 @@ static wxString wxGetPrintDlgError() } return msg; } -#endif // __WXDEBUG__ + +#endif // wxDEBUG_LEVEL + static HGLOBAL wxCreateDevNames(const wxString& driverName, @@ -142,6 +192,9 @@ bool wxWindowsPrintNativeData::IsOk() const bool wxWindowsPrintNativeData::TransferTo( wxPrintData &data ) { + if ( !m_devMode ) + InitializeDevMode(); + if ( !m_devMode ) return false; @@ -151,7 +204,7 @@ bool wxWindowsPrintNativeData::TransferTo( wxPrintData &data ) //// Orientation if (devMode->dmFields & DM_ORIENTATION) - data.SetOrientation( devMode->dmOrientation ); + data.SetOrientation( (wxPrintOrientation)devMode->dmOrientation ); //// Collation if (devMode->dmFields & DM_COLLATE) @@ -333,9 +386,58 @@ bool wxWindowsPrintNativeData::TransferTo( wxPrintData &data ) return true; } -bool wxWindowsPrintNativeData::TransferFrom( const wxPrintData &data ) +void wxWindowsPrintNativeData::InitializeDevMode(const wxString& printerName, WinPrinter* printer) { - HGLOBAL hDevMode = static_cast(m_devMode); + if (m_devMode) + return; + + LPTSTR szPrinterName = (LPTSTR)printerName.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 && !printerName.IsEmpty() ) + { + // Open printer + if ( printer && printer->Open( printerName ) == 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 + { + m_devMode = tempDevMode; + tempDevMode = NULL; + } + } + } + if ( !m_devMode ) { // Use PRINTDLG as a way of creating a DEVMODE object @@ -366,16 +468,13 @@ bool wxWindowsPrintNativeData::TransferFrom( const wxPrintData &data ) pd.hDevMode = NULL; pd.hDevNames = NULL; -#ifdef __WXDEBUG__ - wxString str(wxT("Printing error: ")); - str += wxGetPrintDlgError(); - wxLogDebug(str); -#endif // __WXDEBUG__ +#if wxDEBUG_LEVEL + wxLogDebug(wxT("Printing error: ") + wxGetPrintDlgError()); +#endif // wxDEBUG_LEVEL } else { - hDevMode = pd.hDevMode; - m_devMode = hDevMode; + m_devMode = pd.hDevMode; pd.hDevMode = NULL; // We'll create a new DEVNAMEs structure below. @@ -390,6 +489,18 @@ bool wxWindowsPrintNativeData::TransferFrom( const wxPrintData &data ) } } +} + +bool wxWindowsPrintNativeData::TransferFrom( const wxPrintData &data ) +{ + WinPrinter printer; + LPTSTR szPrinterName = (LPTSTR)data.GetPrinterName().wx_str(); + + if (!m_devMode) + InitializeDevMode(data.GetPrinterName(), &printer); + + HGLOBAL hDevMode = static_cast(m_devMode); + if ( hDevMode ) { GlobalPtrLock lockDevMode(hDevMode); @@ -412,10 +523,9 @@ bool wxWindowsPrintNativeData::TransferFrom( const wxPrintData &data ) { // NB: the cast is needed in the ANSI build, strangely enough // dmDeviceName is BYTE[] and not char[] there - wxStrncpy(reinterpret_cast(devMode->dmDeviceName), + wxStrlcpy(reinterpret_cast(devMode->dmDeviceName), name.wx_str(), - WXSIZEOF(devMode->dmDeviceName) - 1); - devMode->dmDeviceName[WXSIZEOF(devMode->dmDeviceName) - 1] = wxT('\0'); + WXSIZEOF(devMode->dmDeviceName)); } //// Colour @@ -457,6 +567,15 @@ 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 + // enumerating the driver's paper sizes, it probably won't change the actual size, + // it'll just select that custom paper type with its own current setting. + // For a discussion on this, see http://www.codeguru.com/forum/showthread.php?threadid=458617 + // Although m_customWindowsPaperId is intended to work around this, it's + // unclear how it can help you set the custom paper size programmatically. } //else: neither paper type nor size specified, don't fill DEVMODE // at all so that the system defaults are used @@ -499,6 +618,8 @@ bool wxWindowsPrintNativeData::TransferFrom( const wxPrintData &data ) break; default: quality = (short)data.GetQuality(); + devMode->dmYResolution = quality; + devMode->dmFields |= DM_YRESOLUTION; break; } devMode->dmPrintQuality = quality; @@ -540,6 +661,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 ) @@ -697,7 +833,7 @@ bool wxWindowsPrintDialog::ConvertToNative( wxPrintDialogData &data ) pd->hwndOwner = NULL; pd->hInstance = NULL; - pd->lCustData = NULL; + pd->lCustData = 0; pd->lpfnPrintHook = NULL; pd->lpfnSetupHook = NULL; pd->lpPrintTemplateName = NULL;