AutoClose=false的情况下自动关闭下拉框(ToolStripHost)
应用场景:
1,Winform
2,ToolStripHost与输入控件组合焦点可在两者直接自由切换.
3,当输入控件获取焦点后,ToolStripHost不能自动关闭.所以只能将AutoClose设置为false.
实现目标:
组合控件失去焦点或单击其他区域时,隐藏ToolStripHost
实现:
1,失去焦点可在LostFoucus事件处理或重写WndProc方法处理WM_KILLFOCUS消息.
2,单击其他区域时有两种方法处理
(1)通过全局鼠标钩子http://globalmousekeyhook.codeplex.com/获取单击时的坐标并判断坐标是否落在组合控件上.
if (this._dropDown.Visible) { Rectangle baseRect = new Rectangle(base.Parent.PointToScreen(base.Location), base.Size);//输入控件坐标转换为屏幕坐标 Rectangle dropRect = new Rectangle(this._dropDown.Location, this._dropDown.Size);//ToolStripHost坐标本身为屏幕坐标不需转换 if (!baseRect.Contains(e.X, e.Y) && !dropRect.Contains(e.X, e.Y)) this._dropDown.Hide();//隐藏 }
特别说明:构造函数中注册钩子,Dispose方法中卸载钩子.
(2)组合控件实现IMessageFilter接口
在程序调度消息之前处理几个鼠标消息即可
public bool PreFilterMessage(ref Message m) { switch (m.Msg) { case NativeMethods.WM_LBUTTONDOWN: case NativeMethods.WM_RBUTTONDOWN: case NativeMethods.WM_MBUTTONDOWN: case NativeMethods.WM_NCLBUTTONDOWN: case NativeMethods.WM_NCRBUTTONDOWN: case NativeMethods.WM_NCMBUTTONDOWN: OnClickBlank(ref m); break; default: break; } return false; }
在关闭的方法中判断下句柄如果句柄不是组合控件就关闭ToolStripHost
总结:
第一种方法,在加载钩子的时候虽然放到了线程池中但是依然很卡,调试命中断点后鼠标会很卡.
第二种方法,比较好不会出现卡顿的情况
自己在实现的时候遇到了不少困难.最终找到了合适的方法.也希望能给有相同需求的同学一些帮助.
不足之处大家多多批评~~
-----------------------------------
测试时发现,ToolStripHost在获取焦点的情况下单击其他应用程序不会自动关闭.
使用spy++发现当应用程序失去焦点时系统会对应用程序的所有控件send(直接发送到控件不进入消息队列,所以无法在PreFilterMessage过滤) WM_ACTIVEAPP消息.
解决方法,继承ToolStripHost重写WndProc方法处理WM_ACTIVEAPP消息.wParam==0时为引用程序失去焦点.此时可以添加一个自定义事件.在这个自定义事件中进行处理