“请等待”表格隐藏主表格

时间:2010-02-09 13:49:06

标签: c# winforms multithreading

我的应用程序中有一些很长的进程,所以我创建了一个WAIT PLEASE表单,然后调用另一个这样的线程:

public void ShowWait()
    {
        continueWait = true;
        ThreadPool.QueueUserWorkItem((x) =>
            {
                using (frmWait espera = new frmWait())
                {
                    espera.ShowInTaskbar = false;
                    espera.Show();
                    while (continueWait)
                        Application.DoEvents();
                    espera.Close();
                }
            });
    }

关闭我使用的表格:

public void HideWait()
    {
        continueWait = false;
    }

它工作正常,但我有一个问题,当显示等待表单时,主窗体失去焦点,同时运行的任何其他应用程序(Excel,Word等)到顶部,我的应用程序去在所有应用程序的后面。我尝试使用Activate()和Focus(),但只激活任务栏上的框架,但应用程序仍保留在所有应用程序的背面。

对此有何看法?

提前致谢

5 个答案:

答案 0 :(得分:1)

您的代码段不会为我重现问题。真正重要的是主要表格正在发生什么。你看到的情况并不那么罕见。当您的等待表单关闭时,Windows会在您的应用中寻找另一个窗口以获得焦点。如果找不到,它将从另一个进程中选择另一个窗口并将其带到前台。实际上,您的主窗体将在该窗口后面消失。

当您的主窗体被禁用时,保证会发生这种情况,也许您将其Enabled属性设置为false?我想这也可能发生在你的主要表单仍然没有响应Windows消息时,那部分是黑暗的。

通过在后台线程而不是UI线程上执行耗时的代码来避免这些问题(以及用于等待表单的错误的线程单元)。 BackgroundWorker旨在简化这一过程。

答案 1 :(得分:1)

我无法复制其他应用程序,但是,与Fredrik建议放弃while循环有关,这对我有用:

AutoResetEvent processing = new AutoResetEvent(false);

private void HideWait()
{
    processing.Set();
}

private void ShowWait()
{           
    ThreadPool.QueueUserWorkItem((x) =>
    {
        using (frmWait espera = new frmWait())
        {
            espera.ShowInTaskbar = false;
            espera.Show();
            processing.WaitOne();
            espera.Close();
        }
    });
}

修改

避免主要形式失去焦点:

[DllImport("user32.dll")]
static extern bool ShowWindow(IntPtr hWnd, int nCmdShow);

static readonly int SW_SHOWNOACTIVATE = 4;

AutoResetEvent processing = new AutoResetEvent(false);

private void HideWait()
{
    processing.Set();
}

private void ShowWait()
{
    ThreadPool.QueueUserWorkItem(c =>
    {
        using (frmWait espera = new frmWait())
        {
            espera.ShowInTaskbar = false;
            ShowWindow(espera.Handle, SW_SHOWNOACTIVATE);
            processing.WaitOne();
            }
        });
    }
}

答案 2 :(得分:1)

您是否尝试使用接受所有者窗口的Show的重载,并将空引用传递给它?我过去经历过类似的问题,这些问题已经解决了:

espera.Show(null);

调用Show()的行为似乎有所不同(在Control类型中实现,只是设置Visible = true,而Form又会触发Show(owner)中的代码在这种情况下{1}},并调用{{1}}。

答案 3 :(得分:0)

我希望我能正确理解你的问题。所以你想将WaitForm设置在最顶层?如果是这样,你设置

espera.TopMost = true;

属性?

答案 4 :(得分:0)

我认为你想要一个模态形式,试试

espera.ShowDialog();

OTOH我真的不明白你想要什么,所以我可能错了。