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

时间:2010-11-17 16:37:47

标签: c#

我在点击按钮时打印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();

如何强制它打印控件以使其适合页面大小(保留纵横比)?

3 个答案:

答案 0 :(得分:9)

至少有两种不同的方法,包括缩放要打印的图像以适合所选打印机的页面大小

1)使用.NET设施(我自己没有测试过,取消了post):

    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)来自GDI和平面GDI的P/Invoke'ing 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);

答案 1 :(得分:0)

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.

答案 2 :(得分:0)

尝试此代码:

e.Graphics.DrawImage(img, e.Graphics.VisibleClipBounds);