技術沒有先進與落後,只有合適與不合適。html
在程序當中,常常有耗時較長的操做,爲了給用戶更好的體驗,就須要給用戶一個及時的反饋,這種時候就須要用到進度等待窗口。安全
實現進度等待窗口的技術有不少,好比:BackgroundWorker、Thread等。函數
不過技術不是難點,難點在於怎麼使等待窗口美觀實用。因此本文中就基於前幾篇的自定義控件:LProgressBar和LLabel,去實現進度等窗口。工具
相關文章:佈局
[C#] (原創)一步一步教你自定義控件——04,ProgressBar(進度條)性能
[C#] (原創)一步一步教你自定義控件——05,Label(原生控件) 動畫
相信看完的你,必定會有所收穫。線程
本文地址:https://www.cnblogs.com/lesliexin/p/14121618.html3d
爲了在執行耗時操做時,給用戶更好的、更直觀的體驗。orm
(1),支持「取消」操做,固然也支持「不能取消」操做。
(2),支持進度明確與進度不明確時顯示不一樣樣式。
(3),支持明細進度。
Win7:
Win10:
(1),在工程上右擊,選擇「添加」->「窗體(Windows 窗體)」,命名爲:LProgress.cs。
(2),修改窗體相關屬性
Font:微軟雅黑,9pt。比之默認的「宋體,9pt」的效果更加美觀。
BackColor:White。更加美觀,特別是在Win10上。
ForeColor:Black。爲了防止被某些系統主題影響而顯示的不是黑色。
FormBorderStyle:FixedDialog。使用戶不可調用窗口尺寸。
MaximizeBox:False。不顯示最大化按鈕。
MinimizeBox:False。不顯示最小化按鈕。
ShowIcon:False。不顯示窗口圖標。
ShowInTaskbar:False。不在任務欄上顯示圖標。
TopMost:True。置頂顯示窗口。
這裏須要說明一下,在添加控件時,若是如本文這樣窗體與自定義控件工程在同一個解決方案中,那麼在工具欄的最上方會自動顯示當前工具中的自定義控件,選中便可使用。
若是是窗體與自定義控件工程不在同一個解決方案中,好比引用的是自定義控件的DLL文件,那麼就須要將自定義控件DLL拖到工具欄上,此時工具欄上就會顯示出裏面的自定義控件。
控件:LProgressBar
關鍵屬性:
控件:LProgressBar
關鍵屬性:
控件:LLabel
關鍵屬性:
控件:LLabel
關鍵屬性:
控件:Button
關鍵屬性:
這裏說下lbl_Main和lbl_Child爲何不使用原生Label控件,而使用自定義LLabel控件。
由於在實際運行時,窗口大小是固定不變的,因此若是內容過多時,若是使用原生Label,就會在鼠標移上去後顯示懸浮提示,對總體外觀有所影響。若是內容變化快的話,懸浮提示也會頻繁顯示,但提示的文本卻早已過去,沒有提示的意義。
因此此處使用了基於原生控件改造的自定義控件:LLabel。(詳見:[C#] (原創)一步一步教你自定義控件——05,Label(原生控件) )
這樣經過屬性」L_EnableAutoTip=False「,就能夠再也不顯示懸浮提示。
對於耗時操做,有的時候是可讓用戶取消的;而有的時候,則是不能讓用戶取消。因此須要一個屬性去控制是否顯示「取消」按鈕。
同時,爲了美觀,在不顯示「取消」按鈕時,調整窗口高度到合適位置。
一些操做的進度是已知的,好比下載進度、複製進度;而有一些操做的的進度是未知的,好比查詢操做、調用其餘耗時任務等。
針對進度已知仍是進度未知,則進度條的樣式也須要有相應的改變。
當前進度等待窗口的標題
默認的主進度文本
由於大部分時候只須要一個進度,因此子進度條默認是不顯示的。並且,子進度條的做用決定了子進度條自己是能夠靈活顯示/不顯示的。
本屬性只是提供一個初始化的狀態。
由於進度等待窗口是一個單獨的窗體,而耗時操做也是在本窗口中執行,因此就須要進行數據的交互,而此參數便是爲了進行數據的交互。
爲了方便調用,爲窗口增長一帶參數的構造函數。
這裏給你們一個小技巧,在添加構造函數時,能夠借用VS的「快速操做和重構...」功能來快速生成構造函數。
本篇中執行耗時操做所採用的方法是開一新線程去執行,此方法很是簡單且使用方便,因此須要添加一個事件,以讓調用者在事件中執行耗時任務。
由於採用的是線程+事件,因此須要開放一些公共方法,以供調用者在事件實現中使用。
此方法用於更新主進度文本的內容。
(1),在方法中判斷本次更新文本是否與當前顯示文本是否一致:if(sMsg!=sLastMainMsg,是爲了減小沒必要要的賦值,減小閃爍,提升性能。(下同將再也不贅述)
(2),由於是在新線程中操做控件,因此若是直接操做控件的話,好比給控件賦值,將會提示「線程間操做無效。從不是建立控件'XXX'的線程訪問它」的錯誤,這種狀況下須要經過委託的方式去去操做控件。(固然也可使用不安全代碼去解除這種限制,但不推薦使用。)(下同將再也不贅述)
此方法用於在主進度條是進度已知時,更新主進度條的進度。
此方法用於更新子進度文本。
此方法用於在子進度條是進度已知時,更新子進度條的進度。
由於子進度條是靈活顯示的,因此提供本方法去改變進度條的顯示狀態。
由於子進度條是靈活顯示的,因此提供本方法去改變進度條的樣式,是進度已知時樣式仍是進度未知時樣式。
當是進度未知時,要自動啓動進度條動畫。
在事件中實現操做時,可使用本方法手動結束等待窗口。
在窗口加載時,咱們要知足如下條件:
(1),爲了更加美觀,因此咱們不會隱藏掉「關閉」按鈕,可是「關閉」按鈕會和「取消」按鈕功能相沖突,特別是在不能取消時。
因此咱們要將「關閉」按鈕無效化。主要使用到了系統API:GetSystemMenu和RemoveMenu
(2),若是是進度未知時,要令主進度條開始動畫。
(3),開啓新線程。此線程便是用來執行耗時任務的,因此要在此線程方法中觸發事件委託,以供調用者實現。
因此,加載的實現以下:
點擊「取消」時,要知足如下幾個條件:
(1),若是主進度條是進度未知,則中止進度條動畫。
(2),安全退出。
因此,「取消」按鈕的實現以下:
(1),新建窗體,添加LSwitchButton、Button、Label,以下:
(2),在「進度窗口」點擊事件中調用進度等待窗口。
(3),實現耗時任務
(4),運行
本篇所實現的進度等待窗口,技術上很簡單,但在美觀上、功能上並不弱,並且使用起來也簡單。做爲平常使用也是足夠的。
本篇文章的目的更多的是爲了給你們一個使用自定義控件的例子,畢竟自定義控件要在實際的應用中才能體現出價值。
不要被常規思惟所束縛,相信本身所掌握的知識。