创建不规则窗体,最好的做法是覆盖 Form 本身的绘制,自己用代码重绘。很多时候没有必要这么做。下面说几个比较有用的技巧。当然在winform中使用透明控件重叠是个头疼的问题,采用双缓冲是不能解决问题的。目前使用的的增加淡入淡出效果,解决窗体重绘时控件闪烁问题。
1.FadeForm
![](https://i-blog.csdnimg.cn/blog_migrate/8f900a89c6347c561fdf2122f13be562.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/961ddebeb323a10fe0623af514929fc1.gif)
1 using System;
2
3 using System.Drawing;
4
5 using System.Windows.Forms;
6
7 using SK.Common;
8
9
10
11 namespace SK
12 {
13
14 /// <summary>
15
16 /// 提供窗体的淡入淡出,此方式为了缓解窗体空间过多或者透明窗体叠加引起的过多重绘闪烁问题;
17
18 /// 利用拦截WindowMessages,来进行相应的淡入淡出处理
19
20 /// </summary>
21
22 public partial class FadeForm : Form
23 {
24
25 #region Variables and Properties
26
27 private double targetOpacity;//当前不透明度
28
29 private double activeOpacity = 0.99;//活动时不透明度
30
31 private double minimizedOpacity = 0;//最小化时的不透明度
32
33
34
35
36
37 private double userMinOpacity = 0.001;//用户定义最小化窗体时不透明度
38
39 private double closingOpacity = 0.0001;//用户定义关闭窗体时不透明度
40
41
42
43 private double interval = 25;//计时器间隔
44
45 private double duration = 200;//淡入或淡出 透明度改变持续时间,
46
47 private double fadeChangePerTick = 0;// interval/duration 淡入淡出 透明度改变值
48
49
50
51 private System.Windows.Forms.Timer timer;
52
53
54
55 private Message heldMessage = new Message();
56
57
58
59 public double TargetOpacity
60 {
61
62 set
63 {
64
65 targetOpacity = value;
66
67 if (!timer.Enabled) timer.Start();
68
69 }
70
71 get { return targetOpacity; }
72
73 }
74
75
76
77 public double ActiveOpacity
78 {
79
80 get { return activeOpacity; }
81
82 set
83 {
84
85 if (value >= 0) activeOpacity = value;
86
87 else throw new ArgumentOutOfRangeException("The ActiveOpacity must be a positive value");
88
89 }
90
91 }
92
93
94
95 public double MinimizedOpacity
96 {
97
98 get { return minimizedOpacity; }
99
100 set
101 {
102
103 if (value >= 0) minimizedOpacity = value;
104
105 else throw new ArgumentOutOfRangeException("The MinimizedOpacity must be a positive value");
106
107 }
108
109 }
110
111
112
113 public double UserMinOpacity
114 {
115
116 get { return userMinOpacity; }
117
118 set
119 {
120
121 if (value >= 0) userMinOpacity = value;
122
123 else throw new ArgumentOutOfRangeException("The UserMinOpacity must be a positive value");
124
125 }
126
127 }
128
129
130
131 public double ClosingOpacity
132 {
133
134 get { return closingOpacity; }
135
136 set
137 {
138
139 if (value >= 0) closingOpacity = value;
140
141 else throw new ArgumentOutOfRangeException("The ClosingOpacity must be a positive value");
142
143 }
144
145 }
146
147
148
149 public double Interval
150 {
151
152 get { return interval; }
153
154 set
155 {
156
157 if (value >= 0) interval = value;
158
159 else throw new ArgumentOutOfRangeException("The Interval must be a positive value");
160
161 }
162
163 }
164
165
166
167 public double Duration
168 {
169
170 get { return duration; }
171
172 set
173 {
174
175 if (value >= 0) duration = value;
176
177 else throw new ArgumentOutOfRangeException("The Duration must be a positive value");
178
179 }
180
181 }
182
183 #endregion
184
185
186
187 public FadeForm()
188 {
189
190 this.timer = new System.Windows.Forms.Timer();
191
192 this.SuspendLayout();
193
194 this.timer.Interval = 25;
195
196 this.Duration = Double.Parse(System.Configuration.ConfigurationManager.AppSettings["Duration"]);
197
198 this.fadeChangePerTick = this.interval / this.duration;
199
200 this.timer.Tick += new System.EventHandler(this.timer_Tick);
201
202 this.Load += new System.EventHandler(this.FadeForm_Load);
203
204 }
205
206
207
208 #region WindowsMessage
209
210
211
212 /// <summary>
213
214 /// Intercepts WindowMessages before they are processed.
215
216 /// </summary>
217
218 /// <param name="m">Windows Message</param>
219
220 protected override void WndProc(ref Message m)
221 {
222
223 if (m.Msg == (int)WmEnum.WM_SYSCOMMAND || m.Msg == (int)WmEnum.WM_COMMAND)
224 {
225
226 if (m.WParam == (IntPtr)WmEnum.SC_MINIMIZE)
227 {
228
229 if (heldMessage.WParam == (IntPtr)WmEnum.SC_MINIMIZE)
230 {
231
232 heldMessage = new Message();
233
234 TargetOpacity = activeOpacity;
235
236 }
237
238 else
239 {
240
241 heldMessage = m;
242
243 TargetOpacity = minimizedOpacity;
244
245 }
246
247 return;
248
249 }
250
251 else if (m.WParam == (IntPtr)WmEnum.SC_RESTORE
252
253 && this.WindowState == FormWindowState.Minimized)
254 {
255
256 base.WndProc(ref m);
257
258 TargetOpacity = activeOpacity;
259
260 return;
261
262 }
263
264 else if (m.WParam == (IntPtr)WmEnum.SC_CLOSE)
265 {
266
267 heldMessage = m;
268
269 TargetOpacity = minimizedOpacity;
270
271 return;
272
273 }
274
275 }
276
277
278
279 base.WndProc(ref m);
280
281 }
282
283 #endregion
284
285
286
287 private void FadeForm_Load(object sender, EventArgs e)
288 {
289
290 this.Opacity = minimizedOpacity;
291
292 TargetOpacity = activeOpacity;
293
294 }
295
296
297
298 private void timer_Tick(object sender, EventArgs e)
299 {
300
301 if (Math.Abs(targetOpacity - this.Opacity) < fadeChangePerTick)
302 {
303
304 if (targetOpacity == 1) this.Opacity = .999;
305
306 else this.Opacity = targetOpacity;
307
308 base.WndProc(ref heldMessage);
309
310 heldMessage = new Message();
311
312 timer.Stop();
313
314 if (targetOpacity == userMinOpacity)
315
316 this.WindowState = FormWindowState.Minimized;
317
318 if (targetOpacity == closingOpacity)
319
320 this.Close();
321
322 }
323
324 else if (targetOpacity > this.Opacity)
325
326 this.Opacity += fadeChangePerTick;
327
328 else if (targetOpacity < this.Opacity)
329
330 this.Opacity -= fadeChangePerTick;
331
332 }
333
334 }
335
336 }
2.当FormBorderStyle = System.Windows.Forms.FormBorderStyle.None时,应用程序在任务栏中无法弹出右键;下面通过调用API调出右键菜单:
1 [DllImport("user32.dll", EntryPoint = "GetWindowLong", CharSet = CharSet.Auto)]
2 public static extern int GetWindowLong(HandleRef hWnd, int nIndex);
3 [DllImport("user32.dll", EntryPoint = "SetWindowLong", CharSet = CharSet.Auto)]
4 public static extern IntPtr SetWindowLong(HandleRef hWnd, int nIndex, int dwNewLong);
5
6
7 int WS_SYSMENU = 0x00080000; // 系统菜单
8 int WS_MINIMIZEBOX = 0x20000; // 最大最小化按钮
9 int windowLong = GetWindowLong(new HandleRef(this, this.Handle), -16);
10 SetWindowLong(new HandleRef(this, this.Handle), -16, windowLong | WS_MINIMIZEBOX | WS_SYSMENU)