【问题标题】:Splash screen does not return focus to main form启动画面不会将焦点返回到主窗体
【发布时间】:2010-10-07 17:27:07
【问题描述】:

我每个人。使用闪屏时,我目前的注意力有问题。我正在使用带有 .NET 框架 2.0 的 VS2008。此外,我已将我的项目与 VisualBasic.dll 链接起来,因为我使用 ApplicationServices 来管理我的单实例应用程序和启动屏幕。

这是我尝试调试的简化代码 sn-p。

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 版本。

有什么想法吗?

编辑: 我还处理 StartUpNextInstance 事件以将我的命令行参数发送到我的主窗体。出于测试目的,此处已将其删除。

编辑:添加了更多代码。现在你已经完全掌握了我的引导程序。

【问题讨论】:

  • 这是我的代码。 SO 非常重视这一点,需要注明出处。您必须包含指向原始代码的链接和作者姓名。
  • 我很久以前(我认为是几个月前)使用了这段代码,并且只添加了 SplashScreen。对不起,如果它是你的开始。如何添加您的署名和链接?

标签: c# focus splash-screen


【解决方案1】:

问题不详细。

1) SplashScreen 和应用程序的主窗体是什么关系?

2) SplashScreen 如何自动关闭?

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

使它们以串行控制的方式出现。有很多方法。由于几乎没有提供任何细节,我无法确切说明如何。就像VB在项目中做什么,有多少线程在工作,这里使用的自定义表单是什么......等等。

编辑:

实现启动画面的算法(恕我直言):)

1) 创建自定义表单 - 启动画面

2) 在单独的线程上运行它。随心所欲地实现它的行为。

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

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

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

【讨论】:

  • 实际上,VisualBasic 框架自动完成有关 SplashScreen 的工作。它会自动显示它,当显示主窗体时,它会破坏启动画面。我只有主线程在运行。我的加载过程是在 OnCreateMainForm 中完成的, // Do your initialization here is。
  • VB FW 可能是问题所在。正如你所说,当主窗体加载时它会破坏启动画面,然后焦点可能在其关闭动作期间切换到启动画面。我不知道,但您需要检查您使用的 VB FW。您是否仅将其用于飞溅?无需 VB FW 也可以在 C# 中完成。
  • 我开始将它用于 SingleInstance 应用程序。这是一个魅力。它将我的命令行参数传递给打开的应用程序和所有内容。我几天前才添加了启动画面,因为我的初始化可以通过 MessageBox 向用户显示一些消息,所以我需要一个 GUI 元素。
  • 嗯,你得到一些,你失去一些。我不建议使用第三方闭源库,除非强烈推荐。您可以切换到更可靠的库,或编写自己的代码。
  • 您的解决方案似乎不错。目前,我继续使用 VisualBasic 框架,但选择了我已有的混合解决方案。当我处理命令行参数时,我会执行最小化,然后重新更改 de 状态以对表单进行规范化。这个序列可以捕获焦点。在某些情况下它有奇怪的行为,但我必须解决其他问题和功能才能实现。
【解决方案2】:

您需要在主窗体上调用 Activate() 方法才能正确显示它。

【讨论】:

    【解决方案3】:

    在我在不同线程上的一些启动表单实现中,我也看到了这种情况。

    通常,如果我在表单加载中调用this.Activate(); 作为我的第一行代码,它往往会按预期工作。 在隐藏飞溅后放置它通常无法正常工作。

    其他可以提供帮助的方法。

    this.BringToFront();
    this.TopMost = true; //setting this to true and back to false sometimes can help
    

    【讨论】:

      【解决方案4】:

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

      【讨论】:

      • 我曾尝试将 this.Focus() 放入显示的事件中,但没有解决问题。但现在我很困惑。有时对焦效果很好,有时却不行。
      【解决方案5】:

      由于某种不明原因,焦点似乎工作正常。我将尝试将我的主程序的更多正常执行合并到 MyMainForm 中,并尝试找出真正导致焦点更改失败的原因。我会及时通知大家。

      【讨论】:

      • 似乎因为VS我损失了一天。我只是删除了 bin 和 obj 文件夹,用我原来的解决方案重新编译了一切,一切正常。对不起所有这些混乱。
      • 好吧,我又带着同样的问题回来了。由于未知原因,它只是暂时起作用。而且我没有更改任何代码。我不知道它在那么短的时间内工作发生了什么。而且我真的没有想法。
      • 也许是时候寻找替代品了?通过编写代码,您可以避免在此类愚蠢的同步问题上浪费时间。
      • 检查我的答案以获取实现启动画面的算法
      【解决方案6】:

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

      【讨论】:

        【解决方案7】:

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

        我在上面试过但没有运气,但上面有用信息的想法。

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

        这是我的 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;
            }
        

        现在我的应用程序正在按照我希望的方式运行。

        注意:刚刚发布是为了帮助遇到与我遇到的相同问题的任何其他用户。

        快乐编码:)

        【讨论】:

          【解决方案8】:

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

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 2015-12-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2019-08-22
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            相关资源
            最近更新 更多