PrinterSettings - Changing, Storing and Loading Printer Settings


Application Security Testing: An Integral Part of DevOps


Several years ago I had to implement the ability to change the printer and it's settings from within a programm. The output had to be distributed to 3 or more printers. The settings had to be stored to disk to be able to be loaded. It was desired to conform to the MFC Framework.

How to use

Declare the class CPrinterSettings in a CDocument derived class or wherever you find it useful.

#include "PrinterSettings.h"

class CPrnsetupDlg : public CDialog
	CPrinterSettings m_prn_setting1;
	CPrinterSettings m_prn_setting2;

To get a copy of the original MFC printer settings call CopyDefaultMfcPrinter().

	// Get MFC's default printer

To let the user change the settings e.g. paper orientation or printer resolution call PrinterSetup( CWnd* pWnd ).


To cause MFC to use your settings call SetThisPrinter().

	// make m_prn_setting1 the MFC standard printer

	// later you may call RestorePrinter() to
	// restore earlier settings.

To load or save your settings call Save(LPCTSTR filename ) or Load(LPCTSTR filename ).

	// Save our settings to file
	m_prn_setting1.Save( "testfilename");

	// load settings, store them in m_prn_settings1
	m_prn_setting1.Load( "testfilename" ));


Download demo project - 17 Kb

The name of the project is "prnsetup.dsw" (build with VC 6 )

Download source - 5 Kb

The source files are named: PrinterSettings.h and PrinterSettings.cpp



  • Here is how to print to a network printer

    Posted by Legacy on 02/12/2004 12:00am

    Originally posted by: Jocelyn Gennesseaux

    I couldn't print to a network printer using SetPrinterDevice so I made few changes and now it works.

    So replace SetPrinterDevice as follow and don't forget to call SetThisPrinter() after it.

    BOOL CPrinterSettings::SetPrinterDevice(LPCTSTR pszDeviceName) const
    // Open printer
    HANDLE hPrinter;
    if (OpenPrinter((char*)pszDeviceName, &hPrinter, NULL) == FALSE)
    return FALSE;

    // obtain PRINTER_INFO_2 structure and close printer
    DWORD dwBytesReturned, dwBytesNeeded;
    GetPrinter(hPrinter, 2, NULL, 0, &dwBytesNeeded);
    PRINTER_INFO_2* p2 = (PRINTER_INFO_2*)GlobalAlloc(GPTR, dwBytesNeeded);
    if (GetPrinter(hPrinter, 2, (LPBYTE)p2, dwBytesNeeded, &dwBytesReturned) == 0)
    return FALSE;

    // Allocate a global handle for DEVMODE
    HGLOBAL hDevMode = GlobalReAlloc(m_hDevMode, sizeof(*p2->pDevMode) + p2->pDevMode->dmDriverExtra, GHND);
    DEVMODE* pDevMode = (DEVMODE*)GlobalLock(hDevMode);

    // copy DEVMODE data from PRINTER_INFO_2::pDevMode
    memcpy(pDevMode, p2->pDevMode, sizeof(*p2->pDevMode) + p2->pDevMode->dmDriverExtra);

    // Compute size of DEVNAMES structure from PRINTER_INFO_2's data
    DWORD drvNameLen = lstrlen(p2->pDriverName)+1; // driver name
    DWORD ptrNameLen = lstrlen(p2->pPrinterName)+1; // printer name
    DWORD porNameLen = lstrlen(p2->pPortName)+1; // port name

    // Allocate a global handle big enough to hold DEVNAMES.
    HGLOBAL hDevNames = GlobalReAlloc(m_hDevNames, sizeof(DEVNAMES) + (drvNameLen + ptrNameLen + porNameLen)*sizeof(TCHAR), GHND);
    DEVNAMES* pDevNames = (DEVNAMES*)GlobalLock(hDevNames);

    // Copy the DEVNAMES information from PRINTER_INFO_2
    // tcOffset = TCHAR Offset into structure
    int tcOffset = sizeof(DEVNAMES)/sizeof(TCHAR);
    ASSERT(sizeof(DEVNAMES) == tcOffset*sizeof(TCHAR));

    pDevNames->wDriverOffset = tcOffset;
    memcpy((LPTSTR)pDevNames + tcOffset, p2->pDriverName, drvNameLen*sizeof(TCHAR));
    tcOffset += drvNameLen;

    pDevNames->wDeviceOffset = tcOffset;
    memcpy((LPTSTR)pDevNames + tcOffset, p2->pPrinterName, ptrNameLen*sizeof(TCHAR));
    tcOffset += ptrNameLen;

    pDevNames->wOutputOffset = tcOffset;
    memcpy((LPTSTR)pDevNames + tcOffset, p2->pPortName, porNameLen*sizeof(TCHAR));
    pDevNames->wDefault = 0;


    // Notification: settings changed

    return TRUE;

  • Long Printer Names - THANKS

    Posted by Legacy on 12/10/2003 12:00am

    Originally posted by: Deyvi Pilosof

    This source was great, saved me lots of time.

    If you need more than 30 chars for the printer names, you should make the following modification

    CString CPrinterSettings::DevmodePrinterName()
    if(!m_hDevNames) {
    m_strPrinterName = "";
    } else {
    LPDEVNAMES lpDev = (LPDEVNAMES)GlobalLock(m_hDevNames);
    m_strPrinterName=(LPCTSTR)lpDev + lpDev->wDeviceOffset;
    return m_strPrinterName;

  • Load a setups across different OS's

    Posted by Legacy on 10/24/2003 12:00am

    Originally posted by: Jens Froslev-Nielsen

    Hi Here,
    I've having a problem with loading print setups saved from W2K in XP and visa-verse. In my case I've a EPSON 2100 and the dmPrintQuality param is not loaded correctly across the OS's. Saving/Loading from the same! OS seems to work ok.
    Does anyone has a (quick and dirty??) solution? .
    Currently I've two saved to setup's MyPrintEPSON2100-XP and

    Thx - Jens

  • Modifying printer default setting in dialog based application

    Posted by Legacy on 08/02/2003 12:00am

    Originally posted by: Rick

    Many thanks to the earlier posters. The following is an example of what worked in a dialog based application where I wanted to use the CPrintDialog DoModal function where a user could change printer options but where I wanted to printer dialog box to open with certain defaults already in place ( such as for printing out an envelope ). This was in a function in the Dlg class, not the App class.
    When the print dialog box opens the defaults are set to #10 envelope and landscape orientation typical for most envelopes. The user still can change to something else ( another sized envelope if needed ).

    void CCPhoneDlg::OnCopyEnvelopes()
    CDC dcPrint;
    PRINTDLG pDdlg;
    DEVMODE *mode = NULL;
    CPrintDialog dlgPrint(FALSE, PD_ALLPAGES,this);

    mode = (DEVMODE *) GlobalLock(pDdlg.hDevMode);
    mode->dmOrientation = DMORIENT_LANDSCAPE;
    mode->dmPaperSize = DMPAPER_ENV_10;

    dlgPrint.m_pd.hDevMode = mode;
    // Note above line worked,
    // dlgPrint.ResetDC(mode) did not work
    if(dlgPrint.DoModal() == IDOK)
    DOCINFO myPrintJob;
    myPrintJob.cbSize = sizeof(myPrintJob);
    myPrintJob.lpszDocName = "MyPrintJob";
    myPrintJob.lpszOutput = NULL;
    myPrintJob.fwType = NULL;

    ...continue with print job......

  • http://www.ucancode.net

    Posted by Legacy on 08/01/2003 12:00am

    Originally posted by: MFC Diagramming,Flow Class Library with Full Source Code!


  • How can my application see all system's printing operation?

    Posted by Legacy on 04/07/2003 12:00am

    Originally posted by: hnim

    I have to build an application that manages all operations of a desktop such as count number operations that are sucessful/fail or canceled...But i don't know where to begin: which hooks i have to use,how to use it...
    i need help...

  • Pl help me ... to Control the Printer using a programme (VB)

    Posted by Legacy on 03/03/2003 12:00am

    Originally posted by: Isuru Binduhewa

    Pl can anybody help me...
    I need to restrict getting printouts. Such that I need to set a password on any printing job (Ms Word, Notepad, Adobe, etc.) and control the no of printouts allowed.(In VB or c++)

    If some one can help me on this would greately appreciated

  • I want to change the size of the page in print preview

    Posted by Legacy on 07/31/2002 12:00am

    Originally posted by: Ashutosh

    i am using the class CView for printing. So, i want to set the page size of(800x480) pixels which will show in print preview. since when i saw print preview it showing things on approx half of the page. So, anyone can help me.
    thanks in advance.

  • HTML printing problem

    Posted by Legacy on 04/24/2002 12:00am

    Originally posted by: Bahar

    Y doesnt the following code work.
    I'm trying to print a html file.Though the file is seen in the print queue no output is seen in the prinout.
    Plz help.
    thanks in advance

    // Get the default printer.

    DEVMODE* dm = (DEVMODE*)::GlobalLock(dlg.m_pd.hDevMode);

    HDC hdc = dlg.CreatePrinterDC();

    CDC dc;
    dc.Attach( hdc );
    if ( dc )

    DOCINFO docinfo;
    memset(&docinfo, 0, sizeof(docinfo));

    docinfo.cbSize = sizeof(docinfo);
    docinfo.lpszDocName =htmlDocumentName ;



    //CGdiObject* pOldFont = dc.SelectStockObject(SYSTEM_FONT);
    //dc.TextOut(50, 50, _T("Hello World!"), 12);
    TR_PRINT(_T("Orientation %d "),dm->dmOrientation);





  • Create DC from current printer settings

    Posted by Legacy on 04/03/2002 12:00am

    Originally posted by: David Hisel

    Here is what works for me:

    CPrintDialog dlg(FALSE, PD_RETURNDC );
    AfxGetApp()->GetPrinterDeviceDefaults( &dlg.m_pd );
    dlg.m_pd.hDevMode = m_printersettings.CopyDevModeHandle();
    dlg.m_pd.hDevNames = m_printersettings.CopyDevNamesHandle();
    DEVMODE* dm = (DEVMODE*)::GlobalLock(dlg.m_pd.hDevMode);

    HDC hdc = dlg.CreatePrinterDC();
    CDC dc;
    dc.Attach( hdc );

    if ( dc )

    //////////////USE dc HERE////////////////




    I added CopyDevNamesHandle() and CopyDevModeHandle() methods
    to CPrinterSettings class as follows:

    HANDLE CPrinterSettings::CopyDevNamesHandle()
    return CopyHandle( m_hDevNames );

    HANDLE CPrinterSettings::CopyDevModeHandle()
    return CopyHandle( m_hDevMode );


  • Loading, Please Wait ...

  • You must have javascript enabled in order to post comments.

Leave a Comment
  • Your email address will not be published. All fields are required.

Top White Papers and Webcasts

  • As all sorts of data becomes available for storage, analysis and retrieval - so called 'Big Data' - there are potentially huge benefits, but equally huge challenges...
  • The agile organization needs knowledge to act on, quickly and effectively. Though many organizations are clamouring for "Big Data", not nearly as many know what to do with it...
  • Cloud-based integration solutions can be confusing. Adding to the confusion are the multiple ways IT departments can deliver such integration...

Most Popular Programming Stories

More for Developers

RSS Feeds

Thanks for your registration, follow us on our social networks to keep up-to-date
We have made updates to our Privacy Policy to reflect the implementation of the General Data Protection Regulation.