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

SDK风格项目无法设置打印机纸张尺寸但Framework项目正常

问题分析:SDK风格.NET Framework项目中PrintDocument.DefaultPageSettings.PaperSize设置不生效

问题背景

使用System.Drawing.Printing命名空间,通过PrintDocument.DefaultPageSettings.PaperSize属性设置文档纸张尺寸时,SDK风格的.NET Framework 4.7.2项目中该设置始终未实际生效,但传统Framework风格项目(同样目标框架net472、引用相同System.Drawing程序集、打印逻辑完全一致)却能正常工作。

观察到的具体现象

  • 打印输出始终与打印机驱动默认尺寸一致(控制面板中打印机偏好设置的自定义尺寸:宽300、高200,对应驱动DEVMODE的dmFormName、dmPaperLength、dmPaperWidth);
  • 驱动日志显示DevMode输入来自全局默认设置,而非代码中指定的配置;
  • SDK项目中设置PaperSize后,PrintDocument.DefaultPageSettings.PrintableArea属性未被驱动更新,仍保持300x200;而Framework项目中该属性会更新为代码设置的200x100。

根本原因

这是SDK风格.NET Framework项目与传统Framework项目在打印设置初始化逻辑上的差异导致的:

  1. 传统Framework项目的初始化行为
    传统Framework项目在创建PrintDocument实例时,会直接从打印机驱动获取当前的默认DevMode,随后允许代码通过DefaultPageSettings修改该DevMode,修改后的设置会正确传递给打印机驱动。

  2. SDK风格.NET Framework项目的初始化行为
    SDK风格项目(即使目标是.NET Framework)在初始化PrintDocument时,会优先读取**应用程序配置文件(app.config)**中可能存在的打印设置;若配置中无指定内容,会尝试复用全局默认DevMode缓存,而非每次从驱动获取最新设置并允许代码覆盖。这就导致代码中设置的PaperSize无法正确覆盖全局默认值,驱动依然使用控制面板中的偏好设置。

更具体地说,SDK风格项目的System.Drawing.Printing相关组件初始化时,会通过System.Configuration读取配置,而传统Framework项目则直接依赖驱动的即时设置。当代码尝试修改PaperSize时,SDK项目中的DevMode实例可能处于“只读”状态(或未正确标记为已修改),导致驱动忽略代码中的设置,继续使用全局默认值。

解决方案

可以通过以下方式强制SDK风格项目正确应用自定义纸张尺寸:

  • 显式创建并修改DevMode:跳过DefaultPageSettings.PaperSize的直接设置,手动获取打印机的DevMode,修改其纸张尺寸参数后再赋值给PrintDocument:

    using (var printDoc = new PrintDocument())
    {
        // 获取打印机的默认DevMode
        var devMode = printDoc.PrinterSettings.GetHdevmode(printDoc.DefaultPageSettings);
        try
        {
            // 转换为可编辑的DevMode结构体
            var editableDevMode = (DEVMODE)Marshal.PtrToStructure(devMode, typeof(DEVMODE));
            
            // 设置自定义纸张尺寸(示例:宽200,高100,单位为百分之一英寸)
            editableDevMode.dmPaperWidth = 200;
            editableDevMode.dmPaperLength = 100;
            editableDevMode.dmFields |= DM_PAPERSIZE | DM_PAPERWIDTH | DM_PAPERLENGTH;
            
            // 将修改后的DevMode写回
            Marshal.StructureToPtr(editableDevMode, devMode, false);
            printDoc.PrinterSettings.SetHdevmode(devMode);
        }
        finally
        {
            // 释放DevMode内存
            Marshal.FreeHGlobal(devMode);
        }
        
        // 执行打印
        printDoc.Print();
    }
    

    注:需要定义DEVMODE结构体和对应的常量(DM_PAPERSIZE等),可通过P/Invoke声明获取。

  • 清除配置中的默认打印设置:检查项目的app.config文件,若存在<system.drawing.printing>相关配置,删除或注释掉这些配置,强制项目从驱动获取即时设置。

  • 强制刷新页面设置:在设置PaperSize后,调用printDoc.DefaultPageSettings.Margins = printDoc.DefaultPageSettings.Margins;(或其他无意义的修改),标记页面设置为已修改,促使驱动重新读取设置。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.14 03:20:11