SplashScreen.Close() 窃取 MainWindow 的焦点

发布于 2024-12-08 19:49:47 字数 138 浏览 0 评论 0原文

当 SplashScreen 关闭(手动或通过 AutoClose)时,它会在淡出动画期间窃取 MainWindow 的焦点。这会导致主窗口的标题从活动状态切换到非活动状态(灰色),然后再切换到活动状态。有什么技巧可以防止 SplashScreen 抢走焦点吗?

When the SplashScreen closes (either manually or by AutoClose), it steals the focus of the MainWindow during the fade-out animation. This results in the caption of the main window switching from active to inactive (grey) to active. Is there any trick to keep the SplashScreen from stealing focus?

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

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

发布评论

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

评论(2

安稳善良 2024-12-15 19:49:47

告诉 SplashScreen MainWindow 是它的父窗口。当子窗口失去焦点时,其父窗口将获得焦点。如果没有父窗口,则由窗口管理器决定。

splashScreen.Show(mainWindow);

编辑

我刚刚发现有一个 SplashScreen 类。看来您使用的是该类,而不仅仅是我假设的普通表单。

因此,我只是使用 SplashScreen 制作了一个简单的 WPF 应用程序,但对我来说,上述效果并未发生。主窗口没有失去焦点。

我建议您注释掉应用程序初始化代码的部分内容,直到闪烁停止。然后你就有了一个起点来进行更多研究为什么焦点会丢失。

EDIT2

在不知道你的代码的情况下,我尝试重现这种现象,这并不难。无论我尝试什么,焦点变化总是发生在主窗口已经显示并具有焦点时。

因此,我看到的最佳解决方案是在调用启动屏幕的 Close() 方法之后手动显示主窗口:

  1. 从 App.xaml 中删除 StartupUri

  2. 启动应用程序并初始化资源后显示 SplashScreen。经过一段(当前固定的)延迟后,关闭 SplashScreen 并显示主窗口:


public partial class App : Application
{
    const int FADEOUT_DELAY = 2000;

    SplashScreen splash = new SplashScreen("splash.jpg");

    protected override void OnStartup(StartupEventArgs e)
    {
        base.OnStartup(e);
        splash.Show(false, true);

        var worker = new BackgroundWorker();
        worker.DoWork += (sender, ea) =>
            {
                Thread.Sleep(1000);
                splash.Close(new TimeSpan(0, 0, 0, 0, FADEOUT_DELAY));
                // you could reduce the delay and show the main window with a nice transition
                Thread.Sleep(FADEOUT_DELAY); 
                Dispatcher.BeginInvoke(new Action(() => MainWindow.Show()));
            };

        worker.RunWorkerAsync();

        MainWindow = new MainWindow();

        // do more initialization
    }
}

Tell the SplashScreen that MainWindow is its parent window. When a child window loses focus, its parent gets the focus. If there is no parent, the window manager decides.

splashScreen.Show(mainWindow);

EDIT:

I just found out that there's a SplashScreen class. Looks like you use that class and not just a normal Form as I assumed.

So, I just made a simple WPF app with a SplashScreen and for me the mentioned effect didn't happen. The main window didn't lose focus.

I would suggest you to comment potions of your app's initalization code out until the flashing stops. Then you have a starting point for more research why the focus is lost.

EDIT2:

Without knowing your code I tried to reproduce the phenomenon and it wasn't too hard. Whatever I tried, the focus change always happened when the main window was already shown and had focus.

So the best solution I see is to manually show the main window after calling the splash screen's Close() method:

  1. Remove the StartupUri from App.xaml

  2. Show the SplashScreen after starting the app and initializing ressources. After a (currently fixed) delay close the SplashScreen and show the main window:


public partial class App : Application
{
    const int FADEOUT_DELAY = 2000;

    SplashScreen splash = new SplashScreen("splash.jpg");

    protected override void OnStartup(StartupEventArgs e)
    {
        base.OnStartup(e);
        splash.Show(false, true);

        var worker = new BackgroundWorker();
        worker.DoWork += (sender, ea) =>
            {
                Thread.Sleep(1000);
                splash.Close(new TimeSpan(0, 0, 0, 0, FADEOUT_DELAY));
                // you could reduce the delay and show the main window with a nice transition
                Thread.Sleep(FADEOUT_DELAY); 
                Dispatcher.BeginInvoke(new Action(() => MainWindow.Show()));
            };

        worker.RunWorkerAsync();

        MainWindow = new MainWindow();

        // do more initialization
    }
}
看海 2024-12-15 19:49:47

使用 ILSpy,我发现 SplashScreen.Close 方法在某个时刻调用 SetActiveWindow,导致 slpash 屏幕窗口在开始关闭时变为活动状态。 (至少在 .NET 4.0 中是这样。)我在调用 SplashScreen.Close 之后添加了对 MainWindow.Focus 的调用,这解决了问题。

否则,我只能看到主窗口如何仅在淡出动画发生期间处于非活动状态。此外,当主窗口加载时,我会显示一个模式对话框窗口,并且它保持活动状态。但是,当该对话框关闭时,主窗口将不再聚焦,而是最终进入 Visual Studio 窗口或启动我的应用程序的任何窗口。从上面插入 Focus 调用也有助于解决这种情况。

顺便说一句,这里有一篇很好的文章,解释了如何手动使用 SplashScreen 类而不是项目文件选项:http://tech.pro/tutorial/822/wpf-tutorial-using-splash-screens-in-sp1

这是我的应用程序中的一些代码:

在 App.xaml.cs 中:

/// <summary>
/// Application Entry Point.
/// </summary>
[STAThread]
public static void Main()
{
    splashScreen = new SplashScreen("Splashscreen.png");
    splashScreen.Show(false, true);
    Thread.Sleep(2000);   // For demonstration purposes only!

    App app = new App();
    app.InitializeComponent();
    app.Run();
}

在我的主窗口 ViewModel 的 Init 命令中(主窗口已经完全可见):

private void OnInitCommand()
{
    ConnectDatabase();

    App.SplashScreen.Close(TimeSpan.FromMilliseconds(500));
    MainWindow.Instance.Focus();   // This corrects the window focus

    SomeDialog dlg = new SomeDialog();
    dlg.Owner = MainWindow.Instance;
    if (dlg.ShowDialog() == true)
    {
        // Do something with it
    }
    // Now the main window is focused again
}

Using ILSpy, I found that the SplashScreen.Close method calls SetActiveWindow at some point, causing the slpash screen window to become active in the moment it starts closing. (At least in .NET 4.0.) I added a call to my MainWindow.Focus just after calling SplashScreen.Close, and that resolves the issue.

Otherwise, I could see how the main window was inactive only during the time that the fadeout animation took. Additionally, I show a modal dialog window when the main window has loaded, and this remains active. But when that dialog is closed, the main window wouldn't focus anymore and instead I'll end up in the Visual Studio window or whatever started my application. Inserting the Focus call from above also helps in this situation.

BTW, here's a good article that explained me how to use the SplashScreen class manually instead of the project file option: http://tech.pro/tutorial/822/wpf-tutorial-using-splash-screens-in-sp1

This is some code from my application:

In App.xaml.cs:

/// <summary>
/// Application Entry Point.
/// </summary>
[STAThread]
public static void Main()
{
    splashScreen = new SplashScreen("Splashscreen.png");
    splashScreen.Show(false, true);
    Thread.Sleep(2000);   // For demonstration purposes only!

    App app = new App();
    app.InitializeComponent();
    app.Run();
}

In my main window ViewModel's Init command (the main window is already completely visible):

private void OnInitCommand()
{
    ConnectDatabase();

    App.SplashScreen.Close(TimeSpan.FromMilliseconds(500));
    MainWindow.Instance.Focus();   // This corrects the window focus

    SomeDialog dlg = new SomeDialog();
    dlg.Owner = MainWindow.Instance;
    if (dlg.ShowDialog() == true)
    {
        // Do something with it
    }
    // Now the main window is focused again
}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文