1

i m trying to print a text file with Delphi 2010. i found some code but when i run, it asks to save an xps file, it doesn t show print dialog. the code is located at http://www.delphipages.com/forum/showthread.php?t=72986

procedure TForm1.print_btnClick(Sender: TObject);
var
  filename: string;
begin
  filename := 'printfile.txt';
  ShellExecute(handle, 'print', pchar(Filename), nil, nil, SW_NORMAL);
end;

another one is located at http://www.delphibasics.co.uk/Article.asp?Name=Printing

this one is looping "ok" dialogs again and again, it can t print anything.

greetings

nikel
  • 653
  • 4
  • 13
  • 24
  • The "good solution" was deleted because it was wrong. TStringList has no Print command. Neither does TPrintDialog. The Print method your code is calling is [the one inherited from TForm](http://docwiki.embarcadero.com/VCL/en/Forms.TCustomForm.Print). It prints a picture of the form. Did you have a copy of the text file displayed on your form at the time? – Rob Kennedy Jul 24 '11 at 20:47
  • i didn t have a text on my form. i just want it to print a text file created with Delphi. – nikel Jul 24 '11 at 20:57
  • Why don't you print from a TMemo or a TRichEdit? – David Heffernan Jul 24 '11 at 22:48
  • i don t print from them because there are 13 TEdits and 15 TLabels need to be printed. and they have to be designed with txt or rtf. – nikel Jul 24 '11 at 23:39
  • @user859104: Sounds like an excellent opportunity to write your own printing code for this purpose (that is, do not write a generic plain-text file printer!). – Andreas Rejbrand Jul 25 '11 at 00:31
  • Perhaps the end-user would appriciate a print preview in the form of a *visible* `TRichEdit`? Then your problems would be automatically solved. – Andreas Rejbrand Jul 25 '11 at 00:43
  • @David: I don't think the `TMemo` can print, can it? – Andreas Rejbrand Jul 25 '11 at 00:44
  • @andreas Is it only rich edit that can? – David Heffernan Jul 25 '11 at 06:38

3 Answers3

3

Evidently, the default printer on your computer is the XPS-file generator. You would get the same behavior if you chose the "Print" command from the context menu of that file in Windows Explorer. Change your default printer to something else.

Rob Kennedy
  • 161,384
  • 21
  • 275
  • 467
  • ok thanks for the tip. but i think users will need a print dialog too. – nikel Jul 24 '11 at 21:00
  • 2
    You're using ShellExecute to invoke the default printing command for the file. If the user wants the default print command to generate an XPS file, then so be it. – Rob Kennedy Jul 25 '11 at 13:49
3

Option 1

You could write your own printing code. A simple example (uses Printers):

procedure PrintTextFile(const FileName: string; const Numbering: boolean = true);
const
  FONT_NAME = 'Times New Roman';
  FONT_SIZE = 10;
var
  MARGIN: integer;
  sl: TStringList;
  i, h: Integer;
  r, rFooter: TRect;
  s: string;
  DocEnd: integer;
begin
  with TPrintDialog.Create(nil) do
    try
      if not Execute then
        Exit;
    finally
      Free;
    end;
  sl := TStringList.Create;
  try
    sl.LoadFromFile(FileName);
    Printer.BeginDoc;
    Printer.Title := FileName; // or application name or sth else
    Printer.Canvas.Font.Name := FONT_NAME;
    Printer.Canvas.Font.Size := FONT_SIZE;
    MARGIN := 5*Printer.Canvas.TextWidth('M');
    DocEnd := Printer.PageHeight - MARGIN;
    if Numbering then
    begin
      dec(DocEnd, 2*Printer.Canvas.TextHeight('8'));
      rFooter := Rect(0, DocEnd, Printer.PageWidth, Printer.PageHeight - MARGIN);
      DrawText(Printer.Canvas.Handle,
        PChar(IntToStr(Printer.PageNumber)),
        length(IntToStr(Printer.PageNumber)),
        rFooter,
        DT_SINGLELINE or DT_CENTER or DT_BOTTOM);
    end;
    r.Left := MARGIN;
    r.Top := MARGIN;
    for i := 0 to sl.Count - 1 do
    begin
      r.Right := Printer.PageWidth - MARGIN;
      r.Bottom := DocEnd;
      s := sl.Strings[i];
      if s = '' then s := ' ';
      h := DrawText(Printer.Canvas.Handle, // Height of paragraph on paper
        PChar(s),
        length(s),
        r,
        DT_LEFT or DT_TOP or DT_WORDBREAK or DT_CALCRECT);
      if r.Top + h >= DocEnd then
      begin
        Printer.NewPage;
        if Numbering then
          DrawText(Printer.Canvas.Handle,
            PChar(IntToStr(Printer.PageNumber)),
            length(IntToStr(Printer.PageNumber)),
            rFooter,
            DT_SINGLELINE or DT_CENTER or DT_BOTTOM);
        r.Top := MARGIN;
        r.Bottom := DocEnd;
      end;
      if h > Printer.PageHeight - 2*MARGIN then
        raise Exception.Create('Line too long to fit on single page.');
      DrawText(Printer.Canvas.Handle,
        PChar(s),
        length(s),
        r,
        DT_LEFT or DT_TOP or DT_WORDBREAK);
      inc(r.Top, h);
    end;
    Printer.EndDoc;
  finally
    sl.Free;
  end;
end;

Warning: The code above does not work if any single line in the text file is so wide that it cannot fit on a single paper (after it has been wrapped). I am too tired to fix that right now.

Option 2

A nasty trick is to use an invisible TRichEdit to print.

procedure PrintTextFile(AOwner: TWinControl; const FileName: string);
begin
  with TRichEdit.Create(nil) do
    try
      Visible := false;
      Parent := AOwner;
      Lines.LoadFromFile(FileName);
      with TPrintDialog.Create(nil) do
        try
          if Execute then
            Print(FileName);
        finally
          Free;
        end;
    finally
      Free;
    end;
end;

I advice against it, since it is a bit too nasty.

Andreas Rejbrand
  • 105,602
  • 8
  • 282
  • 384
1

Set a default printer on your machine - make sure you have physical access and proper user rights to use it. The xps printer is the MS default print driver when nothing else is set.

Vector
  • 10,879
  • 12
  • 61
  • 101
  • -1 for the fanboi Microsoft bashing. Please take that to slashdot or somewhere else where it belongs; it definitely doesn't belong here. – Ken White Jul 25 '11 at 13:19
  • Removed - thanks for the advice. I did think twice about that but my impression was that the site was geared towards openSource products - but I understand - has nothing to do with the discussion and detracts from the quality and professionalism of the site. There are other places to voice such opinions. – Vector Jul 25 '11 at 13:29
  • 1
    +1 because Mikey is trying to be helpful, and has deleted the troll bits. – Warren P Jul 25 '11 at 15:08
  • Actually the site is geared in getting answers for the questions ;-) If the answer is using open-souce like in JVCL or closed-source like Data Abstract, so be it... – Fabricio Araujo Jul 25 '11 at 17:34
  • And my -1 removed for the removal. :) Can't give a +1 because @Rob gave the same answer 8 hours or so sooner, however. – Ken White Jul 25 '11 at 21:03
  • @Ken - I'm not campaigning for points, but it happens that I saw Rob's answer and added details that he did not mention... "The xps printer is the MS default print driver when nothing else is set" - my answer stressed something that Rob's didn't, and explained why it was defaulting to xps, without any 'evidently'.., which is why I put it up. – Vector Jul 25 '11 at 22:15