您的位置:首页 > 编程语言 > C#

一个Splash Screen控件 (闪屏窗体 C#)

2011-04-16 09:41 656 查看
简介
回首以前,我到处寻找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);
}
}
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: 
相关文章推荐