Link to home
Start Free TrialLog in
Avatar of DonH040699
DonH040699

asked on

Print Utility

I need to write a simple utility program that will print a text file. I could pass the name of the file as an arguement or poll for a specific file name. This is basically to let a DOS program use a Windows only printer. I have just purchased VC++ 6.0. Is there a simple way to do this?
ASKER CERTIFIED SOLUTION
Avatar of nietod
nietod

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 DonH040699
DonH040699

ASKER

The problem I've run into is: new Cannon printers will not print from DOS. I am currently writing to the printer as a file. Everything appears to be normal (the printer icon appears) but no output. From what I've heard, unless the printer says DOS & Windows, it's a windows only printer. Which type of project (in the wizard) should I select?
The printer is just connected to a COM or LPT port, it doesn't knwo what is on the other end.  You can print to it from anything that produces the right signal.

Are you sending a formfeed at the end of the print?
does the printer have a text mode?   Does it have to be placed into that mode (you may need to send it escape sequences to place it in text mode.)  Most printers come with a manuall that list the modes and escape sequences (commands) that can be sent to the printer to affect its various modes, paper sizes, fonts etc.  You may need to look into that.
>> Which type of project (in the
>>wizard) should I select?
To do what?

If you are using VC, then you are not in DOS anyways  (VC doesn't support DOS programs).  Then choose a GUI program in you want a fancy windows GUI interface or choose a console program if you want a DOS-like interface.  However either of these can use the windows API functions to print to the printer.
The program has been printing on any type of printer for several years now. Lately, I have had 2 users systems I couldn't get to print. They both were windows only printers. I'm guessing they have no character recognition of their own and rely on windows loaded print drivers. One user changed back to his old printer and the problem was solved. I have spoken with a friend who had the same problem with his program. He wrote a windows print program that polls for a specific file and prints it. Unfortunately he writes in Delphi and also has his forms set up with field templates. I was hoping it would be less work for me to write a c/c++ program to print the file as is just using the existing spaces and line feeds as before. Do windows programs only print on a field position basis? Can I print a text file as is? Can I make a system call from my DOS program to have the new print program run and quit or will it have to stay running and poll for the text file?
>> I was hoping it would be less work for
>> me to write a c/c++ program to print the
>> file as is just using the existing spaces and
>> line feeds as before.
That can be done with or without using the windows API.  but if it isn't working without using the windows API, its not going to work with the windows API.  So switching to windows will not help if you want to go along this approach.

However, the reason it is not working, is almost certainly the fact that the printer simply si in the wrong mode.  You probably just have to send it an escape sequence to place it in the right mode.  (What we do to handle this is to have a file of printer "commands"  Like commands used to start the print, commands used to change pitch, commands used to finish a page, commands used to finish a print etc.  The entry for this printer would have a "start print command" that places the printer in the correct mode.)  You probalby just need to get the technical manual for the printer to find out the escape sequence you need to send the printer to change it to the right mode.

>> Do windows programs only print on a field
>> position basis?
I'm not sure what you even mean by that.    But I suspect the answer is no anyways.  In windows, 99.999% of the time printing is handled by drawing graphics to a printer DC.  i.e you draw what you want to print and then when you are done the image is sent to the printer.  So the printer never receives the raw text, it receives and image of the text.  However there are procedures for dending data directly to the printer, this allows you to send text directly to the printer and not be concerned with drawing issues.  However these functions are rarely used.  They are WritePrinter() and Escape().  

>> Can I make a system call from my DOS program
>> to have the new print program run and quit
Yes.  But the issue is how to get the new print program to print.  It either has to used the windows API, which is a lot of work.  (If you aren't experienced in it, but I guess it certaily is typical in most windows programs that print.)  Or you have to write directly to the printer, which if you can do this 2nd program, you coudl do from the 1st.

If you choose to do this from a windows program, you can use a windows GUI or windows console program, which doesn't matter since the program will have no used interface.    It will simply look at the command line parameters (that may be a little easier to do from a console) and find the name of the file to be printed.  open the file and then print it using the procedures I mentioned above.
Are you running on Windows NT systems?

There is an article in MSDN that notes some problems when printing from MS-DOS apps in NT:

http://support.microsoft.com/support/kb/articles/Q202/3/33.ASP

there is also a link there to a company that produces a shareware app that claims to solve the problem (it also has the facility that allows any file sent to specified folder to be printed):

http://www.perilous.com/rawprint.htm
I don't know about that knowledge base article.  It says

>> When you print jobs from an MS-DOS-based
>> program within Windows NT, Windows NT does
>> not pass the printer control codes to the printer.

That sounds like it is _always_ true.  Well, I've printed directly to printers from DOS on 100s of NT computers and I have never seen a problem. Its possible that there is a problem under some circumstances, but the article doesn't say what those would be and I've never seen it.
I believe both users have Windows98. I have talked to other people who have experienced the windows only printer problem. To get their DOS programs to print, they had to exchange their new printer for one that says "for DOS and windows". The RawPrint program might be the answer but, it says it bypasses the windows print drivers. I was hoping to have a program that would pop up the windows print box so the user could choose the printer, fax, etc. Some sample code could get me going in the right direction. Thanks, Don
Here is some code from a utility of mine.  Some of it uses a library that I wrote that you (obviously) don't have, but you can write equivalent code.

**************************


void
PrtTxtStr(HWND        WndHnd,
    // window handle for the window that the print dialog
    // should appear in front of.
          const QStr &DscStr,
      //  String class object storing a description fo the print.
          const QStr &TxtStr)
     // string class object storing the text to be printed.
{
   PRINTDLG PrtSet; // Windows' print dialog parameters.

   memset(&PrtSet,0,sizeof(PRINTDLG)); // 0 the parameters.
   PrtSet.lStructSize = sizeof(PRINTDLG); // set the size of the parameters
   PrtSet.hwndOwner = WndHnd; // Specfy owner window.
   PrtSet.hDevMode = NULL; // Indicate there is no printer device
                           // mode data.
   PrtSet.Flags = PD_NOPAGENUMS | PD_NOSELECTION | PD_RETURNDC;
               // Inicate no page range options, no print
               // selection only option, and a DC for the printer
               // should be returned.
               // Your flags might have to be different.
   BOOL PrtFlg = PrintDlg(&PrtSet); // display the print dialog

   if (PrtFlg)  // If user wants to print.
   {
      const int  IchUnt    = 144; // Inch unit, for setting scale,
                        // you might wnat to ignore.
      QDC        DC          (PrtSet.hDC,true); // A class for dealing with
                       // DCs, you can just use the DC.
      DOCINFO    DocInf;  // Document information, you will need.
     // This sets up a scale on the printer DC.
      int        DrwWdt    = DC.GetDrwWdt(QGraUntStd)*IchUnt/100;
      int        DrwHgt    = DC.GetDrwHgt(QGraUntStd)*IchUnt/100;
      int        PhyWdt    = DC.GetPhyWdt(QGraUntStd)*IchUnt/100;
      int        PhyHgt    = DC.GetPhyHgt(QGraUntStd)*IchUnt/100;

      QAry<QStr> LinAry; // Array that holds the lines to be printed.
      int ChrWdt;
      int ChrHgt;

      SetUpPrtDC(DC,IchUnt); // This sets the font and scale.
      DC.GetFntInf(ChrWdt,ChrHgt); // This get font information.


     // Just figure out coordinates.
      int Btm    = PhyHgt - IchUnt - ChrHgt;     // Bottom Y-coordinate.                          //
      int CurY   = Btm + 1;                      // Current Y coordinate                          //
      int WrpWdt = PhyWdt - 3*IchUnt/2;          // Wrap text area width.                         //
      int WrpHgt = PhyHgt - 13*IchUnt/4;         // Wrap text area height.                        //

     // This converts the stirng to be printed to multiple
     // lines of wrapped text.
      DC.GetWrpTxt(LinAry,TxtStr,WrpWdt);


      const int LinCnt = LinAry.GetItmCnt(); // The number of lines to print.
      int       LinPag = WrpHgt/ChrHgt;          // Lines per page.                               //
      int       PagNum = 0;                      // Page number.                                  //
      int       PagCnt = (LinCnt+LinPag-1) / LinPag; // Total page count.                         //
      int       CurOff = 0;                      // Offset into text string.                      //

    // Set up the document information
    // you will need to do.
      DocInf.cbSize = sizeof(DOCINFO);
      DocInf.lpszDocName = DscStr; // Set descruption.
      DocInf.lpszOutput = NULL;
      DocInf.lpszDatatype = NULL;
      DocInf.fwType = 0;
      StartDoc(DC,&DocInf); // Start printing.  You will need to do.

     // Print the text. You will need to do, more or less.
      for (int i=0; i < LinCnt; ++i)             // For each line.                                //
      {
         if (CurY > Btm)
         {
            QStr PagMsg;
            int  PagMsgLen;

            if (PagNum)
               EndPage(DC); // This ends a page,
                             skipped on first page.  You will need.

            StartPage(DC); // This start a new page.  You will need.
            SetUpPrtDC(DC,IchUnt); // This sets the scale again.

            PrtPagHdr(DC,IchUnt,DscStr); // Prints a header, you won't need.
            ++PagNum;                            // Increment the page number.                    //
            CurY = 9*IchUnt/4;
         }
       // Outputs a line of text.  You will use TextOut() or something similar.
         DC.TxtOut(3*IchUnt/4,CurY,LinAry[i]);   // Display the current line.                     //
         CurY += ChrHgt;                         // Calculate next line's position.               //
      }

      if (PagNum)
         EndPage(DC); // End the last page.  You need.
      EndDoc(DC);  // End the print.  You need.
   }
   GlobalFree(PrtSet.hDevMode); // Free device mode data.  You need
                   // Often forgotten.
   GlobalFree(PrtSet.hDevNames); // You need also often forgotten.
}
Great commenting! Where does my my textfile.txt fit in?
well where I obtain a line of text from an array class, you obtain if trom the text file.

         DC.TxtOut(3*IchUnt/4,CurY,LinAry[i]);  

you would get a line and print it doing something like

string Line;
fstream File;

getline(File,Line);
TextOut(hDC,x,y,Line.c_str(),Line.length());
Where do I place the above code and where am I opening the text file for reading? The wizard is starting me with:

#include "stdafx.h"
#include "iostream.h"

int APIENTRY WinMain(HINSTANCE hInstance,
                     HINSTANCE hPrevInstance,
                     LPSTR     lpCmdLine,
                     int       nCmdShow)
{
// TODO: Place code here.

      return 0;
}
You do know how to program don't you?  

I can give you some algorithms and answer specific questions, but you will have to write the program.  

Like any progrma you open the file before you need it and close it when you are done.  Where?  That is up to you and how you design your program.  You can do it in main, you can do it in a procedure, you can do it using a global varaible.
I have been programming in C for many years. As I stated in my question, I have just purchased Visual C++ 6.0. What is the equivilant of:

File *fp
fp = fopen("textfile.txt","rt");
fclose(fp);

It looks as if PrtTxtStr() is a function that would be called in WinMain() after reading the file. Is that correct?

You can continue to use the C code you are familiar with.  Or you can switch to using C++ file stream objects (which are superior in most ways) or you can use the windows API file functions  (the most powerful choice, but also hardest to use.)

>> It looks as if PrtTxtStr() is a function
>> that would be called in WinMain() after
>> reading the file. Is that
>> correct?
Or it could read the file as it works.  it depends on you how you want to design things.  If you read the file first you will have to store the whole text in memory.  That could be a lot of memory if the file is huge.  (but then it will be a lot of paper too, so that might not be likely.)
I've tried using C Code, it won't accept the FILE assignment. I added the function you suggested and got multiple errors, mostly undeclared identifiers. I suspect I need to #include a header file. Am I missing a standard header file or one you created?
>> I've tried using C Code, it won't
>> accept the FILE assignment
What was the error?

>> I added the function you suggested and got
>> multiple errors, mostly undeclared identifiers.
Which one?  if you use the C++ file i/O streams you need to include <fstream> (not <fstream.h>) and the names it defiens are in the "std" namespace, so you might want to add a "using namespace std".  The windows API file functions are defined in <windows.h>.
The error message for FILE is a syntax error expecting ";". Also "FILE" doesn't turn blue like the other key words do. I included <fstream> <windows.h> and added "using namespace std;" which "using namespace" did turn blue. I still get the same errors. Do I need to make wqprint.h? I cut and pasted the code from above. Line 24 is:
          const QStr &DscStr,
     

Compiling...
wqprint.cpp
D:\Program Files\DevStudio\MyProjects\wqprint\wqprint.cpp(24) : error C2143: syntax error : missing ',' before '&'
D:\Program Files\DevStudio\MyProjects\wqprint\wqprint.cpp(24) : error C2059: syntax error : '&'
D:\Program Files\DevStudio\MyProjects\wqprint\wqprint.cpp(29) : error C2065: 'PRINTDLG' : undeclared identifier
D:\Program Files\DevStudio\MyProjects\wqprint\wqprint.cpp(29) : error C2146: syntax error : missing ';' before identifier 'PrtSet'
D:\Program Files\DevStudio\MyProjects\wqprint\wqprint.cpp(29) : error C2065: 'PrtSet' : undeclared identifier
D:\Program Files\DevStudio\MyProjects\wqprint\wqprint.cpp(32) : error C2228: left of '.lStructSize' must have class/struct/union type
D:\Program Files\DevStudio\MyProjects\wqprint\wqprint.cpp(33) : error C2228: left of '.hwndOwner' must have class/struct/union type
D:\Program Files\DevStudio\MyProjects\wqprint\wqprint.cpp(34) : error C2228: left of '.hDevMode' must have class/struct/union type
D:\Program Files\DevStudio\MyProjects\wqprint\wqprint.cpp(36) : error C2228: left of '.Flags' must have class/struct/union type
D:\Program Files\DevStudio\MyProjects\wqprint\wqprint.cpp(36) : error C2065: 'PD_NOPAGENUMS' : undeclared identifier
D:\Program Files\DevStudio\MyProjects\wqprint\wqprint.cpp(36) : error C2065: 'PD_NOSELECTION' : undeclared identifier
D:\Program Files\DevStudio\MyProjects\wqprint\wqprint.cpp(36) : error C2065: 'PD_RETURNDC' : undeclared identifier
D:\Program Files\DevStudio\MyProjects\wqprint\wqprint.cpp(41) : error C2065: 'PrintDlg' : undeclared identifier
D:\Program Files\DevStudio\MyProjects\wqprint\wqprint.cpp(47) : error C2065: 'QDC' : undeclared identifier
D:\Program Files\DevStudio\MyProjects\wqprint\wqprint.cpp(47) : error C2146: syntax error : missing ';' before identifier 'DC'
D:\Program Files\DevStudio\MyProjects\wqprint\wqprint.cpp(47) : error C2065: 'DC' : undeclared identifier
D:\Program Files\DevStudio\MyProjects\wqprint\wqprint.cpp(47) : error C2228: left of '.hDC' must have class/struct/union type
D:\Program Files\DevStudio\MyProjects\wqprint\wqprint.cpp(51) : error C2228: left of '.GetDrwWdt' must have class/struct/union type
D:\Program Files\DevStudio\MyProjects\wqprint\wqprint.cpp(51) : error C2065: 'QGraUntStd' : undeclared identifier
D:\Program Files\DevStudio\MyProjects\wqprint\wqprint.cpp(52) : error C2228: left of '.GetDrwHgt' must have class/struct/union type
D:\Program Files\DevStudio\MyProjects\wqprint\wqprint.cpp(53) : error C2228: left of '.GetPhyWdt' must have class/struct/union type
D:\Program Files\DevStudio\MyProjects\wqprint\wqprint.cpp(54) : error C2228: left of '.GetPhyHgt' must have class/struct/union type
D:\Program Files\DevStudio\MyProjects\wqprint\wqprint.cpp(56) : error C2065: 'QAry' : undeclared identifier
D:\Program Files\DevStudio\MyProjects\wqprint\wqprint.cpp(56) : error C2065: 'LinAry' : undeclared identifier
D:\Program Files\DevStudio\MyProjects\wqprint\wqprint.cpp(56) : warning C4804: '>' : unsafe use of type 'bool' in operation
D:\Program Files\DevStudio\MyProjects\wqprint\wqprint.cpp(56) : warning C4552: '>' : operator has no effect; expected operator with side-effect
D:\Program Files\DevStudio\MyProjects\wqprint\wqprint.cpp(60) : error C2065: 'SetUpPrtDC' : undeclared identifier
D:\Program Files\DevStudio\MyProjects\wqprint\wqprint.cpp(61) : error C2228: left of '.GetFntInf' must have class/struct/union type
D:\Program Files\DevStudio\MyProjects\wqprint\wqprint.cpp(72) : error C2228: left of '.GetWrpTxt' must have class/struct/union type
D:\Program Files\DevStudio\MyProjects\wqprint\wqprint.cpp(72) : error C2065: 'TxtStr' : undeclared identifier
D:\Program Files\DevStudio\MyProjects\wqprint\wqprint.cpp(75) : error C2228: left of '.GetItmCnt' must have class/struct/union type
D:\Program Files\DevStudio\MyProjects\wqprint\wqprint.cpp(84) : error C2065: 'DscStr' : undeclared identifier
D:\Program Files\DevStudio\MyProjects\wqprint\wqprint.cpp(84) : error C2440: '=' : cannot convert from 'int' to 'const char *'
        Conversion from integral type to pointer type requires reinterpret_cast, C-style cast or function-style cast
D:\Program Files\DevStudio\MyProjects\wqprint\wqprint.cpp(95) : error C2146: syntax error : missing ';' before identifier 'PagMsg'
D:\Program Files\DevStudio\MyProjects\wqprint\wqprint.cpp(95) : error C2065: 'PagMsg' : undeclared identifier
D:\Program Files\DevStudio\MyProjects\wqprint\wqprint.cpp(100) : error C2065: 'skipped' : undeclared identifier
D:\Program Files\DevStudio\MyProjects\wqprint\wqprint.cpp(100) : error C2146: syntax error : missing ';' before identifier 'on'
D:\Program Files\DevStudio\MyProjects\wqprint\wqprint.cpp(100) : error C2065: 'on' : undeclared identifier
D:\Program Files\DevStudio\MyProjects\wqprint\wqprint.cpp(100) : error C2146: syntax error : missing ';' before identifier 'first'
D:\Program Files\DevStudio\MyProjects\wqprint\wqprint.cpp(100) : error C2065: 'first' : undeclared identifier
D:\Program Files\DevStudio\MyProjects\wqprint\wqprint.cpp(100) : error C2146: syntax error : missing ';' before identifier 'page'
D:\Program Files\DevStudio\MyProjects\wqprint\wqprint.cpp(100) : error C2065: 'page' : undeclared identifier
D:\Program Files\DevStudio\MyProjects\wqprint\wqprint.cpp(100) : error C2228: left of '.You' must have class/struct/union type
D:\Program Files\DevStudio\MyProjects\wqprint\wqprint.cpp(100) : error C2146: syntax error : missing ';' before identifier 'will'
D:\Program Files\DevStudio\MyProjects\wqprint\wqprint.cpp(100) : error C2065: 'will' : undeclared identifier
D:\Program Files\DevStudio\MyProjects\wqprint\wqprint.cpp(100) : error C2146: syntax error : missing ';' before identifier 'need'
D:\Program Files\DevStudio\MyProjects\wqprint\wqprint.cpp(100) : error C2065: 'need' : undeclared identifier
D:\Program Files\DevStudio\MyProjects\wqprint\wqprint.cpp(102) : error C2228: left of '.StartPage' must have class/struct/union type
D:\Program Files\DevStudio\MyProjects\wqprint\wqprint.cpp(105) : error C2065: 'PrtPagHdr' : undeclared identifier
D:\Program Files\DevStudio\MyProjects\wqprint\wqprint.cpp(110) : error C2228: left of '.TxtOut' must have class/struct/union type
D:\Program Files\DevStudio\MyProjects\wqprint\wqprint.cpp(110) : error C2109: subscript requires array or pointer type
D:\Program Files\DevStudio\MyProjects\wqprint\wqprint.cpp(118) : error C2228: left of '.hDevMode' must have class/struct/union type
D:\Program Files\DevStudio\MyProjects\wqprint\wqprint.cpp(120) : error C2228: left of '.hDevNames' must have class/struct/union type
Error executing cl.exe.

wqprint.exe - 51 error(s), 2 warning(s)
>> the error message for FILE is a
>> syntax error expecting ";"
What is the code yiu were using?  (before and after the line that produced the problem).  Did you include <fstream.h>?

>> I included <fstream> <windows.h>
But <fstream> doesn't define "FILE".  it defines "class fstream".  <fstream.h> defines "FILE".  You can used any of the three methods, but you have to be consistent.

>> Do I need to make wqprint.h?
What do you mean?   what is it?

>> const QStr &DscStr,
That is a string that describes the print.  Use a char[] or a STL string or any other type of string you want.

Those error messages are all meaningless to me without the code.

Although a few of them do suggest that you don't have <windows.h> included.
I will try <fstream.h>. The only code before FILE was the #includes. I cut and pasted the sample code you wrote. The (error lines) match that sample code with "const QStr &DscStr," as line 24.
<<What is wqprint.h? VC++ defines variables and function prototypes in a header file usually with the same name as the source file.
>> I cut and pasted the sample code
>> you wrote
That was just to give you an idea of what you have to do.  That was taken from code that does something _similar_ to your case, but not the same and it depends heavily on classes you don't have.  You will have to write you own code with this a model.
OK. I will use the code as a guideline. The <fstream.h> doesn't let me use FILE so I am using ifstream() & read()sucessfully. When I add OnPreparePrinting, I get another undeclared identifier error. Which header file has the print functions?
The windows print fiunctions are in <windows.h>.

Sorry, I was wrong.  The FILE stuff is in <stdio.h>.  (I don't use the C stuff very often.  Actually, other than answering questions here its been 12+ years.)   But, in the long run you are better off using the C++ stuff (<fstream>) anyway, but if you aren't as familair with it you may have some learnign to do.
#include <windows.h>
#include <stdafx.h>
#include <iostream.h>
#include <fstream>

using namespace std;
char info[4000];

int APIENTRY WinMain(HINSTANCE hInstance,
                     HINSTANCE hPrevInstance,
                     LPSTR     lpCmdLine,
                     int       nCmdShow)
{
       // TODO: Place code here.
ifstream mystream("print.txt");
mystream.read(info,sizeof(info));
OnPreparePrinting(CPrintInfo *pInfo);
      return 0;
}
I still get an error for OnPreParePrinting - undeclared identifier.
Also, I've had 2 more users call with DOS print problems. Is it allowable in the guidelines of this forum to solicit contract work?
OnPreparePrinting is a MFC function.   You are not using MFC are you?

>> Is it allowable in the guidelines of this
>> forum to solicit contract work?
There aren't any rules against it, but it certainly isn't encouraged.

However, your task is not that hard, but you need to have a reasonable grasp of C/C++ (or whataver language you are using) and you need to know the basics of windows API.
You're right. When I chose Console Application, I didn't enable MFC support. I started a new project with MFC, and compliled the code without adding anything to the project. I get a syntax error on the line:
BOOL ResetDC(const DEVMODE* lpDevMode); which is in Afxwin.h It says to add a ',' before the '*'. I don't see how there could be an error in the generated code. This would be a good program to get me started in C++, but as a business decission it might be better to contract it out. My email is DonH@quick-quote.net if you are interested in discussion that option.
I've afraid we charge $225 an hour and this is probably a few hours worth of programming.  
Congatulations, I had no idea what programmers are paid. I guess that's an incentitive for me to catch up. Visual C++ Wizard has many selections. Which would you suggest I start this project with?
I don't see quit all of that $225, a dollar or two has to go to the company

If you don't need a graphical interface, just use a windows console project.  this is a "standard c++" program.  i.e. it has a main() and it can write to and read from a console jus tlike a DOS program used to do.

If you don't even want a console, you can use a windows project, but don't let the wizard create the source for you.  All you want to start with is the standard WinMain() function and do your work in there, and in functions called from there.  Since this program woudl not be creating windows and since it won't have a console (like the abopve one does) there is no interface at all.  So the user can't stop it or control it.  Sometimes that is fine for a simple utility, sometimes not.

Do one of these seem to be what you need?
If I write a program in VC++ 6.0 in C with a WinMain()function, will I end up with a 32 bit program? Do you know if DOS prorams will run in Windows2K?
DOS programs will continue to run long long into the future.  (Not necessarily poorly written ones that"break the rules" like many cheap games, but typical commercial ones.)

VC 6.0 only produces 32 bit programs.  it produces two main types.  GUI prograns i.e. regular windows programs and "win32 console" programs.  These are text based programs that look to the user just like DOS programs.  they run in a console window just like a DOS program does.  However they have full access to 32 bit memory and the windows API, unlike a DOS program

If you write a program with WinMain() you are writting a GUI program, and if it needs to have a user interface it needs to create windows for displaying information and getting user input.  (it can create a console and work just like a DOS program too, but lets not go there.)
I think I will use a console program All I will need is a dialog box that will allow setting the number of copies and maybe a few font selections. I think my biggest problem will be formatting columns. The file I'm printing is an invoice. Can I input control codes into the text file as I write it that will position the text?
a dialog box?  A console is not a graphical program.  it looks like a DOS program--that is, it is text based.  If you want a dialog box you probably want a GUI (graphical user interface) program.

>> Can I input control codes into the text file
>> as I write it that will position the text?
What do you mean?  are these codes to instruct your program where the the text is to be placed.  i.e will your program interpret these code itself and not pass them on to the printer?  If so that is fine.  If you are talking about passing them to the printer no, at least not using the approach suggested so far.  In this apporoach you are sendign the text to the printer using TextOut() which takes parameters that indicate the X,Y position where the text shoudl be placed.
Thanks for turning the light on. I was taking my original DOS print program that opened a data file and then wrote directly to the print port by placing the fields at specific locations and rewrote it to create a text file for the windows print utility to use. What I will be doing now is to have the windows print utility open the data file and use textout() to place the fields at the proper locations. I do want to use the dialog box to allow the user some control. You have spent a lot of time with me and I appreciate it. There are so many choices in the project wizard that I'm not sure which to choose. Could you please suggest which I should use? That will get me started. I will close the question (award the points) and post any new questions if I have any.  
What compiler are you using?

Will the project have any windows other than this dialog?

Will this be the "standard" print set-up dialog?

Do you want to use MFC/VCL/OWL?
I have Visual Studio 6.0. I will use Visual C++. The standard print setup would be fine. I know what Microsoft Foundation Class is but, you lost me after that. Is it Visual C Language / On Ward to the Lounge?
MFC is the only possibilty then, but you don't have to use it.  I don't think you have much need for it.

Choose "File" menu
"New" item
Select the "Pojects" tab
Select "Win32 application"
enter a project name.
press "ok"
Select "an empty project"
press "finish"

Then create a souce code file and add it to the project.

The file should have a WinMain() function that use the PrintDlg() function to create the print set-up dialog.

Thank you for your assistance. I will post anything else as a new question.