在 .Net 中打印预先创建的图形对象

Printing a pre-created graphics object in .Net

我在使用 C# 和 .Net 进行打印时遇到了一点问题。我已经让它与 System.Drawing.Printing 事件中的常规打印事件一起工作,效果很好,但现在,我想用不同的方式来做。

在我直接从 winform 程序打印之前,我会在包含所有信息的 winform 元素上声明一个 printdocument,然后逐步将其重新绘制到图形对象上以便打印它。由于这是在主代码中发生的,而且不是很灵活,我决定为此编写一个库。该库采用打印机名称,获取打印机的最大纸张宽度和纸张高度,用它创建一个图形对象,将其全部涂成白色,然后执行与之前描述的相同的步骤,逐步将整个信息绘制到它上面。

我写了一个函数,returns那个图形对象,现在我想把这个预先构建的图形对象传递给一个打印文档,以便打印它。然而,这是行不通的。我查看了 Microsoft 文档并发现 this little morsel from Microsoft,这对我根本没有帮助。进一步查看堆栈溢出也无助于我的事业,因为我发现没有人 运行 遇到过类似的问题,或者尝试过我正在尝试做的事情。

代码如下: 该函数触发打印机事件。它包含一些来自我编写的库的打印机特定功能,这些功能似乎工作正常。消息框只是用来显示纸张的宽度和高度是否被正确抓取。

private void btnPrinter_Click(object sender, EventArgs e)
        {
           //Test functions to return paper width and height
            MessageBox.Show(GebeDrucker.returnwidth().ToString());
            MessageBox.Show(GebeDrucker.returnheight().ToString());
            //Setting text alignment
            GebeDrucker.F_Alignment(C_BillPrint.Alignments.CENTER);
            GebeDrucker.F_DrawHeading("Company name placeholder", new Font("Arial", 16));
            GebeDrucker.F_DrawLogo(new Bitmap(Bitmap.FromFile(@"C:/Imagelocation/Image.png")));
            GebeDrucker.F_Drawtable(new Font("Roboto condensed", 10));
            GebeDrucker.F_QR("Hier ist min code");
            PaperSize Custom = new PaperSize("Printi", panel1.Width, Convert.ToInt32(Math.Round(panel1.Height*1.01)));
            //printDocument1.DefaultPageSettings.PaperSize = Custom;
            PrintPreviewDialog pb = new PrintPreviewDialog();
            pb.Document = printDocument1;
            pb.ShowDialog();
            printDocument1.Print();
            GVProduct.Rows.Clear();
            GVReceipt.Rows.Clear();
            Calc();
            //panel1.Height = 490; 
        }

以下函数只是 returns Graphics 对象:

/// <summary>
/// Function to return the Graphics object Bill.
/// </summary>
/// <returns>The Bill, represented as a Graphic.</returns>
public Graphics F_ReturnGraphics()
{
    return this.bill;
}

在这里,我尝试在触发打印时用我自己的图形对象覆盖事件中的 e.Graphics。注释掉的是以前的做法,一步步借鉴,效果不错,就是不太灵活。

public void printdoc1_PrintPage(object sender, PrintPageEventArgs e)
{
    /*
    string company = "Company Placeholder Text";
    string Header = " Artikel                    Anzahl             Gesamt";
    string Seperator = "____________________________________";
    string Total = "Gesamt:";


    Font ComCom = new Font("Roboto condensed", 16);
    Font Heading = new Font("Roboto condensed", 10);

    SolidBrush drawBrush = new SolidBrush(Color.Black);

    float C_X = 5.0F;
    float C_Y = 5.0F;
    e.Graphics.DrawString(company, ComCom, drawBrush, C_X, C_Y);

    float L_X = 15.0F;
    float L_Y = 35.0F;

    Size Loco = new Size(180, pCompanyImage.Image.Height-10);

    Bitmap Logo = new Bitmap(pCompanyImage.Image, Loco);
    e.Graphics.DrawImage(Logo, L_X, L_Y);

    float DH_X = 0.0F;
    float DH_Y = 140.0F;

    e.Graphics.DrawString(Header, Heading, drawBrush, DH_X, DH_Y);

    float IT_X = 0.0F;
    float IT_Y = 165.0F;
    float IM_X = 114.0F;
    float IR_X = 166.0F;

    for (int i = 0; i < GVReceipt.RowCount - 1; i++)
    {
        e.Graphics.DrawString(" "+GVReceipt.Rows[i].Cells[0].Value.ToString(), Heading, drawBrush, IT_X, IT_Y);
        e.Graphics.DrawString(GVReceipt.Rows[i].Cells[1].Value.ToString() + "x", Heading, drawBrush, IM_X, IT_Y);
        e.Graphics.DrawString(GVReceipt.Rows[i].Cells[2].Value.ToString() + "€", Heading, drawBrush, IR_X, IT_Y);
        IT_Y = IT_Y + (GVReceipt.RowCount - 2) * GVReceipt.Rows[0].Height;
    }

    float S_X = 6.0F;
    float S_Y = IT_Y + 10.0F;
    e.Graphics.DrawString(Seperator, Heading, drawBrush, S_X, S_Y);

    float T_X = 15.0F;
    float T_Y = S_Y + 20.0F;

    float Su_X = 120.0F;

    e.Graphics.DrawString(Total, ComCom, drawBrush, T_X, T_Y);
    e.Graphics.DrawString(Calc() + "€", ComCom, drawBrush, Su_X, T_Y);

    float SS_Y = T_Y + 20.0F;
    e.Graphics.DrawString(Seperator, Heading, drawBrush, S_X, SS_Y);
    */
    Graphics benis = e.Graphics;
    benis = GebeDrucker.F_ReturnGraphics();
}

尝试直接覆盖 e.Graphics 无效,因为它受到保护。我也不想将我的图形作为位图传递,因为那样我会失去很多分辨率,并且文档打印出来会很模糊。我不知道是否可以从 class 库打印,我想是不可能的,因为这需要 System.Forms 库,我在这里尽量避免,所以我在想也许可以写一个自定义打印事件它需要一个图形对象并尝试将其打印出来,但我不知道如何构造它。也许我的思维方式完全错误,这根本不起作用或需要解决方法。这就是我在这里寻求帮助的原因,我们将不胜感激。

由于Graphics实际上并不包含图像信息。它只是一个用于在现有 canvas(例如 Bitmap)上绘制图形的工具。

一个解决方案您可以简单地将 Graphics 传递给 F_ReturnGraphics:

GebeDrucker.F_ReturnGraphics(e.Graphics);

然后该方法将如下所示:

public void F_ReturnGraphics(Graphics gfx)
{
    gfx.Clear(Color.White); // etc
}

如果您愿意,您也可以再次 return Graphics 对象:

public Graphics F_ReturnGraphics(Graphics gfx)
{
    gfx.Clear(Color.White); // etc
    return gfx;
}