在C#中将Windows窗体复制到多个屏幕上

4
我正在为一家汽车公司开发反馈系统。在收款台上,有一个双显示器设置:一个用于收款人员,一个用于给出反馈的客户。我的需求是在两个屏幕上复制一个Windows表单,作为镜像图像,以便收款人员可以看到客户正在提供的反馈。
我正在使用以下代码在辅助屏幕上显示:
 Screen[] sc;
        Form f = new Form();
        sc = Screen.AllScreens;
        f.FormBorderStyle = FormBorderStyle.None;
        f.Left = sc[1].Bounds.Left;
        f.Top = sc[1].Bounds.Top;
        f.Height = sc[1].Bounds.Height;
        f.Width = sc[1].Bounds.Width;
        f.StartPosition = FormStartPosition.Manual;
        f.Show();

但是,它不会在主屏幕上镜像表单。我也参考了复制窗口的问题,但它会为同一表单创建不同的实例,这不会镜像 Windows 表单。如何在两个屏幕上镜像它?


2
为什么要负评?这似乎是一个真正的问题。 - Oğuz Sezer
你如何期望次要表单镜像原始表单?在你的代码中,你只是打开一个表单(如果“f”是一个表单的话),但是那里没有任何代码来镜像原始表单。然而,“Color c = Color.Red;”这行代码让我感到困惑。 - Jcl
f是Form对象。我想知道如何镜像原始的窗体,在上面的代码中,我展示了如何在第二个屏幕上打开窗体。 - Hot Cool Stud
镜像的需求非常奇怪,而且很少有适用的情况。但你需要编写更多的代码。迭代控件并更改位置属性。每个控件都需要在客户修改其内容时通知另一个表单。使用第二个显示器在硬件上简单地显示与第一个相同的内容是一种非常微不足道的解决方案。 - Hans Passant
@HansPassant 如果镜像表单不需要可编辑(问题中只需查看),那么通过镜像位图也很容易实现,就像我在示例项目中展示的那样。 - Jcl
2个回答

5

有一个可能的方法来实现这个功能,就是在定时器上捕获输入数据的表单,将其转化为图像,并在次级窗体上使用 PictureBox。要将表单捕获为图像,请执行以下操作:

Bitmap bmp = new Bitmap(form.Width, form.Height);
form.DrawToBitmap(bmp, new Rectangle(Point.Empty, bmp.Size));

然后将指定为其他窗体上的图像。
我制作了一个快速示例项目,上传到了这里:https://www.dropbox.com/s/pjuk3zvpbglhodb/SOTestMirror.zip?dl=0
缺少在第二屏幕上打开表单和样式,但显示了一种可能的方法
结果是:Result
记录一下:我不知道为什么当在一个窗体上调用时,它会使用Windows 7 chrome将其复制到位图中,而不是Windows 8中的Chrome。这至少很有趣(我会说是一个Bug)。这运行在Win 8.1上。(由于我没有在任何地方看到过这个问题,因此我在Connect上打开了一个Bug:https://connect.microsoft.com/VisualStudio/feedback/details/1059444/in-windows-8-drawtobitmap-on-a-form-draws-the-windows-7-chrome

有没有办法可以捕获次屏幕而不是窗体? - Hot Cool Stud
是的,可以参考这个答案:https://dev59.com/yXRC5IYBdhLWcg3wP-j4 来将屏幕捕捉为位图。 - Jcl

0

以下是简单的代码,可以从扩展屏幕中截取屏幕截图并显示在图片框中。 您也可以将其保存为图像文件。

将此代码添加到定时器中以在一定时间间隔内刷新屏幕。

private Bitmap bmpScreenshot;
bmpScreenshot = new Bitmap(Screen.AllScreens[1].Bounds.Width,
                                           Screen.AllScreens[1].Bounds.Height,
                                           PixelFormat.Format32bppArgb);

Graphics.FromImage(bmpScreenshot).CopyFromScreen(Screen.AllScreens[1].Bounds.X,
                                         Screen.AllScreens[1].Bounds.Y,
                                         0,
                                         0,
                                         Screen.AllScreens[1].Bounds.Size,
                                         CopyPixelOperation.SourceCopy);

pictureBox1.Image = bmpScreenshot;
pictureBox1.Refresh();
GC.Collect();

你也可以获取主屏幕的截图。


那段代码可以在我评论给原帖的另一个答案中找到:https://dev59.com/yXRC5IYBdhLWcg3wP-j4 (应该是一条评论,因为它并没有回答原问题)。此外,底部的 GC.Collect() 完全不必要(至少对于 OP 所尝试实现的目的而言),除非有特定需要,请避免推荐使用。请参阅 http://blogs.msdn.com/b/ricom/archive/2004/11/29/271829.aspx。 - Jcl

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接