启动画面无法返回主窗体焦点

8

大家好。我在使用启动屏幕时遇到了聚焦问题。我正在使用VS2008,.NET框架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)。在任务栏中,主窗体只是闪烁橙色。如果我从IDE(VS2008)启动应用程序,则焦点运作正常。我正在使用XP Pro。此外,主窗体不在所有其他窗口的顶部。如果注释掉OnCreateSplashScreen()方法,则应用程序可以正常获取焦点。
为了测试正常执行,我使用VS命令提示符启动我的应用程序,我使用项目的Release版本。
有任何想法吗?
编辑:我还处理StartUpNextInstance事件,以将我的命令行参数发送到我的主窗体。出于测试目的,在这里删除了它。
编辑:添加了更多代码。现在你已经知道了我引导的全部范围。

这是我的代码。Stack Overflow非常重视此事,需要进行归属声明。您必须包含原始代码的链接和作者的姓名。 - Hans Passant
我很久以前(好像是几个月前)拿了这段代码,只是为了添加启动屏幕进行了修改。如果这是你的原创,请原谅。我该如何添加你的署名和链接? - Olyan
8个回答

4

为了正确显示主表单,您需要调用Activate()方法。


4

问题没有详细说明。

1)SplashScreen与应用程序的主窗体之间有什么关系?

2)SplashScreen如何自动关闭?

我确定这里的问题是,当 SplashScreen 尚未关闭时,主窗体已经在后台开始加载。由于时间不当,主窗体在后台加载,而 SplashScreen 卸载... 因此任务栏中会出现闪烁。

使它们以串行控制的方式出现。有许多方法。由于几乎没有提供任何细节,因此我无法确切地建议如何。例如,在项目中 VB 在做什么,有多少个线程正在工作,这里使用了哪些自定义表单等等。

编辑:

实现 Splash screen 的算法(依我之见):)

1)创建一个自定义表单 - Splash screen

2)在一个单独的线程上运行它。按您喜欢的方式实现其行为。

3)在您的 Splash screen 表单中,编写一个处理程序来捕获自定义卸载事件处理程序,该处理程序关闭 Splash screen 表单。

4)现在,在主线程中,创建您的主应用程序表单。将其 Visible 属性设置为 false。

5)编写主窗体的 Load 事件处理程序。在此处理程序中,触发一个事件以卸载 Splash screen。然后,使主窗体可见。


实际上,VisualBasic框架会自动处理启动屏幕。它会自动显示并在主窗体显示时销毁启动屏幕。我只有一个主线程在运行。我的加载过程是在OnCreateMainForm中完成的,即// 在此处进行初始化。 - Olyan
那个VB FW可能是问题所在。正如你所说,当主窗体加载时,它会破坏启动画面,然后焦点可能在关闭操作期间切换到启动画面。我不知道,但你需要检查一下你正在使用的VB FW。你只是用它来做启动画面吗?这也可以在C#中完成,而不需要VB FW。 - Nayan
我开始使用它来创建SingleInstance应用程序,这对于这种情况非常方便。它可以将我的命令行参数传递给打开的应用程序,并且一切都很顺利。几天前,我只是添加了一个启动画面,因为我的初始化过程可能需要通过MessageBox向用户显示一些消息,所以我需要一个GUI元素来呈现。 - Olyan
得失常有,除非高度推荐,否则不建议使用第三方闭源库。你可以切换到更可靠的库,或者编写自己的代码。 - Nayan
你的解决方案似乎很不错。目前,我仍然使用VisualBasic框架,但选择了一个混合解决方案,结合了我已经拥有的东西。当我处理命令行参数时,我会最小化窗体,然后将状态重新更改为规范化。这个序列可以正确地捕获焦点。在某些情况下,它会有一些奇怪的行为,但我必须处理其他问题和功能的实现。 - Olyan

3
在我对不同线程上的启动画面实现中,我也曾遇到这种情况。通常,如果我在表单加载时将this.Activate();作为我的第一行代码调用,它会按预期工作。在隐藏启动画面后放置此代码通常无法正确运行。
其他有助于解决问题的方法包括:
this.BringToFront();
this.TopMost = true; //setting this to true and back to false sometimes can help

0

我遇到了同样的问题,想要一个简单的解决方案。

我尝试了上面的方法,但没有成功,不过上面的想法提供了有用的信息。

我尝试了我的技巧,它对我起作用。

这是我的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; 这样就可以工作了,但我不希望 mainWindow 始终处于最顶层。
因此,在 Shown 事件中添加了 this.TopMost = false;
    private void frmMain_Shown(object sender, EventArgs e)
    {
        this.TopMost = false;
    }

现在我的应用程序正如我所希望的那样工作。
注意:我发表这篇文章只是为了帮助其他遇到和我一样问题的用户。
愉快编程 :)

0
尝试在 this.MainForm = new Form1(); 后调用 form1.show()。这对我有用。

0
在你的主窗体的加载事件中添加 this.Activate();

0

如果你在Form1的Load事件中明确设置焦点会怎样呢?


我曾尝试将this.Focus()放在shown事件中,但它并没有解决问题。但现在我感到困惑了。有时焦点工作得很好,有时却不行。 - Olyan

0

由于某些晦涩的原因,似乎焦点功能正常工作。我将尝试将更多的主程序常规操作整合到MyMainForm中,并尝试找出导致焦点更改失败的真正原因。我会随时向大家报告情况。


似乎因为VS我浪费了一天时间。我只是删除了bin和obj文件夹,使用原始解决方案重新编译了所有内容,现在一切都正常工作了。对于这一切的混乱感到抱歉。 - Olyan
好的,我回来了,还是同样的问题。由于某种未知的原因,它只是暂时地工作了。而且我没有改变任何代码。它为什么会在那短暂的时间内工作,我不知道。我真的没有更多的想法了。 - Olyan
也许现在是寻找替代方案的时候了?通过编写自己的代码,您可以避免浪费时间在这些愚蠢的同步问题上。 - Nayan
检查我的答案以实现闪屏界面算法。 - Nayan

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接