Modifying Printer Settings


This article shows how to implement the method given in the Microsoft 'How To' advice on changing printer settings.
From the article -
"SUMMARY
SetPrinter is a new API for Windows 95, Windows NT, Windows 2000, and Windows XP
that allows applications to change various printer attributes. However, as the
code in this article demonstrates, a certain amount of preparation is necessary
in order to call SetPrinter correctly."
The full text including the C code ( C++Builder users will prefer it) is here.
Sources :
http://support.microsoft.com/default.aspx?scid=kb;EN-US;q140285
http://support.microsoft.com/default.aspx?scid=kb;EN-US;Q167345
http://support.microsoft.com/default.aspx?scid=kb;EN-US;Q246772

Below is a translation to Delphi. The logic follows the C example as far as possible, with the exception created by the fact that the Printer_info_2 structure in Delphi does NOT have a 'pDevMode' member.

The procedure below is for setting a printers paper source (bin). It can be easily adapted to set any printer code.

It is hoped that the inclusion of the 'DocumentProperties()' call will also fix some other problems that have been experienced with printing.
These changes will be incorporated in the next release of QuickReport in summer 2002.
// This is translated from the C example given by MS Oct 01
// Also see WinAPI Help on 'DocumentProperties()' and 'SetPrinter'
procedure SetPrinterBin( Printername : pchar; BinCode : integer );
var
    SpaceNeeded : word; // for pDriverinfo2
    pDBuff : _devicemodeA; // dummy
    Driver_info_2 : pDriverinfo2;
    DevModeSize : integer;
    dPtr : Pointer;
 hPrinter : THandle;
begin
     // Get the printer handle
     OpenPrinter(Printername, hPrinter, nil);
     // find out how much space we need for the info stuct
     GetPrinter( hPrinter, 2, 0, 0, @SpaceNeeded);
     // allocate the necessary
     GetMem( Driver_info_2, SpaceNeeded);
     // The second GetPrinter fills in all the current settings
     GetPrinter( hPrinter, 2, Driver_info_2, SpaceNeeded, @SpaceNeeded);
     // If GetPrinter didn't fill in the DEVMODE, try to get it by calling
     // Documentproperties() - this is always true in Delphi, so ...
     // Zero in last arg returns buffer size - if it's -1 the call failed..
     DevModeSize :=  DocumentProperties(0, hPrinter, Printername, pDBuff, pDBuff, 0);
     // get space
     dPtr := allocmem( DevModeSize );
     devmode := pDevmode( dPtr );
     // this call fills our DevMode struct
     DocumentProperties(0, hPrinter, Printername,
                             _devicemodeA( dPtr^), pDBuff, DM_OUT_BUFFER );
     // make changes to devmode
     devmode^.dmFields := DM_DEFAULTSOURCE;
     devmode^.dmDefaultSource := BinCode;
     try
        // implement the change ...
        SetPrinter( hPrinter, 2, devmode, 0);
        // make sure all of devmode is copied back
        DocumentProperties(0, hPrinter, Printername, _devicemodeA( dPtr^),
                    _devicemodeA( dPtr^), DM_IN_BUFFER+DM_OUT_BUFFER );
     except
         // bomb out. If it's a 'Printer index out of bounds' it might
         // be an invalid code.
     end;
     FreeMem( Driver_info_2, SpaceNeeded);
     freemem( dPtr, DevmodeSize);
     Closeprinter( hPrinter );
end;