Difference between revisions of "Using the printer/zh CN"

From Lazarus wiki
Jump to navigationJump to search
(Created page with "{{Using the printer}} ==Introduction== Printing is easy in Lazarus/FreePascal. However, you do need to follow some required steps. First steps first. After those first steps,...")
 
(Deleted English categories)
 
(7 intermediate revisions by one other user not shown)
Line 1: Line 1:
 
{{Using the printer}}
 
{{Using the printer}}
  
==Introduction==
+
==介绍==
Printing is easy in Lazarus/FreePascal. However, you do need to follow some required steps. First steps first. After those first steps, you can branch out to more advanced printing. This article discusses the required steps, as collected from various forum pages and examples. After the basic steps, we are going to print some text. Finally a hint of some more advanced printing is given.
+
【Google机翻】在Lazarus / FreePascal中打印很容易。 但是,您确实需要遵循一些必需的步骤。 第一步。 完成这些第一步之后,您可以扩展到更高级的打印。 本文讨论了所需的步骤,这些步骤是从各个论坛页面和示例中收集的。 完成基本步骤后,我们将打印一些文本。 最后,给出了一些更高级的打印提示。
{{Note| Currently printing in WinCE (using the Printers4Lazarus package) is unsupported.}}
+
{{Note| 不支持WinCE下打印,即使使用 Printers4Lazarus.}}
  
==The basic steps==
+
==基本步骤==
You must do the following to be able to use printers:
+
必须执行如下操作才可以正确使用打印机:
# Add the Printer4Lazarus package to your project requirements.
+
# Printer4Lazarus 包增加到系统中.
# Add the Printers unit to the uses section of your unit.
+
# 引用打印机单元 【Printers】.
# Use the existing Printer object.
+
# 使用现有打印机.
  
===Adding the Printer4Lazarus package to your project requirements===
+
===Printer4Lazarus 包添加到项目中===
The Printer4Lazarus package defines a basic printer and provides platform independent printing. The following can thus be used on various platforms.
+
Printer4Lazarus 包定义了基本打印机,并提供了独立于系统的打印,因此可在任何系统上打印。
  
In the Lazarus IDE, do the following:
+
Lazarus IDE中执行如下操作:
# In the '''Project''' menu, click '''Project Inspector'''. A window is shown with a tree view, one of the branches is named ''Required Packages''. By default, the ''Required Packages'' branch shows the ''LCL'' package.
+
# 菜单栏 '''工程''' - '''工程查看器'''. 会弹出工程查看器窗口 ''需要的包''. 默认 ''需要的包'' 包含 ''LCL'' .
# Click the '''Add''' button, the button with the plus sign at the top of the window.
+
# 点击工程查看器顶部的加号  '''添加''' 按钮。
# Open the '''New Requirements''' page.
+
# 打开 '''新建需要''' 选项。
# From the '''Package Name''' list box, select ''Printer4Lazarus''.
+
# '''包名''' 列表框中选择 ''Printer4Lazarus''.
# Click '''OK'''.
+
# 点击 '''确定'''.
# ''Printer4Lazarus'' is now shown in the ''Required Packages'' branch.
+
# ''Printer4Lazarus'' 这个包就被添加到 ''工程查看器''
  
===Adding the Printers unit to the uses section of your unit===
+
===引用打印单元===
This step is simple and the result could look like this:
+
步骤很简单,看下面的样例,其实就是Uses Printers:
  
 
<syntaxhighlight lang="pascal">
 
<syntaxhighlight lang="pascal">
Line 36: Line 36:
 
</syntaxhighlight>
 
</syntaxhighlight>
  
===Using the existing Printer object===
+
===使用已有打印机对象===
Let's assume you want to click a button to print a text. On your form, put a button called '''PrintBtn''' and in the '''OnClick''' event you can now use the following:
+
加入要点击按钮打印一段文字. 在窗体上放置一个按钮名为 '''PrintBtn''' '''OnClick''' 事件中使用如下代码实现:
  
 
<syntaxhighlight lang="pascal">
 
<syntaxhighlight lang="pascal">
Line 66: Line 66:
 
</syntaxhighlight>
 
</syntaxhighlight>
  
Did I write ''basic'' and ''simple''. The above example is somewhat complex. Next to the basic text output in the bold line, it also provides an example of formatting your text.
+
【Google机翻】我写的是“基本”还是“简单”? 上面的例子有些复杂。 在粗体行的基本文本输出旁边,还提供了格式化文本的示例。
  
From ''begin'' to ''end;'' the following happens:
+
''begin'' ''end;'' 详细发生如下:
* With ''Printer.BeginDoc'' you start printing - however, nothing is sent to the printer until you finish with ''Printer.EndDoc;''.
+
* ''Printer.BeginDoc''开始打印,其实是开始修改打印的内容, 直到 ''Printer.EndDoc;''出现,才真实开始打印。
* The printer uses a Canvas to draw the output on. It is this drawing that ends up on the printed page. ''Canvas.Font'' is the font object used for the output canvas. That is, the ''TextOut'' call we use later will output text using the settings of the font object of that moment.
+
* Printer使用Canvas绘制输出内容. 页面才最终显示在打印页上. ''Canvas.Font'' 是canvas的输出字体 . 也就是说, ''TextOut'' 将使用我们的设置来输出文本内容.
* Everything you draw on the canvas must be positioned using coordinates. So, we calculate a ''LineHeight'' to position text vertically. You could do the same for the horizontal position, which I left here to be ''LEFTMARGIN''.
+
* 【Google机翻】您在画布上绘制的所有内容都必须使用坐标进行定位。 因此,我们计算了“ LineHeight”以垂直放置文本。 您可以对水平位置执行相同的操作,这里我将其命名为“ LEFTMARGIN”。
* The text is drawn with the ''TextOut'' call.
+
* 通过''TextOut'' 调用绘制文本。
* This magnificent result is sent to the printer by ''Printer.EndDoc''.
+
* 这些所有的结果都通过 ''Printer.EndDoc''最终来执行.
  
In some forums it is suggested that the use of ''PrintDialog'' (the printer selection dialog) is required for good functioning, but I did not find this to be true (any more).
+
部分论坛建议使用 ''PrintDialog''控件,因为不使用可能无法运行,但在实际使用中并非这样。
  
 
==Next steps==
 
==Next steps==
Line 152: Line 152:
 
* [[LazReport Documentation]] LazReport can be used to design data-driven reports that can be printed, exported to PDF etc.
 
* [[LazReport Documentation]] LazReport can be used to design data-driven reports that can be printed, exported to PDF etc.
 
* [[LazReport Tutorial]]
 
* [[LazReport Tutorial]]
 
[[Category:Tutorials]]
 
[[Category:Printing]]
 
[[Category:Lazarus]]
 
[[Category:Hardware]]
 

Latest revision as of 22:56, 6 May 2020

Deutsch (de) English (en) español (es) 日本語 (ja) polski (pl) 中文(中国大陆)‎ (zh_CN)

介绍

【Google机翻】在Lazarus / FreePascal中打印很容易。 但是,您确实需要遵循一些必需的步骤。 第一步。 完成这些第一步之后,您可以扩展到更高级的打印。 本文讨论了所需的步骤,这些步骤是从各个论坛页面和示例中收集的。 完成基本步骤后,我们将打印一些文本。 最后,给出了一些更高级的打印提示。

Light bulb  Note: 不支持WinCE下打印,即使使用 Printers4Lazarus.

基本步骤

必须执行如下操作才可以正确使用打印机:

  1. 将 Printer4Lazarus 包增加到系统中.
  2. 引用打印机单元 【Printers】.
  3. 使用现有打印机.

将 Printer4Lazarus 包添加到项目中

Printer4Lazarus 包定义了基本打印机,并提供了独立于系统的打印,因此可在任何系统上打印。

Lazarus IDE中执行如下操作:

  1. 菜单栏 工程 - 工程查看器. 会弹出工程查看器窗口 需要的包. 默认 需要的包 包含 LCL 包.
  2. 点击工程查看器顶部的加号 添加 按钮。
  3. 打开 新建需要 选项。
  4. 包名 列表框中选择 Printer4Lazarus.
  5. 点击 确定.
  6. Printer4Lazarus 这个包就被添加到 工程查看器

引用打印单元

步骤很简单,看下面的样例,其实就是Uses Printers:

unit MainUnit;
 
{$mode objfpc}{$H+}
 
interface
 
uses
  Classes, SysUtils, Forms, Printers;

使用已有打印机对象

加入要点击按钮打印一段文字. 在窗体上放置一个按钮名为 PrintBtnOnClick 事件中使用如下代码实现:

procedure TForm1.PrintBtnClick(Sender: TObject);
const
  LEFTMARGIN = 100;
  HEADLINE = 'I Printed My Very First Text On ';
var
  YPos, LineHeight, VerticalMargin: Integer;
  SuccessString: String;
begin
  with Printer do
  try
    BeginDoc;
    Canvas.Font.Name := 'Courier New';
    Canvas.Font.Size := 10;
    Canvas.Font.Color := clBlack;
    LineHeight := Round(1.2 * Abs(Canvas.TextHeight('I')));
    VerticalMargin := 4 * LineHeight;
    // There we go
    YPos := VerticalMargin;
    SuccessString := HEADLINE + DateTimeToStr(Now);   
    Canvas.TextOut(LEFTMARGIN, YPos, SuccessString);
  finally
    EndDoc;
  end;
end;

【Google机翻】我写的是“基本”还是“简单”? 上面的例子有些复杂。 在粗体行的基本文本输出旁边,还提供了格式化文本的示例。

beginend; 详细发生如下:

  • Printer.BeginDoc开始打印,其实是开始修改打印的内容, 直到 Printer.EndDoc;出现,才真实开始打印。
  • Printer使用Canvas绘制输出内容. 页面才最终显示在打印页上. Canvas.Font 是canvas的输出字体 . 也就是说, TextOut 将使用我们的设置来输出文本内容.
  • 【Google机翻】您在画布上绘制的所有内容都必须使用坐标进行定位。 因此,我们计算了“ LineHeight”以垂直放置文本。 您可以对水平位置执行相同的操作,这里我将其命名为“ LEFTMARGIN”。
  • 通过TextOut 调用绘制文本。
  • 这些所有的结果都通过 Printer.EndDoc最终来执行.

部分论坛建议使用 PrintDialog控件,因为不使用可能无法运行,但在实际使用中并非这样。

Next steps

After the above basic steps, you can do the next steps. I leave it to the reader to try:

  • Make drawings on the paper.
  • Format text nicely.
  • Select another printer and compare results.

In the Lazarus distribution there is an example project that uses Raw printing to the printer. You can find this example with the following location $(lazarusdir)\components\printers\samples\rawmode\rawmodetest.lpi. Another sample shows how to select another printer: $(lazarusdir)\components\printers\samples\dialogs\selectprinter.lpi.

Advanced steps: printing controls

The printer object primarily allows you to draw on a canvas and send that canvas image to the printer. If we continue on the path shown above, then you would use the printer's canvas methods to draw text, ellipses, diamonds and what not.

However, this can hardly be interesting to any serious programmer. You are working on a more perfect CAD program or yet another image file sorter and want to print the wonderful result of your program to your printer. Trying to translate the perfect picture into canvas method calls is not the way: you already have the picture.

Each and every control you put on a form, also draws a picture on a TCanvas object just like the printer. We can use that to bring the picture from the screen to the printer.

Imagine you are going to make a preview program. You create a form and on this form you put a TPanel. This panel will provide the nice grayish background of the preview. On the panel, you put another TPanel object called page. This page will be white and represents the paper. You can nicely size the page.

On this page we put a TShape object, for example a nice red, rounded rectangle. Now try the following in the PrintBtnClick event method:

MyPrinter.BeginDoc;
  page.PaintTo(myPrinter.Canvas, 0, 0);
MyPrinter.EndDoc;

What happens:

  • BeginDoc starts the printing (but nothing is sent yet).
  • page.PaintTo sends the output of our TPanel object that represents the page to the canvas of the printer. Note the following:
    1. You can use the PaintTo method of any control in the control hierarchy. You could also send the output of the whole window to the printer if you want to.
    2. You can send the output of any control with a PaintTo method to the printer, so you can be creative. To send the output of your image sorter to the printer you may send the output of the TImage to the printer.
    3. TCanvas also has a method to copy rectangles from another canvas. However, you can only do that if an object really draws to a canvas. I think most controls rely on containers to provide a real canvas, so you cannot copy rectangles from just any control. At least, it didn't work for me.
    4. Make sure the control you want to paint to the printer is visible. If the control is not visible, nothing will be painted not even to the printer.
  • EndDoc sends the drawing to the printer.

And on we go: resizing

The printer uses a lot more pixels per inch on paper than the monitor uses pixels per inch on the screen. As a result, the output that is redirected from the screen to the printer ends up rather smallish on the paper. Scaling and controlling the layout is important for good looking output. It would be nice if you can have an exact sized copy of what you see on the screen.

For the moment we are not striving for the ideal, just for the idea. As said before, controls do not have their own canvas but rely on the canvas of a container or owner. However, there are components that have their own canvas. I chose TBitMap and then it works as follows.

procedure TForm1.PrintBtnClick(Sender: TObject);
var
  MyPrinter : TPrinter;
  myBitMap : TBitMap;
begin
  myBitMap := TBitMap.Create;
  myBitMap.Width := page.Width;
  myBitMap.Height := page.Height;
  page.BorderStyle:=bsNone;
  page.PaintTo(myBitMap.Canvas, 0, 0);
  page.BorderStyle:=bsSingle;
  //
  MyPrinter := Printer;
  MyPrinter.BeginDoc;
    //page.PaintTo(myPrinter.Canvas, 0, 0);
    //myPrinter.Canvas.Draw(0,0, myBitMap);
    myPrinter.Canvas.CopyRect(Classes.Rect(0, 0, myPrinter.PaperSize.Width, myPrinter.PaperSize.Height),
       myBitMap.Canvas, Classes.Rect(0, 0, myBitMap.Width, myBitMap.Height));
  MyPrinter.EndDoc;
  myBitMap.Free;
end;

For this to work, do not use the Windows unit. The Windows unit has other definitions for Rect. What you see in the example is the following:

  • A bitmap is created and made the same size as the page control.
  • To avoid the border to print, the BorderStyle of the page is switched off before painting it to the bitmap and set back to its old value afterwards.
  • Then printing is started and the BitMap canvas content is copied to the printer canvas.

But notice one thing, in the process page is magnified. The Printer.papersize is considerably bigger than the the size of the bitmap, but the copy process fills the destination rectangle nicely. So, when we want to do this, we must make sure that the page dimensions have the same ratio as the paper dimension. You can figure out how to do it.

A problem with this way of working is of course that the pixels of the screen will show on the printed paper. As said, it is not ideal but it shows a principle. Controls do not have their own canvas; to print controls we first paint them on an object that does have its own canvas: the TBitMap. Now you know how it works, you can figure out a way to create fine artwork or documents. This will need objects that draw themselves properly in a TPanel with low resolution, but also on a TBitMap with high resolution. But, that is food for another article.

See also