简体   繁体   English

C# - 如何打印宽高比/整页

[英]C# - How to print aspect ratio / full page

I am printing the CHART control on button click: 我在点击按钮时打印CHART控件:

chart1.SaveImage(ms, ChartImageFormat.Bmp);
Bitmap bm = new Bitmap(ms);

PrintDocument doc = new PrintDocument();
doc.PrintPage += (s, ev) =>
{
    ev.Graphics.DrawImage(bm, Point.Empty); // adjust this to put the image elsewhere
    ev.HasMorePages = false;
};
doc.DefaultPageSettings.Landscape = true;

doc.Print();

How do I force it to print the control so that it fits to the size of the page (preserving the aspect ratio)? 如何强制它打印控件以使其适合页面大小(保留纵横比)?

There are at least two different ways to do it, both include scaling the image to be printed to fit the page size of the selected printer: 至少有两种不同的方法, 包括缩放要打印的图像以适合所选打印机的页面大小

1) using .NET facilities (haven't tested it myself, lifted from this post ): 1)使用.NET工具(我自己没有测试过,从这篇帖子中取消):

    private void printDocument1_PrintPage(object sender, System.Drawing.Printing.PrintPageEventArgs e)
    {
        Image i = pictureBox1.Image;

        float newWidth = i.Width * 100 / i.HorizontalResolution;
        float newHeight = i.Height * 100 / i.VerticalResolution;

        float widthFactor = newWidth / e.MarginBounds.Width;
        float heightFactor = newHeight / e.MarginBounds.Height;

        if(widthFactor>1 | heightFactor > 1)
        {
            if(widthFactor > heightFactor)
            {
                newWidth = newWidth / widthFactor;
                newHeight = newHeight / widthFactor;
            }
            else
            {
                newWidth = newWidth / heightFactor;
                newHeight = newHeight / heightFactor;
            }
        }
        e.Graphics.DrawImage(i, 0, 0, (int)newWidth, (int)newHeight);
    }
}

2) P/Invoke'ing Windows API calls from the GDI and flat GDI (this is much more complex but faster and you can pass a plain byte array of a bitmap file (read file as byte[]), provide an email to me if need this code): 2) P /调用来自GDI和平面GDI的Windows API调用(这更复杂但更快,你可以传递位图文件的普通字节数组(读取文件为byte []),向我发送电子邮件如果需要这个代码):

  private static extern bool ClosePrinter(IntPtr hPrinter);
  private static extern bool OpenPrinter([MarshalAs(UnmanagedType.LPStr)] string szPrinter, out IntPtr hPrinter, IntPtr pd);
  private static extern int SetJob(IntPtr hPrinter, int JobId, int Level, ref byte pJob, int Command_Renamed);
  private static extern int GdiplusStartup(out IntPtr token, ref StartupInput input, out StartupOutput output);
  private static extern int GdiplusShutdown(IntPtr token);
  internal static extern int GdipLoadImageFromStream([In, MarshalAs(UnmanagedType.Interface)]IStream stream, out IntPtr image);
  internal static extern int GdipDisposeImage(IntPtr image);
  static internal extern int GdipCreateFromHDC2(IntPtr hDC, IntPtr hDevice, out IntPtr graphics);
  static internal extern int GdipDeleteGraphics(IntPtr graphics);
  static internal extern int GdipReleaseDC(IntPtr graphics, IntPtr hdc);
  internal static extern int GdipGetImageDimension(IntPtr image, out float width, out float height);
  internal static extern int GdipGetDpiX(IntPtr graphics, out float dpi);
  internal static extern int GdipGetDpiY(IntPtr graphics, out float dpi);
  static internal extern int GdipDrawImageRectI(IntPtr graphics, IntPtr image, int x, int y, int width, int height);
  private static extern IntPtr CreateDC([MarshalAs(UnmanagedType.LPStr)] string lpszDriver, [MarshalAs(UnmanagedType.LPStr)] string lpszDevice, [MarshalAs(UnmanagedType.LPStr)] string lpszOutput, IntPtr lpInitData);
  private static extern bool DeleteDC(IntPtr hdc);
  private static extern int StartDoc(IntPtr hdc, DOCINFO lpdi);
  private static extern int EndDoc(IntPtr hdc);
  private static extern int StartPage(IntPtr hdc);
  private static extern int EndPage(IntPtr hdc);
  private static extern int GetDeviceCaps(IntPtr hdc, int nIndex);

Here's what I did to get this working. 这就是我为实现这一目标所做的工作。 What's annoying is that the chart control will only draw its contents as the same size that it is sized to on the screen. 令人讨厌的是图表控件只会将其内容绘制为与屏幕大小相同的大小。 The only way I found to get around this is to manually resize it. 我发现解决这个问题的唯一方法是手动调整它。 And then, since it may not like being resized when it's on a form, this also involved temporarily removing it from the form. 然后,因为它可能不喜欢在表单上调整大小时,这也涉及暂时将其从表单中删除。

So with all that, I end up with something like this: 所有这些,我最终得到这样的东西:

Chart ChartBox { get; private set; }

...

var oldParent = ChartBox.Parent;
var oldSize = ChartBox.Size;

ChartBox.Parent = null;
ChartBox.Size = new Size(width, height);

ChartBox.Printing.Print();

ChartBox.Parent = oldParent;
ChartBox.Size = oldSize;

Depending on your form, you may need to save and restore other properties of the chart control as well. 根据您的表单,您可能还需要保存和恢复图表控件的其他属性。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM