在使用Winform的MessageBox作为消息提示时,会有一些不方便的地方。如,MessageBox消息框弹出之后,如果不关闭就会阻塞函数的继续执行;不能自动关闭等。因此,子丰就自己仿照MessageBox的样式写了一个InformationBox提示框,可以实现自动关闭、永远显示在所有窗口的最上方等。首先,贴出几张图片展示一下InformationBox的效果;然后,具体介绍InformationBox的实现方式。
程序下载:点击打开链接
http://download.csdn.net/detail/softimite_zifeng/9731930
1. InformationBox增加了自动关闭功能。消息框的右下角会进行倒计时,倒计时时间可以根据自己的需要设定。倒计到0时,消息框自动关闭。当然,在倒计时的过程中,单击“确定”按钮或窗口关闭按钮,同样能够关闭消息框。
2. InformationBox对“确定”按钮设置了快捷键Ctrl+O。也就是说只需要按下Ctrl+O就相当于单击了“确定”按钮。
3. InformationBox的倒计时实现暂停和开始。只需要双击右下角的暂停或开始按钮即可。这样方便用户有足够的时间对较长或较复杂的提示消息进行查看。
4. 和MessageBox一样,InformationBox可以更改消息框显示的图标,包括消息、错误、询问、警告这4种图标。并 且根据不同的图标,在消息框弹出时,其提示音也不同。
5. InformationBox能够根据标题和内容的长度的增大,自动改变提示框的宽度;并且当内容的长度增大一定程度时,能够实现自动转行。基本做到了与MessageBox无差别。
下面具体介绍一下InformationBox的实现方式:
1. 新建Windows窗口,进行如下的设计。
2. 实现“确定”按钮的快捷方式Ctrl+O。只需要给窗口在的KeyPress事件中编写即可,注意,这里需要将窗口的KeyPreview属性设置为True,否则,无法检测到键盘按下Ctrl+O。
//快捷键
private void InformationBox_KeyPress(object sender, KeyPressEventArgs e)
{
e.Handled = true;
if (e.KeyChar == 15) //确定:Ctrl + O
{
OKButton.PerformClick();
}
}
3. 定义一个枚举(InformationBoxIcon)用于图标的选择。
//图标
public enum InformationBoxIcon
{
Error = 0, //错误
Information = 1, //消息
Question = 2, //询问
Warning = 3 //警告
}
4. 使用线程自动关闭提示框,定义线程函数autoCloseThread。
//自动关闭线程
private void autoCloseThread(object timeObj)
{
try
{
int time = 10 * 5; //默认时间
try
{
time = (int)timeObj * 5;
}
catch
{
time = 10 * 5;
}
while (time > 0)
{
if(!pause)
{
Thread.Sleep(200);
time--;
//更新倒计时
if (time % 5 == 0)
{
TimeLab2.Invoke((EventHandler)(delegate
{
TimeLab2.Text = (time / 5).ToString();
}));
}
}
}
//Thread.Sleep(1000);
TimeLab3.Invoke((EventHandler)(delegate
{
TimeLab1.Visible = false;
TimeLab2.Visible = false;
TimeLab3.Visible = false;
TimeLab4.Visible = true;
}));
Thread.Sleep(500);
this.Invoke((EventHandler)(delegate
{
autoclose = true; //自动关闭
this.Close();
}));
}
catch { }
}
5. 重写窗口InformationBox的Show函数,实现窗口的布局以及自动关闭线程。
//显示
public void Show(IWin32Window owner, string text = "", string caption = "", InformationBoxIcon icon = InformationBoxIcon.Information, int secondsTimeout = 10)
{
if (text == null)
text = "";
if (caption == null)
caption = "";
if (secondsTimeout < 2) //最小倒计时为2
secondsTimeout = 2;
if (secondsTimeout > 99) //最大倒计时为99
secondsTimeout = 99;
//提示框的宽和高
testLab.Text = caption; //标题长度比较
int width = 206;
width = (testLab.Width + 50 > width) ? testLab.Width + 50 : width; //最小宽度为206
testLab.Text = "";
this.Text = caption;
width = (width < 498) ? width : 498; //最大宽度为498
InformationTxt.Text = text;
width = (498 - 380 + InformationTxt.Width > width) ? 498 - 380 + InformationTxt.Width : width; //内容长度比较。这里不需要比较最大宽度,由于InformationTxt设置了最大宽度390
int height = 188;
if (InformationTxt.Height / 17 > 2) //最小高度为188
{
height += 17 * (InformationTxt.Height / 17 - 2); //内容高度比较
}
this.Size = new System.Drawing.Size(width, height); //重绘提示框大小
//倒计时
TimeLab2.Text = secondsTimeout.ToString();
//按钮提示
OKTip.SetToolTip(OKButton, OKButton.Text + " 快捷键: Ctrl+O"); //Ctrl+O:15
PauseTip.SetToolTip(PausePb, "双击暂停倒计时");
//图标,提示音
if(icon == InformationBoxIcon.Error)
{
IconPb.Image = Properties.Resources.ErrorIcon;
System.Media.SystemSounds.Hand.Play();
}
else if (icon == InformationBoxIcon.Information)
{
IconPb.Image = Properties.Resources.InformationIcon;
System.Media.SystemSounds.Asterisk.Play();
}
else if (icon == InformationBoxIcon.Question)
{
IconPb.Image = Properties.Resources.QuestionIcon;
System.Media.SystemSounds.Beep.Play();
}
else if (icon == InformationBoxIcon.Warning)
{
IconPb.Image = Properties.Resources.WarningIcon;
System.Media.SystemSounds.Exclamation.Play();
}
//显示在所有窗体的最上方
this.TopMost = true;
//弹出提示框
base.Show(owner);
//开启倒计时
timeoutThread = new Thread(autoCloseThread);
timeoutThread.IsBackground = true;
timeoutThread.Start(secondsTimeout);
}
6. 实现双击暂停或开始倒计时。
//双击暂停或开始
private void pausePb_DoubleClick(object sender, EventArgs e)
{
//判断当前状态是否暂停
if (pause)
{
pause = false;
PausePb.Image = Properties.Resources.PauseIcon;
PauseTip.RemoveAll();
PauseTip.SetToolTip(PausePb, "双击暂停倒计时");
}
else
{
pause = true;
PausePb.Image = Properties.Resources.StartIcon;
PauseTip.RemoveAll();
PauseTip.SetToolTip(PausePb, "双击开始倒计时");
}
}
7. 编写窗口的FormClosing事件。当倒计时还没有结束时关闭窗口,就将自动关闭窗口线程杀死。
//关闭的操作
private void InformationBox_FormClosing(object sender, FormClosingEventArgs e)
{
if (timeoutThread != null)
{
if (timeoutThread.IsAlive && !autoclose)
{
try
{
timeoutThread.Abort();
}
catch { }
}
}
this.Dispose();
}