在扩展桌面上克隆表单

本文关键字:表单 扩展 桌面 | 更新日期: 2023-09-27 18:07:40

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

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

这需要一种情况,桌面有时是克隆的,其他时间是扩展的。不幸的是,这个解决方案对我来说似乎是不可取的,因为当你在桌面模式之间切换时,在视觉上发生了什么(屏幕变黑,窗口临时重新定位)——这基本上不是一个干净的过渡。这就是为什么我在寻找替代方案。

显然,仅克隆的解决方案是行不通的,所以只能使用扩展模式。

扩展模式很容易让我在监视器A和B上显示两种不同的形式,但我能做些什么,我想让两个监视器显示相同的东西?是否有一种方法可以让我显示c# System.Windows.Forms.Form的"副本"或"克隆",而原始的是打开的,这反映了相同的信息?

这个问题有没有别的解决办法是我忽略了的?或者是"使用DisplaySwitch.exe在显示模式之间切换"方法尽可能好?

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

在扩展桌面上克隆表单

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

现在我有更多的时间来详细说明我的评论。

与其试图将表单A克隆到表单B,不如在两者之间建立某种通信层,这样表单A就不关心它在与什么通信,也不关心显示的数据是相同的还是完全不同的。

要做到这一点,最简单的方法是将中介连接到表单a上的事件,当这些事件被触发时,将必要的数据发送到表单B以呈现它。

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

最优解很可能介于两者之间。

根据你的需要,也就是它必须刷新的频率等,你总是可以选择创建一个表单的位图,并在第二个表单中显示该位图。

我个人认为这有点像hack,使用像@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;
    }
}