Start New Discussion within our Software Development Community

With the help of BCX I managed to create some C++ code that will allow you to send text to your printer and specify the font and other things. Play around with the options to suit your own needs. I have to admire the genius behind BCX, even though it spits out more code than you want! NOTICE: Please experiment with this code, modify it, improve it, and claim it as yours!!!!

// send text to a printer via the LPT1 or USB port
// this program allows you to set tons of printer options
// in the PrinterOpen() and PrinterWrite() functions
// link with gdi32.lib or in case of Dev-C++ with libgdi32.a
// Project>>Project Options>>Parameters>>Add Lib>>libgdi32.a
// BCX generated C code heavily modified for Dev C++
// this is a Console Application    vegaseat   21dec2004

#include <iostream>
#include <windows.h>

static HDC     Prn_hDC;
static long    Prn_FontMetrix;
static long    Prn_LineCtr;
static long    Prn_PrinterOn;
static HFONT   Prn_hFont;
static HFONT   Prn_hFontOld;
static DOCINFO Prn_di;
static LOGFONT Prn_Lf;
static TEXTMETRIC Prn_tm;
static char    Prn_Text[2048];
static char    Prn_Buffer[2048];

// prototypes
char *BCX_TmpStr(size_t);
char *mid (char*, int, int=-1);
char *left (char*, int);
char *extract (char*, char*);
char *str (double);
int  PrinterOpen  (void);
void PrinterWrite (char*);
void EjectPage    (void);
void PrinterClose (void);


using namespace std;

int main()
{
  int k;
	
  cout << "Make sure your printer is connected and on!\n";
	
  PrinterOpen();
  
  // use five lines as top margin
  for(k = 0; k < 5; k++)
    PrinterWrite(" ");
    
  // print next 50 lines of goofy text
    for(k = 1; k <= 50; k++)
  {
    sprintf(Prn_Buffer,"%s %2d %s","Printing line number", k,"    Zzzzzz ...");
    PrinterWrite(Prn_Buffer);
  }
  //EjectPage();  // optional to clear out the printer
  
  PrinterClose();
  
  cin.get();  // wait
  return 0;
}


// circular storage to minimize memory leaks
char *BCX_TmpStr (size_t Bites)
{
  static int StrCnt;
  static char *StrFunc[2048];
  StrCnt = (StrCnt + 1) & 2047;
  if (StrFunc[StrCnt]) free (StrFunc[StrCnt]);
  return StrFunc[StrCnt] = (char*)calloc(Bites+128,sizeof(char));
}


// needed for word wrap feature
char *left (char *S, int length)
{
  register int tmplen = strlen(S);
  char *strtmp = BCX_TmpStr(tmplen);
  strcpy (strtmp,S);
  if (length > tmplen)
    strtmp[tmplen] = 0;
  else
    strtmp[length] = 0;
  return strtmp;
}


// needed for word wrap feature
char *mid (char *S, int start, int length)
{
  register int tmplen = strlen(S);
  char *strtmp;
  if (start > tmplen || start < 1) return BCX_TmpStr(1);
  if (length < 0) length = tmplen - start + 1;
  strtmp = BCX_TmpStr(length);
  strncpy(strtmp,&S[start-1],length);
  strtmp[length] = 0;
  return strtmp;
}


char *extract (char *mane, char *match)
{
  register char *a;
  register char *strtmp = BCX_TmpStr(strlen(mane));
  strcpy(strtmp,mane);
  a = strstr(mane,match);
  if (a) strtmp[a-mane] = 0;
  return strtmp;
}


char *str (double d)
{
  register char *strtmp = BCX_TmpStr(16);
  sprintf(strtmp,"% .15G",d);
  return strtmp;
}


//
// set all the printer options including font
//
int PrinterOpen (void)
{
  int  PointSize = 12;
  char zPrinter[2048];
  
  GetProfileString("WINDOWS","DEVICE","",zPrinter,127);
  // extract up to the comma
  strcpy(zPrinter, (char*)extract(zPrinter,","));
  strcpy(Prn_Text,"Printing ...");
  Prn_hDC = CreateDC("",zPrinter,"",0);
  if (!Prn_hDC) return 0;
  Prn_di.cbSize = sizeof(Prn_di);
  Prn_di.lpszDocName = Prn_Text;
  StartDoc(Prn_hDC,&Prn_di);
  StartPage(Prn_hDC);
  SetTextAlign(Prn_hDC,TA_BASELINE | TA_NOUPDATECP | TA_LEFT);
  SetBkMode(Prn_hDC,TRANSPARENT);
  //
  // Prn_Lf deals with the font, got to play with this, if you
  // want a smaller or larger font size!  Don't forget to change
  // max lines and max char/line in PrinterWrite() accordingly
  //
  Prn_Lf.lfHeight = PointSize*GetDeviceCaps(Prn_hDC,LOGPIXELSY)/72;
  Prn_Lf.lfWidth = 0;
  Prn_Lf.lfEscapement = 0;
  Prn_Lf.lfOrientation = 0;
  Prn_Lf.lfWeight = FW_NORMAL;
  Prn_Lf.lfItalic = 0;
  Prn_Lf.lfUnderline = 0;
  Prn_Lf.lfStrikeOut = 0;
  Prn_Lf.lfCharSet = ANSI_CHARSET;
  Prn_Lf.lfOutPrecision = OUT_DEFAULT_PRECIS;
  Prn_Lf.lfClipPrecision = CLIP_DEFAULT_PRECIS;
  Prn_Lf.lfQuality = PROOF_QUALITY;
  Prn_Lf.lfPitchAndFamily = VARIABLE_PITCH | FF_ROMAN;
  strcpy(Prn_Lf.lfFaceName,TEXT("Courier New"));
  Prn_hFont = CreateFontIndirect(&Prn_Lf);
  Prn_hFontOld = (HFONT)SelectObject(Prn_hDC,Prn_hFont);
  GetTextMetrics(Prn_hDC,&Prn_tm);
  Prn_FontMetrix = Prn_Lf.lfHeight;
  Prn_PrinterOn = 1;
  return 1;
}


void PrinterWrite (char *TextIn)
{
  int LPP = 60;  // max line numbers depending on font size
  int CPL = 80;  // max char/line depending on font size
  char sTemp[2048] = {0};
  if (!Prn_PrinterOn)
  {
    MessageBox (GetActiveWindow(),"Printer Problem!","",0);
    return;
  }
  strcpy(sTemp,TextIn);
  while(1)
  {
    // split text if it exceeds max line characters
	  if (strlen(sTemp) > CPL)
    {
      strcpy(Prn_Text, (char*)left(sTemp,CPL));
      strcpy(sTemp, (char*)mid(sTemp,CPL+1));
    }
    else
    {
      strcpy(Prn_Text,sTemp);
      *sTemp = 0;
    }
    Prn_LineCtr++;
    if (Prn_LineCtr >= LPP)
    {
      // max lines exceeded, eject this page for next page
	    EndPage(Prn_hDC);
      Prn_LineCtr = 0;
      StartPage(Prn_hDC);
    }
    TextOut(Prn_hDC,20,Prn_FontMetrix*Prn_LineCtr,Prn_Text,strlen(Prn_Text));
    if(sTemp[0] == 0) break;
  }
}


void PrinterClose (void)
{
  if (!Prn_PrinterOn) return;
  SelectObject(Prn_hDC,Prn_hFontOld);
  DeleteObject(Prn_hFont);
  EndPage(Prn_hDC);
  EndDoc(Prn_hDC);
  DeleteDC(Prn_hDC);
  Prn_LineCtr = 0;
  Prn_PrinterOn = 0;
}


void EjectPage(void)
{
  EndPage(Prn_hDC);
  Prn_LineCtr = 0;
  StartPage(Prn_hDC);
}
The article starter has earned a lot of community kudos, and such articles offer a bounty for quality replies.