The JPrint class provides the protocol that allows Java applications and applets to draw text and graphics on the printer device. Most of JPrint methods are implemented as thin wrappers for Windows GDI APIs. Here is JPrint API documentation .

The following describes how to use JPrint to create a printed document from within Java.

Several Java code examples are included. To run those examples, click on the symbol when available. Please note that to run JPrint examples, you must install Coroutine for Java.

The first step in printing involves obtaining and setting up a printer. Both GetPrinter and GetDefaultPrinter methods can be used to obtain a printer.

Typically the GetPrinter method displays a Print Dialog to let the user to select a printer and print options:

JPrint jpr=new JPrint();
jpr.GetPrinter(0,nCopies);

There is a version of the GetPrinter method that takes the name of the printer.  

JPrint jpr=new JPrint();
jpr.GetPrinter("HP LaserJet 4P",1);

JPrint offer the EnumeratePrinters method that answers the list of available printers and print servers.

If you want to select the system default printer without displaying the Print Dialog, use the GetDefaultPrinter method:

JPrint jpr=new JPrint();
jpr.GetDefaultPrinter(nCopies);

Once printer is obtained, you may retrieve printer-specific information using the GetDeviceCaps method. For example, you may determine whether the selected printer is capable to print color graphics:

if(jpr.GetDeviceCaps(JPrint. DEVCAPS_NUMCOLORS) > 2) {
//we are here when the selected printer is a color printer
}

The second step is to start a print job by using the StartDoc method.

The third step is to start a new page using the StartPage method. To direct a printer to advance to a new page after the current page is done, use the EndPage method. To print multiple pages, methods StartPage and EndPage must be used for every page of the document.

To change page's orientation, use SetOrientation2Portrait and SetOrientation2Landscape methods. Please note that you must call those methods before StartPage.

Here we reach the point where we can start drawing graphics or text on the current page.

Use DrawText method to draw a text string at the specified logical location. Please note that all coordinates must be in logical units relative to the current page’s left-top corner, that is, from Point(0.0) down-right to Point(jpr.horzPix,jpr.vertPix).

The DrawText method uses the currently selected font and text alignment mode.

To select a Font, use the SelectFont method. The selected font will remain current till the next call to the SelectFont method.

The text alignment mode determines how text is positioned relative to a given location. Text can be aligned to the right or left of the position or centered over it; it can also be aligned above or below the certain point. The SetTextAlign method sets text alignment mode which will remain current till the next call to the SetTextAlign method.

In the following example, we will draw the text string at the left-bottom corner of the page parallel to the east edge of the page:

String txt;
jpr.SelectFont(new Font("Universe", Font.BOLD, 10));
jpr.SelectOrientation(90);
jpr.SetTextAlign(JPrint.TA_TOP | JPrint.TA_LEFT);
jpr.DrawText(txt,0, jpr.vertPix);
jpr.SelectOrientation(0); // restore orientation for further printing

To calculate the width and the height of a character string, use the GetTextExtent method. The GetTextExtent method uses the currently selected font to compute the dimensions of the string. In the following example, we will draw two text strings in the middle of the page:

String upper;
String lower;
jpr.SelectFont(new Font("Universe", Font.BOLD, 26));
Dimension ud=jpr.GetTextExtent(upper);
jpr.SelectFont(new Font("Universe", Font.BOLD|Font.ITALIC, 20));
Dimension ld=jpr.GetTextExtent(lower);
int hh=ud.height*2/100;
int x0=(jpr.horzPix - ud.width)/2 ;
int y0=(jpr.vertPix - ud.height - ld.height - hh)/2;
int x1=(jpr.horzPix - ld.width)/2 ;
int y1=y0+ hh + ud.height;
jpr.SetTextAlign(JPrint.TA_TOP | JPrint.TA_LEFT);
jpr.SelectFont(new Font("Universe", Font.BOLD, 26));
jpr.DrawText(upper,x0,y0);
jpr.SelectFont(new Font("Universe", Font.BOLD|Font.ITALIC, 20));
jpr.DrawText(lower,x1,y1);

To roughly estimate the character string height, use the following formula: aFont.size()*jpr.logPixSy/72.

To draw an Image at the specified logical location, use the DrawImage method. Because the pixels on a screen have different dimensions that the dots on a printer, JPrint scales images to achieve WYSIWYG effect, that is, printed image will have the same size as displayed one. Java applets/applications may also scale an image up and down to, for example, fit it into the target rectangle.

To calculate the width and the height the image would have on the printed page, use the GetImageExtent method.

The following code sample scales the image to 1/2 of the page size and draws it in the center of the page:

Dimension dim=jpr.GetImageExtent(im);
float sh=((float)jpr.vertPix)/((float)(2*dim.height));
float sw=((float)jpr.horzPix)/((float)(2*dim.width));
if(sh < sw)
  sw=sh;
else
  sh=sw;
jpr.DrawImage(im,(jpr.horzPix - (int)(dim.width*sw))/2,
(jpr.vertPix - (int)(dim.height*sh))/2,JPrint.ROP_SRCCOPY,sw,sh);
jpr.SetBkModeTransparent();
jpr.SetTextAlign(JPrint.TA_BASELINE | JPrint.TA_CENTER);
jpr.SelectFont(new Font("Universe", Font.BOLD, 42));
jpr.SelectOrientation(45);
jpr.DrawText("Sample",jpr.horzPix/2,jpr.vertPix/2);

The following code sample shows how to change the page orientation mid-print:

jpr.StartDoc("Java Applet Print 31");
jpr.SetOrientation2Landscape();
jpr.StartPage();
// print image here ......
jpr.EndPage();
jpr.SetOrientation2Portrait();
jpr.StartPage();
// print image here ......
jpr.EndPage();
jpr.EndDoc();
jpr.ReleasePrinter();

To draw a line, move to the location where the line starts using the MoveTo method, select a pen using the SelectPen method, and then draw the line using the LineTo method. Please note that selected pen will remain current till the next call to SelectPen.

The following code sample draws the table with n columns and m rows in the middle of the page:

int nRows=20,nColumns=5;
int oX= jpr.horzPix/4;
int oY= jpr.vertPix/4;
int totSx= jpr.horzPix/2;
int totSy= jpr.vertPix/2;
int x= totSx / nColumns;
int y= totSy / nRows;
jpr.SelectPen(JPrint.PS_SOLID,10);
int n; 
for(n=0;n <=nColumns;n++) {
jpr.MoveTo(oX+x*n,oY);
jpr.LineTo(oX+x*n,oY+totSy);
}
for(n=0;n <=nRows;n++) {
jpr.MoveTo(oX,oY+y*n);
jpr.LineTo(oX+totSx,oY+y*n);
}
// draw column names
jpr.SetTextAlign(JPrint.TA_CENTER|JPrint.TA_TOP);
jpr.SelectFont(new Font("Universe", Font.PLAIN , 10)); 
for(n=0;n < nColumns;n++) {
String name="column "+(n+1);
Dimension dim=jpr.GetTextExtent(name);
jpr.DrawText(name,oX+n*x + x/2,oY+(y-dim.height)/2);
}

To draw a series of lines, use the Polyline method.

To draw a rectangle use the DrawRectangle method. The rectangle is outlined by using the current pen and filled by using the current brush. To select a brush, use the SelectBrush method.

In the following example, we will draw a histogram using DrawRectangle method

int nColumns=10;
int oX= jpr.horzPix/4;
int oY= jpr.vertPix/4;
int totSx= jpr.horzPix/2;
int totSy= jpr.vertPix/2;
int x=totSx/nColumns;
for(int n=0;n < nColumns;n++) {
int y=(n+1)*totSy/nColumns;
int ha;
if(n%5==0) ha=JPrint.HS_HORIZONTAL;
else if(n%5==1) ha=JPrint.HS_VERTICAL;
else if(n%5==2) ha=JPrint.HS_BDIAGONAL;
else if(n%5==3) ha=JPrint.HS_FDIAGONAL;
else if(n%5==4) ha=JPrint.HS_CROSS; 
else ha=JPrint.HS_DIAGCROSS;
jpr.SelectBrush(jpr.BS_HATCHED,ha);
jpr.DrawRectangle(new Rectangle(oX+n*x,oY+totSy-y,x,y));
}
jpr.SelectFont(new Font("Universe", Font.PLAIN , 10)); 
String text="Horizontal Axis";
Dimension dim=jpr.GetTextExtent(text);
jpr.SetTextAlign(JPrint.TA_CENTER|JPrint.TA_TOP);
jpr.DrawText(text,jpr.horzPix/2,oY + totSy + 20);
jpr.SelectOrientation(90);
text="Vertical Axis";
dim=jpr.GetTextExtent(text);
jpr.SetTextAlign(JPrint.TA_CENTER |JPrint.TA_BOTTOM);
jpr.DrawText(text,oX-20,jpr.vertPix/2);

At the end, to send the result to the selected printer, use the EndDoc method. Please note that EndDoc releases all resources.

To send raw data to the printer, open a printer using the OpenPrinter method, start a print job using the StartDocPrinter method, and then use the WritePrinter method to send raw data to the printer. At the end, call the EndDocPrinter method to end the print job, and, finally, call the ClosePrinter method to close the printer.

In the following example, we will send raw data to the printer:

JPrint jpr=new JPrint();
jpr.SetPrintDialogOwner(owner);
if(!jpr.GetPrinter(0,1)) {
  System.out.println("GetPrinter failed");
  return;
}
String printer=jpr.GetPrinterName();
jpr.ReleasePrinter();
String out="Sending raw data...\n\rDone.\f";
int handle=JPrint.OpenPrinter(printer);
if(0 > handle) {
  System.out.println("Unable to open "+printer);
  return;
}
JPrint.StartDocPrinter(handle,"example 6");
JPrint.WritePrinter(handle,out);
JPrint.EndDocPrinter(handle);
JPrint.ClosePrinter(handle);

An instance of com.neva.PrintJobInfo describes a set of values associated with a print job. JPrint offers  

public static PrintJobInfo [] GetPrinterStatus(String name)

that answers information about print jobs in the printer queue for a specified printer.

Interesting that the easiest (and the only) method of determining the status of the printer is by examining the status flag of print jobs in the printer queue. In Windows, a printer does not report its status when the queue is empty. Even if the printer is in an error state such as off-line or out-of-paper. The only time the state of the printer is reported is when the Spooler is attempting to send a print job to the printer. The error status is recorded in the status field of a print job that is currently despooling (printing).

In the following example, the state of the printer is periodically checked by examining the print job queue. PrintMonitor.java accepts a string containing the name of the printer to monitor. This name can be either the local name of the printer or a UNC share name to a network printer. 

import java.util.*;
import com.neva.*;
public class PrintMonitor {
  public static void main(String [] param) {
    String pname=null; 
    if(param!=null && param.length>0)
      pname=param[0];
    else {
      JPrint jpr=JPrint();
      if(!jpr.GetDefaultPrinter(1)) {
        System.out.println("Failed to GetDefaultPrinter()");
        return;
      }
      pname=jpr.GetPrinterName();
      jpr.ReleasePrinter();
    }
    PrinterInfo info=JPrint.GetPrinterInfo(pname);
    if(info!=null) {
      System.out.println("ServerName="+info.ServerName());
      System.out.println("PrinterName="+info.PrinterName());
      System.out.println("PortName="+info.PortName());
      System.out.println("ShareName="+info.ShareName());
      System.out.println("DriverName="+info.DriverName());
      System.out.println("Comment="+info.Comment());
      System.out.println("Location="+info.Location());
      System.out.println("Attributes="+info.Attributes());
      System.out.println("Status="+info.Status());
      System.out.println("Orientation="+info.Orientation());
      System.out.println("PaperSize="+info.PaperSize());
    }
    System.out.println("\n\nPrint Monitor started...\n");
    while(true) {
      PrintJobInfo []  stat=JPrint.GetPrinterStatus(pname);
      if(stat!=null && stat.length>0) {
        int status=stat[0].JobStatus();
        String sn=stat[0].JobStatusName();
        String PrinterStatus="";
        if((PrintJobInfo.JOB_STATUS_OFFLINE & status)>0)
          PrinterStatus+="Offline ";
        if((PrintJobInfo.JOB_STATUS_PAPEROUT & status)>0)
          PrinterStatus+="Out of paper ";
        if((PrintJobInfo.JOB_STATUS_BLOCKED_DEVQ & status)>0)
          PrinterStatus+="Blocked ";
        if((PrintJobInfo.JOB_STATUS_USER_INTERVENTION & status)>0)
          PrinterStatus+="Intervention req. ";
        System.out.println("PRINTER PROBLEM status=0x"+
         Integer.toString(status,16)+" "+PrinterStatus+" "+(sn!=null?sn:""));
      }
      try {
        Thread.sleep(10000);
      } catch(Exception e) {
      }
    }
  }
}

Here is how PrintMonitor reports printer errors (In the case below, the print job was submitted when the printer was offline).