今天在工做中遇到了一個場景。我要調用一個類作DataGridView內容的Excel導出,可是當數據量較大時,導出速度也會變得比較慢。爲此我須要一個進度條,向用戶說明導出狀態。我設計的進度條界面以下圖所示:函數
(由於沒法監控到操做進度,因此ProgressBar的Style被設置爲了Marquee)佈局
滾動條界面佈局以下:ui
要求對界面進行如下設置:this
一、Label控件lblMessage的AutoSize設置爲False,TextAlign設置爲MiddleCenterspa
二、ProgressBar控件pgbRunningStatus的Style設置爲Marquee線程
三、FormRunningStatusBar窗體的FormBorderStyle設置爲FixedToolWindow,ShowIcon和ShowInTaskBar都設置爲False,StartPosition設置爲CenterScreen,TopMost設置爲True設計
界面代碼以下:code
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); /// <summary> /// 屏蔽窗口右上角X鍵,返回值非零表示成功,零表示失敗。 /// </summary> /// <param name="iHWND">窗口的句柄</param> /// <returns>是否成功</returns> 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); } /// <summary> /// 滾動條窗口 /// </summary> /// <param name="title">進度條窗口標題</param> /// <param name="message">進度條窗口描述</param> 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(); /// <summary> /// Load函數 /// </summary> /// <param name="sender"></param> /// <param name="e"></param> private void FormRunningStatusBar_Load(object sender, EventArgs e) { //經過函數返回值就能夠判斷目的是否達到 int iReturn = RemoveXButton(this.Handle.ToInt32()); //執行用戶事件 new Thread(new ThreadStart(() => { UserCustomEvent(this); this.TryClose(); })).Start(); } /// <summary> /// 關閉當前窗體 /// </summary> private void TryClose() { if (this.InvokeRequired) { this.Invoke(new DelegateFunc(TryClose)); } else { this.Close(); } } } }
這段代碼有如下幾點須要注意的地方:orm
一、構造函數中有兩個參數:title爲進度條左上角的標題,message爲進度條上方顯示的文字描述事件
二、函數RemoveXButton用於將右上角的×符號置灰
二、事件UserCustomEvent用於存放進度條展現時須要執行的代碼段,如執行某段代碼時須要顯示進度條,就將代碼寫在這個事件裏便可
三、由於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(); } } }
方法分爲三步:
一、建立FormRunningStatusBar實例,在參數中指定彈出窗的標題和描述
二、實現UserCustomEvent事件,程序在該事件的執行過程當中顯示進度條
三、調用FormRunningStatusBar實例的ShowDialog方法
此時運行程序,就能夠看到文中代碼段的效果了。
一、這段DEMO程序我上傳到百度網盤了,下載地址:http://pan.baidu.com/s/1c9ODqA
二、顯示進度百分比的進度條,實現方法與文中方法大同小異,一是要修改ProgressBar的Style,二是FormRunningStatusBar要增長一個外部能夠調用的方法,用於調整進度條的百分比。
END