Duplicate Windows form on multiple screen in c#
Asked Answered
T

2

6

I am developing a feedback system for an automotive company. On the billing desk, there is a dual monitor setup: one for a billing person and one for a customer who's giving feedback. My need is to duplicate a Windows form on both screens, as mirror images, So that the billing person can see what feedback the customer is giving.

I am using the code below for display on the secondary screen:

 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();

However, it will not mirror the form on the primary screen. I had also referred to the duplicate window question, but it will create different instances for the same form, which will not mirror the Windows form. How can I mirror it on both screens?

Transpose answered 18/12, 2014 at 7:19 Comment(5)
Why negative vote? It seems to be a real question.Magneto
How do you expect the secondary form to mirror the original one? In your code, you are just opening a form (or so it seems, if f is a Form), but there's no code there that would mirror the original one at all. The Color c = Color.Red; line baffles me thoughKeare
f is object of Form. I am asking how can i mirror original one, in above code i had shown how i am opening form on secondary screen.Transpose
The need for mirroring is a very strange one and pretty unlikely to be appropriate. But you'll need to write a lot more code. Iterate the Controls and change the Location property. And every control needs to notify the other form when the customer modifies its content. Doing this in hardware with the second monitor simply displaying the same content as the first is a very trivial solution.Venerable
@HansPassant if there's no need for the mirrored form to be editable (the question says it needs to be seen only), it's trivial to do it by mirroring a bitmap also, as I've shown in my sample projectKeare
K
5

One possible way to do it would be to capture the form that is inputting the data to a image on a timer (use a reasonable delay so that it's "almost realtime") and use it on a PictureBox on the secondary form. To capture the form to a image you do:

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

Then you assign bmp as the image to the PictureBox on the other form.

I've made a quick sample project and uploaded it here: https://www.dropbox.com/s/pjuk3zvpbglhodb/SOTestMirror.zip?dl=0

Lacks opening the form on the secondary screen and styling, but shows a possible way to do it

The result is: Result

For the record: I have no clue why when DrawToBitmap is called on a form it copies to the bitmap using a Windows 7 chrome instead of the Windows 8 one... that's interesting, to say the least (and I'd say a bug). That's running on Win 8.1. (Since I haven't seen this mentioned anywhere, I've opened a bug on Connect: https://connect.microsoft.com/VisualStudio/feedback/details/1059444/in-windows-8-drawtobitmap-on-a-form-draws-the-windows-7-chrome)

Keare answered 18/12, 2014 at 8:26 Comment(2)
is there any way by which i can capture secondary screen instead of form.Transpose
Yes, see this answer: #363486 to capture the screen to a bitmapKeare
M
0

Here are simple code that take a screenshot from the extended screen and display in the picture box. you can save to image file as well.

Add this code in timer to refresh screen at some interval.

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();

you also can get the screenshot of primary screen.

Modernism answered 30/12, 2014 at 13:24 Comment(1)
That code is available in this other answer which I commented to the OP: #363486 (and should be a comment since it's not answering the original question). Also, the GC.Collect() at the bottom is completely unneeded (at least for the purpose of what the OP is trying to achieve), try to avoid recommending it unless there's a specific need for it. Check blogs.msdn.com/b/ricom/archive/2004/11/29/271829.aspxKeare

© 2022 - 2024 — McMap. All rights reserved.