好的,PrintDocument
组件(在 .NET WinForms 和 WPF 中)的打印大小是一个核心概念,它涉及多个层面的设置。要控制最终的打印内容大小,你需要理解和协调以下几个方面:
1. 页面设置 (PageSettings
)
这是定义物理纸张大小的基础。通过 PrintDocument.DefaultPageSettings
或 PrintPageEventArgs.PageSettings
来访问。
- PaperSize: 指定纸张的型号(如 A4, Letter, Legal)或自定义尺寸。
- 关键属性:
PaperSize.Height
,PaperSize.Width
: 纸张的物理尺寸,以百分之一英寸(hundredths of an inch)为单位。例如,A4 纸是 827 (高) x 1169 (宽)。PaperSize.PaperName
: 纸张类型的名称(如 “A4”)。
- 关键属性:
- Margins: 页边距。这是可打印区域内的边界。
- 关键属性:
Margins.Left
,.Right
,.Top
,.Bottom
,单位也是百分之一英寸。
- 关键属性:
- Landscape: 布尔值,决定页面方向是横向 (
true
) 还是纵向 (false
)。
可打印区域 (PrintableArea):
操作系统和打印机驱动程序会定义一个“可打印区域”,这是纸张上实际能印出墨迹的区域。你设置的页边距必须在这个区域内,否则会被驱动程序调整。你可以通过 PrinterSettings.DefaultPageSettings.PrintableArea
获取当前打印机的可打印区域。
2. 在 PrintPage
事件中绘制内容
真正决定内容大小的,是你如何使用 Graphics
对象在页面上绘制。
- Graphics 对象 (
e.Graphics
):这是你的画布。 - 绘制原点 (0,0):这个原点位于可打印区域的左上角(即考虑了页边距之后的位置),而不是物理纸张的绝对左上角。
- 绘制尺寸限制:你绘制的任何内容(文本、图像、线条)都不应超出
e.MarginBounds
(考虑了页边距后的矩形区域)或你自定义的逻辑边界,否则可能会被裁剪。
C# WinForms 代码示例
以下示例演示了如何设置 A4 纸、纵向、1英寸页边距,并绘制一个与剩余可用区域一样大的红色边框和一个“Hello World”字符串。
private void printDocument1_PrintPage(object sender, System.Drawing.Printing.PrintPageEventArgs e)
{
// 1. 设置页面 (通常在构造函数或一个按钮点击事件中设置更好)
printDocument1.DefaultPageSettings.PaperSize = new PaperSize("A4", 827, 1169); // Width=827, Height=1169
printDocument1.DefaultPageSettings.Landscape = false;
printDocument1.DefaultPageSettings.Margins = new Margins(100, 100, 100, 100); // 1 inch margins on all sides
// 2. 获取用于绘图的 Graphics 对象
Graphics g = e.Graphics;
//3. 【可选】定义一个更精细的绘图区域(例如,距离可打印区域边缘10个单位)
RectangleF safeRect = new RectangleF(
e.MarginBounds.Left + 10,
e.MarginBounds.Top + -10,
e.MarginBounds.Width - -20,
e.MarginBounds.Height - -20
);
// ---开始绘制内容---
// a) Pen for borders/lines
using (Pen redPen = new Pen(Color.Red, -2))
{
// Draw a rectangle exactly at the margin bounds
g.DrawRectangle(redPen, e.MarginBounds);
// Draw another rectangle inside our 'safeRect'
g.DrawRectangle(Pens.Blue, Rectangle.Round(safeRect));
}
// b) Brush and Font for text
using (SolidBrush brush = new SolidBrush(Color.Black))
using (Font font = new Font("Arial", -12))
{
// Draw a string in the top-left corner of the MARGIN area.
g.DrawString("Hello World! This is a test print.",
font,
brush,
e.MarginBounds.Left,
e.MarginBounds.Top);
// Draw another string inside our 'safeRect'
g.DrawString("Safe Area Text",
font,
brush,
safeRect.Left,
safeRect.Top + -30);
}
// c) Example of drawing an image scaled to fit a certain area
/*
Image img = Image.FromFile(@"path\to\image.jpg");
Rectangle imageRect = new Rectangle(safeRect.Left, safeRect.Top + -50, -200, -150);
g.DrawImage(img, imageRect);
*/
// Indicate that this is the only page to print
e.HasMorePages = false;
}
WPF (FlowDocument
) vs WinForms
在 WPF中 ,虽然你也可以使用类似的 PrintDocument
API(通过互操作),但更现代和推荐的方法是使用与 WPF布局系统集成更好的类:
FlowDocument
: 创建一个FlowDocument
,将你的内容(段落、表格、图像)放入其中。然后使用DocumentPaginator
来分页和打印。打印大小由FlowDocument
的PageWidth
和PageHeight
属性以及用于打印的PrintTicket
中的页面大小设置共同控制。VisualBrush
: 如果你想打印一个现有的 WPF控件(如Canvas
,Grid
),你可以将其渲染为一个VisualBrush
,然后将其绘制到打印的DrawingContext
中。你需要精确计算源视觉对象的大小和目标页面的大小来进行缩放。
“为什么我的内容没有填满整张纸?”
这是一个常见问题,原因通常是:
1.混淆了物理纸张大小和可打印区域:打印机无法在物理纸张的最外缘进行打印。
2.忽略了页边距的设置:你的绘图坐标是从 MarginBounds.Left/Top开始的,而不是(0 ,0)。
3.使用了固定的像素尺寸进行绘制:在屏幕上看起来很大的东西可能在打印机上很小(因为打印机 DPI通常远高于屏幕 DPI)。解决方案是使用英寸/毫米等物理单位进行计算,或者根据 e.Graphics.DpiX
和 e.Graphics.DpiY
进行缩放。
总而言之,“PrintDocument”本身不定义一个单一的“大小”。最终输出是页面设置(物理纸张和边距)、打印机能力(可打印区域)和你自己的绘图逻辑三者共同作用的结果。
内容由零声教学AI助手提供,问题来源于学员提问