bool wxWindowsPrintNativeData::TransferFrom( const wxPrintData &data ) { HGLOBAL hDevMode = (HGLOBAL)(DWORD) m_devMode; HGLOBAL hDevNames = (HGLOBAL)(DWORD) m_devNames; if (!hDevMode) { // Use PRINTDLG as a way of creating a DEVMODE object PRINTDLG pd; // GNU-WIN32 has the wrong size PRINTDLG - can't work out why. #ifdef __GNUWIN32__ memset(&pd, 0, 66); pd.lStructSize = 66; #else memset(&pd, 0, sizeof(PRINTDLG)); #ifdef __WXWINCE__ pd.cbStruct = sizeof(PRINTDLG); #else pd.lStructSize = sizeof(PRINTDLG); #endif #endif pd.hwndOwner = (HWND)NULL; pd.hDevMode = NULL; // Will be created by PrintDlg pd.hDevNames = NULL; // Ditto //pd.hInstance = (HINSTANCE) wxGetInstance(); pd.Flags = PD_RETURNDEFAULT; pd.nCopies = 1; // Fill out the DEVMODE structure // so we can use it as input in the 'real' PrintDlg if (!PrintDlg(&pd)) { if ( pd.hDevMode ) GlobalFree(pd.hDevMode); if ( pd.hDevNames ) GlobalFree(pd.hDevNames); pd.hDevMode = NULL; pd.hDevNames = NULL; #if defined(__WXDEBUG__) && defined(__WIN32__) wxString str(wxT("Printing error: ")); str += wxGetPrintDlgError(); wxLogDebug(str); #endif } else { hDevMode = pd.hDevMode; m_devMode = (void*)(long) hDevMode; pd.hDevMode = NULL; // We'll create a new DEVNAMEs structure below. if ( pd.hDevNames ) GlobalFree(pd.hDevNames); pd.hDevNames = NULL; // hDevNames = pd->hDevNames; // m_devNames = (void*)(long) hDevNames; // pd->hDevnames = NULL; } } if ( hDevMode ) { LPDEVMODE devMode = (LPDEVMODE) GlobalLock(hDevMode); //// Orientation devMode->dmOrientation = (short)data.GetOrientation(); //// Collation devMode->dmCollate = (data.GetCollate() ? DMCOLLATE_TRUE : DMCOLLATE_FALSE); devMode->dmFields |= DM_COLLATE; //// Number of copies devMode->dmCopies = (short)data.GetNoCopies(); devMode->dmFields |= DM_COPIES; //// Printer name wxString name = data.GetPrinterName(); if (!name.empty()) { //int len = wxMin(31, m_printerName.Len()); wxStrncpy((wxChar*)devMode->dmDeviceName,name.c_str(),31); devMode->dmDeviceName[31] = wxT('\0'); } //// Colour if (data.GetColour()) devMode->dmColor = DMCOLOR_COLOR; else devMode->dmColor = DMCOLOR_MONOCHROME; devMode->dmFields |= DM_COLOR; //// Paper size if (data.GetPaperId() == wxPAPER_NONE) { // DEVMODE is in tenths of a milimeter devMode->dmPaperWidth = (short)(data.GetPaperSize().x * 10); devMode->dmPaperLength = (short)(data.GetPaperSize().y * 10); if(m_customWindowsPaperId != 0) devMode->dmPaperSize = m_customWindowsPaperId; else devMode->dmPaperSize = DMPAPER_USER; devMode->dmFields |= DM_PAPERWIDTH; devMode->dmFields |= DM_PAPERLENGTH; } else { if (wxThePrintPaperDatabase) { wxPrintPaperType* paper = wxThePrintPaperDatabase->FindPaperType( data.GetPaperId() ); if (paper) { devMode->dmPaperSize = (short)paper->GetPlatformId(); devMode->dmFields |= DM_PAPERSIZE; } else { // Fall back on specifying the paper size explicitly devMode->dmPaperWidth = (short)(data.GetPaperSize().x * 10); devMode->dmPaperLength = (short)(data.GetPaperSize().y * 10); devMode->dmPaperSize = DMPAPER_USER; devMode->dmFields |= DM_PAPERWIDTH; devMode->dmFields |= DM_PAPERLENGTH; } } } //// Duplex short duplex; switch (data.GetDuplex()) { case wxDUPLEX_HORIZONTAL: duplex = DMDUP_HORIZONTAL; break; case wxDUPLEX_VERTICAL: duplex = DMDUP_VERTICAL; break; default: // in fact case wxDUPLEX_SIMPLEX: duplex = DMDUP_SIMPLEX; break; } devMode->dmDuplex = duplex; devMode->dmFields |= DM_DUPLEX; //// Quality short quality; switch (data.GetQuality()) { case wxPRINT_QUALITY_MEDIUM: quality = DMRES_MEDIUM; break; case wxPRINT_QUALITY_LOW: quality = DMRES_LOW; break; case wxPRINT_QUALITY_DRAFT: quality = DMRES_DRAFT; break; case wxPRINT_QUALITY_HIGH: quality = DMRES_HIGH; break; default: quality = (short)data.GetQuality(); break; } devMode->dmPrintQuality = quality; devMode->dmFields |= DM_PRINTQUALITY; if (data.GetPrivDataLen() > 0) { memcpy( (char *)devMode+devMode->dmSize, data.GetPrivData(), data.GetPrivDataLen() ); devMode->dmDriverExtra = (WXWORD)data.GetPrivDataLen(); } if (data.GetBin() != wxPRINTBIN_DEFAULT) { switch (data.GetBin()) { case wxPRINTBIN_ONLYONE: devMode->dmDefaultSource = DMBIN_ONLYONE; break; case wxPRINTBIN_LOWER: devMode->dmDefaultSource = DMBIN_LOWER; break; case wxPRINTBIN_MIDDLE: devMode->dmDefaultSource = DMBIN_MIDDLE; break; case wxPRINTBIN_MANUAL: devMode->dmDefaultSource = DMBIN_MANUAL; break; case wxPRINTBIN_ENVELOPE: devMode->dmDefaultSource = DMBIN_ENVELOPE; break; case wxPRINTBIN_ENVMANUAL: devMode->dmDefaultSource = DMBIN_ENVMANUAL; break; case wxPRINTBIN_AUTO: devMode->dmDefaultSource = DMBIN_AUTO; break; case wxPRINTBIN_TRACTOR: devMode->dmDefaultSource = DMBIN_TRACTOR; break; case wxPRINTBIN_SMALLFMT: devMode->dmDefaultSource = DMBIN_SMALLFMT; break; case wxPRINTBIN_LARGEFMT: devMode->dmDefaultSource = DMBIN_LARGEFMT; break; case wxPRINTBIN_LARGECAPACITY: devMode->dmDefaultSource = DMBIN_LARGECAPACITY; break; case wxPRINTBIN_CASSETTE: devMode->dmDefaultSource = DMBIN_CASSETTE; break; case wxPRINTBIN_FORMSOURCE: devMode->dmDefaultSource = DMBIN_FORMSOURCE; break; default: devMode->dmDefaultSource = (short)(DMBIN_USER + data.GetBin() - wxPRINTBIN_USER); break; } devMode->dmFields |= DM_DEFAULTSOURCE; } GlobalUnlock(hDevMode); } if ( hDevNames ) { GlobalFree(hDevNames); } // TODO: I hope it's OK to pass some empty strings to DEVNAMES. m_devNames = (void*) (long) wxCreateDevNames(wxEmptyString, data.GetPrinterName(), wxEmptyString); return true; }
void wxWindowsPrintNativeData::InitializeDevMode(const wxString& printerName, WinPrinter* printer) { if (m_devMode) return; LPTSTR szPrinterName = wxMSW_CONV_LPTSTR(printerName); // 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 successfully 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<LPDEVMODE>( 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 PRINTDLG pd; memset(&pd, 0, sizeof(PRINTDLG)); #ifdef __WXWINCE__ pd.cbStruct = sizeof(PRINTDLG); #else pd.lStructSize = sizeof(PRINTDLG); #endif pd.hwndOwner = NULL; pd.hDevMode = NULL; // Will be created by PrintDlg pd.hDevNames = NULL; // Ditto pd.Flags = PD_RETURNDEFAULT; pd.nCopies = 1; // Fill out the DEVMODE structure // so we can use it as input in the 'real' PrintDlg if (!PrintDlg(&pd)) { if ( pd.hDevMode ) GlobalFree(pd.hDevMode); if ( pd.hDevNames ) GlobalFree(pd.hDevNames); pd.hDevMode = NULL; pd.hDevNames = NULL; #if wxDEBUG_LEVEL wxLogDebug(wxT("Printing error: ") + wxGetPrintDlgError()); #endif // wxDEBUG_LEVEL } else { m_devMode = pd.hDevMode; pd.hDevMode = NULL; // We'll create a new DEVNAMEs structure below. if ( pd.hDevNames ) GlobalFree(pd.hDevNames); pd.hDevNames = NULL; // hDevNames = pd->hDevNames; // m_devNames = (void*)(long) hDevNames; // pd->hDevnames = NULL; } } }