Logging Paper Size of printed jobs (DeviceCapabilities and DEVMODE.dmPaperSize)

Posted on 2006-04-18
Last Modified: 2010-08-05
I have written a program that uses FindNextPrinterChangeNotification to monitor changes in print jobs on a printer and log the information to a database. I am having a problem, however, that sometimes the paper size is reported as 8"x11" when the printed document is actually much larger.

I check the dmPaperWidth and dmPaperLength values of the DEVMODE (provided through JOB_NOTIFY_FIELD_DEVMODE in the PRINTER_NOTIFY_INFO_DATA structure) but often times these values are not used and dmPaperSize is set instead.

In these cases I use the following code to request the Paper Size dimensions (based on the dmPaperSize value) from the printer driver usiing DeviceCapabilites. It works in most cases, but occasionally the DEVMODE reports PaperSize as "1" and DeviceCapabilities says that this means 8"x11" even though this is not the correct size.

        // find out how many paper names there are
      PaperSizeCount = DeviceCapabilities(PrinterName, port, DC_PAPERNAMES, NULL, devMode);
      if(PaperSizeCount < 0) {
            ErrorMessage((string)"Error: DeviceCapabilities failed: " + ToString(GetLastError()));

      // make sure we have atleast one paper name
      else if (PaperSizeCount > 0) {

            PaperNames = new char[PaperSizeCount*64];
            DeviceCapabilities(PrinterName, port, DC_PAPERNAMES, PaperNames,
            if(PaperNames==NULL) ErrorMessage("Error: need more memory for paper names");

            PaperIds = new WORD[PaperSizeCount];
            DeviceCapabilities(PrinterName, port, DC_PAPERS, (char*)PaperIds,
            if(PaperIds==NULL) ErrorMessage("Error: need more memory for paper ids");

            PaperSizes = new POINT[PaperSizeCount];
            DeviceCapabilities(PrinterName, port, DC_PAPERSIZE, (char*)PaperSizes,
            if(PaperSizes==NULL) ErrorMessage("Error: need more memory for paper sizes");

            ErrorMessage("Notice: Found " + ToString(PaperSizeCount) + " PaperSize Defintions for " + PrinterName);
            // pointer to loop through PaperIds
            WORD* p = PaperIds;

            for (long i = 0; i < PaperSizeCount; i++) {
                  if(*p==devMode->dmPaperSize) {
                        memcpy(&ret, &PaperSizes[i], sizeof(POINT));
                        char temp[65];
                        memcpy(temp, &PaperNames[i*64], 64);
                        temp[64] = '\0';
                        ErrorMessage((std::string)"Notice: Found matching Paper Size Definition for " + ToString(devMode->dmPaperSize) + " on " + PrinterName + " : " + temp + " ("  + ToString(ret.x) + "\" x " + ToString(ret.y) + "\")");
            if(i==PaperSizeCount) ErrorMessage("Warning: No match for for Paper Size Code: " + ToString(devMode->dmPaperSize));

      } else {
            ErrorMessage((std::string)"Warning: No Paper Size Codes found for " + PrinterName);

The cases where the paper size is reported incorrectly seems to happen intermittently an unpredictably. I know the problem is happening on our KIP 8000 print driver and our HP 1055 driver because these are large format plotters. It is possible that other printer drivers are also reporting the wrong size, but I have not confirmed this yet.

It seems to me like the problem is in the software that is printing selecting dmPaperSize 1 when it prints yet actually printing a larger document. The drivers seem to accept this without complaint. Is there a better way to obtain the dimensions of the document being printed? Does anyone have any ideas about how I could improve my code to get the correct values in these cases?
Question by:Caroline_Perkins
    LVL 15

    Assisted Solution

    Did you try passing PRINTER_NOTIFY_OPTIONS_REFRESH as the third parameter to FindNextPrinterChangeNotification method

    BOOL FindNextPrinterChangeNotification(
      HANDLE hChange,                // change notification
      PDWORD pdwChange,              // condition that changed
      LPVOID pPrinterNotifyOptions,  // refresh option
      LPVOID *ppPrinterNotifyInfo    // printer information


    Author Comment

    I do pass PRINTER_NOTIFY_OPTIONS_REFRESH for the third parameter, but only if PRINTER_NOTIFY_INFO_DISCARDED is set in the returned notify options. Are you suggesting that I pass this flag everytime I call the function regardless of if PRINTER_NOTIFY_INFO_DISCARDED is set? It doesn't seem to me like this would make any difference... but I can try it if you have reason to think it will solve the problem.
    LVL 49

    Accepted Solution

    This may be related to the driver.  When you bring up the pritner settings, does it allow entry of a custom paper size?

    One thing you are not looking at is the currently-paper bin in use.  the driver might be using that value to flag "special handling" (that's a shot in the dark... but in general, I think you may need to look at every piece of available info and try to find a pattern).

    As to the" intermittentnance" (is that word? lol) of the problem .. is it possible that only certain application programs cause the problem?  For instance, maybe AutoCad handles it one way and Notepad handles it another way.

    Another long shot...
        DMPAPER_USER                256
    is 0x100 which might look like 1 if one is not paying attention...

    Also, check the value of
    It contains bit flags that indicate which of the other fields in the structure apply.  Look in the file WINGDI.H for the definitions (eg, DM_PAPERWIDTH, etc).

    -- Dan

    Author Comment

    I never did find a good solution to this particular problem. It seems to be a problem specific to large format plotter devices. I have had some communication with the someone at KIP and they are being pretty helpful. So maybe they will be able to correct it with a new version of their driver/software. Thanks to both of you for your suggestions.

    Write Comment

    Please enter a first name

    Please enter a last name

    We will never share this with anyone.

    Featured Post

    IT, Stop Being Called Into Every Meeting

    Highfive is so simple that setting up every meeting room takes just minutes and every employee will be able to start or join a call from any room with ease. Never be called into a meeting just to get it started again. This is how video conferencing should work!

    Suggested Solutions

    The following diagram presents a diamond class hierarchy: As depicted, diamond inheritance denotes when two classes (e.g., CDerived1 and CDerived2), separately extending a common base class (e.g., CBase), are sub classed simultaneously by a fourt…
    In Easy String Encryption Using CryptoAPI in C++ ( I described how to encrypt text and recommended that the encrypted text be stored as a series of hexadecimal digits -- because cyphertext may…
    Migrating to Microsoft Office 365 is becoming increasingly popular for organizations both large and small. If you have made the leap to Microsoft’s cloud platform, you know that you will need to create a corporate email signature for your Office 365…
    This video gives you a great overview about bandwidth monitoring with SNMP and WMI with our network monitoring solution PRTG Network Monitor ( If you're looking for how to monitor bandwidth using netflow or packet s…

    760 members asked questions and received personalized solutions in the past 7 days.

    Join the community of 500,000 technology professionals and ask your questions.

    Join & Ask a Question

    Need Help in Real-Time?

    Connect with top rated Experts

    13 Experts available now in Live!

    Get 1:1 Help Now