SplashScreen.Close () крадет фокус MainWindow - PullRequest
4 голосов
/ 07 октября 2011

Когда SplashScreen закрывается (вручную или AutoClose), он захватывает фокус MainWindow во время анимации затухания.Это приводит к тому, что заголовок главного окна переключается с активного на неактивный (серый) на активный.Есть ли какая-нибудь хитрость, чтобы сохранить SplashScreen от кражи фокуса?

Ответы [ 2 ]

5 голосов
/ 07 октября 2011

Сообщите SplashScreen, что MainWindow является его родительским окном. Когда дочернее окно теряет фокус, его родитель получает фокус. Если родителя нет, менеджер окон решает.

splashScreen.Show (MainWindow);

EDIT

Я только что узнал, что есть класс SplashScreen . Похоже, вы используете этот класс, а не просто обычную форму, как я предполагал.

Итак, я только что сделал простое приложение WPF с SplashScreen, и для меня упомянутый эффект не произошел. Главное окно не потеряло фокус.

Я бы предложил вам комментировать части кода инициализации вашего приложения до тех пор, пока мигание не прекратится. Тогда у вас есть отправная точка для дальнейших исследований, почему фокус потерян.

EDIT2

Не зная вашего кода, я пытался воспроизвести это явление, и это было не слишком сложно. Что бы я ни пытался, изменение фокуса всегда происходило, когда главное окно уже было показано и имело фокус.

Итак, лучшее решение, которое я вижу, - это вручную показать главное окно после вызова метода Close () на заставке:

  1. Удалите StartupUri из App.xaml

  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
    }
}
2 голосов
/ 21 августа 2013

Используя ILSpy, я обнаружил, что метод SplashScreen.Close вызывает SetActiveWindow в какой-то момент, в результате чего окно экрана slpash становится активным в тот момент, когда оно начинает закрываться. (По крайней мере, в .NET 4.0.) Я добавил вызов к своему MainWindow.Focus сразу после вызова SplashScreen.Close, и это решило проблему.

В противном случае я мог видеть, что главное окно было неактивно только в течение времени, которое заняла анимация затухания. Кроме того, я показываю модальное диалоговое окно, когда главное окно загружено, и оно остается активным. Но когда это диалоговое окно закрыто, главное окно больше не будет фокусироваться, и вместо этого я окажусь в окне Visual Studio или в любом другом приложении, которое я запустил. Вставка вызова Focus сверху также помогает в этой ситуации.

Кстати, вот хорошая статья, которая объяснила мне, как использовать класс SplashScreen вручную вместо опции файла проекта: http://tech.pro/tutorial/822/wpf-tutorial-using-splash-screens-in-sp1

Это код из моего приложения:

В приложении. 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();
}

В моем главном окне команда Init ViewModel (главное окно уже полностью видно):

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
}
...