Cloning a form on an extended desktop
Asked Answered
W

3

6

Here is my situation (sorry for being long-winded, but I'm finding it difficult to describe this concisely):

We have a C# application (that we develop) that runs on a system with two monitors. However, each monitor faces a different user. That is, user 1, who has control, only sees monitor A and user 2, who has a 'read-only' position only sees monitor B. Up until now, we have been using a cloned display, such that A and B display the same information. However, it is desirable to be able to display different things to users 1 and 2 at specific instances in the workflow.

This calls for a situation where the desktop is sometimes Cloned and other times is Extended. Unfortunately, this solution seems undesirable to me because of what happens visually when you switch between desktop modes (screen goes black, temporary repositioning of windows) - it's basically not a clean transition. This is why I'm exploring alternatives.

Obviously, a Cloned-only solution won't work, so that leaves Extended mode.

Extended mode easily allows me to display two different forms on Monitors A and B, but what can I do for the times I want both monitors showing the same thing? Is there a way for me to show a "copy" or "clone" of a C# System.Windows.Forms.Form while the original is open, that reflects the same information?

Is there another solution to this problem that I'm overlooking? Or is the "switch between display modes using DisplaySwitch.exe" approach as good as it gets?

(assume we have complete control over the platform - hardware and software)

Writein answered 6/9, 2011 at 20:51 Comment(2)
What's wrong with using the exact same system that displays different information but displaying the same information? (probably with good use of the Mediator pattern)Rutherfurd
@Rutherfurd I'm not sure, but I think you're suggesting the approach where, for the situations that the same information needs to be displayed on both A and B, I create two instances of Form X and display one on each monitor? The mediator would then facilitate that both instances, say X1 and X2, of the form stay up-to-date, I suppose. I suppose the main reason I'm trying to avoid this approach is that it implies a fairly significant re-factoring, but it may be the only alternative.Writein
V
2

Consider using a remote access program like TightVNC. It can operate in loopback mode, displaying the main monitor image in the client program. Which you then have to move to the second monitor to get the clone. Together with the custom form that you minimize and restore.

Vala answered 6/9, 2011 at 22:5 Comment(1)
This is an interesting option. I would have to investigate how TightVNC looks on an extended desktop (I need it to be seamless, e.g. no border so that I can "full screen" it on the secondary monitor) and also whether I could use it without violating the GPL.Writein
R
2

To elaborate on my comment now that I have more time.

Rather than trying to clone Form A into Form B, set up some kind of communication layer between the two, such that Form A doesn't care what it's communicating with or whether the data displayed is the same or completely different.

The easiest way to do this is to hook a mediator into events on Form A and, when those events are triggered, send the necessary data to Form B to render it.

In the case where the data is the same, this could be as simple as taking a snapshot every time Form A updates and rendering it on Form B (much like harvardflu's answer, but putting that logic in a mediator), or you could take it as far as running the application process in another thread and updating Form A and Form B simultaneously through different mediators (though, as you suggest, this will probably be a major reengineering).

It is likely that the optimal solution is somewhere in between.

Rutherfurd answered 6/9, 2011 at 22:8 Comment(1)
Thanks for elaborating. I do feel that the "best" solution lies somewhere in this space. How much re-factoring it takes is something I need to look more closely at. Time to prototype, I guess :)Writein
K
0

Depending on your needs, i.e. how often it must refresh etc, there's always the option of creating a bitmap of your form, and displaying that bitmap in a 2nd form.

I'd personally regard this as a bit of a hack, and using the mediator-pattern like @pdr proposes is certainly a cleaner approach. But this might get the job done if you're in need of a quick (and dirty) solution.

The posted code is of prototype quality and should be treated accordingly.

public partial class MainForm : Form
{
    private bool m_Running;

    public MainForm()
    {
        InitializeComponent();

        DuplicateForm f2 = new DuplicateForm(this.Text);
        f2.Show();

        m_Running = true;
        Thread t = new Thread(new ThreadStart(() =>
            {
                while (m_Running)
                {
                    this.Invoke(new MethodInvoker(() =>
                    {
                      Bitmap bm = new Bitmap(Width, Height);
                      // pnl is a Panel with Dock=Fill
                      pnl.DrawToBitmap(bm, new Rectangle(0, 0, Width, Height));
                      f2.SetImage(this, bm);
                     }));

                    Thread.Sleep(500); // or use a timer
                }
            }));

        t.Start();
    }

    private void Form1_FormClosing(object sender, FormClosingEventArgs e)
    {
        m_Running = false;
    }
}

public partial class DuplicateForm : Form
{
    public DuplicateForm(string title)
    {
        InitializeComponent();
        Text = title + " [copy]";
    }

    public void SetImage(Form source, Image img)
    {
        this.Size = source.Size;
        // Picturebox is a PictureBox control with Dock=Fill
        pictureBox1.Image = img;
    }
}
Kaplan answered 6/9, 2011 at 21:43 Comment(1)
The application includes live video, so I while I appreciate the suggestion for a quick hack (in a way, I was asking for one), this likely wouldn't work for me.Writein

© 2022 - 2024 — McMap. All rights reserved.