一、前言
技術沒有先進與落后,只有合適與不合適,
在程式當中,經常有耗時較長的操作,為了給用戶更好的體驗,就需要給用戶一個及時的反饋,這種時候就需要用到進度等待視窗,
實作進度等待視窗的技術有很多,比如:BackgroundWorker、Thread等,
不過技術不是難點,難點在于怎么使等待視窗美觀實用,所以本文中就基于前幾篇的自定義控制元件:LProgressBar和LLabel,去實作進度等視窗,
相關文章:
[C#] (原創)一步一步教你自定義控制元件——04,ProgressBar(進度條)
[C#] (原創)一步一步教你自定義控制元件——05,Label(原生控制元件)
相信看完的你,一定會有所識訓,
本文地址:https://www.cnblogs.com/lesliexin/p/14121618.html
二、前期分析
(一)為什么需要進度等視窗?
為了在執行耗時操作時,給用戶更好的、更直觀的體驗,
(二)預期功能效果
1,功能
(1),支持“取消”操作,當然也支持“不能取消”操作,
(2),支持進度明確與進度不明確時顯示不同樣式,
(3),支持明細進度,
2,效果
Win7:


Win10:


三、開始實作
(一)布局表單
1,新建表單
(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,置頂顯示視窗,
2,添加控制元件
這里需要說明一下,在添加控制元件時,如果如本文這樣表單與自定義控制元件工程在同一個解決方案中,那么在工具列的最上方會自動顯示當前工具中的自定義控制元件,選中即可使用,

如果是表單與自定義控制元件工程不在同一個解決方案中,比如參考的是自定義控制元件的DLL檔案,那么就需要將自定義控制元件DLL拖到工具列上,此時工具列上就會顯示出里面的自定義控制元件,

(1)總體控制元件布局

(2)lPBar_Main(主進度)
控制元件:LProgressBar
關鍵屬性:

(3)lPBar_Child(子進度)
控制元件:LProgressBar
關鍵屬性:

(4)lbl_Main(主進度文本)
控制元件:LLabel
關鍵屬性:

(5)lbl_Child(子進度文本)
控制元件:LLabel
關鍵屬性:

(6)btn_Cancel(取消按鈕)
控制元件:Button
關鍵屬性:

(7)相關說明
這里說下lbl_Main和lbl_Child為什么不使用原生Label控制元件,而使用自定義LLabel控制元件,
因為在實際運行時,視窗大小是固定不變的,所以如果內容過多時,如果使用原生Label,就會在滑鼠移上去后顯示懸浮提示,對整體外觀有所影響,如果內容變化快的話,懸浮提示也會頻繁顯示,但提示的文本卻早已過去,沒有提示的意義,
所以此處使用了基于原生控制元件改造的自定義控制元件:LLabel,(詳見:[C#] (原創)一步一步教你自定義控制元件——05,Label(原生控制元件) )
這樣通過屬性”L_EnableAutoTip=False“,就可以不再顯示懸浮提示,
(二)添加屬性
1,是否顯示“取消”按鈕
對于耗時操作,有的時候是可以讓用戶取消的;而有的時候,則是不能讓用戶取消,所以需要一個屬性去控制是否顯示“取消”按鈕,
同時,為了美觀,在不顯示“取消”按鈕時,調整視窗高度到合適位置,

2,主進度條模式(進度已知/進度未知)
一些操作的進度是已知的,比如下載進度、復制進度;而有一些操作的的進度是未知的,比如查詢操作、呼叫其他耗時任務等,
針對進度已知還是進度未知,則進度條的樣式也需要有相應的改變,

3,視窗標題
當前進度等待視窗的標題

4,默認顯示的主進度文本
默認的主進度文本

5,是否顯示子進度條
因為大部分時候只需要一個進度,所以子進度條默認是不顯示的,而且,子進度條的作用決定了子進度條本身是可以靈活顯示/不顯示的,
本屬性只是提供一個初始化的狀態,

6,自定義引數
因為進度等待視窗是一個單獨的表單,而耗時操作也是在本視窗中執行,所以就需要進行資料的互動,而此引數即是為了進行資料的互動,
(三)添加建構式
為了方便呼叫,為視窗增加一帶引數的建構式,
這里給大家一個小技巧,在添加建構式時,可以借用VS的“快速操作和重構...”功能來快速生成建構式,

(四)添加事件
本篇中執行耗時操作所采用的方法是開一新執行緒去執行,此方法非常簡單且使用方便,所以需要添加一個事件,以讓呼叫者在事件中執行耗時任務,

(五)添加公共方法
因為采用的是執行緒+事件,所以需要開放一些公共方法,以供呼叫者在事件實作中使用,
1,更新主進度文本
此方法用于更新主進度文本的內容,

(1),在方法中判斷本次更新文本是否與當前顯示文本是否一致:if(sMsg!=sLastMainMsg,是為了減少不必要的賦值,減少閃爍,提高性能,(下同將不再贅述)
(2),因為是在新執行緒中操作控制元件,所以如果直接操作控制元件的話,比如給控制元件賦值,將會提示“執行緒間操作無效,從不是創建控制元件'XXX'的執行緒訪問它”的錯誤,這種情況下需要通過委托的方式去去操作控制元件,(當然也可以使用不安全代碼去解除這種限制,但不推薦使用,)(下同將不再贅述)

2,更新主進度條進度值
此方法用于在主進度條是進度已知時,更新主進度條的進度,


3,更新子進度文本
此方法用于更新子進度文本,


4,更新子進度條進度值
此方法用于在子進度條是進度已知時,更新子進度條的進度,


5,改變子進度條顯示狀態
因為子進度條是靈活顯示的,所以提供本方法去改變進度條的顯示狀態,


6,改變子進度條樣式(進度已知/進度未知)
因為子進度條是靈活顯示的,所以提供本方法去改變進度條的樣式,是進度已知時樣式還是進度未知時樣式,
當是進度未知時,要自動啟動進度條影片,



7,退出
在事件中實作操作時,可以使用本方法手動結束等待視窗,

(六)事件實作
1,視窗加載事件
在視窗加載時,我們要滿足以下條件:
(1),為了更加美觀,所以我們不會隱藏掉“關閉”按鈕,但是“關閉”按鈕會和“取消”按鈕功能相沖突,特別是在不能取消時,
所以我們要將“關閉”按鈕無效化,主要使用到了系統API:GetSystemMenu和RemoveMenu

(2),如果是進度未知時,要令主進度條開始影片,
(3),開啟新執行緒,此執行緒即是用來執行耗時任務的,所以要在此執行緒方法中觸發事件委托,以供呼叫者實作,

所以,加載的實作如下:

2,“取消”按鈕事件
點擊“取消”時,要滿足以下幾個條件:
(1),如果主進度條是進度未知,則停止進度條影片,
(2),安全退出,
所以,“取消”按鈕的實作如下:

四、效果演示
(1),新建表單,添加LSwitchButton、Button、Label,如下:

(2),在“進度視窗”點擊事件中呼叫進度等待視窗,

(3),實作耗時任務

(4),運行

五、結束語
本篇所實作的進度等待視窗,技術上很簡單,但在美觀上、功能上并不弱,而且使用起來也簡單,作為日常使用也是足夠的,
本篇文章的目的更多的是為了給大家一個使用自定義控制元件的例子,畢竟自定義控制元件要在實際的應用中才能體現出價值,
不要被常規思維所束縛,相信自己所掌握的知識,
六、源代碼及工程下載
https://files.cnblogs.com/files/lesliexin/05,LProgress.7z
轉載請註明出處,本文鏈接:https://www.uj5u.com/net/239851.html
標籤:.NET技术
上一篇:區塊鏈騙局-礦機模式之資金盤
