使用TMetafilePrinter时如何正确获取纸张尺寸?
解决TMetafilePrinter获取纸张尺寸始终返回屏幕尺寸的问题
你遇到的这个问题很典型——TMetafilePrinter如果没有正确绑定打印机设备并配置纸张参数,它的Canvas Handle会默认关联到屏幕DC,导致GetDeviceCaps返回的是屏幕物理尺寸而非纸张尺寸。下面是具体的分析和解决方案:
问题根源
当你直接创建TMetafilePrinter而未指定打印机、未设置纸张参数就调用BeginDoc时,组件会 fallback 到使用屏幕设备上下文(DC),这就是为什么无论你选A3/A4/A5还是横竖方向,得到的都是固定的屏幕尺寸值。
解决方案
要正确获取打印机纸张的尺寸,需要按以下步骤操作:
- 绑定目标打印机:明确指定要使用的打印机(默认打印机或特定打印机)
- 配置纸张参数:在
BeginDoc前设置纸张大小和页面方向 - 正确获取尺寸:可以通过
GetDeviceCaps获取物理尺寸,或直接使用组件内置属性获取像素尺寸
完整代码示例
var MFPrinter: TMetaFilePrinter; DC: HDC; PhysicalW, PhysicalH, PixelW, PixelH: Integer; begin MFPrinter := TMetaFilePrinter.Create(nil); try // 绑定到系统默认打印机(也可通过PrinterIndex指定特定打印机) MFPrinter.PrinterIndex := Printer.PrinterIndex; // 设置纸张尺寸(可选psA3/psA4/psA5等) MFPrinter.PaperSize := psA4; // 设置页面方向(可选poPortrait纵向/poLandscape横向) MFPrinter.Orientation := poPortrait; // 启动文档打印流程 MFPrinter.BeginDoc; try DC := MFPrinter.Canvas.Handle; // 获取纸张物理尺寸(单位:毫米) PhysicalW := GetDeviceCaps(DC, HORZSIZE); PhysicalH := GetDeviceCaps(DC, VERTSIZE); ShowMessageFmt('纸张物理尺寸:%dmm × %dmm', [PhysicalW, PhysicalH]); // 获取纸张像素尺寸(基于打印机DPI) PixelW := MFPrinter.PageWidth; PixelH := MFPrinter.PageHeight; ShowMessageFmt('纸张像素尺寸:%dpx × %dpx', [PixelW, PixelH]); finally // 结束文档流程 MFPrinter.EndDoc; end; finally MFPrinter.Free; end; end;
额外注意事项
- 如果需要使用自定义纸张尺寸,可以设置
MFPrinter.PaperSize为psCustom,然后手动指定PaperWidth和PaperHeight(单位:百分之一英寸) - 若设置的纸张尺寸不被当前打印机驱动支持,组件会自动 fallback 到打印机的默认纸张,建议先调用
MFPrinter.Refresh加载打印机的可用纸张列表 GetDeviceCaps的HORZSIZE/VERTSIZE返回物理尺寸,HORZRES/VERTRES返回对应像素数,可根据你的业务需求选择
内容的提问来源于stack exchange,提问作者Pele




