开发者

"Wait Please" form hides main form

开发者 https://www.devze.com 2022-12-19 10:28 出处:网络
I have some long processes in my app, so I\'ve created a WAIT PLEASE form and I call on another thread like this:

I have some long processes in my app, so I've created a WAIT PLEASE form and I call on another thread like this:

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

And to close the form I use:

public void HideWait()
    {
        continueWait = false;
    }

It works fine, but I have a problem, when the wait form is shown, the main form losses the focus and any othe开发者_如何学Cr application running (Excel, Word, etc) at the same time goes to the top and my app goes to the back of all applications. I tried to use Activate() and Focus() but only the frame on the taskbar activates, but the app remains on the back of all applications.

Any light on this?

Thanks in advance


I can't reproduce other apps going to top but, related to Fredrik's suggestion to drop the while loop, this works for me:

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

EDIT:

To avoid the main form losing focus:

[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();
            }
        });
    }
}


Your code snippet doesn't repro the problem for me. What really matters is what is going on with the main form. What you see happening is not that unusual. When your wait form closes, Windows goes hunting for another window in your app to give the focus to. If it cannot find one, it will pick another window from another process and bring it to the foreground. In effect, your main form will disappear behind that window.

This is guaranteed to happen when your main form is disabled, perhaps you set its Enabled property to false? I imagine it can also happen when your main form is still unresponsive to Windows messages, that part is murky.

Avoid these kind of problems (and the incorrect threading apartment you use for the wait form) by executing the time consuming code on a background thread instead of the UI thread. BackgroundWorker was designed to make that easy.


Did you try using the overload of Show which accepts an owner window, and pass a null reference to it? I have experienced similar issues in the past which have been solved that way:

espera.Show(null);

There seem to be some difference in the behavior of calling Show() (which is implemented in the type Control and that simply sets Visible = true, which in turn triggers code in the type Form in this case), and calling Show(owner).


I hope I understand your problem correctly. So you want to set the WaitForm always on top? If so, have you set the

espera.TopMost = true;

property?


I think you want a modal form, try

espera.ShowDialog();

OTOH i don't really understand what you want so i might be wrong.

0

精彩评论

暂无评论...
验证码 换一张
取 消

关注公众号