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

8
  • 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. It prints a picture of the form. Did you have a copy of the text file displayed on your form at the time? Commented Jul 24, 2011 at 20:47
  • i didn t have a text on my form. i just want it to print a text file created with Delphi. Commented Jul 24, 2011 at 20:57
  • Why don't you print from a TMemo or a TRichEdit? Commented Jul 24, 2011 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. Commented Jul 24, 2011 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!). Commented Jul 25, 2011 at 0:31

3 Answers 3

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.

Sign up to request clarification or add additional context in comments.

7 Comments

thanks for the reply. but the first code gives error: [DCC Error] Unit1.pas(155): E2003 Undeclared identifier: 'Numbering'
@user859104 Numbering is declared as the second parameter of the function: did you copy the full code?
@Andreas: Why don't you use Printer.Canvas.TextOut?
oh i forgot adding the parameters to function. it works fine now. thanks a lot.
@Jens: I need two addition features. (1) Word-wrapping and (2) centering inside a box (without computing the top-left pixel manually...).
|
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.

2 Comments

ok thanks for the tip. but i think users will need a print dialog too.
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.
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.

6 Comments

-1 for the fanboi Microsoft bashing. Please take that to slashdot or somewhere else where it belongs; it definitely doesn't belong here.
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.
+1 because Mikey is trying to be helpful, and has deleted the troll bits.
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...
And my -1 removed for the removal. :) Can't give a +1 because @Rob gave the same answer 8 hours or so sooner, however.
|

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.