We help IT Professionals succeed at work.

We've partnered with Certified Experts, Carl Webster and Richard Faulkner, to bring you a podcast all about Citrix Workspace, moving to the cloud, and analytics & intelligence. Episode 2 coming soon!Listen Now

x

How to change print quality (i.e. DRAFT) ?

moosach
moosach asked
on
Medium Priority
728 Views
Last Modified: 2013-12-03
Hi everybody,

maybe I get help again here. Sorry, I don't have more points at the time.


Problem: Printing in print quality "DRAFT" with matrix printers does not run. The printer always works with the print quality "NEAR LETTER QUALITY".

We use a matrix printer with a EPSON-LQ-2550 emulation and the driver "Epson LQ-2550" on a Windows NT 4.0 system with service pack 3.
Notepad is able to print documents using the print quality "DRAFT" with that printer.

The sample code below shows the way, how we try to activate the draft mode. This way seems to be impossible because the flag "DM_PRINTQUALITY" of the DEVMODE structure member "dmPrintQuality" is clear. So, I have to assume, that
the printer driver does not support to change the print quality.

Is this assumption correct?

---

By the way, the SetPrinter function returns always "FALSE" and the returnvalue of GetLastError () ist 5. The printer is configured with "access to everyone". So I use the ResetDC () function to update the printer settings.  

Regards, Toni


---




/*
*/
#include <windows.h>
#include <winspool.h>
#include <wingdi.h>
#include <wtypes.h>
#include <string.h>
#include <stdio.h>

#define UNCLEN      256
int MyPrint(LPSTR);
      char        gszDevice[UNCLEN], gszDriver[UNCLEN], gszOutput[UNCLEN] ,gszDriverName[UNCLEN];

main(int argc , char ** argv)
{
/*
//code pages
      int i;
      UINT Page=atoi(argv[1]);
       if (SetConsoleOutputCP(Page))
            for (i=0;i<256;i++)
            {      printf("%3.3d=%c\r\n",i,i);
      
            }
*/

      MyPrint(argv[1]);

      return 0;
}

HDC GetPrinterDC (void)
{
      static char szPrinter [80] ;
      char        *szDevice, *szDriver, *szOutput ;

      GetProfileString ("windows", "device", ",,,", szPrinter, 80) ;

      if (NULL != (szDevice = strtok (szPrinter, "," )) &&
            NULL != (szDriver = strtok (NULL,      ", ")) &&
            NULL != (szOutput = strtok (NULL,      ", ")))
      {      strcpy(gszDevice,szDevice);
            strcpy(gszDriver,szDriver);
            strcpy(gszDriverName,szDriver);
          strcat(gszDriverName, ".DRV");
            strcpy(gszOutput,szOutput);
            return CreateDC (szDriver, szDevice, szOutput, NULL) ;
      }

      return 0 ;
}


/*****************************************************************************
 *
 *      Function:       SetDraft()
 *                      
 *                      
 *****************************************************************************
 *                      
 *      Parameter:      char *szDevice   Printer device
 *                      HDC   hPrnDC   Handle of the device context
 *                      
 *****************************************************************************
 *                      
 *      Return:         0  Printer settings available
 *                      <0   Task failed
 *                      
 ****************************************************************************/


DWORD SetDraft(char *szDevice, HDC hPrnDC)
{
  int status = 0;

  HANDLE  hPrinter;
  HGLOBAL hGlobal = NULL;
  PRINTER_INFO_2 *pi2 = NULL;

  DWORD dwNeed = 0;
  DWORD dwError = 0;
  DEVMODE *pDevModeOut = NULL,
        *pDevModeIn =NULL;

  LPBYTE p = NULL;             /* Returned area containing printer settings */


    if (!OpenPrinter (szDevice, &hPrinter, NULL))
    {
        MessageBox(NULL, "OpenPrinter failed!", NULL, MB_OK);
          status =  -1;
        return status;
    }

    GetPrinter(hPrinter, 2, 0, 0, &dwNeed);

    /* Allocate memory  */
    if ((hGlobal = GlobalAlloc(LPTR,dwNeed)) == NULL)
    {                                                   /* Not enough space */
      status =  -2;
      ClosePrinter(hPrinter);
      return(status);
    }
    if ((pi2 = (PRINTER_INFO_2 *)GlobalLock(hGlobal)) == NULL)
    {                                                   /* Not enough space */
      status =  -3;
      ClosePrinter(hPrinter);
      GlobalFree(hGlobal);
      return(status);
    }

    /* Get PRINTER_INFO_2 structure */
    if ( (! GetPrinter( hPrinter, 2, (LPBYTE)pi2, dwNeed, &dwNeed) ) )
    {
      status =  -4;
      ClosePrinter(hPrinter);
      GlobalUnlock(hGlobal);
      GlobalFree(hGlobal);
      return(status);
   }

    /* Set draft mode */
   
    if ( pi2->pDevMode != NULL )
      {
            printf("PRINTER: %s, YRes: %d, PrQ: %d, Draft: %d\n",pi2->pDevMode->dmDeviceName,
                                                        pi2->pDevMode->dmYResolution,
                                                        pi2->pDevMode->dmPrintQuality,
                                                                          (short) DMRES_DRAFT);

            if (pi2->pDevMode->dmFields & DM_PRINTQUALITY)
        {
             pi2->pDevMode->dmPrintQuality = DMRES_DRAFT;
          }
            else
            {
                  printf("Flag: DM_PRINTQUALITY not set\n");
            }
      }

    if ( DocumentProperties( NULL, hPrinter, szDevice, pi2->pDevMode,
                 pi2->pDevMode, DM_IN_BUFFER | DM_OUT_BUFFER ) != IDOK)
    {
      status =  -5;
      ClosePrinter(hPrinter);
      GlobalUnlock(hGlobal);
      GlobalFree(hGlobal);
      return(status);
    }
    /* Update printer settings */
   
//  if ( SetPrinter( hPrinter, 2, (LPBYTE)pi2, 0) == FALSE )  /* returns always "FALSE" */
      if ( ResetDC(hPrnDC,pi2->pDevMode) == FALSE )
    {
        DWORD error;

        error = GetLastError ();
        printf("GetLastError( SetPrinter ): %d\n", error);
      status =  -6;
    }

    ClosePrinter(hPrinter);
    GlobalUnlock(hGlobal);
    GlobalFree(hGlobal);
    return(status);
}                                                    

int MyPrint(LPSTR FileName)
{      BOOL EndOfFile=FALSE;
      //printing variables
      int       JobNumber;
      HDC       hPrnDC;
    DOCINFO     di;
    HFONT       hOldFont=NULL;
    HFONT      hFont=NULL;
    HFONT      hFontBig=NULL;
    HFONT      hFontBold=NULL;
    HFONT      hFontUnderline=NULL;

    int         nxLogPix, nyLogPix, dxPrinter, dyPrinter;
    int            iPageNum=0;
    DWORD       dwOldColor=0;
    DWORD       status=0;

    char    szBuffer[256];
    int     nx;
    int     ny;
      static char szPrinter [80] ;
      char        *szDevice, *szDriver, *szOutput ;


    // get a handle to the default printer
/*      if (NULL == (hPrnDC = GetPrinterDC ()))         */
/*          return FALSE ;                                 */

    GetProfileString ("windows", "device", ",,,", szPrinter, 80) ;

      if (NULL != (szDevice = strtok (szPrinter, "," )) &&
            NULL != (szDriver = strtok (NULL,      ", ")) &&
            NULL != (szOutput = strtok (NULL,      ", ")))
      {      strcpy(gszDevice,szDevice);
            strcpy(gszDriver,szDriver);
            strcpy(gszDriverName,szDriver);
          strcat(gszDriverName, ".DRV");
            strcpy(gszOutput,szOutput);
            hPrnDC = CreateDC (szDriver, szDevice, szOutput, NULL) ;
      }
      else { return FALSE; }

      if ( hPrnDC == NULL ) { return FALSE; }

//       status = SetDraft ( szDevice, hPrnDC );

    di.cbSize      = sizeof(DOCINFO);
    di.lpszDocName = (LPSTR)"TESTPRINT";
    di.lpszOutput  = NULL;

    // issue STARTDOC
      JobNumber=StartDoc(hPrnDC, &di);
    if (JobNumber < 0)
    {    // "STARTDOC escape problem"
         DeleteDC(hPrnDC);
         return FALSE;
    }

/*
{

    PRINTDLG dlg;

    ZeroMemory(&dlg, sizeof(dlg));
    dlg.lStructSize = sizeof(dlg);
    dlg.hwndOwner = NULL;


    if (PrintDlg(&dlg) == IDOK)
    {
        LPDEVMODE   pdm;
        LPDEVMODE   pdm1;
        LPDEVNAMES  pdn;
        char        szText[80];

        SetPaperName(szDevice,"A4",hPrnDC);
        pdm1 = (LPDEVMODE)GetPrinterDevmode(szDevice);
       
        pdm = GlobalLock(dlg.hDevMode);
        pdn = GlobalLock(dlg.hDevNames);

        wsprintf(szText, "dmDefaultSource = %d", pdm->dmDefaultSource);
        MessageBox(NULL, szText, pdm->dmFormName, MB_OK);

        ResetDC (hPrnDC, pdm);

        GlobalUnlock(dlg.hDevMode);
        GlobalUnlock(dlg.hDevNames);

        GlobalFree(dlg.hDevMode);
        GlobalFree(dlg.hDevNames);
    }
}
*/


              // get any information
          // get logical pixels per inch
          nxLogPix  = GetDeviceCaps(hPrnDC, LOGPIXELSX);
          nyLogPix  = GetDeviceCaps(hPrnDC, LOGPIXELSY);

          // get page resolution
          dxPrinter = GetDeviceCaps(hPrnDC, HORZRES);
          dyPrinter = GetDeviceCaps(hPrnDC, VERTRES);

      // create font
      {      
#define BASEH      100
            int  nWidth=nxLogPix / 10;      // logical average character width
            int  nHeight=nWidth * 2;      // logical height of font
            int  nEscapement=0;                  // angle of escapement
            int  nOrientation=0;            // base-line orientation angle
            int  fnWeight=FW_DONTCARE;      // font weight
            DWORD  fdwItalic=0;                  // italic attribute flag
            DWORD  fdwUnderline=0;            // underline attribute flag
            DWORD  fdwStrikeOut=0;            // strikeout attribute flag
            DWORD  fdwCharSet=ANSI_CHARSET;// character set identifier
            DWORD  fdwOutputPrecision=0;// output precision
            DWORD  fdwClipPrecision=0;      // clipping precision
            DWORD  fdwQuality=DRAFT_QUALITY;      // output quality
                        // DRAFT_QUALITY
                        // PROOF_QUALITY
            DWORD  fdwPitchAndFamily=FIXED_PITCH | FF_MODERN;      // pitch and family
 
            hFont=CreateFont(nHeight,nWidth,nEscapement,nOrientation,fnWeight,fdwItalic,fdwUnderline
                                           ,fdwStrikeOut,fdwCharSet,fdwOutputPrecision,fdwClipPrecision,fdwQuality
                                           ,fdwPitchAndFamily,"Courier 10cpi");       

        }
    hOldFont = SelectObject(hPrnDC,hFont);       
                                                                   /* Set print mode = DRAFT */
      status = SetDraft ( szDevice, hPrnDC );

                      //      SetTextAlign(hPrnDC,TA_UPDATECP);
      
    nx=nxLogPix;
    ny=nyLogPix;
      // start printing a page
    StartPage(hPrnDC);
                    

    // write something to printer
    wsprintf(szBuffer, "This is a line of text on page %d", 2);

      // normal
    SelectObject(hPrnDC,hFont);
    TextOut(hPrnDC, nx, 2*ny, szBuffer, strlen(szBuffer));
            
    // end the page; resets the dc to normal defaults
    EndPage(hPrnDC);
            

      if (EndDoc(hPrnDC) < 0)    // end the document
      {
            //"EndDoc function problem"
            return FALSE;
      }

      // CLEANUP
    // deselect font
    SelectObject(hPrnDC, hOldFont);
    DeleteDC(hPrnDC);

      return TRUE;
}


Comment
Watch Question

Author

Commented:
I can't believe that nobody is able to help me :-((((((

Commented:
Didn't you try the following simple approach?

1. Obtain default DEVMODE for printer.
pd.Flags |= PD_RETURNDEFAULT;
 PrintDlg(&pd);

2. Obtain pointer to DEVMOVE
LPDEVMODE lpDevMode = GlobalLock(pd.hDevMode)
lpDevMode->dmPrintQuality = DMRES_DRAFT;
::GlobalUnlock(pd.hDevMode);

3. Now tell PrintDlg to init to values given
    in hDevMode field of PRINTDLG structure,
   and supply handle to modified structure.

I used this simple code to switch to landscape mode
instead of default portrait one.

Author

Commented:
Hi belov,

thanks for your comment. Make an answer from it and get the points, because your approach will most probably work.

I asked Microsoft directly in the meanwhile concerning my problem and got today following answer from the support guys :
 
.............................

This is a response regarding DRAFT printing mode.

 You are correct that if the DM_PRINTQUALITY field of
the DEVMODE is cleared, then that field is not supported. Therefore, your driver does not support  changing the print quality. Further, I suspect that even if it did support  such a change, you would not see much change in performance or output when  using a non-default font.

The reason Notepad seems to support draft mode is
that it does not create and select a font. It simply begins printing using the default font for the printer. You will probably see similar performance to Notepad if you remove  your font code and use the default font.

I hope this helps.

........................

So it is a problem of my printer and not from my code.

But your answer was nevertheless correct. So get your points ;-)

Regards

Toni

Author

Commented:
Hi belov,

thanks for your comment. Make an answer from it and get the points, because your approach will most probably work.

I asked Microsoft directly in the meanwhile concerning my problem and got today following answer from the support guys :
 
.............................

This is a response regarding DRAFT printing mode.

 You are correct that if the DM_PRINTQUALITY field of
the DEVMODE is cleared, then that field is not supported. Therefore, your driver does not support  changing the print quality. Further, I suspect that even if it did support  such a change, you would not see much change in performance or output when  using a non-default font.

The reason Notepad seems to support draft mode is
that it does not create and select a font. It simply begins printing using the default font for the printer. You will probably see similar performance to Notepad if you remove  your font code and use the default font.

I hope this helps.

........................

So it is a problem of my printer and not from my code.

But your answer was nevertheless correct. So get your points ;-)

Regards

Toni
Commented:
I suggest the following, more simple approach.

1. Obtain default DEVMODE values for printer.
pd.Flags |= PD_RETURNDEFAULT;
PrintDlg(&pd);

2. Obtain pointer to DEVMOVE
LPDEVMODE lpDevMode = GlobalLock(pd.hDevMode)
lpDevMode->dmPrintQuality = DMRES_DRAFT;
::GlobalUnlock(pd.hDevMode);

3. If hDevMode field of PRINTDLG is not NULL,
PrintDlg will attempt to initialize printer according
to given DEVMODE values, so you can supply
handle to modified structure. Even if your printer really
does not support that mode, it won't do any harm :)


Not the solution you were looking for? Getting a personalized solution is easy.

Ask the Experts
Access more of Experts Exchange with a free account
Thanks for using Experts Exchange.

Create a free account to continue.

Limited access with a free account allows you to:

  • View three pieces of content (articles, solutions, posts, and videos)
  • Ask the experts questions (counted toward content limit)
  • Customize your dashboard and profile

*This site is protected by reCAPTCHA and the Google Privacy Policy and Terms of Service apply.

OR

Please enter a first name

Please enter a last name

8+ characters (letters, numbers, and a symbol)

By clicking, you agree to the Terms of Use and Privacy Policy.