今天在工作中遇到了一个场景。我要调用一个类做DataGridView内容的Excel导出,但是当数据量较大时,导出速度也会变得比较慢。为此我需要一个进度条,向用户说明导出状态。我设计的进度条界面如下图所示:
(因为无法监控到操作进度,所以ProgressBar的Style被设置为了Marquee)
滚动条界面布局如下:
要求对界面进行以下设置:
1、Label控件lblMessage的AutoSize设置为False,TextAlign设置为MiddleCenter
2、ProgressBar控件pgbRunningStatus的Style设置为Marquee
3、FormRunningStatusBar窗体的FormBorderStyle设置为FixedToolWindow,ShowIcon和ShowInTaskBar都设置为False,StartPosition设置为CenterScreen,TopMost设置为True
界面代码如下:
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading;
using System.Windows.Forms;
namespace RunningStatusBarTest
{
public partial class FormRunningStatusBar : Form
{
[System.Runtime.InteropServices.DllImport("USER32.DLL")]
public static extern int GetSystemMenu(int hwnd, int bRevert);
[System.Runtime.InteropServices.DllImport("USER32.DLL")]
public static extern int RemoveMenu(int hMenu, int nPosition, int wFlags);
///
/// 屏蔽窗口右上角X键,返回值非零表示成功,零表示失败。
///
/// 窗口的句柄
/// 是否成功
public int RemoveXButton(int iHWND)
{
int iSysMenu;
const int MF_BYCOMMAND = 0x400; //0x400-关闭
iSysMenu = GetSystemMenu(this.Handle.ToInt32(), 0);
return RemoveMenu(iSysMenu, 6, MF_BYCOMMAND);
}
///
/// 滚动条窗口
///
/// 进度条窗口标题
/// 进度条窗口描述
public FormRunningStatusBar(string title, string message)
{
InitializeComponent();
this.Text = title;
this.lblMessage.Text = message;
}
public delegate void UserCustomHandle(object sender);
public event UserCustomHandle UserCustomEvent;
private delegate void DelegateFunc();
///
/// Load函数
///
///
///
private void FormRunningStatusBar_Load(object sender, EventArgs e)
{
//通过函数返回值就可以判断目的是否达到
int iReturn = RemoveXButton(this.Handle.ToInt32());
//执行用户事件
new Thread(new ThreadStart(() =>
{
UserCustomEvent(this);
this.TryClose();
})).Start();
}
///
/// 关闭当前窗体
///
private void TryClose()
{
if (this.InvokeRequired)
{
this.Invoke(new DelegateFunc(TryClose));
}
else
{
this.Close();
}
}
}
}
这段代码有以下几点需要注意的地方:
1、构造函数中有两个参数:title为进度条左上角的标题,message为进度条上方显示的文字描述
2、函数RemoveXButton用于将右上角的×符号置灰
2、事件UserCustomEvent用于存放进度条展示时需要执行的代码段,如执行某段代码时需要显示进度条,就将代码写在这个事件里即可
3、因为UserCustomEvent是另起线程来做的,该事件执行完毕后需要调用FormRunningStatusBar窗体的Close函数,因为是跨线程调用Close函数,因此需要使用委托实现TryClose函数
调用FormRunningStatusBar的一个DEMO窗口
代码如下:
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading;
using System.Windows.Forms;
namespace RunningStatusBarTest
{
public partial class FormMain : Form
{
public FormMain()
{
InitializeComponent();
}
private void btnTest_Click(object sender, EventArgs e)
{
FormRunningStatusBar runningBar = new FormRunningStatusBar("文件导出", "正在导出文件,请稍后……");
runningBar.UserCustomEvent += (obj) =>
{
//TODO 用户指定操作写在这里,本例中的操作假定执行10秒
DateTime dtStartTime = DateTime.Now;
while (true)
{
DateTime dtNow = DateTime.Now;
if ((dtNow - dtStartTime).Seconds >= 10)
{
break;
}
}
};
runningBar.ShowDialog();
}
}
}
方法分为三步:
1、创建FormRunningStatusBar实例,在参数中指定弹出窗的标题和描述
2、实现UserCustomEvent事件,程序在该事件的执行过程中显示进度条
3、调用FormRunningStatusBar实例的ShowDialog方法
此时运行程序,就可以看到文中代码段的效果了。
1、这段DEMO程序我上传到百度网盘了,下载地址:http://pan.baidu.com/s/1c9ODqA
2、显示进度百分比的进度条,实现方法与文中方法大同小异,一是要修改ProgressBar的Style,二是FormRunningStatusBar要增加一个外部可以调用的方法,用于调整进度条的百分比。
END