Splash Screen 加载窗体

  对于windows开 发人员来说在打开VS开发工具时,总是先呈现一个SplashScreen界面,登上几秒钟后才打开VS的主界面。这样的效果一般是在主界面需要加载大量 资源,为避免主界面变成“死”界面,而提供一个友好的Loading画面。为实现该效果,我们通常在加载主界面Application.Run(new MainForm())之前打开一个SplashScreen窗口,并在SplashScreen窗口中加载数据。

  微软提供了WindowsFormsApplicationBase类,该类提供了SplashScreen属性,及 OnCreateSplashScreen虚方法的接口。在实现自己的SplashScreen窗口时,主要重载 OnCreateSplashScreen方法,并创建一个Form对象,赋值给SplashScreen属性,并且该类还提供了 MinimumSplashScreenDisplayTime属性,用于设置SplashScreen窗口的呈现时间。当然你可以自己控制 SplashScreen窗口的呈现和关闭。

1. 实现Application类

首先我们需要实现WindowsFormsApplicationBase的基类SplashScreenApplication,并重新定义OnCreateSplashScreen方法。

WindowsFormsApplicationBase 类是位于Microsoft.VisualBasic.ApplicationServices命名空间下,需要添加 Microsoft.VisualBasic.dll引用。

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

using Microsoft.VisualBasic.ApplicationServices;

namespace Test_Splash_Screen
{
    internal sealed class SplashScreenApplication : WindowsFormsApplicationBase
    {
        public SplashScreenApplication()
        {
            base.IsSingleInstance = true;
            base.EnableVisualStyles = true;
            base.MinimumSplashScreenDisplayTime = 2000;
        }

        protected override void OnCreateMainForm()
        {
            this.MainForm=new Main_Form();
            //base.OnCreateMainForm();
        }

        protected override void OnCreateSplashScreen()
        {
            this.SplashScreen = new SplashScreenForm();
            //base.OnCreateSplashScreen();
        }
    }
}

其中Main_Form为主窗口,SplashScreenForm为Loading窗口,并设置2000毫秒SplashScreen自动关闭,并试图打开主窗体。

Application会首先执行OnCreateSplashScreen方法,然后执行OnCreateMainForm窗口。需要注意的是,2000毫秒并不是两个方法的执行的时间间隔,而是主窗体创建2000毫秒后才关闭SplashScreen窗体,并显示主窗体。这里的 SplashScreenForm不能用于加载数据,因为2000毫秒结束就会关闭,我们不能保证SplashScreen可以在2000毫秒吧数据加载完成。

2. 实现加载效果

这里SplashScreen的目的是加载数据,而不是简单的友好效果,因此简单的2000毫秒不能达到我们加载数据的需求。鉴于此,我们需要自己控制 SplashScreen界面,当数据加载完成后才能关闭SplashScreen窗口,并显示主界面。

为达到加载数据的效果,这里会在 SpashScreen界面显示加载数据的过程。代码如下:

using System;
using System.Collections.Generic;
using System.Text;
using System.Threading.Tasks;

using System.Threading;
using Microsoft.VisualBasic.ApplicationServices;

namespace Test_Splash_Screen
{
    internal sealed class SplashScreenApplication2 : WindowsFormsApplicationBase
    {
       public ManualResetEvent resetEvent = new ManualResetEvent(true);

       public void SplashScreenApplication2()
        {
            base.IsSingleInstance = true;
            base.EnableVisualStyles = true;
        }

        protected override void OnCreateMainForm() {
            if (resetEvent.WaitOne()) {
                this.MainForm = new Main_Form();
            }
        }

        protected override void OnCreateSplashScreen() {
            this.SplashScreen = new SplashScreenForm();
        }
    }
}

为演示加载过程,SplashScreenForm还负责了加载数据:

public partial class SplashScreenForm : Form {
        static string[] Resources = new string[]{
            "Check update.",
            "Updating",
            "Downloading xxx.dll from remote server.",
            "Downloading xxx.config from remote server.",
            "Updated.",
            "Check if the devices pluged in.",
            "Open devices.",
            "Load data from database.",
            "Load file data from remote.",
            "Download necessary files.",
            "Ready"
        };

        public SplashScreenForm() {
            InitializeComponent();
            this.Opacity = 0.8;
            Program.app.resetEvent.Reset();
        }

        private void SplashScreenForm_Load(object sender, EventArgs e) {
            backgroundWorker1.RunWorkerAsync();
        }

        private delegate void run();

        private void backgroundWorker1_DoWork(object sender, DoWorkEventArgs e) {
            float total = 0f;
            float pre = 100f / Resources.Length;

            foreach (string res in Resources) {
                total += pre;
                backgroundWorker1.ReportProgress((int)total, res);
                Thread.Sleep(1000);
            }
        }

        private void backgroundWorker1_ProgressChanged(object sender, ProgressChangedEventArgs e) {
            this.Invoke(new run(() => {
                label1.Text = e.UserState.ToString();
                progressBar1.Value = e.ProgressPercentage;
            }));
        }

        private void backgroundWorker1_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e) {
            this.Invoke(new run(() => {
                label1.Text = "Inititalization finished.";
                progressBar1.Value = 100;

            }));

            Thread.Sleep(1000);

            this.Invoke(new run(() => {
                this.Close();
                Program.app.resetEvent.Set();
            }));
        }
    }

程序入口:

static class Program {
        public static SplashScreenApplication app = new SingleInstanceApplication();
        /// <summary>
        /// The main entry point for the application.
        /// </summary>
        [STAThread]
        static void Main(string[] args) {
            app.Run(args);
        }
    }

运行效果
运行效果如下图:

其他
另外我们的加载数据过程只在SplashScreen窗口中,那么MainForm就不能加载太耗时的资源了,否则关闭SplashScreen窗口后,
才开始创建MainForm窗体,就其不到Loading的效果了。如果希望在MainForm中加载数据的,也可以修改代码,在MainForm中控制
SplashScreen的关闭。

参考文章

1. SplashScreen实现加载数据

时间: 2024-08-07 08:29:06

Splash Screen 加载窗体的相关文章

[转] 从 dll 程序集中动态加载窗体

无涯 原文 从 dll 程序集中动态加载窗体 [原创] 昨天晚上花了一晚上时间写了一个从程序集中动态加载窗体的程序.将任何包含窗体的代码编译成 dll 文件,再把 dll 文件拷贝到本程序的目录下,本程序运行时即可动态检查到 dll 文件中的窗体,将窗体类的类型在程序菜单中显示出来,点击菜单即可运行对应的窗体. 本程序主要用到了 Assembly 类动态加载程序集,再得到程序集中包含类的 Type 类型,动态生成类实例,动态调用类方法.个人觉得这是一种提供高度松耦合,可随意扩展的程序结构框架,希

winform 加载窗体时弹出另一个窗体并显示进度条的源码

winform 加载窗体时弹出另一个窗体并显示进度条的源码 //frmA: 源窗体 //------------------------------------------ //引用 using System.Threading; BackgroundWorker worker; public frmA() { InitializeComponent(); worker = new BackgroundWorker(); worker.DoWork += new DoWorkEventHandl

C# 多线程 异步加载 窗体

C# 多线程 异步加载 窗体 分类: C#2014-05-28 16:57 1286人阅读 评论(0) 收藏 举报 异步加载 我们在使用 windowform 编程的时候,我们或许可能会越到,各种在窗体加载的时候,会进行其他的操作: 1.若是在加载之前,操作--->整个界面出来的很慢,而且若是时间长的话,页面很久才能出来, 2.若是写在加载之后处理的话,虽然界面出来了,这个时候,出现了假死的状体.但是不能乱点,一点,就有卡死的现象. 现在我们利用异步,和多线程来控制,并且加上进度条.来做一个界面

C# Winform 加载窗体/对象时的等待页面设计

在设计应用程序过程中,有时候加载对象需时较长,我们可以显示一个Loading等待页面,对用户来说就比较友好了. 这个还是涉及到多线程,下面是步骤. 一.创建好Loading窗体: 一个Panel用于显示转圈动画(仿Win10的Loading),一个Loading文本标签.动画的代码来自网络. public partial class Fm20Loading : Form { public Fm20Loading() { InitializeComponent(); //LblMessage.Te

Skeleton Screen加载占位图(内容出现前显示灰色占位图)的分析与实现

今天有几个好友问了这个叫加载占位图的实现方法,我还在此问题下做了个回答.由于国内对这个的名词是各有各的叫法,所以这里直接用加载占位图来解释.相信很多人都看到过图中这样的加载方式: 这个图是一个国内知名站点的,相比以往的loading圈圈,看起来是不是美观了许多.据说这个Idea是一个谷歌工程师在2013年时想到的.我不喜欢去讨论概念之类.直接用知名站点来通俗易懂的解释: 以往:发起ajax-loading.gif/svg-ajax结果.现在:发起ajax-具有css3动感(比如闪烁)的灰色布局d

通过反射获取DLL的类实现加载窗体

1.创建一个DLL 类库,并新建一个窗体类,这个直接在vs上操作就好 2. 建立一个Testassembly工程 新建一个测试类 namespace Testassembly { public partial class Form1 : Form { public Form1() { InitializeComponent(); } private void Form1_Load(object sender, EventArgs e) { string ss = AppDomain.Curren

pannel加载窗体

public static void loadFillForm(Panel panel, System.Windows.Forms.Form frm) { if (frm != null && panel != null) { frm.FormBorderStyle = System.Windows.Forms.FormBorderStyle.None; frm.ShowIcon = false; frm.ShowInTaskbar = false; frm.TopLevel = fals

Panel 中加载窗体

pnlMain.Controls.Clear(); ControlAnalyzer1 CA1 = new ControlAnalyzer1(); CA1.TopLevel = false; CA1.Size = pnlMain.Size; pnlMain.Controls.Add(CA1); CA1.Show(); 原文地址:https://www.cnblogs.com/z45281625/p/10717684.html

C# WPF有趣的登录加载窗体

时间如流水,只能流去不流回! 点赞再看,养成习惯,这是您给我创作的动力! 本文 Dotnet9 https://dotnet9.com 已收录,站长乐于分享dotnet相关技术,比如Winform.WPF.ASP.NET Core等,亦有C++桌面相关的Qt Quick和Qt Widgets等,只分享自己熟悉的.自己会的. 阅读导航: 一.先看效果 二.本文背景 三.代码实现 四.文章参考 五.代码下载 一.先看效果 二.本文背景 在YouTube上看到的一个视频,文末有链接,使用前端时间介绍的