2008. április 22., kedd

How to print a file directly to a printer


Problem/Question/Abstract:

How to print a file directly to a printer

Answer:

Solve 1:

uses
  WinSpool;

procedure PrintFile(const sFileName: string);
const
  BufSize = 16384;
type
  TDoc_Info_1 = record
    pDocName: pChar;
    pOutputFile: pChar;
    pDataType: pChar;
  end;
var
  Count, BytesWritten: integer;
  hPrinter: THandle;
  Device: array[0..255] of char;
  Driver: array[0..255] of char;
  Port: array[0..255] of char;
  hDeviceMode: THandle;
  DocInfo: TDoc_Info_1;
  f: file;
  Buffer: Pointer;
begin
  Printer.PrinterIndex := -1;
  Printer.GetPrinter(Device, Driver, Port, hDeviceMode);
  if not WinSpool.OpenPrinter(@Device, hPrinter, nil) then
    exit;
  DocInfo.pDocName := 'MyDocument';
  DocInfo.pOutputFile := nil;
  DocInfo.pDatatype := 'RAW';
  if StartDocPrinter(hPrinter, 1, @DocInfo) = 0 then
  begin
    WinSpool.ClosePrinter(hPrinter);
    exit;
  end;
  if not StartPagePrinter(hPrinter) then
  begin
    EndDocPrinter(hPrinter);
    WinSpool.ClosePrinter(hPrinter);
    exit;
  end;
  System.Assign(f, sFileName);
  try
    Reset(f, 1);
    GetMem(Buffer, BufSize);
    while not eof(f) do
    begin
      Blockread(f, Buffer^, BufSize, Count);
      if Count > 0 then
      begin
        if not WritePrinter(hPrinter, Buffer, Count, BytesWritten) then
        begin
          EndPagePrinter(hPrinter);
          EndDocPrinter(hPrinter);
          WinSpool.ClosePrinter(hPrinter);
          FreeMem(Buffer, BufSize);
          exit;
        end;
      end;
    end;
    FreeMem(Buffer, BufSize);
    EndDocPrinter(hPrinter);
    WinSpool.ClosePrinter(hPrinter);
  finally
    System.Closefile(f);
  end;
end;

procedure WriteRawStringToPrinter(PrinterName: string; S: string);
var
  Handle: THandle;
  N: DWORD;
  DocInfo1: TDocInfo1;
begin
  if not OpenPrinter(PChar(PrinterName), Handle, nil) then
  begin
    ShowMessage('error ' + IntToStr(GetLastError));
    Exit;
  end;
  with DocInfo do
  begin
    pDocName := PChar('test doc');
    pOutputFile := nil;
    pDataType := 'RAW';
  end;
  StartDocPrinter(Handle, 1, ocInfo);
  StartPagePrinter(Handle);
  WritePrinter(Handle, PChar(S), Length(S), N);
  EndPagePrinter(Handle);
  EndDocPrinter(Handle);
  ClosePrinter(Handle);
end;

The PrinterName parameter must be the name of the printer as it is installed. For example, if the name of the printer is "HP LaserJet 5MP" then that is what you should pass.


Solve 2:

The procedure below spools a RAW PCL file to the printer. Mainly you need to use the WritePrinter API call along with OpenPrinter.

procedure PrintPCL;
var
  Handle: THandle;
  numwrite: DWORD;
  Docinfo1: TDocInfo1;
  PrintFile, InFile, SampForm: TMemoryStream;
  buffer: array[0..4096] of char;
  HPLetter, HPLegal, NC: array[0..15] of char;
  temp: array[0..3] of char;
  FF: char;
  numread: longint;
  x: integer;
  FileName: string;
begin
  if (OpenPrinter(PrinterName, Handle, nil)) then
  begin
    FF := Chr(12);
    strcopy(HPLetter, chr(27));
    strcat(HPLetter, '&l6d66p1h2A');
    strcopy(HPLegal, chr(27));
    strcat(HPLegal, '&l6d84p4h3A');
    strcopy(NC, chr(27));
    strcat(NC, '&l');
    strcat(NC, StrPCopy(temp, InttoStr(NumCopies)));
    strcat(NC, 'X');
    try
      PrintFile := TMemoryStream.Create;
      for x := 0 to Printlist.Count - 1 do
      begin
        FileName := Copy(PrintList[x], 1, pos(',', printlist[x]) - 1);
        InFile := TMemoryStream.Create;
        InFile.LoadFromFile(FileName);
        if (Integer(filename[Length(FileName) - 1]) = 49) then
          PrintFile.Write(HPLetter, Strlen(HPLetter))
        else
          PrintFile.Write(HPLegal, Strlen(HPLegal));
        PrintFile.Write(NC, strlen(NC));
        PrintFile.CopyFrom(InFile, 0);
        InFile.Free;
        if Sample then
        begin
          try
            SampForm := TMemoryStream.Create;
            SampForm.LoadFromFile(AppPath + 'SAMPLE.PRN');
            PrintFile.Copyfrom(SampForm, 0);
          finally
            SampForm.Free;
          end;
        end;
        PrintFile.Write(FF, SizeOf(FF));
      end;
      DocInfo1.pDocName := PChar('PCLPrinter');
      DocInfo1.pOutputFile := nil;
      DocInfo1.pDataType := 'RAW';
      PrintFile.Seek(0, 0);
      StartDocPrinter(Handle, 1, @DocInfo1);
      StartPagePrinter(Handle);
      numread := 0;
      numwrite := 0;
      while (numread = numwrite) and (PrintFile.Position <> PrintFile.Size) do
      begin
        numread := PrintFile.Read(buffer, sizeof(buffer));
        WritePrinter(Handle, @buffer, numread, numwrite);
        UpdateProgress(round((PrintFile.Position / PrintFile.Size) * 100));
      end;
      EndPagePrinter(Handle);
      EndDocPrinter(Handle);
      ClosePrinter(Handle);
    finally
      PrintFile.Free;
    end;
  end;
end;

Nincsenek megjegyzések:

Megjegyzés küldése