做winform项目时,有可能用到异步耗时加载数据啥的,这个时候就需要我们封装一个正在加载的效果。下面是实现思路:
步骤一:把当前form界面使用句柄的方式截图出一个图片,这个图片会在下面用到,使用句柄获取截图的方式会在最后代码展示里附录上。
步骤二:定义一个和当前form一样大小的panel,让这个panel带到当前form的Z顺序的最前面,把当前界面覆盖住,这样当前form的控件就不可点击。
步骤三:把从步骤一获取的图片设置为步骤而定义的panel的背景,这样让这个panel看起来是和界面一样的。
步骤四:在panel中间定义一个新的panel放置加载Loading图片和文字。
下面是封装的代码:
1 public partial class customForm : Form 2 { 3 #region properties 4 5 /// <summary> 6 /// 显示的等待框 7 /// </summary> 8 private System.Windows.Forms.Panel waitingBox; 9 10 Panel waitingBoxInnerPanel; 11 12 Label waitingBoxLab; 13 14 private PictureBox _waitPicBox; 15 16 private bool _IsWaitingBoxCreated = false; 17 18 private bool _isOnWaiting = false; 19 20 #endregion 21 22 public baseLogin() 23 { 24 InitializeComponent(); 25 26 //设置程序图标 27 Icon = Icon.FromHandle(Properties.Resources.icon.GetHicon()); 28 29 //Task.Delay(1000).ContinueWith((t) => { CreateWaitingBox(); }); 30 } 31 32 public void ShowProgress(string message = "", int second = 60) 33 { 34 if (_isOnWaiting) 35 { 36 return; 37 } 38 _isOnWaiting = true; 39 this.Invoke(new Action(() => 40 { 41 CreateWaitingBox(); 42 SetWaitingMessage(message); 43 waitingBox.Visible = true; 44 waitingBox.BringToFront(); 45 })); 46 } 47 48 public void ShowMessage(string message = "", int second = 2) 49 { 50 if (_isOnWaiting) 51 { 52 return; 53 } 54 _isOnWaiting = true; 55 CreateWaitingBox(); 56 SetWaitingMessage(message); 57 if (IsHandleCreated) 58 { 59 this.Invoke(new Action(() => 60 { 61 waitingBox.Visible = true; 62 waitingBox.BringToFront(); 63 })); 64 Task.Delay(second * 1000).ContinueWith((t) => 65 { 66 DisMissMessage(); 67 }); 68 } 69 } 70 71 public void DisMissMessage() 72 { 73 if (waitingBox == null) 74 { 75 return; 76 } 77 if (!waitingBox.Visible) 78 { 79 return; 80 } 81 else 82 { 83 this.Invoke(new Action(() => 84 { 85 waitingBox.Visible = false; 86 this._isOnWaiting = false; 87 })); 88 } 89 } 90 91 #region private 92 93 private void CreateWaitingBox() 94 { 95 96 if (this.IsHandleCreated) 97 { 98 this.Invoke(new Action(() => 99 { 100 //Image backImg = this.CreateBacgroundImage(); 101 Control frm = this; 102 Image backImg = CaptureImage(ref frm); 103 if (!_IsWaitingBoxCreated) 104 { 105 waitingBox = new Panel() 106 { 107 Visible = false, 108 }; 109 waitingBox.BackColor = Color.FromArgb(234, 244, 252); 110 111 waitingBoxInnerPanel = new Panel(); 112 waitingBoxInnerPanel.Width = 280; 113 waitingBoxInnerPanel.Height = 80; 114 waitingBoxInnerPanel.BackColor = Color.Gray; 115 waitingBoxInnerPanel.Padding = new Padding(8, 5, 5, 5); 116 117 waitingBoxLab = new Label(); 118 waitingBoxLab.TextAlign = ContentAlignment.MiddleLeft; 119 waitingBoxLab.AutoEllipsis = true; 120 waitingBoxLab.Dock = DockStyle.Fill; 121 122 waitingBoxInnerPanel.Controls.Add(waitingBoxLab); 123 124 PictureBox pb = new PictureBox(); 125 pb.Dock = DockStyle.Left; 126 pb.Size = new System.Drawing.Size(72, 70); 127 pb.Image = Properties.Resources.loading; 128 pb.Margin = new System.Windows.Forms.Padding(3, 3, 20, 3); 129 pb.SizeMode = PictureBoxSizeMode.StretchImage; 130 this._waitPicBox = pb; 131 waitingBoxInnerPanel.Controls.Add(pb); 132 133 waitingBox.Controls.Add(waitingBoxInnerPanel); 134 //waitingBox.BringToFront(); 135 if (!this.Controls.Contains(waitingBox)) 136 { 137 this.Controls.Add(waitingBox); 138 } 139 //waitingBox.Show(); 140 141 this._IsWaitingBoxCreated = true; 142 143 } 144 145 Rectangle rect = this.ClientRectangle; 146 waitingBox.Width = rect.Width; 147 waitingBox.Height = rect.Height; 148 waitingBox.Location = new Point(rect.X, rect.Y); 149 150 waitingBox.BackgroundImage = backImg; 151 waitingBox.BackgroundImageLayout = ImageLayout.Stretch; 152 })); 153 } 154 } 155 156 /// <summary> 157 /// 设置等待显示的信息 158 /// </summary> 159 /// <param name="message">The message.</param> 160 /// User:Ryan CreateTime:2012-8-5 16:22. 161 private void SetWaitingMessage(string message) 162 { 163 if (this.IsHandleCreated) 164 { 165 this.Invoke(new Action(() => 166 { 167 message = " " + message.Trim(); 168 if (this.waitingBoxLab != null && this.waitingBoxInnerPanel != null) 169 { 170 using (Graphics g = this.CreateGraphics()) 171 { 172 int w = Convert.ToInt32(g.MeasureString(message, this.waitingBoxLab.Font).Width); 173 w = w >= 200 ? w : 200; 174 w = this.Width - 100 >= w ? w : this.Width - 100; 175 this.waitingBoxInnerPanel.Width = w + 60; 176 waitingBoxInnerPanel.Location = new Point(waitingBox.Bounds.X + waitingBox.Width / 2 - waitingBoxInnerPanel.Width / 2, 177 waitingBox.Bounds.Y + waitingBox.Height / 2 - waitingBoxInnerPanel.Height); 178 } 179 180 this.waitingBoxLab.Text = message; 181 } 182 })); 183 } 184 } 185 186 private Bitmap CreateBacgroundImage() 187 { 188 Rectangle rect = this.ClientRectangle; 189 int w = rect.Width; 190 int h = rect.Height; 191 try 192 { 193 Bitmap img = new Bitmap(w, h); 194 using (Graphics g = Graphics.FromImage(img)) 195 { 196 g.CopyFromScreen(new Point(this.Location.X, this.Location.Y), new Point(0, 0), new Size(w, h)); 197 } 198 //img.Save("a.jpg"); 199 return img; 200 } 201 catch (Exception ex) 202 { 203 return null; 204 } 205 } 206 207 208 public Bitmap CaptureImage(ref Control c) 209 { 210 int hDC; 211 int sh; 212 int sw; 213 if (c == null) 214 { 215 hDC = GetDC(0); 216 sw = Screen.PrimaryScreen.Bounds.Width; 217 sh = Screen.PrimaryScreen.Bounds.Height; 218 } 219 else 220 { 221 hDC = GetDC((int)c.Handle); 222 sw = c.Width; 223 sh = c.Height; 224 } 225 int hMDC = CreateCompatibleDC(hDC); 226 int hBMP = CreateCompatibleBitmap(hDC, sw, sh); 227 int hBMPOld = SelectObject(hMDC, hBMP); 228 BitBlt(hMDC, 0, 0, sw, sh, hDC, 0, 0, 0xcc0020); 229 hBMP = SelectObject(hMDC, hBMPOld); 230 Bitmap result = Image.FromHbitmap(new IntPtr(hBMP)); 231 DeleteDC(hDC); 232 DeleteDC(hMDC); 233 DeleteObject(hBMP); 234 return result; 235 } 236 [DllImport("gdi32.dll", EntryPoint = "CreateCompatibleBitmap")] 237 public static extern int CreateCompatibleBitmap(int hdc, int nWidth, int nHeight); 238 [DllImport("gdi32.dll", EntryPoint = "CreateCompatibleDC")] 239 public static extern int CreateCompatibleDC(int hdc); 240 [DllImport("user32.dll", EntryPoint = "GetDC")] 241 public static extern int GetDC(int hwnd); 242 [DllImport("gdi32.dll", EntryPoint = "DeleteDC")] 243 public static extern int DeleteDC(int hdc); 244 [DllImport("gdi32.dll", EntryPoint = "SelectObject")] 245 public static extern int SelectObject(int hdc, int hObject); 246 [DllImport("gdi32.dll", EntryPoint = "DeleteObject")] 247 public static extern int DeleteObject(int hObject); 248 [DllImport("gdi32.dll", EntryPoint = "BitBlt")] 249 public static extern int BitBlt(int hDestDC, int x, int y, int nWidth, int nHeight, int hSrcDC, int xSrc, int ySrc, int dwRop); 250 251 252 #endregion 253 254 }
下面是示例代码:
1 public partial class Form1:customForm 2 { 3 private void button1_Click(object sender,EventArgs e) 4 { 5 ShowMessage("我是消息"); 6 } 7 }