The Winform application implements a common message window and a winform window.
I remember that I have published an article "Winform application for universal mask layer", which is a message window for transparent masks. The function focuses on animation display + message reminder, the results look cool, and I have re-designed the common message window in this article. The function focuses on message reminders and progress reports. Of course, if you have time, you can combine the two methods, this will be more perfect. I am still focusing on implementation functions here. Because the code is relatively simple, I directly paste all the code and you can directly copy it to the local for testing, if any problem is found, you can correct it or report it to me. I will improve it. Thank you!
Using System; using System. collections. generic; using System. componentModel; using System. data; using System. drawing; using System. text; using System. threading; using System. windows. forms; namespace WindowsFormsApplication1 {// <summary> // wait window: displays the message window in a friendly manner when processing time-consuming work. /// Author: Zuowenjun // Date: // URL: http://www.zuowenjun.cn /// </Summary> public partial class FRM_Waitting: Form {private SynchronizationContext formContext; public string Message {get {return labMessage. text;} set {labMessage. text = value ;}} public Action <WaittingForWorkObject> WorkAction {get; set;} public object WorkActionParam {get; set;} public Exception WorkException {get; private set ;} public class WaittingForWorkObject {private Send OrPostCallback UpdateMessageAction = null; public SynchronizationContext Context {get; private set;} public object UserData {get; private set;} public void UpdateMessage (string msg) {this. context. post (UpdateMessageAction, msg);} public WaittingForWorkObject (FRM_Waitting parentForm) {this. context = parentForm. formContext; this. userData = parentForm. workActionParam; this. updateMessageAction = Delegate (object o) {parentForm. message = o. toString () ;}}} public static void WaittingForWork (Action <WaittingForWorkObject> workAction, object workParam = null, string text = "Please wait", string message = "in system processing, please wait... ") {var waittingForm = new FRM_Waitting (text, message, workAction, workParam); waittingForm. showDialog (); if (waittingForm. workException! = Null) {throw waittingForm. workException ;}} public FRM_Waitting () {InitializeComponent ();} public FRM_Waitting (string text, string message, Action <WaittingForWorkObject> workAction, object workParam = null): this () {this. text = text; this. message = message; this. workAction = workAction; this. workActionParam = workParam;} private void FRM_Waitting_Load (object sender, EventArgs e) {} privat E void FRM_Waitting_Shown (object sender, EventArgs e) {formContext = SynchronizationContext. Current; if (WorkAction! = Null) {Thread workThread = new Thread (DoWork); workThread. isBackground = true; workThread. start () ;}} private void DoWork () {try {var wfObject = new WaittingForWorkObject (this); WorkAction (wfObject);} catch (Exception ex) {WorkException = ex ;} formContext. send (delegate (object o) {this. close () ;}, null );}}}
The following code is automatically generated by the system:
Namespace WindowsFormsApplication1 {partial class FRM_Waitting {// <summary> // Required designer variable. /// </summary> private System. componentModel. IContainer components = null; // <summary> // Clean up any resources being used. /// </summary> /// <param name = "disposing"> true if managed resources shocould be disposed; otherwise, false. </param> protected override void Dispose (bool disposing) {If (disposing & (components! = Null) {components. dispose ();} base. dispose (disposing );} # region Windows Form Designer generated code // <summary> // Required method for Designer support-do not modify // the contents of this method with the code editor. /// </summary> private void InitializeComponent () {this. labMessage = new System. windows. forms. label (); this. suspendLayout (); // labMessage // this. labMessage. dock = System. windows. forms. dockStyle. fill; this. labMessage. font = new System. drawing. font ("", 9.75F, System. drawing. fontStyle. regular, System. drawing. graphicsUnit. point, (byte) (134); this. labMessage. location = new System. drawing. point (0, 0); this. labMessage. name = "labMessage"; this. labMessage. padding = new System. windows. forms. padding (5); this. labMessage. size = new System. drawing. size (453,125); this. labMessage. tabIndex = 0; this. labMessage. text = "Message"; this. labMessage. textAlign = System. drawing. contentAlignment. middleCenter; this. labMessage. useWaitCursor = true; // FRM_Waitting // this. autoScaleDimensions = new System. drawing. sizeF (6F, 12F); this. autoScaleMode = System. windows. forms. autoScaleMode. font; this. clientSize = new System. drawing. size (453,125); this. controlBox = false; this. controls. add (this. labMessage); this. formBorderStyle = System. windows. forms. formBorderStyle. fixedSingle; this. name = "FRM_Waitting"; this. showIcon = false; this. showInTaskbar = false; this. startPosition = System. windows. forms. formStartPosition. centerParent; this. text = "FRM_Waitting"; this. useWaitCursor = true; this. load + = new System. eventHandler (this. FRM_Waitting_Load); this. shown + = new System. eventHandler (this. FRM_Waitting_Shown); this. resumeLayout (false);} # endregion private System. windows. forms. label labMessage ;}}
The above code is relatively simple. Here I will briefly describe the implementation principle of the message window:
1. encapsulate the time-consuming processing logic code into a delegate (Aciton <FRM_Waitting.WaittingForWorkObject> );
2. Obtain and save the current synchronization context so that the UI can be operated across threads;
3. Create and run a background thread and specify the thread to DoWork );
4. instantiate the WaittingForWorkObject object in the DoWork method, pass it to the delegate in 1, and then execute the delegate, so that time-consuming operations are processed in the background thread;
5. Use try catch to catch possible exceptions in the DoWork method. If an exception occurs, save it to the WorkException attribute;
6. After the execution is complete (whether or not an error is reported), send the message window closing command in the same context to close the message window;
7. Check whether the WorkException attribute is not empty in the static WaittingForWork method. If not, throw an error again, so that the main thread can know what exceptions have occurred;
Note: For compatibility.. NET 2.0 and later versions. The Code uses the anonymous method, instead of the Lambada expression. You can choose any one in actual use. The following test examples provide the new and old code writing methods, for comparison.
The following are various test examples:
/// <Summary> /// test: A message window is displayed. /// </summary> private void Test1 () {// the old mode is compatible. NET2.0 and later) FRM_Waitting.WaittingForWork (delegate (FRM_Waitting.WaittingForWorkObject o) {// write the time-consuming processing logic code here. The following describes the time-consuming Thread simulation. sleep (10*1000) ;}); // new method (. NET4.0 and above) // FRM_Waitting.WaittingForWork (o) => // {// write the time-consuming processing logic code here. below is the simulation time-consuming // Thread. sleep (10*1000 );//});}
The effect is as follows:
/// <Summary> /// test: A message window is displayed normally, and a custom message is displayed with the window title /// </summary> private void Test1_1 () {// old mode (compatible. NET2.0 and later) FRM_Waitting.WaittingForWork (delegate (FRM_Waitting.WaittingForWorkObject o) {// write the time-consuming processing logic code here. The following describes the time-consuming Thread simulation. sleep (10*1000);}, null, "guest please wait", "guest officer, the store is working hard for you. Please wait a moment... "); // new method (. NET4.0 and above) // FRM_Waitting.WaittingForWork (o) => // {// write the time-consuming processing logic code here. below is the simulation time-consuming // Thread. sleep (10*1000); //}, null, "guest please wait", "guest, the store is working hard for you. Please wait a moment... ");}
The effect is as follows:
/// <Summary> /// test: A message window is displayed normally and an error is thrown in the background thread, the error message is displayed on the foreground. // </summary> private void Test1_2 () {try {// the old mode is compatible. NET2.0 and above) // FRM_Waitting.WaittingForWork (delegate (FRM_Waitting.WaittingForWorkObject o) // write the time-consuming processing logic code here. The following is the simulation time-consuming // Thread. sleep (10*1000); // throw new Exception ("the error thrown in the background thread! "); //}); // New method (. NET4.0 and above) FRM_Waitting.WaittingForWork (o) =>{// write the time-consuming processing logic code here. The following describes the time-consuming Thread simulation. sleep (10*1000); throw new Exception ("the error thrown in the background thread! ") ;}) ;}Catch (Exception ex) {MessageBox. Show (" Exception occurred: "+ ex. Message );}}
The effect is as follows:
/// <Summary> /// test: The loading progress is displayed in the message window. /// </summary> private void Test2 () {// the old mode (compatible. NET2.0 and above) // FRM_Waitting.WaittingForWork (delegate (FRM_Waitting.WaittingForWorkObject o) // {// write the time-consuming processing logic code here. The following is the simulation time/for (int I = 1; I <= 10; I ++) // {// Thread. sleep (1000); // o. updateMessage (string. format ("{0} items in total, {1} items already loaded", 10, I); //}); // new method (. NET4.0 and above) FRM_Waitting.WaittingForWork (o) =>{// write the time-consuming processing logic code here. The following is the simulation time-consuming for (int I = 1; I <= 10; I ++) {Thread. sleep (1000); o. updateMessage (string. format ("{0} items in total, {1} items already loaded", 10, I ));}});}
The effect is as follows:
/// <Summary> /// test: The loading progress is displayed in the message window, and the loading progress is displayed in the main window (both non-message windows are supported) update the control content /// </summary> private void Test3 () {// the old method (compatible. NET2.0 and above) FRM_Waitting.WaittingForWork (delegate (FRM_Waitting.WaittingForWorkObject o) {// write the time-consuming processing logic code here. The following is the simulation time-consuming for (int I = 1; I <= 10; I ++) {Thread. sleep (1000); o. updateMessage (string. format ("{0} items in total, {1} items already loaded", 10, I); o. context. send (delegate (object d) {this. listBox1.Items. add (d) ;}, string. format ("{0} items in total, {1} items already loaded", 10, I) ;}}); // new method (. NET4.0 and above) // FRM_Waitting.WaittingForWork (o) => // {// write the time-consuming processing logic code here. below is the simulation time-consuming // for (int I = 1; I <= 10; I ++) // {// Thread. sleep (1000); // o. updateMessage (string. format ("{0} items in total, {1} items already loaded", 10, I); // o. context. send (d => this. listBox1.Items. add (d), string. format ("{0} items in total, {1} items already loaded", 10, I ));//}//});}
The effect is as follows:
After reading the test results above, what do you think is it that can meet your daily requirements? I think it can basically be met. Of course, if you find more situations, please leave a comment below.