当SplashScreen关闭时(手动或通过AutoClose),它会在淡出动画期间窃取MainWindow的焦点。这导致主窗口的标题从活动切换到非活动(灰色)到活动。是否有任何技巧可以防止SplashScreen窃取焦点?
答案 0 :(得分:5)
告诉SplashScreen MainWindow是其父窗口。当子窗口失去焦点时,其父窗口会获得焦点。如果没有父级,则窗口管理器决定。
<击> splashScreen.Show(主窗口); 击>
修改强>:
我刚刚发现有一个SplashScreen课程。看起来你使用那个类而不仅仅是我假设的普通表格。
所以,我刚用SplashScreen制作了一个简单的WPF应用程序,对我来说,上面提到的效果并没有发生。主窗口没有失去焦点。
我建议你评论应用程序的初始化代码的药水,直到闪烁停止。然后你有了一个起点,可以进一步研究为什么失去焦点。
<强> EDIT2 强>:
在不知道你的代码的情况下,我试图重现这种现象并且并不太难。无论我尝试什么,焦点变化总是在主窗口已经显示并具有焦点时发生。
所以我看到的最佳解决方案是在调用启动画面的Close()方法后手动显示主窗口:
从App.xaml中删除StartupUri
启动应用程序并初始化资源后显示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
}
}
答案 1 :(得分:2)
使用ILSpy,我发现SplashScreen.Close
方法在某个时刻调用SetActiveWindow
,导致slpash屏幕窗口在它开始关闭时变为活动状态。 (至少在.NET 4.0中。)我在调用MainWindow.Focus
后刚刚调用SplashScreen.Close
,这解决了问题。
否则,我只能在fadeout动画拍摄期间看到主窗口是如何处于非活动状态的。此外,我在主窗口加载时显示模态对话框窗口,并保持活动状态。但是当该对话框关闭时,主窗口将不再聚焦,而是我将最终进入Visual Studio窗口或任何启动我的应用程序。从上面插入Focus
来电也有助于解决这种情况。
BTW,这是一篇很好的文章,它解释了如何手动使用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
}