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 に答える