The Winform application implements a general mask layer and a winform mask.

Source: Internet
Author: User

The Winform application implements a general mask layer and a winform mask.

On the WEB, when we need to process big data or complex logic, because of the long time consumption, we usually display a translucent mask layer on the page during processing, put an icon or prompt above: processing... in this way, the user experience is better. However, in Winform client programs, the processing of the mask layer is usually not that simple or nice-looking. What I want to explain today is, the Winform universal mask layer I implemented can implement a mask layer similar to that on the WEB. It can be transparent and Display Dynamic images and text. How can this be achieved, I will explain it one by one.

First, we need to clarify the effect we want to achieve: transparent + dynamic icons + Text

Transparent: This is simple. You only need to set the Opacity of the form to a value lower than 100%. Here I use 85%;

Dynamic icons: This is relatively complicated because Winform does not currently have ready-made controls for displaying animations directly. Fortunately, ImageAnimator is a component that supports frame-by-frame animation, we only need to bind the image to the Animate method of ImageAnimator (that is, ImageAnimator. animate (m_Image, EventHandler delegate);), and then rewrite the OnPaint form. For specific code implementation, see the source code published below.

Text: This is simple, just put it in a Label Control

In order to keep the icon and text in the center position (regardless of the size), I use a TableLayoutPanel, which is divided into two rows. The Label is placed upstream and set to center, place the Panel downstream to provide the animation area.

Complete code implementation ):

Using System; using System. collections. generic; using System. componentModel; using System. data; using System. drawing; using System. linq; using System. text; using System. windows. forms; using System. reflection; using System. threading; using System. threading. tasks; namespace TEMS {public partial class FrmProcessing: Form {private static Image m_Image = null; private EventHandler evtHandler = null; private Para MeterizedThreadStart workAction = null; private object workActionArg = null; private Thread workThread = null; public string Message {get {return lbMessage. text;} set {lbMessage. text = value ;}} public bool WorkCompleted = false; public Exception WorkException {get; private set;} public void SetWorkAction (ParameterizedThreadStart workAction, object arg) {this. workAction = workAction; this. WorkActionArg = arg;} public FrmProcessing (string msg) {InitializeComponent (); this. message = msg;} protected override void OnPaint (PaintEventArgs e) {base. onPaint (e); if (m_Image! = Null) {// obtain the frame to be rendered next to the current GIF animation. UpdateImage (); // display the frames to be rendered in the current GIF animation at a certain position on the interface. Int x = (int) (panImage. clientRectangle. width-m_Image.Width)/2; int y = 0; // e. graphics. drawImage (m_Image, new Rectangle (x, y, m_Image.Width, m_Image.Height); panImage. createGraphics (). drawImage (m_Image, new Rectangle (x, y, m_Image.Width, m_Image.Height);} if (this. workCompleted) {this. close () ;}} private void FrmProcessing_Load (object sender, EventArgs e) {if (this. owner! = Null) {this. startPosition = FormStartPosition. manual; this. location = new Point (this. owner. left, this. owner. top); // MessageBox. show (string. format ("X = {0}, Y = {1}", this. owner. left, this. owner. top); this. width = this. owner. width; this. height = this. owner. height;} else {Rectangle screenRect = Screen. primaryScreen. workingArea; this. location = new Point (screenRect. width-this. width)/2, (screenRe Ct. height-this. height)/2);} // associate the delegate with a processing method evtHandler = new EventHandler (OnImageAnimate); if (m_Image = null) {Assembly assy = Assembly. getExecutingAssembly (); // get the GIF animation file to be loaded m_Image = Image. fromStream (assy. getManifestResourceStream (assy. getName (). name + ".Resources.loading2.gif");} // call the start animation method BeginAnimate ();} // start the animation method private void BeginAnimate () {if (m_Image! = Null) {// when the GIF animation changes a frame every certain time, an event is triggered. This method is used to change each frame of the current image, the method associated with the current delegate is called. ImageAnimator. animate (m_Image, evtHandler) ;}// delegate the associated method private void OnImageAnimate (Object sender, EventArgs e) {// In this method, this only causes the current winform to be repainted, and then calls the OnPaint () method of the winform to re-paint) this. invalidate () ;}// get the frame to be rendered next to the current GIF animation. When any next operation on the current GIF animation is performed on this frame, private void UpdateImage () {ImageAnimator. updateFrames (m_Image);} // close the display animation. This method can be called when winform is disabled or when a button is triggered to stop rendering the current GIF animation. Private void StopAnimate () {m_Image = null; ImageAnimator. StopAnimate (m_Image, evtHandler);} private void FrmProcessing_Shown (object sender, EventArgs e) {if (this. workAction! = Null) {workThread = new Thread (ExecWorkAction); workThread. isBackground = true; workThread. start () ;}} private void ExecWorkAction () {try {var workTask = new Task (arg) =>{ this. workAction (arg) ;}, this. workActionArg); workTask. start (); Task. waitAll (workTask);} catch (Exception ex) {this. workException = ex;} finally {this. workCompleted = true ;}}}}

The following is the automatically generated code:

Namespace TEMS {partial class FrmProcessing {// <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. tableLayoutPanel1 = new System. windows. forms. tableLayoutPanel (); this. lbMessage = new System. windows. forms. label (); this. panImage = new System. windows. forms. panel (); this. tableLayoutPanel1.SuspendLayout (); this. suspendLayout (); // tableLayoutPanel1 // this. tableLayoutPanel1.ColumnCount = 1; this. tableLayoutPanel1.ColumnStyles. add (new System. windows. forms. columnStyle (); this. tableLayoutPanel1.Controls. add (this. lbMessage, 0, 0); this. tableLayoutPanel1.Controls. add (this. panImage, 0, 1); this. tableLayoutPanel1.Dock = System. windows. forms. dockStyle. fill; this. tableLayoutPanel1.Location = new System. drawing. point (0, 0); this. tableLayoutPanel1.Name = "tableLayoutPanel1"; this. tableLayoutPanel1.RowCount = 2; this. tableLayoutPanel1.RowStyles. add (new System. windows. forms. rowStyle (System. windows. forms. sizeType. percent, 50F); this. tableLayoutPanel1.RowStyles. add (new System. windows. forms. rowStyle (System. windows. forms. sizeType. percent, 50F); this. tableLayoutPanel1.Size = new System. drawing. size (582,318); this. tableLayoutPanel1.TabIndex = 1; // lbMessage // this. lbMessage. backColor = System. drawing. color. transparent; this. lbMessage. dock = System. windows. forms. dockStyle. fill; this. lbMessage. font = new System. drawing. font ("", 14.25F, System. drawing. fontStyle. regular, System. drawing. graphicsUnit. point, (byte) (134); this. lbMessage. location = new System. drawing. point (3, 0); this. lbMessage. name = "lbMessage"; this. lbMessage. padding = new System. windows. forms. padding (0, 0, 0, 30); this. lbMessage. size = new System. drawing. size (576,159); this. lbMessage. tabIndex = 1; this. lbMessage. text = "lbMessage \ r \ nadsfadsf"; this. lbMessage. textAlign = System. drawing. contentAlignment. botshortenter; // panImage // this. panImage. dock = System. windows. forms. dockStyle. fill; this. panImage. location = new System. drawing. points (3,162); this. panImage. name = "panImage"; this. panImage. size = new System. drawing. size (576,153); this. panImage. tabIndex = 2; // FrmProcessing // this. autoScaleDimensions = new System. drawing. sizeF (6F, 12F); this. autoScaleMode = System. windows. forms. autoScaleMode. font; this. backColor = System. drawing. systemColors. control; this. clientSize = new System. drawing. size (582,318); this. controls. add (this. tableLayoutPanel1); this. cursor = System. windows. forms. cursors. waitCursor; this. formBorderStyle = System. windows. forms. formBorderStyle. none; this. name = "FrmProcessing"; this. opacity = 0.85D; this. startPosition = System. windows. forms. formStartPosition. manual; this. text = "FrmProcessing"; this. load + = new System. eventHandler (this. frmProcessing_Load); this. shown + = new System. eventHandler (this. frmProcessing_Shown); this. tableLayoutPanel1.ResumeLayout (false); this. resumeLayout (false);} # endregion private System. windows. forms. tableLayoutPanel tableLayoutPanel1; private System. windows. forms. label lbMessage; private System. windows. forms. panel panImage ;}}View Code

In the code, the SetWorkAction method is used to set the delegate method to be processed asynchronously. After the form is displayed (FrmProcessing_Shown), a new thread is created to process the time-consuming logic code segment, with a WorkCompleted attribute, this mainly indicates that the processing time-consuming logic code has been completed (whether or not an error is reported). When the window weight is painted (OnPaint), it will continuously judge whether the value is true, if true, the current window is closed.

In addition, the OnPaint method of Panel is not rewritten because although motion graphs can be displayed, partial re-painting still requires the screen weight to be painted due to the flashing of motion graphs.

For ease of use, I have also defined a general method specifically used to display the form of the mask layer. The method is defined as follows:

    public static class Common    {        public static void ShowProcessing(string msg, Form owner, ParameterizedThreadStart work, object workArg = null)        {            FrmProcessing processingForm = new FrmProcessing(msg);            dynamic expObj = new ExpandoObject();            expObj.Form = processingForm;            expObj.WorkArg = workArg;            processingForm.SetWorkAction(work, expObj);            processingForm.ShowDialog(owner);            if (processingForm.WorkException != null)            {                throw processingForm.WorkException;            }        }            }

It is easy to use now, as shown below:

Common. showProcessing ("processing... please wait... ", this, (obj) =>{// write the time-consuming code here. The window is automatically closed when the code processing is complete}, null );

The effect is as follows:

You can copy the above Code directly to the new form for immediate use. If there are any deficiencies in the above Code, please comment and point out, thank you!

Related Article

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.