如何调整TStringGrid打印逻辑实现带页眉页脚页面的网格居中输出
问题结论
完全不需要重构整套打印逻辑,现有代码框架只要调整坐标计算规则,就可以实现将TStringGrid在预设页眉页脚的页面空白区居中打印,不需要换全新的实现方案。
现有代码的核心问题
你当前的代码所有打印坐标都是硬编码固定值:
- 网格横向所有坐标起点直接写死为页面最左侧
X=0,完全没计算网格本身的总宽度 - 纵向坐标直接写死从
Y=300开始累加,既没匹配预留页眉页脚的边界位置,也没计算网格本身的总高度
相当于直接把网格贴在页面左上角打印,自然没法实现居中定位。
调整思路
只需要在原有代码的坐标逻辑基础上,新增三个计算步骤即可:
- 先计算你要预留的空白可打印区域边界
对照你的页面版式,把页眉、页脚、左右固定占位区域的位置换算成打印机画布坐标,定义出中间可用的空白矩形范围。比如页眉占页面顶部300打印单位、页脚占页面底部400打印单位、左右各留200边距,直接把这个范围存成一个TRect变量即可。 - 提前统计整个网格的实际打印总尺寸
沿用你原有代码的缩放规则:每列实际打印宽度为5 * sGrid.ColWidths[列索引],每一行实际打印高度为固定150打印单位,循环累加出整个网格的总宽度、总高度。 - 计算居中偏移量
- 横向居中偏移:可打印区域左边界 + (可打印区域总宽度 - 网格总宽度) / 2
- 纵向居中偏移:可打印区域上边界 + (可打印区域总高度 - 网格总高度) / 2
原有代码里所有硬编码的起点坐标(比如X方向的0、Y方向的300),全部替换成对应计算出来的偏移值即可。
可直接参考的核心调整代码片段
procedure PrintGrid(sGrid: TStringGrid; sTitle: string); var X1, X2, Y1, Y2: Integer; TmpI, F: Integer; TR: TRect; // 新增变量:网格总尺寸、居中偏移、可打印区域 GridTotalWidth, GridTotalHeight, OffsetX, OffsetY: Integer; PrintableArea: TRect; begin Printer.Title := sTitle; Printer.BeginDoc; Printer.Canvas.Pen.Color := 0; Printer.Canvas.Font.Name := 'Times New Roman'; Printer.Canvas.Font.Size := 12; // ========= 新增的居中计算逻辑 ========= // 1. 定义预留可打印区域:根据你的实际页面边距调整数值 // 示例值:左边界200,上边界300,右边界=打印页宽-200,下边界=打印页高-400 PrintableArea := Rect( 200, 300, Printer.PageWidth - 200, Printer.PageHeight - 400 ); // 2. 统计网格总打印尺寸 GridTotalWidth := 0; for TmpI := 1 to sGrid.ColCount - 1 do GridTotalWidth := GridTotalWidth + 5 * sGrid.ColWidths[TmpI]; GridTotalHeight := 150 * sGrid.RowCount; // 沿用原150单位固定行高 // 3. 计算居中偏移坐标 OffsetX := PrintableArea.Left + (PrintableArea.Right - PrintableArea.Left - GridTotalWidth) div 2; OffsetY := PrintableArea.Top + (PrintableArea.Bottom - PrintableArea.Top - GridTotalHeight) div 2; // ===================================== // 原有列遍历逻辑,仅替换硬编码的起点坐标 for F := 1 to sGrid.ColCount - 1 do begin // 原X1 := 0; 替换为基于偏移量计算 X1 := OffsetX; for TmpI := 1 to (F - 1) do X1 := X1 + 5 * (sGrid.ColWidths[TmpI]); // 原Y1 := 300; 替换为基于偏移量计算 Y1 := OffsetY; X2 := OffsetX; for TmpI := 1 to F do X2 := X2 + 5 * (sGrid.ColWidths[TmpI]); Y2 := Y1 + 150; // 表头行高固定150 TR := Rect(X1, Y1, X2 - 30, Y2); Printer.Canvas.Font.Style := [fsBold]; Printer.Canvas.Font.Size := 7; Printer.Canvas.TextRect(TR, X1 + 50, Y1 + 50, sGrid.Cells[F, 0]); Printer.Canvas.Font.Style := []; for TmpI := 1 to sGrid.RowCount - 1 do begin Y1 := OffsetY + 150 * TmpI; Y2 := OffsetY + 150 * (TmpI + 1); TR := Rect(X1, Y1, X2 - 30, Y2); Printer.Canvas.TextRect(TR, X1 + 50, Y1 + 50, sGrid.Cells[F, TmpI]); end; end; Printer.EndDoc; end;
注意事项
- 调整时不需要改动原有的字体设置、单元格绘制逻辑,仅替换坐标计算的基准值即可,不会影响原有打印的显示效果
- 如果计算得到的偏移值为负数,说明网格总尺寸超过了预留的空白区域范围,可适当调低列宽、行高的缩放系数,保证网格能完整落在可打印区内,不会被页眉、页脚遮挡
- 你原有代码里独立打印标题的逻辑,如果对应位置已经属于预留页眉区域,可以直接删掉,避免和预设的页眉内容重叠
内容的提问来源于stack exchange,提问作者PrimeBeat
相关产品推荐
相关产品推荐

