You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

在C# Windows Form中实现发票打印及解决内容覆盖问题

WinForm打印发票内容重叠问题解决办法

嘿,作为编程新手遇到这种打印布局问题太正常啦,别担心!我来帮你梳理一下问题所在和解决办法~

你遇到的内容覆盖上一行的问题,核心原因是打印时没有正确控制绘制内容的Y坐标偏移——每次绘制新内容时,没有把绘制位置往下移动,导致新内容直接叠在了上一行的位置上。

结合你给出的代码片段,我猜你可能是在设置打印预览时,没有正确关联PrintDocument的PrintPage事件,或者在绘制文本时没有维护当前的Y位置变量。下面是具体的修正思路和示例代码:

关键解决步骤

  • 用PrintDocument作为打印逻辑的核心载体,所有内容绘制都在它的PrintPage事件中完成
  • 维护一个currentY变量,记录当前绘制内容的垂直位置,每次绘制后更新这个值(加上文本高度+行间距)
  • 使用Graphics.MeasureString获取文本的实际高度,确保行间距适配不同字体大小

修正后的示例代码

// 先定义全局的PrintDocument实例,用于承载打印逻辑
private PrintDocument _printDocument = new PrintDocument();

private void ShowPrintPreview()
{
    Form previewForm = new Form();
    PrintPreviewControl previewControl = new PrintPreviewControl();

    // 将PrintDocument关联到预览控件,预览内容由它生成
    previewControl.Document = _printDocument;
    // 订阅PrintPage事件,在这里绘制发票的所有内容
    _printDocument.PrintPage += OnPrintPage;

    // 配置预览窗体和控件
    previewControl.Dock = DockStyle.Fill;
    previewForm.Controls.Add(previewControl);
    previewForm.Size = new Size(800, 600);
    previewForm.Text = "发票打印预览";
    previewForm.ShowDialog();
}

// 打印内容的核心处理事件
private void OnPrintPage(object sender, PrintPageEventArgs e)
{
    // 初始化垂直起始位置,从页边距顶部往下50像素开始
    float currentY = e.MarginBounds.Top + 50;
    float leftX = e.MarginBounds.Left; // 用页边距定位,避免内容超出纸张范围
    float lineSpacing = 8; // 自定义行间距

    // 1. 绘制发票标题
    Font titleFont = new Font("微软雅黑", 16, FontStyle.Bold);
    string titleText = "XX科技有限公司 增值税普通发票";
    e.Graphics.DrawString(titleText, titleFont, Brushes.Black, leftX, currentY);
    // 更新Y坐标:标题高度 + 行间距
    currentY += e.Graphics.MeasureString(titleText, titleFont).Height + lineSpacing * 2;

    // 2. 绘制客户信息
    Font infoFont = new Font("微软雅黑", 10);
    string customerText = "客户名称:张三 | 联系电话:138XXXX1234";
    e.Graphics.DrawString(customerText, infoFont, Brushes.Black, leftX, currentY);
    currentY += e.Graphics.MeasureString(customerText, infoFont).Height + lineSpacing;

    // 3. 绘制商品列表(示例)
    string[] goodsList = { "商品1:编程入门教程 | 单价:59元 | 数量:1", "商品2:鼠标 | 单价:39元 | 数量:2" };
    foreach (string goods in goodsList)
    {
        e.Graphics.DrawString(goods, infoFont, Brushes.Black, leftX, currentY);
        currentY += e.Graphics.MeasureString(goods, infoFont).Height + lineSpacing;
    }

    // 4. 绘制总金额
    string totalText = $"总金额:{(59 + 39*2)}元";
    Font totalFont = new Font("微软雅黑", 10, FontStyle.Bold);
    e.Graphics.DrawString(totalText, totalFont, Brushes.Red, leftX, currentY);

    // 释放字体资源,避免内存泄漏
    titleFont.Dispose();
    infoFont.Dispose();
    totalFont.Dispose();
}

额外提示

  • 如果你需要打印多页,可以在PrintPage事件中设置e.HasMorePages = true,并维护页码等状态
  • 测试时可以先用打印预览确认布局,没问题再实际打印
  • 尽量使用系统自带字体,避免目标机器没有对应字体导致布局错乱

作为新手,刚开始接触WinForm打印确实容易忽略坐标控制的细节,多调试几次就能掌握啦~

内容的提问来源于stack exchange,提问作者Daron

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.21 03:41:27