ToolStrip 有时不响应鼠标单击

发布于 2024-07-12 12:05:12 字数 148 浏览 7 评论 0原文

我有一个 .NET 2.0 WinForms 应用程序,主窗体上有一个 ToolStrip。 有时,ToolStrip 图标不会响应第一次鼠标单击,因此我必须单击该图标两次。 它只是一个带有几个图标和工具提示文本的标准 ToolStrip,我没有做任何特别的事情。 这常见吗?

I have a .NET 2.0 WinForms application with a ToolStrip on my main form. Sometimes, the ToolStrip icons don't respond to the first mouse click, so I have to click the icon twice. It's just a standard ToolStrip with several icons and tooltip texts, I don't do anything special. Is this common?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(5

孤独患者 2024-07-19 12:05:12

我前段时间遇到了同样的问题,我在 Rick Brewster 的博客,引用 此链接。 这个想法是在派生类 ToolStripEx 中覆盖“WndProc”。 该解决方案的核心如下所示:

protected override void WndProc(ref Message m)
{
    base.WndProc(ref m);

    if (m.Msg == NativeConstants.WM_MOUSEACTIVATE &&
        m.Result == (IntPtr)NativeConstants.MA_ACTIVATEANDEAT)
    {
        m.Result = (IntPtr)NativeConstants.MA_ACTIVATE;
    }
}

I had the same problem some time ago, and I found a solution in Rick Brewster's blog, referencing this link. The idea is to overwrite 'WndProc' in a derived class ToolStripEx. The core of that solution looks like this:

protected override void WndProc(ref Message m)
{
    base.WndProc(ref m);

    if (m.Msg == NativeConstants.WM_MOUSEACTIVATE &&
        m.Result == (IntPtr)NativeConstants.MA_ACTIVATEANDEAT)
    {
        m.Result = (IntPtr)NativeConstants.MA_ACTIVATE;
    }
}
爱情眠于流年 2024-07-19 12:05:12

您可以创建自己的从 ToolStrip 继承的类,并使用自定义属性 ClickThrough 来打开或关闭该行为:

Public Class ToolStripExtended : Inherits ToolStrip
    Private Const WM_MOUSEACTIVATE As UInteger = &H21
    Private Const MA_ACTIVATE As UInteger = 1
    Private Const MA_ACTIVATEANDEAT As UInteger = 2
    Private Const MA_NOACTIVATE As UInteger = 3
    Private Const MA_NOACTIVATEANDEAT As UInteger = 4

    Private _clickThrough As Boolean = False

    Public Sub New()
        MyBase.New()
    End Sub

    ''' <summary>
    ''' Gets or sets whether the ToolStripEx honours item clicks when its containing form does
    ''' not have input focus.
    ''' </summary>
    ''' <remarks>
    ''' Default value is false, which is the same behaviour provided by the base ToolStrip class.
    ''' </remarks>
    Public Property ClickThrough() As Boolean
        Get
            Return Me._clickThrough
        End Get

        Set(value As Boolean)
            Me._clickThrough = value
        End Set
    End Property

    Protected Overrides Sub WndProc(ByRef m As Message)
        MyBase.WndProc(m)

        If _clickThrough AndAlso m.Msg = WM_MOUSEACTIVATE AndAlso m.Result = New IntPtr(MA_ACTIVATEANDEAT) Then
            m.Result = New IntPtr(MA_ACTIVATE)
        End If
    End Sub
End Class

You can create your own class that inherits from the ToolStrip and use a custom property ClickThrough to switch the behaviour on or off:

Public Class ToolStripExtended : Inherits ToolStrip
    Private Const WM_MOUSEACTIVATE As UInteger = &H21
    Private Const MA_ACTIVATE As UInteger = 1
    Private Const MA_ACTIVATEANDEAT As UInteger = 2
    Private Const MA_NOACTIVATE As UInteger = 3
    Private Const MA_NOACTIVATEANDEAT As UInteger = 4

    Private _clickThrough As Boolean = False

    Public Sub New()
        MyBase.New()
    End Sub

    ''' <summary>
    ''' Gets or sets whether the ToolStripEx honours item clicks when its containing form does
    ''' not have input focus.
    ''' </summary>
    ''' <remarks>
    ''' Default value is false, which is the same behaviour provided by the base ToolStrip class.
    ''' </remarks>
    Public Property ClickThrough() As Boolean
        Get
            Return Me._clickThrough
        End Get

        Set(value As Boolean)
            Me._clickThrough = value
        End Set
    End Property

    Protected Overrides Sub WndProc(ByRef m As Message)
        MyBase.WndProc(m)

        If _clickThrough AndAlso m.Msg = WM_MOUSEACTIVATE AndAlso m.Result = New IntPtr(MA_ACTIVATEANDEAT) Then
            m.Result = New IntPtr(MA_ACTIVATE)
        End If
    End Sub
End Class
弥繁 2024-07-19 12:05:12

我在其他开发环境(VB6)中也遇到过这种情况,结果是因为第一次单击被工具栏吸收以获取焦点。 或者,换句话说,工具栏不会响应单击,直到它获得焦点。 要对此进行测试,请在单击按钮之前尝试单击工具栏的空白部分。 如果您在单击工具栏后不必单击两次按钮,那么这可能就是问题所在。 我认为我解决这个问题的方法(这是几年前的事了,所以请原谅我的黑客攻击)是以编程方式将焦点放在 MouseOver 事件中的工具栏上。

I've had that in other dev environments (VB6), and it turned out to be because the first click was being absorbed by the toolbar to acquire the focus. Or, to put it another way, the toolbar wouldn't respond to a click until it had the focus. To test this, try clicking on an empty part of the toolbar before you click on the button. If you never have to click twice on the button after you've clicked on the toolbar then that might be the problem. I think they I got around it (and this was years ago, so please excuse the hack) was to programatically give the focus to the toolbar in the MouseOver event.

著墨染雨君画夕 2024-07-19 12:05:12

如果应用程序窗口没有获得焦点,则必须单击 ToolStrip 按钮两次。 第一次单击将焦点设置到窗口,第二次单击引发单击事件。 (不幸的是)这是默认行为,并且是设计使然。 Microsoft Word 显示相同的行为(即使 .NET ToolStrip 不是同一控件)。

If the application window hasn’t got the focus, you have to click the ToolStrip button twice. The first click sets the focus to the window, the second raises the click event. This is (unfortunately) the default behaviour and it’s by design. Microsoft Word shows the same behaviour (even though the .NET ToolStrip is not the same control).

你是暖光i 2024-07-19 12:05:12

这是@Doc Brown 解决方案的实现:

public class ToolStripX : ToolStrip
{
    private const int WM_MOUSEACTIVATE = 0x0021;
    private const int MA_ACTIVATEANDEAT = 2;
    private const int MA_ACTIVATE = 1;

    protected override void WndProc(ref Message m)
    {
        base.WndProc(ref m);

        if (m.Msg == WM_MOUSEACTIVATE &&
            m.Result == (IntPtr)MA_ACTIVATEANDEAT)
        {
            m.Result = (IntPtr)MA_ACTIVATE;
        }
    }
}

Here is the implementation for @Doc Brown's solution:

public class ToolStripX : ToolStrip
{
    private const int WM_MOUSEACTIVATE = 0x0021;
    private const int MA_ACTIVATEANDEAT = 2;
    private const int MA_ACTIVATE = 1;

    protected override void WndProc(ref Message m)
    {
        base.WndProc(ref m);

        if (m.Msg == WM_MOUSEACTIVATE &&
            m.Result == (IntPtr)MA_ACTIVATEANDEAT)
        {
            m.Result = (IntPtr)MA_ACTIVATE;
        }
    }
}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文