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

C#实现多方向Word文档单打印池打印及适配需求求助

解决方案:多方向Word文档单打印池打印及适配处理

核心思路

  1. 预先提取所有页面的图片及方向信息,存入集合
  2. 使用单个PrintDocument,通过PrintPage事件的e.HasMorePages逐页打印,在事件内动态设置当前页面的方向
  3. 通过比例缩放实现“Fit to Page”,并调整边距解决横向打印偏移问题

重构后的完整代码

using System;
using System.Collections.Generic;
using System.Drawing;
using System.Drawing.Printing;
using System.IO;
using System.Runtime.InteropServices;
using Microsoft.Office.Interop.Word;

public class WordPrinter
{
    private List<(Image PageImage, bool IsLandscape)> _printPages = new List<(Image, bool)>();
    private int _currentPageIndex = 0;
    private Application _wordApp;
    private Document _doc;

    public void PrintWordDocument(string filePath)
    {
        try
        {
            // 初始化Word应用并打开文档
            object missing = Type.Missing;
            _wordApp = new Application { Visible = false };
            _doc = _wordApp.Documents.Open(filePath, ref missing);

            // 提取所有页面的图片和方向信息
            foreach (Window window in _doc.Windows)
            {
                foreach (Pane pane in window.Panes)
                {
                    for (int i = 1; i <= pane.Pages.Count; i++)
                    {
                        Page wordPage = pane.Pages[i];
                        byte[] pageBits = (byte[])wordPage.EnhMetaFileBits;

                        using (MemoryStream ms = new MemoryStream(pageBits))
                        {
                            Image pageImage = Image.FromStream(ms);
                            // 判断页面方向:Word中Height/Width单位是磅,纵向时Height>Width
                            bool isLandscape = wordPage.Width > wordPage.Height;
                            _printPages.Add((pageImage, isLandscape));
                        }
                    }
                }
            }

            // 配置打印任务
            using (PrintDocument pd = new PrintDocument())
            {
                pd.PrintPage += Doc_PrintPage;
                // 可选:指定打印机
                // pd.PrinterSettings.PrinterName = "你的打印机名称";
                pd.Print();
            }
        }
        catch (Exception ex)
        {
            // 添加实际错误日志或处理逻辑
            Console.WriteLine($"打印出错:{ex.Message}");
        }
        finally
        {
            // 清理Word COM资源,避免残留进程
            if (_doc != null)
            {
                _doc.Close(SaveChanges: false);
                Marshal.ReleaseComObject(_doc);
            }
            if (_wordApp != null)
            {
                _wordApp.Quit(SaveChanges: false);
                Marshal.ReleaseComObject(_wordApp);
            }
            // 释放图片资源
            foreach (var page in _printPages)
            {
                page.PageImage.Dispose();
            }
            _printPages.Clear();
        }
    }

    private void Doc_PrintPage(object sender, PrintPageEventArgs e)
    {
        if (_currentPageIndex >= _printPages.Count)
        {
            e.HasMorePages = false;
            return;
        }

        var currentPage = _printPages[_currentPageIndex];
        _currentPageIndex++;

        // 动态设置当前页面的打印方向
        e.PageSettings.Landscape = currentPage.IsLandscape;

        // 处理Fit to Page:按比例缩放图片到可打印区域(扣除边距)
        Image img = currentPage.PageImage;
        Rectangle printArea = e.MarginBounds;

        // 计算等比例缩放系数
        float scaleX = (float)printArea.Width / img.Width;
        float scaleY = (float)printArea.Height / img.Height;
        float scale = Math.Min(scaleX, scaleY);

        // 计算居中绘制的位置和尺寸
        int drawWidth = (int)(img.Width * scale);
        int drawHeight = (int)(img.Height * scale);
        int x = printArea.Left + (printArea.Width - drawWidth) / 2;
        int y = printArea.Top + (printArea.Height - drawHeight) / 2;

        // 绘制图片
        e.Graphics.Clear(Color.White);
        e.Graphics.DrawImage(img, x, y, drawWidth, drawHeight);

        // 判断是否还有下一页
        e.HasMorePages = _currentPageIndex < _printPages.Count;
    }
}

关键问题解决说明

1. 单打印池实现

  • 不再为每页创建独立的PrintDocument,用一个实例完成全部页面打印
  • 通过_currentPageIndex跟踪打印进度,e.HasMorePages控制打印流程,整个任务会被打印机识别为单个打印池

2. 逐页方向设置

  • 在PrintPage事件中直接修改e.PageSettings.Landscape,该设置仅对当前打印页生效,不影响全局配置
  • 提取Word页面时,通过wordPage.Width > wordPage.Height准确判断方向(Word页面单位为磅,无需转换即可比较)

3. 横向打印边距过大问题

  • 使用e.MarginBounds作为打印区域基准,该区域是扣除打印机默认边距后的可打印范围
  • 基于MarginBounds计算绘制位置,避免超出可打印区域导致的偏移或裁剪

4. Fit to Page功能实现

  • 计算图片与打印区域的宽高比例,取较小值作为缩放系数,保证图片完整且不变形
  • 计算居中位置,让缩放后的图片在打印区域内居中显示,提升打印美观度

额外注意事项

  • 必须调用Marshal.ReleaseComObject释放Word COM对象,避免后台残留Word进程
  • 图片资源使用后要调用Dispose(),防止内存泄漏
  • 如需自定义边距,可在PrintDocument初始化时设置pd.DefaultPageSettings.Margins,或在PrintPage事件中修改e.PageSettings.Margins

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.01 21:47:13