在扩展桌面上克隆表单

发布于 2024-12-03 12:20:58 字数 609 浏览 0 评论 0原文

这是我的情况(很抱歉啰嗦,但我发现很难简洁地描述这一点):

我们有一个 C# 应用程序(我们开发的),在具有两个监视器的系统上运行。然而,每个显示器都面向不同的用户。也就是说,具有控制权的用户 1 只能看到监视器 A,而具有“只读”位置的用户 2 只能看到监视器 B。到目前为止,我们一直在使用克隆显示器,以便 A 和 B 显示相同的信息。然而,希望能够在工作流中的特定实例向用户 1 和 2 显示不同的内容。

这就需要一种桌面有时被克隆、有时被扩展的情况。不幸的是,这个解决方案对我来说似乎并不理想,因为当您在桌面模式之间切换时视觉上会发生什么(屏幕变黑,窗口临时重新定位) - 这基本上不是一个干净的过渡。这就是我正在探索替代方案的原因。

显然,仅克隆的解决方案不起作用,因此需要扩展模式。

扩展模式允许我轻松地在显示器 A 和 B 上显示两种不同的形式,但是当我希望两个显示器显示相同的内容时我该怎么办?有没有办法让我在原始文件打开时显示 C# System.Windows.Forms.Form 的“副本”或“克隆”,反映相同的信息?

我忽略的这个问题还有其他解决方案吗?或者“使用 DisplaySwitch.exe 在显示模式之间切换”方法是否足够好?

(假设我们完全控制平台 - 硬件和软件)

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)

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

浪荡不羁 2024-12-10 12:20:58

考虑使用远程访问程序,例如 TightVNC。它可以运行在环回模式下,在客户端程序中显示主监控图像。然后您必须移动到第二台显示器才能获得克隆。与您最小化和恢复的自定义表单一起。

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.

生来就爱笑 2024-12-10 12:20:58

现在我有更多时间来详细阐述我的评论。

不要试图将表单 A 克隆到表单 B 中,而是在两者之间建立某种通信层,这样表单 A 就不会关心它正在与什么进行通信,也不会关心显示的数据是否相同或完全不同。

最简单的方法是将调解器挂接到表单 A 上的事件中,当这些事件被触发时,将必要的数据发送到表单 B 来呈现它。

在数据相同的情况下,这可能就像每次表单 A 更新时拍摄快照并将其呈现在表单 B 上一样简单(很像 harvardflu 的答案,但将该逻辑放在中介中),或者您可以采取它至于在另一个线程中运行应用程序进程并通过不同的中介同时更新表单 A 和表单 B(尽管,正如您所建议的,这可能是一个重大的重新设计)。

最佳解决方案可能介于两者之间。

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.

吃不饱 2024-12-10 12:20:58

根据您的需要,即必须刷新的频率等,始终可以选择创建表单的位图,并以第二种形式显示该位图。

我个人认为这是一种黑客行为,并且使用 @pdr 提出的中介模式肯定是一种更干净的方法。但如果您需要快速(且肮脏)的解决方案,这可能会完成工作。

发布的代码具有原型质量,应进行相应处理。

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;
    }
}

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;
    }
}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文