首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >Winforms:如何用ToolStripDropDown模拟AutoClose

Winforms:如何用ToolStripDropDown模拟AutoClose
EN

Stack Overflow用户
提问于 2014-04-02 14:29:18
回答 1查看 873关注 0票数 0

我目前正在写一个ComboBox,其中我用自己的建议下拉菜单替换了建议下拉列表。为此,我创建了一个用列表框填充的ToolStripDropDown。当用户在combobox文本字段中键入文本时,将更新此列表框。

我的问题是,如果我将ToolStripDropDown的AutoClose属性设置为true,似乎即使文本字段具有焦点,ToolStripDropDown也会“窃取”大量消息,包括键盘消息。

如果我将AutoClose属性设置为false,一切都会正常工作。但是下拉列表并不是关闭的,例如,如果用户在组合框之外单击。

我想知道如何做我自己的"AutoClose“,但我不确定如何实现它。你知道该怎么做吗?

EN

回答 1

Stack Overflow用户

发布于 2014-04-03 07:38:10

我找到了一个解决方案。查看ToolStripManager代码(感谢ReSharper!),我发现当AutoClose设置为true时,管理器会监视应用程序消息,以便检测用户何时在下拉列表之外单击。我用下面的方式修改了他们的代码:

代码语言:javascript
复制
class MyComboBox : ComboBox, IMessageFilter
{
        private ToolStripDropDown m_dropDown;

        MyComboBox()
        {
            ...
            Application.AddMessageFilter(this);
            ...
        }

        protected override void Dispose(bool disposing)
        {
            ...
            Application.RemoveMessageFilter(this);
            base.Dispose(disposing);
        }


        private const int WM_LBUTTONDOWN = 0x0201;
        private const int WM_RBUTTONDOWN = 0x0204;
        private const int WM_MBUTTONDOWN = 0x0207;
        private const int WM_NCLBUTTONDOWN = 0x00A1;
        private const int WM_NCRBUTTONDOWN = 0x00A4;
        private const int WM_NCMBUTTONDOWN = 0x00A7;

        [DllImport("user32.dll", ExactSpelling = true, CharSet = CharSet.Auto)]
        [ResourceExposure(ResourceScope.None)]
        public static extern int MapWindowPoints(IntPtr hWndFrom, IntPtr hWndTo, [In, Out] ref Point pt, int cPoints);

        public bool PreFilterMessage(ref Message m)
        {
            if (m_dropDown.Visible)
            {
                switch (m.Msg)
                {
                    case WM_LBUTTONDOWN:
                    case WM_RBUTTONDOWN:
                    case WM_MBUTTONDOWN:
                    case WM_NCLBUTTONDOWN:
                    case WM_NCRBUTTONDOWN:
                    case WM_NCMBUTTONDOWN:
                        //
                        // When a mouse button is pressed, we should determine if it is within the client coordinates
                        // of the active dropdown.  If not, we should dismiss it.
                        //
                        int i = unchecked((int)(long)m.LParam);
                        short x = (short)(i & 0xFFFF);
                        short y = (short)((i >> 16) & 0xffff);
                        Point pt = new Point(x, y);
                        MapWindowPoints(m.HWnd, m_dropDown.Handle, ref pt, 1);
                        if (!m_dropDown.ClientRectangle.Contains(pt))
                        {
                            // the user has clicked outside the dropdown
                            pt = new Point(x, y);
                            MapWindowPoints(m.HWnd, Handle, ref pt, 1);
                            if (!ClientRectangle.Contains(pt))
                            {
                                // the user has clicked outside the combo
                                hideDropDown();
                            }
                        }
                        break;
                }
            }
            return false;
        }
}
票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/22803183

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档