(十九)c#Winform自定义控件-停靠窗体
程序员文章站
2023-04-04 19:04:28
前提 入行已经7,8年了,一直想做一套漂亮点的自定义控件,于是就有了本系列文章。 开源地址:https://gitee.com/kwwwvagaa/net_winform_custom_control 如果觉得写的还行,请点个 star 支持一下吧 欢迎前来交流探讨: 企鹅群568015492 目录 ......
前提
入行已经7,8年了,一直想做一套漂亮点的自定义控件,于是就有了本系列文章。
开源地址:
如果觉得写的还行,请点个 star 支持一下吧
欢迎前来交流探讨: 企鹅群568015492
目录
准备工作
这是一个可停靠在指定位置或停靠在某个控件旁边的无焦点窗体,市区焦点会关闭
开始
添加一个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 }
用处及效果
用处:弹出菜单,文本框弹出键盘等
最后的话
如果你喜欢的话,请到 点个星 星吧