【问题标题】:How to print a Windows Form without showing/displaying it如何在不显示/显示的情况下打印 Windows 窗体
【发布时间】:2016-03-13 01:56:11
【问题描述】:

我正在尝试自动打印一系列 Windows 窗体。我不需要给他们看。我在互联网上找到的代码示例仅在我使用show() 显示表单时才有效!我需要用数据初始化表单并将其发送到打印机这是我正在使用的代码:

public partial class Form2_withoutShow : Form{

     PrintDocument PrintDoc;

     Bitmap memImage;

     public Form2_withoutShow (Data data)
     {

        InitializeComponent();

        /*
           Initialize Data (texboxes, charts ect.) here
       */

        this.PrintDoc = new PrintDocument();
        this.PrintDoc.PrintPage += PrintDoc_PrintPage;
        this.PrintDoc.DefaultPageSettings.Landscape = true;
     }


     public void Print()
     {
        this.PrintDoc.Print();
     }

     void PrintDoc_PrintPage(object sender, PrintPageEventArgs e)
     {

        int x = SystemInformation.WorkingArea.X;
        int y = SystemInformation.WorkingArea.Y;
        int width = this.Width;
        int height = this.Height; 

        Rectangle bounds = new Rectangle(x, y, width, height);

        Bitmap img = new Bitmap(width, height); 

        this.DrawToBitmap(img, bounds);
        Point p = new Point(10, 10);

        e.Graphics.DrawImage(img, p);
     }

     private void Form2_withoutShow_Load(object sender, EventArgs e)
     {
         // remove TITLEBar
         this.ControlBox = false;
         this.Text = String.Empty;
     }
}

我在for循环中从另一个类调用Print()方法,并通过构造函数传递要初始化的数据。

MSDN example 捕获屏幕上应显示表单的部分。这对我不起作用。如果我不调用show(),我现在使用的方法只会产生空窗口的打印。如何在不调用show() 方法的情况下将数据放入表单?像在显示窗口时最小化窗口这样的方法也不起作用,因为这也是打印结果:最小化的窗口。

【问题讨论】:

  • 你解决了吗?
  • 不,我不是,我的目标是打印协议,我认为这可以使用填充数据的 gui 来完成。我最终使用 MigraDocs 创建了一个 PDF 并将其发送到打印机......
  • @ErAcube 有一个答案。你检查了吗?
  • 是的,感谢您的指出。我刚刚注意到了。

标签: c# .net winforms data-binding printing


【解决方案1】:

在显示表单之前,表单及其控件不处于Created 状态。要强制创建表单及其控件,只需调用表单的内部 CreateControl(bool fIgnoreVisible) 方法即可:

var f = new Form1();
var createControl = f.GetType().GetMethod("CreateControl",
                BindingFlags.Instance | BindingFlags.NonPublic);
createControl.Invoke(f, new object[] { true });

var bm = new Bitmap(f.Width, f.Height);
f.DrawToBitmap(bm, new Rectangle(0, 0, bm.Width, bm.Height));
bm.Save(@"d:\bm.bmp");

同时删除表单Load 事件处理程序中的代码,并将它们放入表单的构造函数中。

注意

该问题还有其他解决方法:

  • 例如,您可以在屏幕边界之外的位置显示表单,然后再次隐藏它。将Location 设置为(-32000, -32000),将StartPosition 设置为Manual,然后将ShowHide 设置为绘制位图之前的表单。
  • 或者作为另一个例子,您可以在将Opacity设置为0,然后将ShowHide设置为位图之前的表单。

【讨论】:

  • 一般来说,使用RDLCreports之类的报告工具可以更好地满足此类要求;就像您使用 PDF 工具所做的一样,但报告更友好。无论如何,出于学习目的或应该通过打印表格来完成任务的情况,我与一些工作选项分享了这个答案。首选第一个选项。
  • 非常感谢您的详尽回答。您能解释一下为什么 createControl 方法必须以 invoke 开头吗?如果我只是打电话给this.CreateControl() 就不起作用?
  • 不客气 :) 您需要的重载是CreateControl(bool fIgnoreVisible),它是内部的,所以即使您想在该表单的构造函数中调用它,也不能。因此,使用该方法的唯一方法是使用 Reflection 调用它
  • 我做了一个打印方法并在那里调用它。它与您的反射方法一起使用。我会在重载的情况下尝试一下。
  • 您不能在没有反射的情况下使用该重载。如答案中所述,过载是内部的。你这样做的方式(如答案)是正确的。您无需更改任何内容。
猜你喜欢
  • 2011-01-04
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-08-24
相关资源
最近更新 更多