【问题标题】:ToolStrip sometimes not responding to a mouse clickToolStrip 有时不响应鼠标单击
【发布时间】:2010-10-03 02:32:23
【问题描述】:

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

【问题讨论】:

    标签: .net winforms toolstrip


    【解决方案1】:

    前段时间我也遇到过同样的问题,在Rick Brewster's blog找到了解决方法。这个想法是在派生类 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;
        }
    }
    

    【讨论】:

    • 这是完美的,比我尝试过的任何替代品都要好。
    • 还要确保设计器代码中的myToolStrip.ClickThrough = true,否则它不起作用。
    【解决方案2】:

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

    【讨论】:

    • 谢谢,无论如何,这似乎不是我的情况。如果我将焦点设置到另一个控件(比如说 ToolStrip 外部的按钮),然后单击 ToolStrip 按钮,则单击被接受。
    【解决方案3】:

    您可以创建自己的继承自 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
    

    【讨论】:

      【解决方案4】:

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

      【讨论】:

      • MS Word 和 .NET ToolStrip 按钮之间存在区别:当 Word 应用程序没有焦点时,Word 中的菜单和符号不会被鼠标光标突出显示。它们仅在 Word 具有焦点时突出显示。另一方面,即使应用程序没有焦点,.NET ToolStrip 也会突出显示其按钮,假装鼠标单击会立即激活按钮。
      【解决方案5】:

      这是@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;
              }
          }
      }
      

      【讨论】:

        猜你喜欢
        • 2012-03-12
        • 1970-01-01
        • 2015-02-26
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多