一个Splash Screen控件 (闪屏窗体 C#)
2011-04-16 09:41
656 查看
简介
回首以前,我到处寻找Splash Screen的例子,不过我找不到一个符合我的需求的例子。我需要一个简单的、容易复用的、可靠的、安全的——没有线程或子控件;并且,我希望它能够在启动的时候立即出现并停留在屏幕上,在必要的时候消失,当然你可以随时让它复现。我也看到有不少基于.NET下Win Form做的例子,而,这篇文章中,我将使用System.Runtime.InteropServices创建一个继承与控件类的最顶层窗口。我非常喜欢这个方案,因为,我发现它很容易定制。
代码使用
添加SplashScreen.cs到你的程序中,到你的程序的Main函数中,一般来说这个函数在Program.cs文件里。
SplashScreen实现于Singleton模板类。通过一个私有的构造函数,和一个引用到已创建的实例的静态的成员完成...(设计模式上的概念,自己可以看看),最终目的,保证只有一个实例在同时运行。
调用方法
SplashScreen类原理
该类重写了CreateParams属性,以添加WS_EX_TOPMOST属性,这会使得窗口一直在最上方。同时,还增设了WS_EX_TOOLWINDOW,这样窗口就不会出现在任务栏,并且不会被你的Alt+Tab窗口切换看到。
然后,重写OnHandleCreated,设置其父窗口为你的桌面。
当然,到目前为止看似已经完成了窗口出现在最上方。不过,如果有另外一个窗口被设置成Top-Most呢?你的窗口就不会在最上面了。所以,我们需要再一次设置topmost属性,这些通过SetWindowPos API实现,控件会在BeginDisplay中调用,以保证窗口永远是最上层的窗口。
绘图逻辑
绘图部分重写了两个函数OnPaint和OnPaintBackground。如果BackgroundImage属性设置了,那么OnPaintBackground会绘制它,否则以当前BackColor填充背景。
在OnPaint里,控件得到TitleString和CommentaryString值,计算大小和位置,使用Graphics.DrawString绘制文字。
回首以前,我到处寻找Splash Screen的例子,不过我找不到一个符合我的需求的例子。我需要一个简单的、容易复用的、可靠的、安全的——没有线程或子控件;并且,我希望它能够在启动的时候立即出现并停留在屏幕上,在必要的时候消失,当然你可以随时让它复现。我也看到有不少基于.NET下Win Form做的例子,而,这篇文章中,我将使用System.Runtime.InteropServices创建一个继承与控件类的最顶层窗口。我非常喜欢这个方案,因为,我发现它很容易定制。
代码使用
添加SplashScreen.cs到你的程序中,到你的程序的Main函数中,一般来说这个函数在Program.cs文件里。
SplashScreen实现于Singleton模板类。通过一个私有的构造函数,和一个引用到已创建的实例的静态的成员完成...(设计模式上的概念,自己可以看看),最终目的,保证只有一个实例在同时运行。
调用方法
// program.cs ... using SplashScreenControl;namespace WindowsApplication1 { static class Program { /// /// The main entry point for the application. /// [STAThread] static void Main() { Application.EnableVisualStyles(); Application.SetCompatibleTextRenderingDefault( false ); // the following demonstrates how to get hold of the // instance object and change control properties SplashScreen.Instance.Font = new System.Drawing.Font( "Verdana", 11.75F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0)) ); // begin displaying the splash screen before running the // application form SplashScreen.SetBackgroundImage( WindowsApplication1.Resources.splashbg ); SplashScreen.SetTitleString( "SplashScreen Demo" ); SplashScreen.BeginDisplay(); // run the application Application.Run( new Form1() ); } } }
SplashScreen类原理
该类重写了CreateParams属性,以添加WS_EX_TOPMOST属性,这会使得窗口一直在最上方。同时,还增设了WS_EX_TOOLWINDOW,这样窗口就不会出现在任务栏,并且不会被你的Alt+Tab窗口切换看到。
// splashscreen.cs protected override CreateParams CreateParams { get { CreateParams cp = base.CreateParams; cp.ExStyle |= WS_EX_TOOLWINDOW| WS_EX_TOPMOST; cp.Parent = IntPtr.Zero; return cp; } }
然后,重写OnHandleCreated,设置其父窗口为你的桌面。
// splashscreen.cs protected override void OnHandleCreated(EventArgs e) { if ( this.Handle != IntPtr.Zero ) { IntPtr hWndDeskTop = GetDesktopWindow(); SetParent( this.Handle, hWndDeskTop ); } base.OnHandleCreated(e); }
当然,到目前为止看似已经完成了窗口出现在最上方。不过,如果有另外一个窗口被设置成Top-Most呢?你的窗口就不会在最上面了。所以,我们需要再一次设置topmost属性,这些通过SetWindowPos API实现,控件会在BeginDisplay中调用,以保证窗口永远是最上层的窗口。
绘图逻辑
绘图部分重写了两个函数OnPaint和OnPaintBackground。如果BackgroundImage属性设置了,那么OnPaintBackground会绘制它,否则以当前BackColor填充背景。
// splashscreen.cs protected override void OnPaintBackground( PaintEventArgs e ) { if ( Bounds.Width > 0 && Bounds.Height > 0 && Visible ) { try { Rectangle rect = new Rectangle(0, 0, Bounds.Width, Bounds.Height); Graphics g = e.Graphics; g.SetClip(e.ClipRectangle); if (BackgroundImage == null) { SolidBrush solidBrush = new SolidBrush(BackColor); g.FillRectangle(solidBrush, rect); solidBrush.Dispose(); } else { g.DrawImage(BackgroundImage, rect, 0, 0, BackgroundImage.Width, BackgroundImage.Height, GraphicsUnit.Pixel); } } catch (Exception exception) { System.Diagnostics.StackFrame stackFrame = new System.Diagnostics.StackFrame(true); Console.WriteLine( "/nException: {0}, /n/t{1}, /n/t{2}, /n/t{3}/n", this.GetType().ToString(), stackFrame.GetMethod().ToString(), stackFrame.GetFileLineNumber(), exception.Message); } } }
在OnPaint里,控件得到TitleString和CommentaryString值,计算大小和位置,使用Graphics.DrawString绘制文字。
// splashscreen.cs protected override void OnPaint( PaintEventArgs e ) { if ( Bounds.Width > 0 && Bounds.Height > 0 && Visible ) { try { Graphics g = e.Graphics; g.SetClip(e.ClipRectangle); g.TextRenderingHint = TextRenderingHint.ClearTypeGridFit; float nClientHeight = ClientRectangle.Height; //start the text two thirds down: m_nTextOffsetY = Convert.ToInt32(Math.Ceiling(((nClientHeight / 3) * 2))) + m_nLeading; if (TitleString != string.Empty) { Font fontTitle = new Font(Font, FontStyle.Bold); SizeF sizeF = g.MeasureString(TitleString, fontTitle, ClientRectangle.Width, m_stringFormat); m_nTextOffsetY += Convert.ToInt32( Math.Ceiling(sizeF.Height)); RectangleF rectangleF = new RectangleF( ClientRectangle.Left + m_nTextOffsetX, ClientRectangle.Top + m_nTextOffsetY, sizeF.Width, sizeF.Height); SolidBrush brushFont = new SolidBrush(ForeColor); g.DrawString(TitleString, fontTitle, brushFont, rectangleF, m_stringFormat); brushFont.Dispose(); fontTitle.Dispose(); m_nTextOffsetY += m_nLeading; } if (CommentaryString != string.Empty) { SizeF sizeF = g.MeasureString(CommentaryString, Font, ClientRectangle.Width, m_stringFormat); m_nTextOffsetY += Convert.ToInt32( Math.Ceiling(sizeF.Height)); RectangleF rectangleF = new RectangleF(ClientRectangle.Left + m_nTextOffsetX, ClientRectangle.Top + m_nTextOffsetY, sizeF.Width, sizeF.Height); SolidBrush brushFont = new SolidBrush(ForeColor); g.DrawString(CommentaryString, Font, brushFont, rectangleF, m_stringFormat); brushFont.Dispose(); } } catch (Exception exception) { System.Diagnostics.StackFrame stackFrame = new System.Diagnostics.StackFrame(true); Console.WriteLine("/nException: {0}, /n/t{1}, /n/t{2}, /n/t{3}/n", this.GetType().ToString(), stackFrame.GetMethod().ToString(), stackFrame.GetFileLineNumber(), exception.Message); } } }
相关文章推荐
- 一个Splash Screen控件 (闪屏窗体 C#)
- C#源代码—在windows窗体中添加一个名为lblShow的Lable控件2
- .net C# 跨越线程调用窗体上的控件一个完整的例子
- C#第十周任务之最后一项之创建一个如下的窗体,并在窗体上放置一个菜单、一个工具栏控件。菜单内容如第二个图所示。工具栏上有两个按钮,分别对应“打开文本文件”、“保存文本文件”。菜单和工具栏具体功能实现可
- [Gabriel的专栏] 用C#如何遍历一个窗体中的某一种控件
- C# 使用Panel控件实现在一个窗体中嵌套另一个窗体
- C# 在一个窗体中调用另一个窗体的控件可能出现的问题
- 在DevExpress程序中使用SplashScreenManager控件实现启动闪屏和等待信息窗口
- C#源代码—在windows窗体中添加一个名为lblShow的Lable控件4,创建可变字符串,字符串转换为字符型
- 用C#如何遍历一个窗体中的某一种控件
- 用C#如何遍历一个窗体中的某一种控件
- 用C#如何遍历一个窗体中的某一种控件
- C# winform中一个类中如何调用另一个窗体的控件或方法
- c#中把一个控件从一个窗体移到另一个窗体
- 用C#如何遍历一个窗体中的某一种控件
- C# 实现一个窗体调用另一个窗体的控件
- C# winform中一个类中如何调用另一个窗体的控件或方法
- 在C#中使用Panel控件实现在一个窗体中嵌套另一个窗体
- c#中一个窗体调用另一个窗体的控件及方法(转贴)
- 如何遍历一个窗体中的某一种控件 c#实现