入行已经7,8年了,一直想做一套漂亮点的自定义控件,于是就有了本系列文章。
GitHub:https://github.com/kwwwvagaa/NetWinformControl
码云:https://gitee.com/kwwwvagaa/net_winform_custom_control.git
如果觉得写的还行,请点个 star 支持一下吧
https://www.cnblogs.com/bfyx/p/11364884.html
这是一个可停靠在指定位置或停靠在某个控件旁边的无焦点窗体,市区焦点会关闭
添加一个Form,命名为FrmAnchor,实现接口IMessageFilter
有2个构造函数
1 #region 构造函数
2 /// <summary>
3 /// 功能描述:构造函数
4 /// 作 者:HZH
5 /// 创建日期:2019-02-27 11:49:08
6 /// 任务编号:POS
7 /// </summary>
8 /// <param name="parentControl">父控件</param>
9 /// <param name="childControl">子控件</param>
10 /// <param name="deviation">偏移</param>
11 public FrmAnchor(Control parentControl, Control childControl, Point? deviation = null)
12 {
13 m_parentControl = parentControl;
14 InitializeComponent();
15 this.Size = childControl.Size;
16 this.HandleCreated += FrmDownBoard_HandleCreated;
17 this.HandleDestroyed += FrmDownBoard_HandleDestroyed;
18 this.Controls.Add(childControl);
19 childControl.Dock = DockStyle.Fill;
20 Point p = parentControl.Parent.PointToScreen(parentControl.Location);
21 int intX = 0;
22 int intY = 0;
23 if (p.Y + parentControl.Height + childControl.Height > Screen.PrimaryScreen.Bounds.Height)
24 {
25 intY = p.Y - childControl.Height - 1;
26 blnDown = false;
27 }
28 else
29 {
30 intY = p.Y + parentControl.Height + 1;
31 blnDown = true;
32 }
33
34 if (p.X + childControl.Width > Screen.PrimaryScreen.Bounds.Width)
35 {
36 intX = Screen.PrimaryScreen.Bounds.Width - childControl.Width;
37
38 }
39 else
40 {
41 intX = p.X;
42 }
43 if (deviation.HasValue)
44 {
45 intX += deviation.Value.X;
46 intY += deviation.Value.Y;
47 }
48 this.Location = new Point(intX, intY);
49 }
50
51 public FrmAnchor(Control parentControl, Size size, Point? deviation = null)
52 {
53 m_parentControl = parentControl;
54 InitializeComponent();
55 this.Size = size;
56 this.HandleCreated += FrmDownBoard_HandleCreated;
57 this.HandleDestroyed += FrmDownBoard_HandleDestroyed;
58
59 Point p = parentControl.Parent.PointToScreen(parentControl.Location);
60 int intX = 0;
61 int intY = 0;
62 if (p.Y + parentControl.Height + size.Height > Screen.PrimaryScreen.Bounds.Height)
63 {
64 intY = p.Y - size.Height - 1;
65 blnDown = false;
66 }
67 else
68 {
69 intY = p.Y + parentControl.Height + 1;
70 blnDown = true;
71 }
72
73 if (p.X + size.Width > Screen.PrimaryScreen.Bounds.Width)
74 {
75 intX = Screen.PrimaryScreen.Bounds.Width - size.Width;
76
77 }
78 else
79 {
80 intX = p.X;
81 }
82 if (deviation.HasValue)
83 {
84 intX += deviation.Value.X;
85 intY += deviation.Value.Y;
86 }
87 this.Location = new Point(intX, intY);
88 }
89
90 #endregion
消息筛选器处理一下
private void FrmDownBoard_HandleDestroyed(object sender, EventArgs e)
{
Application.RemoveMessageFilter(this);
}
private void FrmDownBoard_HandleCreated(object sender, EventArgs e)
{
Application.AddMessageFilter(this);
}
public bool PreFilterMessage(ref Message m)
{
if (m.Msg != 0x0201 || this.Visible == false)
return false;
var pt = this.PointToClient(MousePosition);
this.Visible = this.ClientRectangle.Contains(pt);
return false;
}
无焦点处理
1 #region 无焦点窗体
2
3 [System.Runtime.InteropServices.DllImport("user32.dll")]
4 private extern static IntPtr SetActiveWindow(IntPtr handle);
5 private const int WM_ACTIVATE = 0x006;
6 private const int WM_ACTIVATEAPP = 0x01C;
7 private const int WM_NCACTIVATE = 0x086;
8 private const int WA_INACTIVE = 0;
9 private const int WM_MOUSEACTIVATE = 0x21;
10 private const int MA_NOACTIVATE = 3;
11 protected override void WndProc(ref Message m)
12 {
13 if (m.Msg == WM_MOUSEACTIVATE)
14 {
15 m.Result = new IntPtr(MA_NOACTIVATE);
16 return;
17 }
18 else if (m.Msg == WM_NCACTIVATE)
19 {
20 if (((int)m.WParam & 0xFFFF) != WA_INACTIVE)
21 {
22 if (m.LParam != IntPtr.Zero)
23 {
24 SetActiveWindow(m.LParam);
25 }
26 else
27 {
28 SetActiveWindow(IntPtr.Zero);
29 }
30 }
31 }
32 base.WndProc(ref m);
33 }
34
35 #endregion
1 private void timer1_Tick(object sender, EventArgs e)
2 {
3 if (this.Owner != null)
4 {
5 Form frm = this.Owner as Form;
6 IntPtr _ptr = ControlHelper.GetForegroundWindow();
7 if (_ptr != frm.Handle)
8 {
9 this.Hide();
10 }
11 }
12 }
显示和关闭动画
1 private void FrmAnchor_VisibleChanged(object sender, EventArgs e)
2 {
3 timer1.Enabled = this.Visible;
4 if (Visible)
5 {
6 if (blnDown)
7 ControlHelper.AnimateWindow(this.Handle, 100, ControlHelper.AW_VER_POSITIVE);
8 else
9 {
10 ControlHelper.AnimateWindow(this.Handle, 100, ControlHelper.AW_VER_NEGATIVE);
11 }
12 }
13 else
14 {
15 if (blnDown)
16 ControlHelper.AnimateWindow(this.Handle, 100, ControlHelper.AW_VER_NEGATIVE | ControlHelper.AW_HIDE);
17 else
18 {
19 ControlHelper.AnimateWindow(this.Handle, 100, ControlHelper.AW_VER_POSITIVE | ControlHelper.AW_HIDE);
20
21 }
22 }
23 }
再看一下完整代码
1 // 版权所有 黄正辉 交流群:568015492 QQ:623128629
2 // 文件名称:FrmAnchor.cs
3 // 创建日期:2019-08-15 16:04:24
4 // 功能描述:FrmAnchor
5 // 项目地址:https://gitee.com/kwwwvagaa/net_winform_custom_control
6
7 using System;
8 using System.Collections.Generic;
9 using System.ComponentModel;
10 using System.Data;
11 using System.Drawing;
12 using System.Linq;
13 using System.Text;
14 using System.Windows.Forms;
15
16 namespace HZH_Controls.Forms
17 {
18 /// <summary>
19 /// 功能描述:停靠窗体
20 /// 作 者:HZH
21 /// 创建日期:2019-02-27 11:49:03
22 /// 任务编号:POS
23 /// </summary>
24 public partial class FrmAnchor : Form, IMessageFilter
25 {
26 Control m_parentControl = null;
27 private bool blnDown = true;
28 #region 构造函数
29 /// <summary>
30 /// 功能描述:构造函数
31 /// 作 者:HZH
32 /// 创建日期:2019-02-27 11:49:08
33 /// 任务编号:POS
34 /// </summary>
35 /// <param name="parentControl">父控件</param>
36 /// <param name="childControl">子控件</param>
37 /// <param name="deviation">偏移</param>
38 public FrmAnchor(Control parentControl, Control childControl, Point? deviation = null)
39 {
40 m_parentControl = parentControl;
41 InitializeComponent();
42 this.Size = childControl.Size;
43 this.HandleCreated += FrmDownBoard_HandleCreated;
44 this.HandleDestroyed += FrmDownBoard_HandleDestroyed;
45 this.Controls.Add(childControl);
46 childControl.Dock = DockStyle.Fill;
47 Point p = parentControl.Parent.PointToScreen(parentControl.Location);
48 int intX = 0;
49 int intY = 0;
50 if (p.Y + parentControl.Height + childControl.Height > Screen.PrimaryScreen.Bounds.Height)
51 {
52 intY = p.Y - childControl.Height - 1;
53 blnDown = false;
54 }
55 else
56 {
57 intY = p.Y + parentControl.Height + 1;
58 blnDown = true;
59 }
60
61 if (p.X + childControl.Width > Screen.PrimaryScreen.Bounds.Width)
62 {
63 intX = Screen.PrimaryScreen.Bounds.Width - childControl.Width;
64
65 }
66 else
67 {
68 intX = p.X;
69 }
70 if (deviation.HasValue)
71 {
72 intX += deviation.Value.X;
73 intY += deviation.Value.Y;
74 }
75 this.Location = new Point(intX, intY);
76 }
77
78 public FrmAnchor(Control parentControl, Size size, Point? deviation = null)
79 {
80 m_parentControl = parentControl;
81 InitializeComponent();
82 this.Size = size;
83 this.HandleCreated += FrmDownBoard_HandleCreated;
84 this.HandleDestroyed += FrmDownBoard_HandleDestroyed;
85
86 Point p = parentControl.Parent.PointToScreen(parentControl.Location);
87 int intX = 0;
88 int intY = 0;
89 if (p.Y + parentControl.Height + size.Height > Screen.PrimaryScreen.Bounds.Height)
90 {
91 intY = p.Y - size.Height - 1;
92 blnDown = false;
93 }
94 else
95 {
96 intY = p.Y + parentControl.Height + 1;
97 blnDown = true;
98 }
99
100 if (p.X + size.Width > Screen.PrimaryScreen.Bounds.Width)
101 {
102 intX = Screen.PrimaryScreen.Bounds.Width - size.Width;
103
104 }
105 else
106 {
107 intX = p.X;
108 }
109 if (deviation.HasValue)
110 {
111 intX += deviation.Value.X;
112 intY += deviation.Value.Y;
113 }
114 this.Location = new Point(intX, intY);
115 }
116
117 #endregion
118
119 private void FrmDownBoard_HandleDestroyed(object sender, EventArgs e)
120 {
121 Application.RemoveMessageFilter(this);
122 }
123
124 private void FrmDownBoard_HandleCreated(object sender, EventArgs e)
125 {
126 Application.AddMessageFilter(this);
127 }
128
129 #region 无焦点窗体
130
131 [System.Runtime.InteropServices.DllImport("user32.dll")]
132 private extern static IntPtr SetActiveWindow(IntPtr handle);
133 private const int WM_ACTIVATE = 0x006;
134 private const int WM_ACTIVATEAPP = 0x01C;
135 private const int WM_NCACTIVATE = 0x086;
136 private const int WA_INACTIVE = 0;
137 private const int WM_MOUSEACTIVATE = 0x21;
138 private const int MA_NOACTIVATE = 3;
139 protected override void WndProc(ref Message m)
140 {
141 if (m.Msg == WM_MOUSEACTIVATE)
142 {
143 m.Result = new IntPtr(MA_NOACTIVATE);
144 return;
145 }
146 else if (m.Msg == WM_NCACTIVATE)
147 {
148 if (((int)m.WParam & 0xFFFF) != WA_INACTIVE)
149 {
150 if (m.LParam != IntPtr.Zero)
151 {
152 SetActiveWindow(m.LParam);
153 }
154 else
155 {
156 SetActiveWindow(IntPtr.Zero);
157 }
158 }
159 }
160 base.WndProc(ref m);
161 }
162
163 #endregion
164
165 public bool PreFilterMessage(ref Message m)
166 {
167 if (m.Msg != 0x0201 || this.Visible == false)
168 return false;
169 var pt = this.PointToClient(MousePosition);
170 this.Visible = this.ClientRectangle.Contains(pt);
171 return false;
172 }
173
174 private void FrmAnchor_Load(object sender, EventArgs e)
175 {
176
177 }
178
179
180 private void FrmAnchor_VisibleChanged(object sender, EventArgs e)
181 {
182 timer1.Enabled = this.Visible;
183 if (Visible)
184 {
185 if (blnDown)
186 ControlHelper.AnimateWindow(this.Handle, 100, ControlHelper.AW_VER_POSITIVE);
187 else
188 {
189 ControlHelper.AnimateWindow(this.Handle, 100, ControlHelper.AW_VER_NEGATIVE);
190 }
191 }
192 else
193 {
194 if (blnDown)
195 ControlHelper.AnimateWindow(this.Handle, 100, ControlHelper.AW_VER_NEGATIVE | ControlHelper.AW_HIDE);
196 else
197 {
198 ControlHelper.AnimateWindow(this.Handle, 100, ControlHelper.AW_VER_POSITIVE | ControlHelper.AW_HIDE);
199
200 }
201 }
202 }
203
204 private void timer1_Tick(object sender, EventArgs e)
205 {
206 if (this.Owner != null)
207 {
208 Form frm = this.Owner as Form;
209 IntPtr _ptr = ControlHelper.GetForegroundWindow();
210 if (_ptr != frm.Handle)
211 {
212 this.Hide();
213 }
214 }
215 }
216
217 }
218 }
1 namespace HZH_Controls.Forms
2 {
3 partial class FrmAnchor
4 {
5 /// <summary>
6 /// Required designer variable.
7 /// </summary>
8 private System.ComponentModel.IContainer components = null;
9
10 /// <summary>
11 /// Clean up any resources being used.
12 /// </summary>
13 /// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param>
14 protected override void Dispose(bool disposing)
15 {
16 if (disposing && (components != null))
17 {
18 components.Dispose();
19 }
20 base.Dispose(disposing);
21 }
22
23 #region Windows Form Designer generated code
24
25 /// <summary>
26 /// Required method for Designer support - do not modify
27 /// the contents of this method with the code editor.
28 /// </summary>
29 private void InitializeComponent()
30 {
31 this.components = new System.ComponentModel.Container();
32 System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(FrmAnchor));
33 this.timer1 = new System.Windows.Forms.Timer(this.components);
34 this.SuspendLayout();
35 //
36 // timer1
37 //
38 this.timer1.Tick += new System.EventHandler(this.timer1_Tick);
39 //
40 // FrmAnchor
41 //
42 this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.None;
43 this.ClientSize = new System.Drawing.Size(45, 48);
44 this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.None;
45 this.Icon = ((System.Drawing.Icon)(resources.GetObject("$this.Icon")));
46 this.Name = "FrmAnchor";
47 this.ShowIcon = false;
48 this.ShowInTaskbar = false;
49 this.StartPosition = System.Windows.Forms.FormStartPosition.Manual;
50 this.Text = "FrmAnchor";
51 this.TopMost = true;
52 this.Load += new System.EventHandler(this.FrmAnchor_Load);
53 this.VisibleChanged += new System.EventHandler(this.FrmAnchor_VisibleChanged);
54 this.ResumeLayout(false);
55
56 }
57
58 #endregion
59
60 private System.Windows.Forms.Timer timer1;
61 }
62 }
用处:弹出菜单,文本框弹出键盘等