C++ output to default printer

Hi

I have written a simple console application in Visual C++ v6 that generates an invoice, the invoice has to go to screen, append to log file, and out to printer as well. I have the out to screen using a "cout" in a loop, similarly, appending the log is done like this:

#INCLUDE <fstream.h>
ofstream outfp;
void main()
{
outfp.open("c:log.txt", ios::app);
outfp << "OUTPUT TEXT";
outfp.close();
}

I want an output to the default printer in a similar way, it needs to be SIMPLE as i'm a TOTAL BEGINNER in C++. I think the problem lies in discovering the default printer, it may be a network printer for example, or USB etc. I've read there is a method using "Document.PrintOut" that will allow to print a text file, but can't find how. The SIMPLEST WORKING SOLUTION is what i'm after!

Thanks all, in advance

s1desh0w
s1desh0wAsked:
Who is Participating?
 
Gary BenadeConnect With a Mentor Commented:
to do that you would break things up a bit like this.

bool startpage( PRINTDLG * pd)
{
  HANDLE hOwner = NULL;  // you can assign the handle of you application here instead of NULL.
  DOCINFO docinfo;            // a windows document info structure
  docinfo.cbSize = sizeof( docinfo);        // windows wants to know the size of the structure
  docinfo.lpszDatatype = (LPTSTR) NULL;  // NULL means default
  docinfo.lpszOutput = NULL;             // NULL means default
  docinfo.lpszDocName = "Job Name";     // give the job a name that will show in the windows spooler, you can use the invoice number
  docinfo.fwType = 0;                  
  memset( pd, 0, sizeof(PRINTDLG));   // clear the buffer by setting it all to 0's
  pd->lStructSize = sizeof(PRINTDLG); // windows wants to know the size of the structure
  pd->hwndOwner = (HWND*)hOwner;         // a dialog needs an owner, just like a puppy
  pd->Flags = PD_RETURNDC;         // tell windows that we want a device context (a way to talk ) to the printer the user selects
  if (PrintDlg( pd) != 0)              // show the windows select printer dialogue to set options and select destination printer
  {                                             // if the user selected print
      StartDoc(pd->hDC, &docinfo);    // start a new document for the printer
      StartPage(pd->hDC);                 // start a new page in that document
      return true;
  }
  return false;
}
void endpage( PRINTDLG * pd)
{
    EndPage(pd->hDC);                    // end the page
    EndDoc(pd->hDC);                     // end the document and send it to the windows spooler
    DeleteDC(pd->hDC);                   // close the device context to free resources
}
void textout( PRINTDLG * pd, int x, int y, char * str)
{
    TextOut( pd->hDC, x, y, str, strlen( str));  
}

//Your code would look like this

void doinvoice( void)
{
  PRINTDLG pd;                  // a windows print dialog structure
  char str[1025];                           // our string buffer
  if( startpage( &pd))
  {
      strcpy( str,"INVOICE: 10243");    // use whatever method you like to populate str
      textout( &pd,1,1,str);
      strcpy( str,"NAME: NAME");    
      textout( &pd, 1,50,str);
      endpage( &pd);    
  }
}  
0
 
Gary BenadeCommented:
If you are writing a windows app (since you mention default printers I assume you are) this will work

  TPrinter * Prntr = Printer();
  TRect r = Rect(200,200,Prntr->PageWidth-200,Prntr->PageHeight-200);
  Prntr->BeginDoc();
  Prntr->Canvas->TextRect(r, 200, 200, "Text");  // use any TCanvas methods on the printers canvas
  Prntr->EndDoc();
0
 
Gary BenadeCommented:
Have a sneaky feeling that VC++ doesnt support the TPrinter object

In that case you can always resort to this

#include <stdio.h>

FILE *fp = fopen("LPT1", "w");
fprintf(fp,"What's up, Doc?\n");
fclose(fp);
0
Cloud Class® Course: Microsoft Windows 7 Basic

This introductory course to Windows 7 environment will teach you about working with the Windows operating system. You will learn about basic functions including start menu; the desktop; managing files, folders, and libraries.

 
Gary BenadeCommented:
or with streams

    ofstream optr("LPT1", ios::out);
    optr << "Hello\n" << "\f" << flush;  // with a formfeed
    optr.close();
0
 
s1desh0wAuthor Commented:
hi Hobbit

thanks for your reply, it's not a windows app i should have said it is a console app. I tried your second bit of code, but it just hung. same on the 3rd, havn't tried the 1st. I'm on a networked printer here, attached to a server via usb, but this would obviously vary from machine to machine.

The code showed no errors but is that all the code needed or might i have to include more? i.e. includes etc, i have stdio.h there already... is lpt1 a virtual port, i.e. it will always get sent to the default, or rather is it a physical port? I'm rather confused and have very limited knowledge of C++.

Thanks


0
 
Gary BenadeCommented:
LPT1 is a physical port, so you waould have to have something plugged in for it to work. Does your console app run under windows, or is it DOS based?

If its a windows app, give example one a try, it should work if VC++ ships with the TPrinter object
0
 
s1desh0wAuthor Commented:
with the 1st code i get 14 errors, i checked about 6 of them and they are all "undeclared identifier", must i include more headers etc? The app is a win32 console app.

Thanks
0
 
Gary BenadeCommented:
you need to #include "printers.hpp"
0
 
s1desh0wAuthor Commented:
hi, Hobbit

I tried

#include "printers.hpp"
#include <printers.hpp>
#include <"printers.hpp">

no good, i just discovered as well that i don't have the Cstring.h file either which i needed for string concatination, i guess thats a whole other question!! I guess there is no easy way of addressing the default printer like you can a port?
0
 
Gary BenadeCommented:
this uses nothing but standard windows functions

  HANDLE hOwner = NULL;  // you can assign the handle of you application here instead of NULL.
  PRINTDLG pd;
  DOCINFO docinfo;
  docinfo.cbSize = sizeof( docinfo);
  docinfo.lpszDatatype = (LPTSTR) NULL;
  docinfo.lpszOutput = NULL;
  docinfo.lpszDocName = "Job Name";
  docinfo.fwType = 0;
  memset( &pd, 0, sizeof(PRINTDLG));
  pd.lStructSize = sizeof(PRINTDLG);
  pd.hwndOwner = hOwner;
  pd.Flags = PD_RETURNDC;
  char str[10];
  strcpy( str,"test");
  if (PrintDlg( &pd) != 0)
  {
    StartDoc(pd.hDC, &docinfo);
    StartPage(pd.hDC);
    TextOut( pd.hDC, 1, 1, str, strlen( str));
    EndPage(pd.hDC);
    EndDoc(pd.hDC);
    DeleteDC(pd.hDC);
  }
0
 
Gary BenadeCommented:
why bother with Cstrings, just use the standard c functions

  char str[10];
  strcpy( str,"test");
  strcat( str, "Gary");  // str now contains testGary
0
 
Gary BenadeCommented:
you may need some( or all) of these headers to make things work

#include <windows.h>
#include <winbase.h>
#include <commdlg.h>
#include <string.h>
#include <stdio.h>
0
 
s1desh0wAuthor Commented:
thanks very much for the strings tip, that works fine. I'm scared by that code above, is it really necessary? I don't like using code i don't understand myself, it leads to bigger problems in the future i find.

If i have to use this can you tell me exactly what i'd have to do with it? Really i was hoping for an easy way to address the default printer like you suggested with streams to "LPT1", if only!!
0
 
Gary BenadeCommented:
to make it less scary ;) I have commented the code. Play around with it a bit and you'll soon get the hang of things

  HANDLE hOwner = NULL;  // you can assign the handle of you application here instead of NULL.
  PRINTDLG pd;                  // a windows print dialog structure
  DOCINFO docinfo;            // a windows document info structure
  docinfo.cbSize = sizeof( docinfo);        // windows wants to know the size of the structure
  docinfo.lpszDatatype = (LPTSTR) NULL;  // NULL means default
  docinfo.lpszOutput = NULL;             // NULL means default
  docinfo.lpszDocName = "Job Name";     // give the job a name that will show in the windows spooler, you can use the invoice number
  docinfo.fwType = 0;                  
  memset( &pd, 0, sizeof(PRINTDLG));   // clear the buffer by setting it all to 0's
  pd.lStructSize = sizeof(PRINTDLG); // windows wants to know the size of the structure
  pd.hwndOwner = hOwner;         // a dialog needs an owner, just like a puppy
  pd.Flags = PD_RETURNDC;         // tell windows that we want a device context (a way to talk ) to the printer the user selects
  char str[1025];                           // our string buffer
  if (PrintDlg( &pd) != 0)              // show the windows select printer dialogue to set options and select destination printer
  {                                             // if the user selected print
    StartDoc(pd.hDC, &docinfo);    // start a new document for the printer
    StartPage(pd.hDC);                 // start a new page in that document
    strcpy( str,"INVOICE: 10243");    
    TextOut( pd.hDC, 1, 1, str, strlen( str));  // print it a x=1, y=1
    strcpy( str,"NAME: BOB");
    TextOut( pd.hDC, 1, 50, str, strlen( str));  // print it a x=1, y=50
    strcpy( str,"ADDR: 1 SNAKE RD");
    TextOut( pd.hDC, 1, 100, str, strlen( str));  // print it a x=1, y=100
    EndPage(pd.hDC);                    // end the page
    EndDoc(pd.hDC);                     // end the document and send it to the windows spooler
    DeleteDC(pd.hDC);                   // close the device context to free resources
  }
0
 
s1desh0wAuthor Commented:
Thanks for your reply, i have pasted this lot into a function ( void out_to_printer() ) and added the includes above void main, as you would. It is showing me 1 error at the following line:

pd.hwndOwner = hOwner;

The error reads:

error C2440: '=' : cannot convert from 'void *' to 'struct HWND__ *'

Further to this i'm not sure how to get the data output in this way, for invoice to screen i have used cout << "all my variables and text with endl's and all that kind of thing", for output to file i have similarly used a stream called outfp, so outfp << "an exact copy of what goes to screen". It would be great to use this method, but the data to output is not stored in a variable, rather it is constructed at the point of output, in runtime, so i don't know how to pass or reference the output using this code.

Sorry if i am waffling here but i am doing my best to explain with limited knowledge of C++ and programming lingo!

Again, thanks for all your help!
0
 
s1desh0wAuthor Commented:
Thanks for all your help, i have not actually tested the code above but i am accepting this as the answer. I have opted for naming the port.

Regards

s1desh0w
0
Question has a verified solution.

Are you are experiencing a similar issue? Get a personalized answer when you ask a related question.

Have a better answer? Share it in a comment.

All Courses

From novice to tech pro — start learning today.