Заставка не возвращает фокус в основную форму - PullRequest
8 голосов
/ 07 октября 2010

Я каждый. В настоящее время у меня проблема с фокусом при использовании заставки. Я использую VS2008, с .NET Framework 2.0. Кроме того, я связал свой проект с VisualBasic.dll, так как я использую ApplicationServices для управления своим единственным приложением и заставкой.

Вот фрагмент кода, упрощенный из того, что я пытался отладить.

namespace MyProject
{
    public class Bootstrap
    {
        /// <summary>
        /// Main entry point of the application. It creates a default 
        /// Configuration bean and then creates and show the MDI
        /// Container.
        /// </summary>
        [STAThread]
        static void Main(string[] args)
        {
            // Creates a new App that manages the Single Instance background work
            Application.EnableVisualStyles();
            Application.SetCompatibleTextRenderingDefault(false);
            App myApp = new App();
            myApp.Run(args);
        }
    }

    public class App : WindowsFormsApplicationBase
    {
        public App()
            : base()
        {
            // Make this a single-instance application
            this.IsSingleInstance = true;
            this.EnableVisualStyles = true;

            // There are some other things available in the VB application model, for
            // instance the shutdown style:
            this.ShutdownStyle = Microsoft.VisualBasic.ApplicationServices.ShutdownMode.AfterMainFormCloses;

            // Add StartupNextInstance handler
            this.StartupNextInstance += new StartupNextInstanceEventHandler(this.SIApp_StartupNextInstance);
        }

        protected override void OnCreateSplashScreen()
        {
            this.SplashScreen = new MyMainForm();
            this.SplashScreen.StartPosition = FormStartPosition.CenterScreen;
        }
        protected override void OnCreateMainForm()
        {
            // Do your initialization here
            //...
            System.Threading.Thread.Sleep(5000);  // Test
            // Then create the main form, the splash screen will automatically close
            this.MainForm = new Form1();
        }
        /// <summary>
        /// This is called for additional instances. The application model will call this 
        /// function, and terminate the additional instance when this returns.
        /// </summary>
        /// <param name="eventArgs"></param>
        protected void SIApp_StartupNextInstance(object sender,
            StartupNextInstanceEventArgs eventArgs)
        {
            // Copy the arguments to a string array
            string[] args = new string[eventArgs.CommandLine.Count];
            eventArgs.CommandLine.CopyTo(args, 0);

            // Create an argument array for the Invoke method
            object[] parameters = new object[2];
            parameters[0] = this.MainForm;
            parameters[1] = args;

            // Need to use invoke to b/c this is being called from another thread.
            this.MainForm.Invoke(new MyMainForm.ProcessParametersDelegate(
                ((MyMainForm)this.MainForm).ProcessParameters),
                parameters);
        }
    }
}

Теперь, что происходит, когда я запускаю приложение, экран заставки отображается, как и ожидалось, но когда он уничтожен, он не возвращает фокус основной форме (Form1 в тесте). MainForm просто мигает оранжевым на панели задач. Если я запускаю приложение из IDE (VS2008), фокус работает просто отлично. Я использую XP Pro. Кроме того, основная форма находится не поверх всех остальных окон. Если я закомментирую метод OnCreateSplashScreen (), приложение будет сфокусировано нормально.

Чтобы проверить нормальное выполнение, я использую командную строку VS для запуска моего приложения. Я использую версию Release моего проекта.

Есть идеи?

Edit: Я также обрабатываю событие StartUpNextInstance, чтобы отправлять аргументы командной строки в мою основную форму. Для целей тестирования он был удален здесь.

Редактировать: добавлено немного больше кода. Теперь у вас есть полный объем моей начальной загрузки.

Ответы [ 7 ]

4 голосов
/ 07 октября 2010

Вопрос не в деталях.

1) Какая связь между SplashScreen и основной формой приложения?

2) Как автоматически закрывается SplashScreen?

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

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

РЕДАКТИРОВАТЬ:

Алгоритм реализации экрана-заставки (IMHO) :)

1) Создайте пользовательскую форму - заставку

2) Запустите ее в отдельном потоке.Реализуйте его так, как вам нравится.

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

4) Теперь вернемся восновной поток, создайте основную форму приложения.Установите для свойства Visible значение false.

5) Запишите четный обработчик события Load главной формы.В этом обработчике запускается событие для разгрузки экрана-заставки.Затем сделайте видимой основную форму.

3 голосов
/ 05 сентября 2011

Вам необходимо вызвать метод Activate () в главной форме, чтобы правильно его отобразить.

2 голосов
/ 10 февраля 2012

В некоторых моих реализациях форм-заставок в другом потоке я также видел эту ситуацию.

обычно, если я вызываю this.Activate(); в качестве первой строки кода в загрузке формы, она работает как положено. установка этого значения после скрытия всплеска обычно не работает правильно.

другие методы, которые могут помочь.

this.BringToFront();
this.TopMost = true; //setting this to true and back to false sometimes can help
0 голосов
/ 25 июля 2014

У меня была та же проблема, и я хотел для нее простого решения.

Я пытался выше, но не повезло, но идеи сверху полезной информации.

Я попробовал свой трюк, и он мне помог.

Это мой код Programs.cs, который работает нормально:

static class Program
{
    /// <summary>
    /// The main entry point for the application.
    /// </summary>
    [STAThread]
    static void Main()
    {
        Application.EnableVisualStyles();
        Application.SetCompatibleTextRenderingDefault(false);
        var mainWindow = new frmMain();
        splashScreen.DisplaySplashScreen(mainWindow, 10000);
        **mainWindow.TopMost = true;**
        Application.Run(mainWindow);
    }
}

Обратите внимание на то, что mainWindow.TopMost = true;

Ok работает достаточно, но я не хочу mainWindowчтобы остаться на вершине.

Так что в Shown событие я добавил this.TopMost = false;

    private void frmMain_Shown(object sender, EventArgs e)
    {
        this.TopMost = false;
    }

Теперь мое приложение работает так, как я хотел, чтобы оно работало.

Примечание: Просто опубликовано, чтобы помочь любому другому пользователю, столкнувшемуся с той же проблемой, с которой я столкнулся.

Happy Coding:)

0 голосов
/ 18 декабря 2013

попробуй позвонить form1.show() после this.MainForm = new Form1(); у меня сработало.

0 голосов
/ 07 октября 2010

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

0 голосов
/ 07 октября 2010

Что если вы явно установите фокус в своем событии Form1 Load?

...