使用 PrintDocument 打印图像。如何调整图像以适合纸张尺寸

Posted

技术标签:

【中文标题】使用 PrintDocument 打印图像。如何调整图像以适合纸张尺寸【英文标题】:Printing image with PrintDocument. how to adjust the image to fit paper size 【发布时间】:2012-04-16 11:26:01 【问题描述】:

在 C# 中,我尝试使用 PrintDocument 类和以下代码打印图像。图像大小为 1200 像素宽和 1800 像素高。我正在尝试使用小型斑马打印机在 4*6 纸上打印此图像。但是程序只打印 4*6 的大图像。这意味着它没有将图像调整为纸张尺寸!

     PrintDocument pd = new PrintDocument();
     pd.PrintPage += (sender, args) =>
     
           Image i = Image.FromFile("C://tesimage.PNG");
           Point p = new Point(100, 100);
           args.Graphics.DrawImage(i, 10, 10, i.Width, i.Height);
     ;
     pd.Print();

当我使用 Window Print 打印相同的图像时(右键单击并选择打印,它会自动缩放到纸张尺寸并正确打印。这意味着一切都在 4*6 纸中。)我如何在我的 C# 中做同样的事情程序?

【问题讨论】:

如果您喜欢答案,请接受。它给予回答您的人的荣誉,并帮助其他寻找答案的人更快地找到正确的答案 【参考方案1】:

您传递给 DrawImage 方法的参数应该是您想要的图像在纸上的大小,而不是图像本身的大小,然后 DrawImage 命令将为您处理缩放。可能最简单的方法是使用以下 DrawImage 命令覆盖。

args.Graphics.DrawImage(i, args.MarginBounds);

注意:如果图像的比例与矩形不同,这会使图像倾斜。对图像大小和纸张大小进行一些简单的数学运算后,您可以创建一个适合纸张边界的新矩形,而不会扭曲图像。

【讨论】:

这应该是答案!感谢它按预期工作的解决方案。 args.Graphics.DrawImage(i, args.PageBounds);【参考方案2】:

不要践踏 BBoy 已经不错的答案,但我已经完成了保持纵横比的代码。我接受了他的建议,所以他应该在这里获得部分荣誉!

PrintDocument pd = new PrintDocument();
pd.DefaultPageSettings.PrinterSettings.PrinterName = "Printer Name";
pd.DefaultPageSettings.Landscape = true; //or false!
pd.PrintPage += (sender, args) =>

    Image i = Image.FromFile(@"C:\...\...\image.jpg");
    Rectangle m = args.MarginBounds;

    if ((double)i.Width / (double)i.Height > (double)m.Width / (double)m.Height) // image is wider
    
        m.Height = (int)((double)i.Height / (double)i.Width * (double)m.Width);
    
    else
    
        m.Width = (int)((double)i.Width / (double)i.Height * (double)m.Height);
    
    args.Graphics.DrawImage(i, m);
;
pd.Print();

【讨论】:

好答案,但我用 args.PageBounds 替换了 args.MarginBounds【参考方案3】:

BBoy 提供的解决方案效果很好。但就我而言,我不得不使用

e.Graphics.DrawImage(memoryImage, e.PageBounds);

这将只打印表单。当我使用 MarginBounds 时,即使表单小于监视器屏幕,它也会打印整个屏幕。 PageBounds 解决了这个问题。感谢 BBoy!

【讨论】:

【参考方案4】:

你可以在这里使用我的代码

//Print Button Event Handeler
private void btnPrint_Click(object sender, EventArgs e)

    PrintDocument pd = new PrintDocument();
    pd.PrintPage += PrintPage;
    //here to select the printer attached to user PC
    PrintDialog printDialog1 = new PrintDialog();
    printDialog1.Document = pd;
    DialogResult result = printDialog1.ShowDialog();
    if (result == DialogResult.OK)
    
        pd.Print();//this will trigger the Print Event handeler PrintPage
    


//The Print Event handeler
private void PrintPage(object o, PrintPageEventArgs e)

    try
    
        if (File.Exists(this.ImagePath))
        
            //Load the image from the file
            System.Drawing.Image img = System.Drawing.Image.FromFile(@"C:\myimage.jpg");

            //Adjust the size of the image to the page to print the full image without loosing any part of it
            Rectangle m = e.MarginBounds;

            if ((double)img.Width / (double)img.Height > (double)m.Width / (double)m.Height) // image is wider
            
                m.Height = (int)((double)img.Height / (double)img.Width * (double)m.Width);
            
            else
            
                m.Width = (int)((double)img.Width / (double)img.Height * (double)m.Height);
            
            e.Graphics.DrawImage(img, m);
        
    
    catch (Exception)
    

    

【讨论】:

e.Graphics.DrawImage(img, m); 解决了我的问题.. +1【参考方案5】:

答案:

public void Print(string FileName)

    StringBuilder logMessage = new StringBuilder();
    logMessage.AppendLine(string.Format(CultureInfo.InvariantCulture, "-------------------[ START - 0 - 1 -------------------]", MethodBase.GetCurrentMethod(), DateTime.Now.ToShortDateString()));
    logMessage.AppendLine(string.Format(CultureInfo.InvariantCulture, "Parameter: 1: [Name - 0, Value - 1", "None]", Convert.ToString("")));

    try
    
        if (string.IsNullOrWhiteSpace(FileName)) return; // Prevents execution of below statements if filename is not selected.

        PrintDocument pd = new PrintDocument();

        //Disable the printing document pop-up dialog shown during printing.
        PrintController printController = new StandardPrintController();
        pd.PrintController = printController;

        //For testing only: Hardcoded set paper size to particular paper.
        //pd.PrinterSettings.DefaultPageSettings.PaperSize = new PaperSize("Custom 6x4", 720, 478);
        //pd.DefaultPageSettings.PaperSize = new PaperSize("Custom 6x4", 720, 478);

        pd.DefaultPageSettings.Margins = new Margins(0, 0, 0, 0);
        pd.PrinterSettings.DefaultPageSettings.Margins = new Margins(0, 0, 0, 0);

        pd.PrintPage += (sndr, args) =>
        
            System.Drawing.Image i = System.Drawing.Image.FromFile(FileName);

            //Adjust the size of the image to the page to print the full image without loosing any part of the image.
            System.Drawing.Rectangle m = args.MarginBounds;

            //Logic below maintains Aspect Ratio.
            if ((double)i.Width / (double)i.Height > (double)m.Width / (double)m.Height) // image is wider
            
                m.Height = (int)((double)i.Height / (double)i.Width * (double)m.Width);
            
            else
            
                m.Width = (int)((double)i.Width / (double)i.Height * (double)m.Height);
            
            //Calculating optimal orientation.
            pd.DefaultPageSettings.Landscape = m.Width > m.Height;
            //Putting image in center of page.
            m.Y = (int)((((System.Drawing.Printing.PrintDocument)(sndr)).DefaultPageSettings.PaperSize.Height - m.Height) / 2);
            m.X = (int)((((System.Drawing.Printing.PrintDocument)(sndr)).DefaultPageSettings.PaperSize.Width - m.Width) / 2);
            args.Graphics.DrawImage(i, m);
        ;
        pd.Print();
    
    catch (Exception ex)
    
        log.ErrorFormat("Error : 0\n By : 1-2", ex.ToString(), this.GetType(), MethodBase.GetCurrentMethod().Name);
    
    finally
    
        logMessage.AppendLine(string.Format(CultureInfo.InvariantCulture, "-------------------[ END  - 0 - 1 -------------------]", MethodBase.GetCurrentMethod().Name, DateTime.Now.ToShortDateString()));
        log.Info(logMessage.ToString());
    

【讨论】:

以上代码测试我自己并在我的 wpf kisok 应用程序中正常工作。 可能是最好的答案;尽管应该删除日志消息内容,因为这依赖于不存在的其他代码。【参考方案6】:

同意 TonyM 和 BBoy - 这是原始 4*6 打印标签的正确答案。 (args.PageBounds)。这对我打印 Endicia API 服务运输标签很有用。

private void SubmitResponseToPrinter(ILabelRequestResponse response)
    
        PrintDocument pd = new PrintDocument();
        pd.PrintPage += (sender, args) =>
        
            Image i = Image.FromFile(response.Labels[0].FullPathFileName.Trim());
            args.Graphics.DrawImage(i, args.PageBounds);
        ;
        pd.Print();
    

【讨论】:

PageBounds 为我工作,MarginBounds 打印得太小了。谢谢!【参考方案7】:

所有这些答案都有问题,那就是总是将图像拉伸到页面大小并在尝试此操作时截断一些内容。 找到更简单的方法。 我自己的解决方案只有拉伸(这是正确的词吗?)如果图像太大,可以使用多个副本和页面方向。

                PrintDialog dlg = new PrintDialog();

            if (dlg.ShowDialog() == true)
            
                BitmapImage bmi = new BitmapImage(new Uri(strPath));

                Image img = new Image();
                img.Source = bmi;

                if (bmi.PixelWidth < dlg.PrintableAreaWidth ||
                           bmi.PixelHeight < dlg.PrintableAreaHeight)
                
                    img.Stretch = Stretch.None;
                    img.Width = bmi.PixelWidth;
                    img.Height = bmi.PixelHeight;
                


                if (dlg.PrintTicket.PageBorderless == PageBorderless.Borderless)
                
                    img.Margin = new Thickness(0);
                
                else
                
                    img.Margin = new Thickness(48);
                
                img.VerticalAlignment = VerticalAlignment.Top;
                img.HorizontalAlignment = HorizontalAlignment.Left;

                for (int i = 0; i < dlg.PrintTicket.CopyCount; i++)
                
                    dlg.PrintVisual(img, "Print a Image");
                
            

【讨论】:

您可以在答案中包含代码而不是链接到它吗?

以上是关于使用 PrintDocument 打印图像。如何调整图像以适合纸张尺寸的主要内容,如果未能解决你的问题,请参考以下文章

C# printDocument 直接打印Word文档

如何使用 PrintDocument 在热敏打印机上打印文本文件?

C# - 如何使用 PrintDocument 以编程方式打印现有 PDF 文件

printdocument 添加空白页

winform使用PrintDocument控件打印

使用 printdocument 打印多页