Windows Form经常会在启动主界面的时候预先有启动画面,这也是因为用户体验的需要,用户知道已经启动application,而不是在load resource的时候等待。因此这里不能用单线程的思路,单单只是设计一个界面而已,而需要在splash画面的时候同时Load resource。那么这个技术有两个线程,一个是splash画面,二是load resource。搜了一些资料,下面进行一些总结:

 using System;
 using System.Collections.Generic;
 using System.Linq;
 using System.Windows.Forms;
 using System.Threading;

 namespace WindowsTest
 {
     static class Program
     {
         /// <summary>
         /// 应用程序的主入口点。
         /// </summary>
         [STAThread]
         static void Main()
         {
             Application.EnableVisualStyles();
             Application.SetCompatibleTextRenderingDefault(false);

             Thread thUI = new Thread(new ThreadStart(ShowSplashWindow));
             thUI.Name = "Splash UI";
             thUI.Priority = ThreadPriority.Normal;
             thUI.Start();

             Thread th = new Thread(new ThreadStart(LoadResources));
             th.Name = "Resource Loader";
             //th.Priority = ThreadPriority.Highest;
             th.Priority = ThreadPriority.Normal;
             th.Start();
             th.Join();

             if (splashForm != null)
             {
                 splashForm.Invoke(new MethodInvoker(delegate { splashForm.Close(); }));
             }

             thUI.Join();
             Application.Run(new MainForm());
         }

         public static SplashForm splashForm
         {
             get;
             set;
         }

         private static void ShowSplashWindow()
         {
             splashForm = new SplashForm();
             Application.Run(splashForm);
         }

         private static void LoadResources()
         {
             ; i <= ; i++)
             {
                 if (splashForm != null)
                 {
                     splashForm.Invoke(new MethodInvoker(delegate { splashForm.label1.Text = "Loading some things... " + DateTime.Now.ToString(); }));
                 }
                 Thread.Sleep();
             }
             splashForm.Invoke(new MethodInvoker(delegate { splashForm.label1.Text = "Done. " + DateTime.Now.ToString(); }));
         }
     }
 }

这段代码的问题在于画面启动完主界面是最小化了,不解为何如此

http://www.sufeinet.com/forum.php?mod=viewthread&action=printable&tid=2697

这里的代码比较成熟了,我做了一些小小的改变。用ApplicationContext来解决splash form和main form之间的转换,而在Program的类的InitApp function里如果要改变splash from的label1则需要Invoke来异步调用SplashFrom的PrintMsg function,否则会卡卡面。在SplashForm_Load函数里用到了线程池技术,这里不能用invoke,因为invoke必须使用类实例,而Program是static类,InitApp也是static的,在InitApp里可以用线程池来实现。另外贴下线程池的适用场合

Program.cs:

 using System;
 using System.Collections.Generic;
 using System.Linq;
 using System.Windows.Forms;
 using System.Threading;

 namespace WindowsTest
 {
     static class Program
     {
         /// <summary>
         /// 应用程序的主入口点。
         /// </summary>
         [STAThread]
         static void Main()
         {
             Application.EnableVisualStyles();
             Application.SetCompatibleTextRenderingDefault(false);

             MyApplicationContent appContent = new MyApplicationContent(new MainForm(), new SplashForm());
             Application.Run(appContent);
         }

         //模拟耗时操作,这里假调程序需要访问网络来实现登录验证
         //这是一个耗时操作,我们需要在执行的过程中,向用户实时显示一些信息
         //那么,多线程是唯一的解决方案,在主线程执行这些,界面会死掉的
         public static void InitApp(Object parm)
         {
             SplashForm startup = parm as SplashForm;
             startup.Invoke(new UiThreadProc(startup.PrintMsg), "正在初始化...");
             Thread.Sleep();
             startup.Invoke(new UiThreadProc(startup.PrintMsg), "正在验证用户身份信息...");
             Thread.Sleep();
             startup.Invoke(new UiThreadProc(startup.PrintMsg), "用户身份验证成功。");
             Thread.Sleep();
             startup.Invoke(new UiThreadProc(startup.PrintMsg), "正在登录...");
             Thread.Sleep();
             bool loginSuccess = true;
             //这里可以根据执行的结果判断,如果登录失败就退出程序,否则显示主窗体
             if (loginSuccess)
             {
                 startup.Invoke(new UiThreadProc(startup.PrintMsg), "登录成功,欢迎使用!");
                 Thread.Sleep();
                 startup.Invoke(new UiThreadProc(startup.CloseForm), false);
             }
             else
             {
                 startup.Invoke(new UiThreadProc(startup.CloseForm), true);
             }
         }
     }

     public delegate void UiThreadProc(Object o);
     //WinForm里,默认第一个创建的窗体是主窗体,所以需要用应用程序域来管理
     public class MyApplicationContent : ApplicationContext
     {
         private Form realMainForm;

         public MyApplicationContent(Form mainForm, Form flashForm)
             : base(mainForm)
         {
             this.realMainForm = mainForm;
             this.MainForm = flashForm;
         }

         protected override void OnMainFormClosed(object sender, EventArgs e)
         {
             if (sender is SplashForm)
             {
                 SplashForm splashForm = sender as SplashForm;

                 if (!splashForm.Exit)
                 {
                     this.MainForm = realMainForm;

                     realMainForm.Show();
                 }
                 else
                 {
                     base.OnMainFormClosed(sender, e);
                 }
             }
             else
             {
                 base.OnMainFormClosed(sender, e);
             }
         }
     }
 }

SplashForm.cs:

 using System;
 using System.Collections.Generic;
 using System.ComponentModel;
 using System.Data;
 using System.Drawing;
 using System.Linq;
 using System.Text;
 using System.Windows.Forms;
 using System.Threading;

 namespace WindowsTest
 {
     public partial class SplashForm : Form
     {
         private bool exit;

         public bool Exit
         {
             get { return exit; }
         }

         public SplashForm()
         {
             InitializeComponent();
         }

         //显示文字信息
         public void PrintMsg(Object msg)
         {
             label1.Text = msg.ToString();
         }

         //关闭启动窗体,如果需要中止程序,传参数false
         public void CloseForm(Object o)
         {
             this.exit = Convert.ToBoolean(o);
             this.Close();
         }

         private void SplashForm_Load(object sender, EventArgs e)
         {
             ThreadPool.QueueUserWorkItem(new WaitCallback(Program.InitApp), this);
         }
     }
 }

只需要将Program.cs里的InitApp里的Thread.Sleep改成实际的load resource代码即可

C#: 启动画面设计的更多相关文章

  1. 跨平台移动开发phonegap/cordova 3.3全系列教程-app启动画面

    1.app启动画面设计 用photoshop设计启动画面,图片分辨率为720*1280 保存的文件名为splash.png 将splash.png复制到res\drawable,如图 PS:要先添加闪 ...

  2. 为你的Web程序加个启动画面

    .Net开发者一定熟悉下面这个画面: 这就是宇宙第一IDE Visual Studio的启动画面,学名叫Splash Screen(或者Splash Window).同样,Javar们一定对Eclip ...

  3. IOS编程教程(八):在你的应用程序添加启动画面

    IOS编程教程(八):在你的应用程序添加启动画面   虽然你可能认为你需要编写闪屏的代码,苹果已经可以非常轻松地把它做在Xcode中.不需要任何编码.你只需要做的是设置一些配置. 什么是闪屏 对于那些 ...

  4. MFC之窗体改动工具栏编程状态栏编程程序启动画面

    1窗体外观的改动 (1)改动在CMainFrame::preCreateWindow(CREATESTRUCT& cs) 改动标题:cs.style&=FWS_ADDTOTITLE; ...

  5. android 之 启动画面的两种方法

    现在,当我们打开任意的一个app时,其中的大部分都会显示一个启动界面,展示本公司的logo和当前的版本,有的则直接把广告放到了上面.启动画面的可以分为两种设置方式:一种是两个Activity实现,和一 ...

  6. Cordova应用程序修改启动画面或者Icon

    1)  制作启动画面图片或icon ionic resources //同时生成icon和splash ionic resources --icon //只生成icon ionic resources ...

  7. iOS7的启动画面设置及asset catalogs简介

    如果上网搜索一下“iOS App图标设置”或者“iOS App启动画面设置”肯定能找到不少文章,但内容大多雷同,就是让你按照某种尺寸制作若干张png图片,再按照苹果的命名规范,加入到项目中去,一行代码 ...

  8. iOS 启动画面 代码自定义

    先来看一个可能会遇到的问题: 如果你已经删除了xcode为你的项目自动生成的LaunchScreen.storyboard, 然后你在测试你的app的时候发现,屏幕里出现了黑色的区域,如上图(画红线的 ...

  9. Qt5 程序启动画面动图效果

    2333终于实现动图,先弄了一个窗口去掉标题栏假装就是启动画面了,还是那只萌萌的猫这次会动了! 基类用的是QWidget  类名称MainView #ifndef MAINVIEW_H #define ...

随机推荐

  1. 【转】下载量最高的 100 个 Laravel 扩展包推荐

    说明 Laravel 另一个令人喜欢的地方,是拥有活跃的开发者社区,而活跃的开发者社区带来的,是繁华的扩展包生态. 本文对 Packagist 上打了 Laravel 标签 的扩展包进行整理,截止到现 ...

  2. 关于Memo或者Edit之类控件, 直接设置Text无法撤销的解决方案

    昨天看到群里有人问使用Memo1.Text := '11111';来设置内容的代码无法使用Memo1.Undo的方式来撤销 测试了一下果然如此, 跟踪了VCL代码, 发现Text := '11111' ...

  3. JavaScript POST 请求如何跨域

    前天遇到一个问题,就是我上传图片的时候,这个图片需要上传给某个API的接口 这样问题就来了,我们之前上传图片的时候都是先上传到我们自己的后台里面,然后通过后台,再把这个流传到图片服务器上. 但是上传到 ...

  4. Redis-分布式

    package test.jedis; import java.util.HashSet; import java.util.Set; import org.junit.Test; import re ...

  5. 关于pom.xml的一些问题的理解

    最近在pom上出了一些问题,搞了一天才理解了一些问题,记录一下. 当在覆盖本地repository包之后,pom.xml上面出现了一个x. 当mvn->update project之后,还是有许 ...

  6. [LeetCode]题解(python):053-Maximum Subarray

    题目来源 https://leetcode.com/problems/maximum-subarray/ Find the contiguous subarray within an array (c ...

  7. [LeetCode]题解(python):033-Search in Rotated Sorted Array

    题目来源 https://leetcode.com/problems/search-in-rotated-sorted-array/ Suppose a sorted array is rotated ...

  8. 利用HTML和JS制作隔行换背景颜色的表格

    1.源代码如下: <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://ww ...

  9. JMeter学习-005-JMeter 主要组件概要介绍及执行顺序

    本文将对 JMeter 主要组件(主要涉及 Threads(Users).Test Fragment.逻辑控制器.配置元件.定时器.前置处理器.Sampler.后置处理器.断言.监听器 十大组件)进行 ...

  10. sell -- 解码16进制unicode

    1. //System.out.println("decodeUnicode:" + decodeUnicode("0049"));//I public sta ...