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时为引用程序失去焦点.此时可以添加一个自定义事件.在这个自定义事件中进行处理

posted @ 2011-09-16 14:20  TimAndy  阅读(1638)  评论(4编辑  收藏