概述,上次我们介绍了半遮挡式的遮罩层,本次我们介绍整个窗体的遮盖层,在winform中我们也完成这样的操作,提高用户的体验感和操作性,避免不必要的操作.

首先,我们需要新建一个窗体,做如下设置,如下代码:

   1:  namespace FlexGridLoading
   2:  {
   3:      public partial class FrmProcessing : Form
   4:      {
   5:          private static Image m_Image = null;
   6:          private EventHandler evtHandler = null;
   7:          private ParameterizedThreadStart workAction = null;
   8:          private object workActionArg = null;
   9:          private Thread workThread = null;
  10:          public string Message
  11:          {
  12:              get
  13:              {
  14:                  return lbMessage.Text;
  15:              }
  16:              set
  17:              {
  18:                  lbMessage.Text = value;
  19:              }
  20:          }
  21:   
  22:          public bool WorkCompleted = false;
  23:          public Exception WorkException
  24:          { get; private set; }
  25:          public void SetWorkAction(ParameterizedThreadStart workAction, object arg)
  26:          {
  27:              this.workAction = workAction;
  28:              this.workActionArg = arg;
  29:          }
  30:   
  31:          public FrmProcessing(string msg)
  32:          {
  33:              InitializeComponent();
  34:              this.Message = msg;
  35:          }
  36:   
  37:          protected override void OnPaint(PaintEventArgs e)
  38:          {
  39:              base.OnPaint(e);
  40:   
  41:              if (m_Image != null)
  42:              {
  43:                  //获得当前gif动画下一步要渲染的帧。
  44:                  UpdateImage();
  45:   
  46:                  //将获得的当前gif动画需要渲染的帧显示在界面上的某个位置。
  47:                  int x = (int)(panImage.ClientRectangle.Width - m_Image.Width) / 2;
  48:                  int y = 0;
  49:                  //e.Graphics.DrawImage(m_Image, new Rectangle(x, y, m_Image.Width, m_Image.Height));
  50:                  panImage.CreateGraphics().DrawImage(m_Image, new Rectangle(x, y, m_Image.Width, m_Image.Height));
  51:              }
  52:              if (this.WorkCompleted)
  53:              {
  54:                  this.Close();
  55:              }
  56:          }
  57:          private void FrmProcessing_Load(object sender, EventArgs e)
  58:          {
  59:              if (this.Owner != null)
  60:              {
  61:                  this.StartPosition = FormStartPosition.Manual;
  62:                  this.Location = new Point(this.Owner.Left, this.Owner.Top);
  63:                  //MessageBox.Show(string.Format("X={0},Y={1}", this.Owner.Left, this.Owner.Top));
  64:                  this.Width = this.Owner.Width;
  65:                  this.Height = this.Owner.Height;
  66:              }
  67:              else
  68:              {
  69:                  Rectangle screenRect = Screen.PrimaryScreen.WorkingArea;
  70:                  this.Location = new Point((screenRect.Width - this.Width) / 2, (screenRect.Height - this.Height) / 2);
  71:              }
  72:   
  73:              //为委托关联一个处理方法
  74:              evtHandler = new EventHandler(OnImageAnimate);
  75:   
  76:              if (m_Image == null)
  77:              {
  78:                  Assembly assy = Assembly.GetExecutingAssembly();
  79:                  //获取要加载的gif动画文件
  80:                  m_Image = FlexGridLoading.Properties.Resources.loading; ;
  81:              }
  82:              //调用开始动画方法
  83:              BeginAnimate();
  84:          }
  85:   
  86:   
  87:          //开始动画方法
  88:   
  89:          private void BeginAnimate()
  90:          {
  91:              if (m_Image != null)
  92:              {
  93:                  //当gif动画每隔一定时间后,都会变换一帧,那么就会触发一事件,该方法就是将当前image每变换一帧时,都会调用当前这个委托所关联的方法。
  94:                  ImageAnimator.Animate(m_Image, evtHandler);
  95:              }
  96:          }
  97:   
  98:          //委托所关联的方法
  99:   
 100:          private void OnImageAnimate(Object sender, EventArgs e)
 101:          {
 102:              //该方法中,只是使得当前这个winform重绘,然后去调用该winform的OnPaint()方法进行重绘)
 103:              this.Invalidate();
 104:          }
 105:   
 106:          //获得当前gif动画的下一步需要渲染的帧,当下一步任何对当前gif动画的操作都是对该帧进行操作)
 107:   
 108:          private void UpdateImage()
 109:          {
 110:              ImageAnimator.UpdateFrames(m_Image);
 111:          }
 112:   
 113:          //关闭显示动画,该方法可以在winform关闭时,或者某个按钮的触发事件中进行调用,以停止渲染当前gif动画。
 114:   
 115:          private void StopAnimate()
 116:          {
 117:              m_Image = null;
 118:              ImageAnimator.StopAnimate(m_Image, evtHandler);
 119:          }
 120:   
 121:          private void FrmProcessing_Shown(object sender, EventArgs e)
 122:          {
 123:              if (this.workAction != null)
 124:              {
 125:                  workThread = new Thread(ExecWorkAction);
 126:                  workThread.IsBackground = true;
 127:                  workThread.Start();
 128:              }
 129:          }
 130:   
 131:          private void ExecWorkAction()
 132:          {
 133:              try
 134:              {
 135:                  var workTask = new Task((arg) =>
 136:                  {
 137:                      this.workAction(arg);
 138:                  },
 139:                              this.workActionArg);
 140:   
 141:                  workTask.Start();
 142:                  Task.WaitAll(workTask);
 143:              }
 144:              catch (Exception ex)
 145:              {
 146:                  this.WorkException = ex;
 147:              }
 148:              finally
 149:              {
 150:                  this.WorkCompleted = true;
 151:              }
 152:   
 153:          }
 154:      }
 155:  }

然后,为了我们方便调用不用在每个页面调用时去new并且设置很多属性,我们需要调用一个通用的Command类

   1:  namespace FlexGridLoading
   2:  {
   3:      public static class Common
   4:      {
   5:   
   6:          public static void ShowProcessing(string msg, Form owner, ParameterizedThreadStart work, object workArg = null)
   7:          {
   8:              FrmProcessing processingForm = new FrmProcessing(msg);
   9:              dynamic expObj = new ExpandoObject();
  10:              expObj.Form = processingForm;
  11:              expObj.WorkArg = workArg;
  12:              processingForm.SetWorkAction(work, expObj);
  13:              processingForm.ShowDialog(owner);
  14:              if (processingForm.WorkException != null)
  15:              {
  16:                  throw processingForm.WorkException;
  17:              }
  18:          }
  19:   
  20:   
  21:      }
  22:  }
 
最后我们需要在加载Grid耗时的地方添加这样的代码,
   1:          private void button1_Click(object sender, EventArgs e)
   2:          {
   3:              Common.ShowProcessing("正在处理中,请稍候...", this, (obj) =>
   4:              {
   5:                  //这里写处理耗时的代码,代码处理完成则自动关闭该窗口
   6:                  Thread.Sleep(5000);
   7:              }, null);
   8:          }
运行的结果如图:
image

如果你有疑问,可以到GCDN获得技术支持:

http://gcdn.grapecity.com.cn/showforum-68.html

GCDNhttp://gcdn.grapecity.com.cn/

官方网站/developer