• Status: Solved
  • Priority: Medium
  • Security: Public
  • Views: 1089
  • Last Modified:

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
0
s1desh0w
Asked:
s1desh0w
  • 10
  • 6
1 Solution
 
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
 
Gary BenadeCommented:
or with streams

    ofstream optr("LPT1", ios::out);
    optr << "Hello\n" << "\f" << flush;  // with a formfeed
    optr.close();
0
VIDEO: THE CONCERTO CLOUD FOR HEALTHCARE

Modern healthcare requires a modern cloud. View this brief video to understand how the Concerto Cloud for Healthcare can help your organization.

 
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
 
Gary BenadeCommented:
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
 
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

Featured Post

What does it mean to be "Always On"?

Is your cloud always on? With an Always On cloud you won't have to worry about downtime for maintenance or software application code updates, ensuring that your bottom line isn't affected.

  • 10
  • 6
Tackle projects and never again get stuck behind a technical roadblock.
Join Now