Changing the Printer's Paper Size

Using the API to change the size of paper current used by a printer requires several calls to the DocumentProperties() function among others.  More specifically, you first need to call the OpenPrinter() function to open the printer (and get its handle).  Next, call DocumentProerties() with a zero fMode parameter to get the number of bytes required for the DEVMODE structure.  Allocate that amount of memory, then call  DocumentProperties() again, this time to get the device mode information (a pointer to the device mode structure used by the printer).  With this pointer, manipulate the appropriate fields to change the paper size, then call DocumentProperties() yet again, this time to get the final DEVMODE to pass into the CreateDC() function.
 

KEYWORDS: ChangeDisplaySettings(), EnumDisplaySettings(), DEVMODE. 
 



 

//---------------------------------------------------------------------------

void __fastcall TForm1::PrintButtonClick(TObject *Sender)
{
    // get the default printer name, driver, and port
    char *def_string = "no printer";
    char buffer[MAX_PATH];
    GetProfileString("windows", "device", def_string,
                     buffer, MAX_PATH);

    AnsiString Abuffer(buffer);
    AnsiString Device, Driver, Port;

    // parse the buffer to extract individual properties
    int first_comma = Abuffer.Pos(",");
    Device = Abuffer.SubString(1, first_comma - 1);
    Abuffer = Abuffer.SubString(first_comma + 1,
              Abuffer.Length() - first_comma);
    int second_comma = Abuffer.Pos(",");
    Driver = Abuffer.SubString(1, second_comma - 1);
    Port = Abuffer.SubString(second_comma + 1,
                             Abuffer.Length() - second_comma);

    // open the printer
    HANDLE HPrinter;
    if (OpenPrinter(Device.c_str(), &HPrinter, NULL))
    {
        // call DocumentProerties() with a zero fMode parameter
        // to get the number of bytes required
        long int num_bytes;
        num_bytes = DocumentProperties(NULL, HPrinter, Device.c_str(),
                                       NULL, NULL, 0);

        // allocate the memory
        unsigned char *buffer = new unsigned char[num_bytes];

        // call DocumentProperties() again, this time to get the
        // device mode information
        DocumentProperties(NULL, HPrinter, Device.c_str(),
                           (PDEVMODE)buffer, NULL, DM_OUT_BUFFER);
        
        PDEVMODE pdm = (PDEVMODE)buffer;

        // modify the appropriate fields
        pdm->dmPaperSize = DMPAPER_10X14;  // for example

        // tell Windows which fields we changed
        pdm->dmFields = pdm->dmFields | DM_PAPERSIZE;

        // call DocumentProperties() yet again, this time to get
        // the final DEVMODE to pass into the CreateDC() function
        DocumentProperties(NULL, HPrinter, Device.c_str(),
                           pdm, pdm, DM_OUT_BUFFER | DM_IN_BUFFER);

        // create a printer device context
        HDC HPrinterDC = CreateDC(Driver.c_str(), Device.c_str(),
                                  NULL, pdm);
        if (HPrinterDC)
        {
            DOCINFO di;
            di.cbSize = sizeof(DOCINFO);
            di.lpszDocName = "Test Print";
            di.lpszOutput = (LPTSTR) NULL;
            di.lpszDatatype = (LPTSTR) NULL;
            di.fwType = 0;

            // start printing
            if (StartDoc(HPrinterDC, &di))
            {
                if (StartPage(HPrinterDC))
                {
                    float fLogPelsX1, fLogPelsY1;

                    fLogPelsX1 =
                       (float)GetDeviceCaps(HPrinterDC, LOGPIXELSX);
                    fLogPelsY1 =
                       (float)GetDeviceCaps(HPrinterDC, LOGPIXELSY);

                    RECT R = Rect(0, 0, fLogPelsX1 * 8.5, fLogPelsY1 * 11);
                    // print some text
                    ::DrawText(HPrinterDC, Memo1->Text.c_str(),
                               Memo1->Text.Length(), &R,
                               DT_LEFT | DT_EDITCONTROL | DT_WORDBREAK);
                               
                    EndPage(HPrinterDC);
                }
                EndDoc(HPrinterDC);
            }
            DeleteDC(HPrinterDC);
        }
        delete [] buffer;
        ClosePrinter(HPrinter);
    }
}