Link to home
Start Free TrialLog in
Avatar of Thomas Stockbruegger
Thomas StockbrueggerFlag for Germany

asked on

Need some help with LPDEVMODE and printing

Hello,
I have a printer with 3 printer tray. One with white paper, one with red paper, one with green paper.
I would like to print one copy in red and green.
with dev->dmDefaultSource=DMBIN_AUTO;
 or dev->dmDefaultSource=0; I will print white

 dev->dmDefaultSource=1  I will print red
 dev->dmDefaultSource=2  I will print green

Is it possible to change that....so when all white pages are done then the printer will do the same in red and green.


The only thing I come up with is to call 3 functions with different  dev->dmDefaultSource values.
It is possilbe to change that in only one function =OnBnClickedButton_Printing()
500 points with a solution.
Thank you for your help. Printing is difficult.
Best regards,
Thomas





void CAuftragsHistory_Lieferschein_Dialog::OnBnClickedButton_Printing()
{
      
       HANDLE hDevMode;
          HANDLE hDevNames;

   if (GetPrinterDevice(_T("\\\\DSERVER\\Brother HL-7050 series"), &hDevNames, &hDevMode)) //  
     {
          AfxGetApp()->SelectPrinter(hDevNames, hDevMode);
          CPrintDialog dlgPrint(FALSE,PD_PAGENUMS|PD_USEDEVMODECOPIESANDCOLLATE , this);

      //--------------------------- Papier Auswahl DEVMODE ----------------------------------
          if(AfxGetApp()->GetPrinterDeviceDefaults(&dlgPrint.m_pd))
          {               
                    LPDEVMODE dev=dlgPrint.GetDevMode();
                GlobalUnlock(dev);
      
              dev->dmOrientation=DMORIENT_PORTRAIT;  //Hochformat
              dev->dmPaperSize=DMPAPER_A4;
              dev->dmCopies=1;  
              dev->dmDefaultSource=DMBIN_AUTO;
 
     
                //Wichtig !!!dmFields setzen
              dev->dmFields |=DM_PAPERLENGTH|DM_PAPERWIDTH|DM_ORIENTATION|DM_DEFAULTSOURCE;
              }
      
        dlgPrint.m_pd.Flags &= ~PD_RETURNDC;   // Reset flag set by constructor.
            //---------------------------------------------------------------------------
            // Force the CPrintDialog to use our device mode & name.
             dlgPrint.m_pd.hDevMode  = CopyHandle(hDevMode);
             dlgPrint.m_pd.hDevNames = CopyHandle(hDevNames);


           

               //if(dlgPrint.DoModal()==IDOK) //Ohne CPrintDialogBox
         //    {
            
               GlobalFree(hDevMode);
               GlobalFree(hDevNames);
               hDevMode  = CopyHandle(dlgPrint.m_pd.hDevMode);  // Save new copies.
               hDevNames = CopyHandle(dlgPrint.m_pd.hDevNames); // Save new copies.

                     CDC dc;
                     HDC hDCPrint = dlgPrint.CreatePrinterDC();
                     //------------------
                     dc.Attach(hDCPrint);
                     //------------------
                      
                     dc.m_bPrinting=TRUE;
                                  
            //------------------------------------
               DOCINFO Print;
                   memset( &Print, 0, sizeof(DOCINFO) );
                   Print.cbSize = sizeof (DOCINFO);
                   Print.lpszDocName = "Drucken im Dialog";
                   Print.lpszOutput = (LPTSTR) NULL;
                   Print.lpszDatatype = (LPTSTR) NULL;
                   Print.fwType = 0;
                //-----------------------------------
                                      
            BOOL bPrintingOK = dc.StartDoc(&Print);
                 CPrintInfo pInfo;
              pInfo.m_rectDraw.SetRect(0,0,dc.GetDeviceCaps(HORZRES), dc.GetDeviceCaps(VERTRES));
                 
               //~~~~~~~~~~~~~~~~~~~~~~~~~
             OnBeginPrinting(&dc,&pInfo);  // call prepare
               //~~~~~~~~~~~~~~~~~~~~~~~~~


      




     for(UINT page=pInfo.GetMinPage();page<=pInfo.GetMaxPage() &&bPrintingOK ; page++)
               {
                   //begin a new page
              dc.StartPage();
                   pInfo.m_nCurPage=page;
                   //~~~~~~~~~~~~~~~~~~~~~~~~~
                 OnPrint(&dc,&pInfo); // call Print your Page
                   //~~~~~~~~~~~~~~~~~~~~~~~~~
                  bPrintingOK=(dc.EndPage()>0);
                 }
           
                //~~~~~~~~~~~~~~~~~~~~~~~~~
                   OnEndPrinting(&dc,&pInfo); // call your clean up
                   //~~~~~~~~~~~~~~~~~~~~~~~~~
                if(bPrintingOK)
                           {
                      dc.EndDoc();
                           }
                           else
                           {
                                 dc.AbortDoc();
                           }
                     
                           dc.DeleteDC();
             //  }// Ohne CPrintDialogBox

              GlobalFree(dlgPrint.m_pd.hDevMode);
              GlobalFree(dlgPrint.m_pd.hDevNames);
       }
                  
 
 }

ASKER CERTIFIED SOLUTION
Avatar of AndyAinscow
AndyAinscow
Flag of Switzerland image

Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
Avatar of Thomas Stockbruegger

ASKER

Hello Andy,
thanks for the code.
with your code I am calling the function also 3 times (PrintToTray).
Okay...thats is fewer coding....but the same as I would call 3 different OnBnClickedButton_Printing() functions
with different dev->dmDefaultSource values.

I thought I can change the OnBnClickedButton_Printing() arround here:
  for(UINT page=pInfo.GetMinPage();page<=pInfo.GetMaxPage() &&bPrintingOK ; page++)
               {
                   //begin a new page
              dc.StartPage();
                   pInfo.m_nCurPage=page;
                  .
                  .
                  .
or is this not possible?
Let me know
Thank you.
My first thoughts are it would end up with code being repeated (because you need to print the page three times within that loop), unless there is a real requirement it is probably easier to print the complete document to one paper colour, then another, then another.


Note:  It ought to work and I might have misunderstood your intention.
okay...thats okay...so my coding (a little more)  was okay.

by the way how difficult is that?
"unless there is a real requirement it is probably easier to print the complete document to one paper colour, then another, then another"
Andy,
by the way when I call my function I got an error.
But not allways...sometimes...can you help me ?
afxcrit.cpp
1.BMP
Print the complete document at one go, three times, to different trays.

void CAuftragsHistory_Lieferschein_Dialog::OnBnClickedButton_Printing()
{
  PrintToTray(0);
  PrintToTray(1);
  PrintToTray(2);
}
Are you multithreading for the printing?
This is how I call the 3 function (only with different values 0-1-2)

void CAuftragsHistory_Lieferschein_Dialog::OnBnClickedButton_Drucken()
{    

    int iLieferscheinNr=atoi(m_strLieferscheinNr);//MemberVariable
        
      m_button_Drucken.EnableWindow(false);//disable
      Sleep(1000);
    //===============
      VERIFY(Drucken_weiss());
       Sleep(1000);
      if(iLieferscheinNr<200000) MessageBox(" Drucke Lieferschein " +m_strLieferscheinNr);
      if(iLieferscheinNr>200000) MessageBox(" Drucke Warenbegleitschein " +m_strLieferscheinNr);
    //===============
    Sleep(1000);
       VERIFY(Drucken_rot());
        //===============
      Sleep(1000);
       VERIFY(Drucken_gruen());
      //===============
      Sleep(1000);
      
      m_button_Drucken.EnableWindow(true);//not disable


 
 
}
Why do you have the Sleep statements?

I assume the three Drucken_xxx functions are effectively what you had originally (three pieces of identical code apart from specifying which printer tray)

because I thought that will erase the error
Why do you have the Sleep statements?

I assume the three Drucken_xxx functions are effectively what you had originally (three pieces of identical code apart from specifying which printer tray) = yes

you see that I don´t use the printdialog
   //if(dlgPrint.DoModal()==IDOK) //Ohne CPrintDialogBox
         //    {
but when I use the dialog, until now I have no error
Please let me know, thanks.
Hello Andy,
this is my code for GetPrinterDevice....perhaps the error comes from here?
please help, thanks



//#######################################################################################
bool CAuftragsHistory_Lieferschein_Dialog::GetPrinterDevice(LPTSTR pszPrinterName, HGLOBAL* phDevNames, HGLOBAL* phDevMode)
{
      // if NULL is passed, then assume we are setting app object's
    // devmode and devnames
    if (phDevMode == NULL || phDevNames == NULL)
      {
            MessageBox("EPSON LQ-680Pro Port 2 Wiegekarte-1error");
        return FALSE;
      }


    // Open printer
    HANDLE hPrinter;
    if (OpenPrinter(pszPrinterName, &hPrinter, NULL) == FALSE)
      {
            MessageBox("EPSON LQ-680Pro Port 2 Wiegekarte-2error");
        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)
      {
       GlobalFree(p2);
       ClosePrinter(hPrinter);
       MessageBox("EPSON LQ-680Pro Port 2 Wiegekarte-3error");
       return FALSE;
    }
     ClosePrinter(hPrinter);

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

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

    // 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 = GlobalAlloc(GHND, sizeof(DEVNAMES) +(drvNameLen + ptrNameLen + porNameLen)*sizeof(TCHAR));
    ASSERT(hDevNames);
    DEVNAMES* pDevNames = (DEVNAMES*)GlobalLock(hDevNames);
    ASSERT(pDevNames);

    // 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;

    GlobalUnlock(hDevNames);
    GlobalFree(p2);   // free PRINTER_INFO_2

    // set the new hDevMode and hDevNames
    *phDevMode = hDevMode;
    *phDevNames = hDevNames;
    return TRUE;
}

//#######################################################################################
HANDLE CAuftragsHistory_Lieferschein_Dialog::CopyHandle(HANDLE h)
{
      // Return a handle to a copy of the data
    // that the passed handle was for.
    if (!h) return NULL;

    BYTE*   lpCopy;
    BYTE*   lp;
    HANDLE   hCopy;
    DWORD   dwLen = GlobalSize(h);
    if (hCopy = GlobalAlloc(GHND, dwLen))
    {
        lpCopy = (BYTE*)GlobalLock(hCopy);
        lp     = (BYTE*)GlobalLock(h);

        CopyMemory(lpCopy,lp,dwLen);

        GlobalUnlock(hCopy);
        GlobalUnlock(h);
    }

    return hCopy;

}

//#######################################################################################
This is getting really away from the original question.
I don't know if I have the time to study your code in detail - occasional errors are usually very difficult to track down.

Again - are you using multiple threads?  If yes then that might be the cause.
Again - are you using multiple threads?  If yes then that might be the cause.
Sorry...but I don´t know if yes or no, what is multiple threads
AfxBeginThread, CreateThread

If you don't know then probably not
okay...then I do not use it
Andy,
the strange thing is that the stop and exeptions only happens with the GetPrinterDevice
I did printing before with the printdialog and default printer with no error at all.
The only thing I had to do is to enable the Property button of the printerdialog, because otherwise it sometimes crashed.
The printer I use here is the default printer....the printing must be done without the dialog.
Is there a other way to print here without the GetPrinterDevice...if that is the cause of the error, and without the printdialog?
I'll try to think about it.
okay...I appreciate your help....printing is very strange....thank you
 Andy,
one other hint......

if I change    if (GetPrinterDevice(_T("\\\\DSERVER\\Brother HL-7050 series"), &hDevNames, &hDevMode)) //  



to   if (GetPrinterDevice(_T("PowerPDF 2005"), &hDevNames, &hDevMode)) //  



to print a PDF with GetPrinterDevice ... I can press the button 100´s times wiht no error at all

        HANDLE hDevMode;
          HANDLE hDevNames;

   if (GetPrinterDevice(_T("PowerPDF 2005"), &hDevNames, &hDevMode)) //       {
          AfxGetApp()->SelectPrinter(hDevNames, hDevMode);
          CPrintDialog dlgPrint(FALSE,PD_PAGENUMS|PD_USEDEVMODECOPIESANDCOLLATE , this);

Andy,
If I go on and on to printing this is my  Call Stack when I crash with printing

>      KERNEL32.DLL!77eaf870()      
       KERNEL32.DLL!77eae67e()

Threads
>      2504      CStockbrueggerView::OnPaint      77eaf870      Normal      0
       2352      Win32 Thread      77888f03      Normal      0
       2120      Win32 Thread      77888b37      Normal      0
     
 

Hi Andy, please take a look at my new question...I think I have to clean first my program with errors, Thank you