C#ListBox.MouseEnter / MouseLeave和滚动条

时间:2011-06-29 00:20:00

标签: c# winforms listbox mouseover

我的表单左侧有一个ListBox。用户可以选择“自动隐藏”它,使其消失在左侧,只有当用户将鼠标移动到其上时才会重新出现。

如果ListBox中的项目很少,则此功能可以很好地工作。

然而,只要我将足够多的项目放入ListBox以便现在有一个滚动条,就会发生有趣的事情。仅当用户将鼠标移动到滚动条之后的ListBox时,才会触发MouseEnter代码。这意味着我必须拥有更多的滚动条宽度,或者它们永远无法显示它。

此外,如果ListBox未对焦,则用户根本无法滚动。如果他们尝试单击滚动条进行滚动,则ListBox将消失。如果他们在ListBox内部单击以使其聚焦(以便他们可以使用鼠标滚轮滚动),那么他们将失去他们的选择。

有什么方法可以扩展MouseEnter和MouseLeave的范围以包含滚动条?

2 个答案:

答案 0 :(得分:1)

这是设计使用,滚动条不是控件客户区的一部分。它位于非客户区域,类似于表单顶部的标题栏。 Windows对它们的处理方式不同,鼠标移动消息如WM_MOUSEMOVE则通过WM_NCMOUSEMOVE宣布。 Winforms没有非客户端通知的事件。这是你通常想要它的方式,你不想知道被操纵的滚动条。功能,而不是错误。除了这种情况。

作为一种变通方法,您可以从ListBox继承并覆盖WndProc()以查看WM_NCMOUSEMOVE消息(m.Msg == 0xa0)。或200毫秒定时器,用于检查鼠标所在的位置。

答案 1 :(得分:0)

我一直在努力解决基本相同(或非常相似)的问题。最终,我想出了以下解决方法,我认为与使用MouseLeave相比,最终最终可以提供出色的功能(就最终用户体验而言)。即使ListBox在MouseLeave事件中没有怪异/意外的行为,但我认为无论如何该解决方法还是一个更好的选择。

我仍然使用MouseEnter来放大ListBox。但是,与其让ListBox使用MouseLeave缩小尺寸,不如让我发现实际上将其放大直到用户在窗体上的其他任何位置单击都更好。我在窗体上其他任何地方捕获了MouseDown事件,然后在用户单击窗体上除ListBox以外的任何位置时,将ListBox缩小到原始大小。

在表单构造器中,我放置了此循环:

---
layout: T4V4Home
#home: true
#heroImage: /ueda4googleplaystore.png
heroText: Hero Title
tagline: Hero subtitle
actionText: Get Started →
actionLink: /guide/
features:

然后创建此方法:

    foreach (Control control in Controls)
    {
        control.MouseDown += RedirectMouseDown;
    }

然后在表单的MouseDown事件中:

    private void RedirectMouseDown(object sender, MouseEventArgs e)
    {
        Control control = (Control)sender;
        Point screenPoint = control.PointToScreen(new Point(e.X, e.Y));
        Point formPoint = PointToClient(screenPoint);
        MouseEventArgs args = new MouseEventArgs(e.Button, e.Clicks, formPoint.X, formPoint.Y, e.Delta);            
        OnMouseDown(args);
    }