在单独的线程中打开表单,并将其保存在应用程序中的其他窗口之上

时间:2018-02-02 13:39:36

标签: c# multithreading winforms

关于这个问题的另一个问题。相信我已经彻底调查过,但仍然没有找到适合我应用的解决方案。

简介: 我的应用程序由一个主窗体和几个窗体组成,在需要时显示为模态。 然后我有一个"屏幕转储"表单,这是一个带按钮的小表单。按下此按钮后,将对屏幕进行屏幕转储。

通过按主窗体上的相应按钮显示以上所有表格。

我想要的是什么: 显示时,屏幕转储表单应始终位于我的应用程序的所有其他窗口之上(也是使用ShowModal()显示的窗口)。如果这自动意味着在所有其他程序之上也是可以接受的。

我尝试了什么: 我很确定我必须在一个单独的线程中打开表单,以便即使其他表单以模态显示也能保持可操作性。 我尝试过如下:

private void btnScreenDump_MouseDown(object sender, MouseEventArgs e)
        {
            Thread thread = new Thread(ThreadProc);
            thread.SetApartmentState(ApartmentState.STA);
            thread.Start();
        }

private void ThreadProc()
        {
            using (FormScreenDump frmScreenDump1 = new FormScreenDump())
            {
                frmScreenDump1.TopMost = true;                  
                Application.Run(frmScreenDump1);
            }                
        }

问题/疑问是什么? 问题1: 表格frmScreenDump1根本不是最顶层的。每当在我的应用程序中单击任何其他表单时,表单frmScreenDump1就会落后于应用程序。 当frmScreenDump1.TopMost = true时,为什么表单不是最顶层的?,为了得到这种行为我必须改变什么?

问题2: 我希望表单frmScreenDump1在主窗体关闭时自动关闭。当这个表单在一个单独的线程上运行时,我该怎么做呢?

非常感谢任何帮助!

2 个答案:

答案 0 :(得分:3)

您不应该在其他线程中打开表单。所有与UI相关的代码(和对象) 必须 在UI线程上,否则可能会发生意外情况。这可能就是为什么你的表单不是最顶层的,即使你已经设置它。

如果要在激活此表单时将其他表单显示为模态,则不会将其他表单显示为模态。相反,每当新的表单打开/关闭时,它都会更改父/所有者表单的Enabled属性。

或者,将表单放在单独的应用程序中,然后从主应用程序中将其作为新进程启动。

答案 1 :(得分:-1)

根据其他TopMost相关问题的用户,

Form.TopMost正在为应用程序内的所有表单工作,但是你有两个应用程序[哪个错误,我误读了]。

因此,如果将表单作为对话框打开,那么您正在构建一个截屏函数。这就是为什么线程和新表单的额外应用程序。我有一次相同的要求,我通过让我的屏幕截图功能没有对它自己的点击事件作出反应来解决它,而是我使用鼠标钩来跟踪用户点击按钮所在位置的时间。警告:在VS调试模式下启动应用程序时,鼠标挂钩会导致严重滞后。