0

(edit This question has received few downvotes. I don't know a reason and still cannot see what's wrong with it. I can edit this if downvoters could comment about what they wish to see better written or lack of valuable info I have not given).

I have Intermec PM4i label printer and Generic text print driver. I am able to print text file script from Notepad or Delphi calls ShellExecute('printto',..) shellapi function.

I found few raw printing examples but none work. How can Delphi app print to Generic_text_driver without shellapi function? This is not GDI printer.canvas capable driver.

I have tried "everything" even legacy PASSTHROUGH printing examples. Only working method is Notepad.exe or shellexecute('printto', 'tempfile.txt',...) which I guess is using Notepad internally. I can see notepad printing dialog flashing on screen. I would like to control this directly from Delphi application.

This printFileToGeneric did not work.

// https://groups.google.com/forum/#!topic/borland.public.delphi.winapi/viHjsTf5EqA
Procedure PrintFileToGeneric(Const sFileName, printerName, docName: string; ejectPage: boolean);
Const
  BufSize = 16384;
Var
  Count : Integer;
  BytesWritten: DWORD;
  hPrinter: THandle;
  DocInfo: TDocInfo1;
  f: file;
  Buffer: Pointer;
  ch: Char;
Begin
  If not WinSpool.OpenPrinter(PChar(printerName), hPrinter, nil) Then
    raise Exception.Create('Printer not found');

  Try
    DocInfo.pDocName := PChar(docName);
    DocInfo.pOutputFile := nil;
    DocInfo.pDatatype := 'RAW';
    If StartDocPrinter(hPrinter, 1, @DocInfo) = 0 Then
      Raise Exception.Create('StartDocPrinter failed');

    Try
      If not StartPagePrinter(hPrinter) Then
        Raise Exception.Create('StartPagePrinter failed');

      System.Assign(f, sFileName);
      Try
        Reset(f, 1);
        GetMem(Buffer, BufSize);
        Try
          While not eof(f) Do Begin
            Blockread(f, Buffer^, BufSize, Count);
            If Count > 0 Then Begin
              If not WritePrinter(hPrinter, Buffer, Count, BytesWritten) Then
                Raise Exception.Create('WritePrinter failed');
            End;
          End;
        Finally
          If ejectPage Then Begin
            ch:= #12;
            WritePrinter( hPrinter, @ch, 1, BytesWritten );
          End;
          FreeMem(Buffer, BufSize);
        End;
      Finally
        EndPagePrinter(hPrinter);
        System.Closefile( f );
      End;
    Finally
      EndDocPrinter(hPrinter);
    End;
  Finally
    WinSpool.ClosePrinter(hPrinter);
  End;
End;

The following prtRaw helper util example did not work.

prtRaw.StartRawPrintJob/StartRawPrintPage/PrintRawData/EndRawPrintPage/EndRawPrintJob
http://www.swissdelphicenter.ch/torry/showcode.php?id=940

The following AssignPrn method did not work.

function testPrintText(params: TStrings): Integer;
var
  stemp:String;
  idx: Integer;
  pOutput: TextFile;
begin
  Result:=0;    
    idx := getPrinterIndexByName( params.Values['printer'] );
    if (idx<0) then Raise Exception.Create('Printer not found');
    WriteLn('Use printer(text) ' + IntToStr(idx) + ' ' + Printer.Printers[idx] );

    Printer.PrinterIndex := idx;
    stemp := params.Values['jobname'];
    if (stemp='') then stemp:='rawtextprint';
    Printer.Title:=stemp;

    AssignPrn(pOutput);
    ReWrite(pOutput);

    stemp := 'INPUT ON'+#10;
    stemp := stemp + 'NASC 1252'+#10;
    stemp := stemp + 'BF OFF'+#10;
    stemp := stemp + 'PP 30,480:FT "Swiss 721 BT",8,0,100'+#10;
    stemp := stemp + 'PT "Test text 30,480 position ABC'+#10;
    Write(pOutput, stemp);
    //Write(pOutput, 'INPUT ON:');
    //Write(pOutput, 'NASC 1252:');
    //Write(pOutput, 'BF OFF:');
    //Write(pOutput, 'PP 30,480:FT "Swiss 721 BT",8,0,100:');
    //Write(pOutput, 'PT "Test text 30,480 position ABC":');
    //Write(pOutput, 'Text line 3 goes here#13#10');
    //Write(pOutput, 'Text line 4 goes here#13#10');    

    CloseFile(pOutput);
end;

This Printer.Canvas did not print anything, it should have had print something because Notepad is internally using GDI printout. Something is missing here.

function testPrintGDI(params: TStrings): Integer;
var
  filename, docName:String;
  idx: Integer;
  lines: TStrings;
begin
  Result:=0;
  idx := getPrinterIndexByName( params.Values['printer'] );
  if (idx<0) then Raise Exception.Create('Printer not found');
  WriteLn('Use printer(gdi) ' + IntToStr(idx) + ' ' + Printer.Printers[idx] );
  docName := params.Values['jobname'];
  if (docName='') then docName:='rawtextprint';

  filename := params.values['input'];
  If Not FileExists(filename) then Raise Exception.Create('input file not found');

  Printer.PrinterIndex := idx;
  Printer.Title := docName;
  Printer.BeginDoc;
  lines := readTextLines(filename);
  try
    for idx := 0 to lines.Count-1 do begin
      Printer.Canvas.TextOut(10, 10*idx, lines[idx]);
    end;
  finally
    FreeAndNil(lines);
    Printer.EndDoc;
  end;
end;

Only three methods working are printing from Notepad.exe, Delphi ShellExecute call or open a raw TCP socket to IP:PORT address and write text lines to a socket outputstream.

function testPrintPrintTo(params: TStrings): Integer;
var
  filename, printerName:String;
  idx: Integer;
  exInfo: TShellExecuteInfo;
  device,driver,port: array[0..255] of Char;
  hDeviceMode: THandle;
  timeout:Integer;
  //iRet: Cardinal;
begin
  Result:=0;

  idx := getPrinterIndexByName( params.Values['printer'] );
  if (idx<0) then Raise Exception.Create('Printer not found');
  WriteLn('Use printer(printto) ' + IntToStr(idx) + ' ' + Printer.Printers[idx] );

  filename := params.values['input'];
  If Not FileExists(filename) then Raise Exception.Create('input file not found');
  filename := uCommon.absoluteFilePath(filename);

  Printer.PrinterIndex := idx;
  Printer.GetPrinter(device, driver, port, hDeviceMode);
  printerName := Format('"%s" "%s" "%s"', [device, driver, port]);

  FillChar(exInfo, SizeOf(exInfo), 0);
  with exInfo do begin
    cbSize := SizeOf(exInfo);
    fMask := SEE_MASK_NOCLOSEPROCESS or SEE_MASK_FLAG_DDEWAIT;
    Wnd := 0;
    exInfo.lpVerb := 'printto';
    exInfo.lpParameters := PChar(printerName);
    lpFile := PChar(filename);
    lpDirectory := nil;
    nShow := SW_HIDE;
  end;
  WriteLn('printto ' + printerName);

  if Not ShellExecuteEx(@exInfo) then begin
    Raise Exception.Create('ShellExecuteEx failed');
    exit;
  end;

  try
    timeout := 30000;
    while WaitForSingleObject(exInfo.hProcess, 50) <> WAIT_OBJECT_0 do begin
      Writeln('wait timeout ' + IntToStr(timeout));
      dec(timeout, 50);
      if (timeout<1) then break;
    end;
  finally
    CloseHandle(exInfo.hProcess);
  end;

  {iRet:=ShellExecute(0, 'printto',
      PChar(filename),
      PChar(printerName), //Printer.Printers[idx]),
      nil, //PChar(filepath),
      SW_HIDE  // SW_SHOWNORMAL
  );
  Writeln('printto return code ' + IntToStr(iRet)); // >32 OK }

end;
Whome
  • 10,181
  • 6
  • 53
  • 65
  • Notepad prints to gdi printers – David Heffernan Nov 08 '14 at 07:35
  • So I could use Printer.Canvas.TextOut('...') delphi function to generictext driver(Intermec PM4i label printer) maybe. Not calling any graphics draw functions may keep it simple as possible. Will try this once get back to office. – Whome Nov 08 '14 at 07:58

2 Answers2

1

you can use this procedure: where the LabelFile is the full path of the label file,we are using this code and works with generic text driver printer and the printer is set as the default printer. it works with zebra printer and windows xp operating system.

i hope this will help you.

function PrintLabel(LabelName: String): Boolean;
var
  EfsLabel,dummy: TextFile;
  ch : Char;
begin
try
try
   Result:= False;
   AssignFile(EfsLabel,LabelName);
   Reset(EfsLabel);
   Assignprn(dummy);
   ReWrite(Dummy);

   While not Eof(EfsLabel) do
   begin
    Read(EfsLabel, Ch);
    Write(dummy, Ch);
   end;

   Result:= True;

except
  Result:=False;
  LogMessage('Error Printing Label',[],LOG_ERROR);
end;

finally
CloseFile(EfsLabel);
CloseFile(dummy);
end;

end;
  • If this should help please reformat your code (indentation!) or it is hard to look through. – Markus Dec 25 '14 at 12:14
0

You are able to print to this printer from Notepad. Notepad prints using the standard GDI mechanism. If Notepad can do this then so can you. Use Printer.BeginDoc, Printer.Canvas etc. to print to this printer.

David Heffernan
  • 601,492
  • 42
  • 1,072
  • 1,490
  • I tested this from Delphi using Printer component, Printer.BeginDoc / Printer.Canvas.TextOut('test print') / Printer.EndDoc. Nothing was printed. Notepad is doing some extra tricks with generictext print driver. I gave up and implemented a raw tcp socket to printerIP:9100 and send proprietary FingerPrint+DirectProtocol commands by hand. – Whome Nov 10 '14 at 08:16
  • Notepad is not doing any extra tricks. It's just a GDI printer. I honestly cannot imagine what else you are looking for. It sounds to me as though you don't want advice and want to do it your way. In which case, why ask? – David Heffernan Nov 10 '14 at 23:37
  • Whoohaa, why this hostility? As you can see I have tried extensively and provided all example code. Some of you may find it valuable. It is what it is, (Delphi)Printer.canvas did not work through generictext driver. Notepad did work through a same driver. I submit the very same text document through a raw socket 11.22.33.44:9100 and it works. Sure I'm missing one part in a delphi code but cannot figure it out. You have tried this label printer? – Whome Nov 11 '14 at 08:25
  • Notepad manages to print using GDI. I guess your code that attempts to print is flawed. – David Heffernan Nov 11 '14 at 08:27