如何找到实际可打印区域? (PrintDocument的) [英] How to find the actual printable area? (PrintDocument)

查看:2484
本文介绍了如何找到实际可打印区域? (PrintDocument的)的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

为什么查不到这个神奇的矩形这么难吗?

Why is finding out this magic Rectangle so difficult?

在OnPrintPage事件我有PrintPageEventArgs,我试图用最大可打印区域的范围内的图形绘制。

In the OnPrintPage event I have PrintPageEventArgs and I am trying to draw using the Graphics within the bounds of the maximum printable area.

我一直在使用PageBounds试过,PrintableArea,Graphics.VisibleClipBounds等,所有未能始终如一地得到绘图区域,特别是从横向到纵向布局切换时。 PrintableArea似乎并不当你从横向切换到肖像永远改变。

I have tried using PageBounds, PrintableArea, Graphics.VisibleClipBounds, etc. All fail to consistently get the drawing area, especially when switching from Landscape to Portrait layout. PrintableArea does not seem to ever change when you switch from Landscape to Portrait.

我也注意到,有在Graphics.VisibleClipBounds是如何依靠,如果我做一个打印preVIEW和实际的打印设置不同。在preVIEW它总是显示纵向宽度/高度,所以我要检查它是否是preVIEW,我必须手动交换宽度/高度时,它是一道风景线。

I have also noticed that there is a difference in how Graphics.VisibleClipBounds is set depending on if I'm doing a print preview and an actual print. In a preview it always shows Portrait width/height, so I have to check if it is a preview and I have to manually swap the width/height when it is a Landscape.

我需要一个算法来计算的可打印区域的,因为它涉及到当前的Graphics上下文,即不实际的绘制中使用的不是一个武断的理论打印区域。

I need an algorithm to calculate the printable area as it relates to the current Graphics context, not an arbitrary theoretical print area that isn't used in actual drawing.

我关心的是处理图形矩阵进行偏移。到目前为止,我已经注意到之间的Graphics上下文是如何pre-翻译使用依赖于类似的因素硬利润率严重不一致:

My concern is dealing with the Graphics matrix offset. So far I have noticed severe inconsistencies between how the Graphics context is pre-translated using the hard margins depending on factors like:


  • 如果OriginAtMargins是真是假(不表现为我想)

  • 如果我打印到打印机或使用打印previewControl(我要检查,如果这是一个打印到preVIEW或打印页面,妥善处理翻译)

  • 如果我用我在家里还是我的打印机在工作的打印机(两者表现不同)

有来处理这一个标准的方式?如果我只是重置矩阵?当我设置OriginAtMargins为真,图形为pre-翻译为84,84,但是我的利润100,100。硬利润率16,16。难道不应该被翻译为100,100?自0,0应该在页面边界,而不是硬边缘。

Is there a standard way to handle this? Should I just reset the matrix? When I set OriginAtMargins to true, the Graphics is pre-translated to 84,84, but my margins are 100,100. The hard margins are 16,16. Shouldn't it be translated to 100,100? Since 0,0 should be at the page bounds, not the hard margins.

基本上我的方法应该得到最好的打印矩形总是工作。我只是需要确保我的绘画原点(0,0)是在页面的左上角,以便上述矩形是任何使用我的一个一致的,独立于设备的方式。

Basically my method should always work at getting the best printable rectangle. I just need a consistent, device-independent way of making sure that my drawing origin (0, 0) is at the top-left of the page in order for the above Rectangle to be of any use to me.

推荐答案

您的问题缺少一点点清晰,以最好的矩形是什么。我会假设你的意思打印时将100%可见的最大的矩形。

Your question lacks a little clarity as to what the "best" rectangle is. I'm going to assume you mean the largest rectangle that will be 100% visible when printed.

所以让我们通过确保我们了解打印文档图形对象起源是和OriginAtMargins财产如何影响这个原点开始。

So lets start by making sure we understand what the print document graphics object "origins" are and how the OriginAtMargins property affects this origin.

OriginAtMargins - 获取或设置一个值,指示是否位置
  与页面相关的图形对象就位于内
  用户指定的保证金或在的可打印区域的左上角
  页面。结果
    - <一个href=\"http://msdn.microsoft.com/en-us/library/system.drawing.printing.printdocument.aspx\">PrintDocument在MSDN上类定义

OriginAtMargins - Gets or sets a value indicating whether the position of a graphics object associated with a page is located just inside the user-specified margins or at the top-left corner of the printable area of the page.
- PrintDocument Class Definition on MSDN

因此​​,与 OriginAtMargins 设置为(默认)图形对象将被调整到PrintableArea矩形(约5/32从我激光打印机在每一页的边缘,旧激光打印机可多了,新的喷墨打印机可以打印右边缘,软件PDF打印机将打印右边缘)。所以,在0,0我的图形对象实际上是16,16我的激光打印机的物理页(打印机可能会有所不同)。

So with OriginAtMargins set to false (default) the graphics object will be adjusted to the PrintableArea rectangle (about 5/32 from each page edge for my laser printer, old laser printers may be more, new inkjets may print right to the edge, software PDF printers will print right to the edge). So 0,0 in my graphics object is actually 16,16 on the physical page of my laser printer (your printer may be different).

使用默认的1英寸页边距和 OriginAtMargins 设置为真正,图形对象将被调整到100,100,650,1100矩形对于正常的画像信页面。这是每个物理页边缘内一英寸。因此,0,0在图形对象实际上是100,100物理页面上。

With the default 1 inch page margins and OriginAtMargins set to true, the graphics object will be adjusted to the 100,100,650,1100 rectangle for a normal portrait letter page. This is one inch inside each physical page edge. So 0,0 in your graphics object is actually 100,100 on the physical page.

边距也被称为它们在软件中定义的,而不是受物理打印装置软边缘。这意味着他们将在软件应用到当前页面的大小,反映了实际的页面尺寸纵向或横向。

Margins are also known as "soft margins" as they are defined in software and not affected by the physical printing device. This means they will be applied to the current page size in software and reflect the actual page dimension portrait or landscape.

PrintableArea也被称为硬边距其中反映打印装置的物理限制。这将改变从打印机到打印机,从制造商到制造商。因为这些都是硬件的测量,当你设置的页面为横向/纵向他们不旋转。物理限制不会改变打印机无论软件打印设置上,所以我们需要确保我们运用他们在正确的轴取决于我们对打印文档(方向)软件设置。

PrintableArea is also known as "hard margins" which reflect the physical limitations of your printing device. This will vary from printer to printer, from manufacturer to manufacturer. Because these are hardware measurements, they do not rotate when you set the page to landscape/portrait. The physical limitations won't change on the printer regardless of software print settings, so we need to make sure we apply them on the correct axis depending on our software settings for the print document (orientation).

因此​​,按照样品code您发布的粗糙模型,这里有一个PrintDocument.PrintPage事件处理程序,将吸引尽可能大的矩形,同时仍然可见(默认的PrintDocument。 OriginsAtMargins )。如果设置 PrintDocument.OriginsAtMargins 真正这将吸引尽可能大的矩形,同时仍然配置内部可见软边距(从页面边缘默认为1)。

So following the rough model of the sample code you posted, here's a PrintDocument.PrintPage event handler that will draw a rectangle as large as possible while still being visible (with the default PrintDocument.OriginsAtMargins being false). If you set PrintDocument.OriginsAtMargins to true it will draw a rectangle as large as possible while still being visible inside the configured soft margins (defaults to 1" from page edges).

PrintAction printAction = PrintAction.PrintToFile;

private void printDocument_BeginPrint(object sender, PrintEventArgs e)
{
    // Save our print action so we know if we are printing 
    // a preview or a real document.
    printAction = e.PrintAction;

    // Set some preferences, our method should print a box with any 
    // combination of these properties being true/false.
    printDocument.OriginAtMargins = false;   //true = soft margins, false = hard margins
    printDocument.DefaultPageSettings.Landscape = false;
}

private void printDocument_PrintPage(object sender, PrintPageEventArgs e)
{
    Graphics g = e.Graphics;

    // If you set printDocumet.OriginAtMargins to 'false' this event 
    // will print the largest rectangle your printer is physically 
    // capable of. This is often 1/8" - 1/4" from each page edge.
    // ----------
    // If you set printDocument.OriginAtMargins to 'false' this event
    // will print the largest rectangle permitted by the currently 
    // configured page margins. By default the page margins are 
    // usually 1" from each page edge but can be configured by the end
    // user or overridden in your code.
    // (ex: printDocument.DefaultPageSettings.Margins)

    // Grab a copy of our "soft margins" (configured printer settings)
    // Defaults to 1 inch margins, but could be configured otherwise by 
    // the end user. You can also specify some default page margins in 
    // your printDocument.DefaultPageSetting properties.
    RectangleF marginBounds = e.MarginBounds;

    // Grab a copy of our "hard margins" (printer's capabilities) 
    // This varies between printer models. Software printers like 
    // CutePDF will have no "physical limitations" and so will return 
    // the full page size 850,1100 for a letter page size.
    RectangleF printableArea = e.PageSettings.PrintableArea;

    // If we are print to a print preview control, the origin won't have 
    // been automatically adjusted for the printer's physical limitations. 
    // So let's adjust the origin for preview to reflect the printer's 
    // hard margins.
    if (printAction == PrintAction.PrintToPreview)
        g.TranslateTransform(printableArea.X, printableArea.Y);

    // Are we using soft margins or hard margins? Lets grab the correct 
    // width/height from either the soft/hard margin rectangles. The 
    // hard margins are usually a little wider than the soft margins.
    // ----------
    // Note: Margins are automatically applied to the rotated page size 
    // when the page is set to landscape, but physical hard margins are 
    // not (the printer is not physically rotating any mechanics inside, 
    // the paper still travels through the printer the same way. So we 
    // rotate in software for landscape)
    int availableWidth = (int)Math.Floor(printDocument.OriginAtMargins ? marginBounds.Width : (e.PageSettings.Landscape ? printableArea.Height : printableArea.Width));
    int availableHeight = (int)Math.Floor(printDocument.OriginAtMargins ? marginBounds.Height : (e.PageSettings.Landscape ? printableArea.Width : printableArea.Height));

    // Draw our rectangle which will either be the soft margin rectangle 
    // or the hard margin (printer capabilities) rectangle.
    // ----------
    // Note: we adjust the width and height minus one as it is a zero, 
    // zero based co-ordinates system. This will put the rectangle just 
    // inside the available width and height.
    g.DrawRectangle(Pens.Red, 0, 0, availableWidth - 1, availableHeight - 1);
}

这是确定可用的宽度和高度可用的两行是什么,我认为你是在你的问题寻找。这两行考虑是否要软利润率或硬的利润率和打印文档是否被配置为横向或纵向。

The two lines that determine available width and available height are what I think you were looking for in your question. Those two lines take into account whether you want soft margins or hard margins and whether the print document is configured for landscape or portrait.

我用 Math.Floor()的讨巧为丢弃任何东西过去小数(例如:817.96 - > 817)只是为了确保可用宽度和高度只是可用的尺寸内。我在失败安全在这里,如果你想,你可以保持浮动基于坐标(而不是INT),只是注意由于舍入误差,这将导致在裁剪的图形(如果舍817.96高达818然后打印机驱动程序决定的不再可见)。

I used Math.Floor() for the easy way out to just drop anything past the decimal (ex: 817.96 -> 817) just to make sure the available width and height was just inside the available dimensions. I'm "failing safe" here, if you wanted to you could maintain float based co-ordinates (instead of int), just be careful to watch for rounding errors that will result in the clipped graphics (if it rounds 817.96 up to 818 and then the printer driver decides that's no longer visible).

我纵向和横向与戴尔3115CN,三星SCX-4x28和CutePDF打印机软件硬利润率和利润率软测试此过程。如果没有充分解决您的问题,考虑修改你的问题,以澄清魔术矩形和最佳矩形。

I tested this procedure in both portrait and landscape with both hard margins and soft margins on a Dell 3115CN, a Samsung SCX-4x28 and CutePDF software printer. If this didn't adequately address your question, consider revising your question to clarify "magic rectangle" and "best rectangle".

编辑:注意关于软边距

软利润率在软件应用,并且不考虑打印机的硬件限制。这是故意和设计。如果你想和输出可以通过打印机的驱动程序被裁剪您可以设置打印区域外的软利润率。如果这是不可取您的应用程序,你需要在你的程序code调整页边距。要么你可以prevent用户从可打印区域之外选择利润(或者警告他们,如果他们这样做),或者你可以强制在code一些最大/最小条件当你真正开始打印(图)文档。

Soft margins are applied in software and do not take into consideration the hardware limitations of the printer. This is intentional and by design. You can set the soft margins outside the printable area if you want and the output may be clipped by your printer's driver. If this is undesirable for your application, you need to adjust the margins in your program code. Either you can prevent the user from selecting margins outside the printable area (or warn them if they do) or you can enforce some min/max conditions in your code when you actually start printing (drawing) the document.

事例:如果您在Microsoft Word 2007中一个警告对话框弹出,上面写着一个或多个页边距设的可打印区域之外设置页边距为0,0,0,0页面,选择修复按钮以适当增加页边距。如果您单击修复,Word将简单的硬边缘复制到软边缘,所以该对话框会立即显示0.16的所有利润(我的激光打印机的能力)。

Example Case: If you set the page margins to 0,0,0,0 in Microsoft Word 2007 a warning dialog pops up that reads "One or more margins are set outside the printable area of the page. Choose the Fix button to increase the appropriate margins." If you click fix, Word will simply copy the hard margins into the soft margins, so the dialog now shows 0.16" for all margins (my laser printer's capabilities).

这是预期的行为。如果打印页被裁剪,因为用户忽略此警告并使用0,0,0,0页边距这是不是一个错误/问题与Microsoft Word。这是你的应用程序一样。您需要强制执行的限制无论如果您的使用情况适当。无论是显示一个警告对话框,或者您可以强制限制更加强烈code(不提供选择的用户)。

This is expected behavior. It is not a bug/problem with Microsoft Word if the printed page is clipped because the user ignored this warning and used 0,0,0,0 page margins. This is the same in your application. You need to enforce the limits for whatever if appropriate in your use case. Either with a warning dialog, or you can force the limit more strongly in code (don't offer a choice to the user).

好吧,所以也许你不想刚刚得到的硬的利润,而是获得利润软,然后强制软利润率保持在可打印区域内打印时。让我们在这里发展出一个新的战略。

Alright so maybe you don't want to just get the hard margins, but rather get the soft margins and then enforce that the soft margins remain inside the printable area when printing. Let's develop another strategy here.

在这个例子中我将使用在起源的利润率,并允许用户选择他们想要的任何保证金,但我会在code所选择的边缘不可打印区域外执行。如果选定的利润率可打印区域之外,我只是要调整它们的可打印区域内。

In this example I will use the origins at margins, and allow the user to select any margin they want, but I'm going to enforce in code that the selected margin not be outside the printable area. If the selected margins are outside the printable area, I'm simply going to adjust them to be inside the printable area.

PrintAction printAction = PrintAction.PrintToFile;

private void printDocument_BeginPrint(object sender, PrintEventArgs e)
{
    // Save our print action so we know if we are printing 
    // a preview or a real document.
    printAction = e.PrintAction;

    // We ALWAYS want true here, as we will implement the 
    // margin limitations later in code.
    printDocument.OriginAtMargins = true;

    // Set some preferences, our method should print a box with any 
    // combination of these properties being true/false.
    printDocument.DefaultPageSettings.Landscape = false;
    printDocument.DefaultPageSettings.Margins.Top = 100;
    printDocument.DefaultPageSettings.Margins.Left = 0;
    printDocument.DefaultPageSettings.Margins.Right = 50;
    printDocument.DefaultPageSettings.Margins.Bottom = 0;
}

private void printDocument_PrintPage(object sender, PrintPageEventArgs e)
{
    Graphics g = e.Graphics;

    // If you set printDocumet.OriginAtMargins to 'false' this event 
    // will print the largest rectangle your printer is physically 
    // capable of. This is often 1/8" - 1/4" from each page edge.
    // ----------
    // If you set printDocument.OriginAtMargins to 'false' this event
    // will print the largest rectangle permitted by the currently 
    // configured page margins. By default the page margins are 
    // usually 1" from each page edge but can be configured by the end
    // user or overridden in your code.
    // (ex: printDocument.DefaultPageSettings.Margins)

    // Grab a copy of our "hard margins" (printer's capabilities) 
    // This varies between printer models. Software printers like 
    // CutePDF will have no "physical limitations" and so will return 
    // the full page size 850,1100 for a letter page size.
    RectangleF printableArea = e.PageSettings.PrintableArea;
    RectangleF realPrintableArea = new RectangleF(
        (e.PageSettings.Landscape ? printableArea.Y : printableArea.X),
        (e.PageSettings.Landscape ? printableArea.X : printableArea.Y),
        (e.PageSettings.Landscape ? printableArea.Height : printableArea.Width),
        (e.PageSettings.Landscape ? printableArea.Width : printableArea.Height)
        );

    // If we are printing to a print preview control, the origin won't have 
    // been automatically adjusted for the printer's physical limitations. 
    // So let's adjust the origin for preview to reflect the printer's 
    // hard margins.
    // ----------
    // Otherwise if we really are printing, just use the soft margins.
    g.TranslateTransform(
        ((printAction == PrintAction.PrintToPreview) ? realPrintableArea.X : 0) - e.MarginBounds.X,
        ((printAction == PrintAction.PrintToPreview) ? realPrintableArea.Y : 0) - e.MarginBounds.Y
    );

    // Draw the printable area rectangle in PURPLE
    Rectangle printedPrintableArea = Rectangle.Truncate(realPrintableArea);
    printedPrintableArea.Width--;
    printedPrintableArea.Height--;
    g.DrawRectangle(Pens.Purple, printedPrintableArea);

    // Grab a copy of our "soft margins" (configured printer settings)
    // Defaults to 1 inch margins, but could be configured otherwise by 
    // the end user. You can also specify some default page margins in 
    // your printDocument.DefaultPageSetting properties.
    RectangleF marginBounds = e.MarginBounds;

    // This intersects the desired margins with the printable area rectangle. 
    // If the margins go outside the printable area on any edge, it will be 
    // brought in to the appropriate printable area.
    marginBounds.Intersect(realPrintableArea);

    // Draw the margin rectangle in RED
    Rectangle printedMarginArea = Rectangle.Truncate(marginBounds);
    printedMarginArea.Width--;
    printedMarginArea.Height--;
    g.DrawRectangle(Pens.Red, printedMarginArea);
}

这篇关于如何找到实际可打印区域? (PrintDocument的)的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆