入行已经7,8年了,一直想做一套漂亮点的自定义控件,于是就有了本系列文章。
GitHub:https://github.com/kwwwvagaa/NetWinformControl
码云:https://gitee.com/kwwwvagaa/net_winform_custom_control.git
Install-Package HZH_Controls
https://www.cnblogs.com/bfyx/p/11364884.html
GDI+画图,不了解先百度
思路:
控件扩展属性,在组件中对需要显示倒影的控件的父控件添加Paint事件,在Paint事件中绘制控件,并旋转180,然后画到父控件上,然后再覆盖一层渐变色,完美。
添加一个类ShadowComponent 继承Component,实现 IExtenderProvider接口,扩展属性
代码比较少,直接放上来了
1 /// <summary>
2 /// The m control cache
3 /// </summary>
4 Dictionary<Control, bool> m_controlCache = new Dictionary<Control, bool>();
5
6 #region 构造函数 English:Constructor
7 /// <summary>
8 /// Initializes a new instance of the <see cref="ShadowComponent" /> class.
9 /// </summary>
10 public ShadowComponent()
11 {
12
13 }
14
15 /// <summary>
16 /// Initializes a new instance of the <see cref="ShadowComponent" /> class.
17 /// </summary>
18 /// <param name="container">The container.</param>
19 public ShadowComponent(IContainer container)
20 : this()
21 {
22 container.Add(this);
23 }
24 #endregion
25
26 /// <summary>
27 /// 指定此对象是否可以将其扩展程序属性提供给指定的对象。
28 /// </summary>
29 /// <param name="extendee">要接收扩展程序属性的 <see cref="T:System.Object" />。</param>
30 /// <returns>如果此对象可以扩展程序属性提供给指定对象,则为 true;否则为 false。</returns>
31 public bool CanExtend(object extendee)
32 {
33 if (extendee is Control && !(extendee is Form))
34 return true;
35 return false;
36 }
37
38 /// <summary>
39 /// Gets the show shadow.
40 /// </summary>
41 /// <param name="control">The control.</param>
42 /// <returns><c>true</c> if XXXX, <c>false</c> otherwise.</returns>
43 [Browsable(true), Category("自定义属性"), Description("是否显示倒影"), DisplayName("ShowShadow"), Localizable(true)]
44 public bool GetShowShadow(Control control)
45 {
46 if (m_controlCache.ContainsKey(control))
47 return m_controlCache[control];
48 else
49 return false;
50 }
51
52 /// <summary>
53 /// Sets the show shadow.
54 /// </summary>
55 /// <param name="control">The control.</param>
56 /// <param name="isShowShadow">if set to <c>true</c> [is show shadow].</param>
57 public void SetShowShadow(Control control, bool isShowShadow)
58 {
59 control.ParentChanged += control_ParentChanged;
60 m_controlCache[control] = isShowShadow;
61 }
62
63 /// <summary>
64 /// Handles the ParentChanged event of the control control.
65 /// </summary>
66 /// <param name="sender">The source of the event.</param>
67 /// <param name="e">The <see cref="EventArgs"/> instance containing the event data.</param>
68 void control_ParentChanged(object sender, EventArgs e)
69 {
70 Control control = sender as Control;
71 if (control.Parent != null && m_controlCache[control])
72 {
73 if (!lstPaintEventControl.Contains(control.Parent))
74 {
75 lstPaintEventControl.Add(control.Parent);
76 Type type = control.Parent.GetType();
77 System.Reflection.PropertyInfo pi = type.GetProperty("DoubleBuffered", System.Reflection.BindingFlags.Instance | System.Reflection.BindingFlags.NonPublic);
78 pi.SetValue(control.Parent, true, null);
79 control.Parent.Paint += Parent_Paint;
80 }
81 }
82 }
83
84 /// <summary>
85 /// The LST paint event control
86 /// </summary>
87 List<Control> lstPaintEventControl = new List<Control>();
88 /// <summary>
89 /// The shadow height
90 /// </summary>
91 private float shadowHeight = 0.3f;
92
93 /// <summary>
94 /// Gets or sets the height of the shadow.
95 /// </summary>
96 /// <value>The height of the shadow.</value>
97 [Browsable(true), Category("自定义属性"), Description("倒影高度,0-1"), Localizable(true)]
98 public float ShadowHeight
99 {
100 get { return shadowHeight; }
101 set { shadowHeight = value; }
102 }
103 /// <summary>
104 /// The BLN loading
105 /// </summary>
106 bool blnLoading = false;
107 /// <summary>
108 /// Handles the Paint event of the Parent control.
109 /// </summary>
110 /// <param name="sender">The source of the event.</param>
111 /// <param name="e">The <see cref="PaintEventArgs"/> instance containing the event data.</param>
112 void Parent_Paint(object sender, PaintEventArgs e)
113 {
114 if (blnLoading)
115 return;
116 if (shadowHeight > 0)
117 {
118 var control = sender as Control;
119 var lst = m_controlCache.Where(p => p.Key.Parent == control && p.Value);
120 if (lst != null && lst.Count() > 0)
121 {
122 blnLoading = true;
123 e.Graphics.SetGDIHigh();
124 foreach (var item in lst)
125 {
126 Control _control = item.Key;
127
128 using (Bitmap bit = new Bitmap(_control.Width, _control.Height))
129 {
130 _control.DrawToBitmap(bit, _control.ClientRectangle);
131 using (Bitmap bitNew = new Bitmap(bit.Width, (int)(bit.Height * shadowHeight)))
132 {
133 using (var g = Graphics.FromImage(bitNew))
134 {
135 g.DrawImage(bit, new RectangleF(0, 0, bitNew.Width, bitNew.Height), new RectangleF(0, bit.Height - bit.Height * shadowHeight, bit.Width, bit.Height * shadowHeight), GraphicsUnit.Pixel);
136 }
137 bitNew.RotateFlip(RotateFlipType.Rotate180FlipNone);
138 e.Graphics.DrawImage(bitNew, new Point(_control.Location.X, _control.Location.Y + _control.Height + 1));
139 Color bgColor = GetParentColor(_control);
140 LinearGradientBrush lgb = new LinearGradientBrush(new Rectangle(_control.Location.X, _control.Location.Y + _control.Height + 1, bitNew.Width, bitNew.Height), Color.FromArgb(50, bgColor), bgColor, 90f); //75f 表示角度
141 e.Graphics.FillRectangle(lgb, new Rectangle(new Point(_control.Location.X, _control.Location.Y + _control.Height + 1), bitNew.Size));
142 }
143 }
144 }
145 }
146 }
147 blnLoading = false;
148 }
149
150 /// <summary>
151 /// Gets the color of the parent.
152 /// </summary>
153 /// <param name="c">The c.</param>
154 /// <returns>Color.</returns>
155 private Color GetParentColor(Control c)
156 {
157 if (c.Parent.BackColor != Color.Transparent)
158 {
159 return c.Parent.BackColor;
160 }
161 return GetParentColor(c.Parent);
162 }
如果你喜欢的话,请到 https://gitee.com/kwwwvagaa/net_winform_custom_control 点个星星吧