PrintDocument默认坐标系原点在页面左上角,但实际可用原点为e.MarginBounds左上角;套打需统一用毫米单位、禁用缩放、缓存首页偏移量,并优先使用打印机内置字体。

PrintDocument 打印时坐标系原点在哪?
默认原点在页面左上角,但实际打印机有不可打印区域(俗称“页边距”),PrintDocument 的 Graphics 对象的 (0, 0) 会落在这个区域之外——导致你画的文本或图片直接被裁掉。
正确做法是用 e.MarginBounds 而非 e.PageBounds 做定位基准:
private void printDoc_PrintPage(object sender, PrintPageEventArgs e)
{
// ✅ 正确:以可打印区域左上角为 (0, 0)
float x = e.MarginBounds.Left + 20;
float y = e.MarginBounds.Top + 30;
e.Graphics.DrawString("订单号:1001", font, brush, x, y);
// ❌ 错误:e.PageBounds.Left 可能是负数,且包含物理边距
// e.Graphics.DrawString("...", font, brush, e.PageBounds.Left, e.PageBounds.Top);
}
-
e.MarginBounds是驱动上报的真实可用区域,受纸张类型、打印机设置影响 - 套打必须严格对齐,建议先用 A4 白纸打印带标尺的测试页,实测
e.MarginBounds的偏移值并固化到配置中 - 某些旧型号针式打印机(如 EPSON LQ-630K)会把顶部不可打印区报得比实际大,需手动补偿 2–3mm
如何让套打内容精准落在预设位置(比如发票表格线内)?
套打不是“画出来就行”,而是“严丝合缝卡进已有印刷线”。关键在于:统一单位、关闭自动缩放、禁用打印机驱动的“适应页面”功能。
- 所有坐标和尺寸统一用
GraphicsUnit.Millimeter,避免英寸/像素混用导致换算偏差 - 在
PrintDocument打印前显式设置PrinterSettings.PrinterResolution(如果支持),否则 Windows 可能按 600dpi 渲染却发给 300dpi 打印机,造成比例失真 - 必须调用
e.Graphics.PageScale = 1.0f,防止 GDI+ 因 DPI 缩放自动调整坐标系 - 在打印机属性里关掉“适应页面大小”“缩小以适合”等选项,这些开关会让驱动偷偷缩放整个输出
PrintDocument 打印多页时,为什么第二页内容错位了?
常见现象:第一页套打正常,第二页整体下移或右偏几毫米。根本原因是 PrintPageEventArgs 的 MarginBounds 在多页场景下可能不一致——尤其当打印机执行“进纸重定位”时,部分驱动会微调第二页起始位置。
- 不要依赖
e.MarginBounds每次都一样,应在BeginPrint事件中一次性测量并缓存基准偏移量 - 示例:
private RectangleF _pageArea; private void printDoc_BeginPrint(object sender, PrintEventArgs e) { // 只测第一页,后续页全部复用 using (var g = Graphics.FromHwnd(IntPtr.Zero)) { var testDoc = new PrintDocument(); testDoc.PrinterSettings = printDoc.PrinterSettings; _pageArea = testDoc.DefaultPageSettings.Bounds; // 实际应创建临时 PrintPageEventArgs 模拟,但更稳妥是打印测试页后人工校准 } } - 更可靠的做法:打印前用同一台打印机、同一纸张、同一驱动版本,打出 5 张测试页,测量每页
MarginBounds.Top的标准差;若超过 0.3mm,说明该打印机不适合高精度套打,需换机型或改用 RAW 指令直打
为什么用 PrintDocument 打印中文经常出现乱码或字体缺失?
不是编码问题,而是 GDI+ 默认不嵌入字体,且打印机本身不支持 TrueType 渲染。Windows 会尝试用位图模拟,结果就是模糊、偏移、缺字。
- 必须使用打印机内置字体(如宋体-GB2312、SimSun),而不是系统 TTF 字体。用
new Font("SimSun", 9),别用new Font("Microsoft YaHei", 9) - 避免
Graphics.DrawString的StringFormat启用LineAlignment或Alignment,它们在非抗锯齿模式下会导致中文基线计算错误 - 针式打印机务必设置
e.Graphics.TextRenderingHint = TextRenderingHint.SingleBitPerPixelGridFit,启用点阵渲染,否则宋体小字号会糊成一片 - 如果必须用自定义字体,只能转成
Bitmap再用DrawImage输出,但会损失清晰度且增大内存占用
PrintDocument 配置,在 EPSON 和 OKI 上可能偏移方向相反。上线前务必用目标机型实测,别信“理论上应该可以”。



















