1

我正在使用PrintDocument.Print()启动打印过程,其中我打印数据网格 (C1FlexGrid) 和一些页眉和页脚信息。这是一个有点复杂的打印过程。我正在使用标准PrintDocument方法,但由于我想要点击页面,我可以控制正在发生的一切。

我遇到的问题是我想缩小将绘制网格控件的区域。当我绘制页眉和页脚时,我正在计算它们将占用的空间,以及网格应该占用的空间。网格控件有它自己的PrintDocumentGridRenderer类,该类提供了PrintPage()我调用的方法,以使其在 PrintDocument 的Graphics对象上呈现网格。

我无法弄清楚如何限制网格可以容纳的区域,但是我已经绘制页眉/页脚并知道剩余空间是什么之后再做。

这是一些代码,我认为是本质:

private void PrintDocument_PrintPage(Object sender, PrintPageEventArgs e)
{
    //I tried putting a non-drawing version of DrawHeadersAndFooters() here to get the calculated space and then reset the Margin...but it's always one call behind the Graphics object, meaning that it has no effect on the first page.  In fact, because Setup() gets called with two different margins at that point, the pages end up very badly drawn.

    _gridRenderer.Setup(e);  //this is the PrintDocumentGridRender object and Setup() figures out page layout (breaks and such)

    DrawHeadersAndFooters(e.Graphics, e.MarginBounds);
    Int32 newX = _printProperties.GridBounds.X - e.MarginBounds.X;
    Int32 newY = _printProperties.GridBounds.Y - e.MarginBounds.Y;
    e.Graphics.TranslateTransform(newX, newY);
    _gridRenderer.PrintPage(e, _currentPage - 1);  //grid control's print method
    e.HasMorePages = _currentPage < _printProperties.Document.PrinterSettings.ToPage;
    _currentPage++;
}

private void DrawHeadersAndFooters(Graphics graphics, Rectangle marginBounds)
{
    Rectangle textRect = new Rectangle();
    Int32 height = 0;
    //loop lines in header paragraph to get total height required
    //there are actually three, across the page, but just one example for bevity...
    if (!String.IsNullOrEmpty(_printProperties.HeaderLeft))
    {
        Int32 h = 0;
        foreach (String s in _printProperties.HeaderLeft.Split(new String[] { "\r\n" }, StringSplitOptions.RemoveEmptyEntries))
            h += (Int32)graphics.MeasureString(s, _printProperties.HeaderLeftFont, width, stringFormat).Height;
        height = (h > height) ? h : height;
    } //repeat for other two, keeping the greatest of 3 heights in the end
    textRect.X = marginBounds.X;
    textRect.Y = (Int32)_printProperties.Document.DefaultPageSettings.PrintableArea.Y;  //a global storage for printing information I need to keep in memory
    textRect.Width = width;
    textRect.Height = height;

    stringFormat.Alignment = StringAlignment.Near;
    graphics.DrawString(_printProperties.HeaderLeft, _printProperties.HeaderLeftFont, new SolidBrush(_printProperties.HeaderLeftForeColor), textRect, stringFormat);

    _printProperties.GridBounds = new Rectangle(marginBounds.X, textRect.Y, marginBounds.Width, marginBounds.Bottom - textRect.Y);  //here I think I have the space into which the grid _should_ be made to fit
}

您可以看到,PrintDocument_PrintPage()我正在对Graphics对象应用变换,它将网格向下移动到标题下方。

截屏:

在此处输入图像描述

所以,问题:

我想自下而上缩小该区域,以使该网格的底部刚好在页脚上方。您可以通过查看右下角看到渲染的网格图像与我已经绘制的页脚重叠。这就是我需要的帮助。如何在Graphics不做类似的事情的情况下缩小绘图空间ScaleTransform(),这似乎根本不是正确的想法。

4

1 回答 1

1

答案被证明是对逻辑的彻底重组。我没有尝试全部弄清楚并同时渲染它,而是将计算代码重构为一个单独的方法,我可以在调用PrintDocument.Print().

这一切都归结为我以前不知道的这个小宝石:

Graphics graphics = _printProperties.Document.PrinterSettings.CreateMeasurementGraphics();

这给了我一个新Graphics的打印文档对象,我可以用它在打印之前进行所有计算。一旦我有了它,存储它然后在实际的页眉和页脚渲染中使用结果就很简单了。

它还为我提供了调整网格调用之前所需Margins的信息。PrintDocument.DefaultPageSettingsPrint()

一些代码供参考:

//The margins I intend to adjust
System.Drawing.Printing.Margins margins = _printProperties.Document.DefaultPageSettings.Margins;

//Get paper width/height respecting orientation
Int32 paperWidth = 
    _printProperties.Document.DefaultPageSettings.Landscape ? 
    _printProperties.Document.DefaultPageSettings.PaperSize.Height : 
    _printProperties.Document.DefaultPageSettings.PaperSize.Width;
Int32 paperHeight = 
    _printProperties.Document.DefaultPageSettings.Landscape ? 
    _printProperties.Document.DefaultPageSettings.PaperSize.Width : 
    _printProperties.Document.DefaultPageSettings.PaperSize.Height;

//Calculate printable bounds using user-defined margins and paper size
Rectangle marginBounds = new Rectangle(_printProperties.MarginLeft, _printProperties.MarginTop,
    paperWidth - (_printProperties.MarginLeft + _printProperties.MarginRight),
    paperHeight - (_printProperties.MarginTop + _printProperties.MarginBottom));

//Calculate Rectangles for every header/footer element
CalculatePrintRegions(marginBounds);

//If certain elements exist, use the calculated sizes to adjust the margins
Boolean hasHeader =
    !String.IsNullOrEmpty(_printProperties.HeaderLeft) ||
    !String.IsNullOrEmpty(_printProperties.HeaderCenter) ||
    !String.IsNullOrEmpty(_printProperties.HeaderRight);
Boolean hasHeader2 = 
    !String.IsNullOrEmpty(_printProperties.Header2Range) || 
    !String.IsNullOrEmpty(_printProperties.Header2Date);
Boolean hasFooter =
    !String.IsNullOrEmpty(_printProperties.FooterLeft) ||
    !String.IsNullOrEmpty(_printProperties.FooterCenter) ||
    !String.IsNullOrEmpty(_printProperties.FooterRight);
if (hasHeader)
{
    Int32 topAdd = Math.Max(Math.Max(_printProperties.HeaderLeftRect.Height, _printProperties.HeaderCenterRect.Height), _printProperties.HeaderRightRect.Height);
    if (hasHeader2)
        topAdd += Math.Max(_printProperties.Header2RangeRect.Height, _printProperties.Header2DateRect.Height);
    margins.Top = _printProperties.HeaderLeftRect.Top + topAdd + 10;
}
if (hasFooter)
    margins.Bottom = paperHeight - (_printProperties.FooterLeftRect.Top - 10);

//This used to be the starting point, everything above was added in answer to the problem
_printProperties.IsPrinting = true;  //used by drawing code to control drawing of certain elements (such as not showing selection/highlight)
_printProperties.IsPreview = Preview;
_printProperties.IsDryRun = true;  //to get page count into _gridRenderer before displaying prompt
_printProperties.Document.Print();

请注意,由于我手动绘制所有页眉/页脚文本,边距对其没有影响,因此调整它们只会影响网格渲染。

于 2014-06-12T15:04:51.000 回答