我有一个.NET 2.0 WinForms应用程序,在我的主窗体上有一个ToolStrip。有时,ToolStrip图标不会响应第一次鼠标单击,所以我必须点击两次图标。这只是一个带有几个图标和工具提示文本的标准ToolStrip,我没有做任何特殊处理。这种情况常见吗?
我之前也遇到了同样的问题,并在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;
}
}
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
我在其他开发环境(VB6)中遇到过这个问题,原因是第一次点击被工具栏吸收以获取焦点。换句话说,在工具栏获得焦点之前,工具栏不会响应单击事件。要测试这一点,请在单击按钮之前单击工具栏的空白部分。如果在单击工具栏后再次单击按钮,则可能存在该问题。我认为解决方法(这是多年前的事情,所以请原谅我使用的技巧)是在MouseOver事件中编程地将焦点赋予工具栏。
如果应用程序窗口没有焦点,则必须单击ToolStrip按钮两次。第一次单击将焦点设置到窗口,第二次引发单击事件。这是(不幸的是)默认行为,并且是有意设计的。Microsoft Word显示相同的行为(即使.NET ToolStrip不是相同的控件)。
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;
}
}
}
myToolStrip.ClickThrough = true
,否则它将无法正常工作。 - SharpC