2009-01-23 74 views
5

我的主窗體上有一個.NET 2.0 WinForms應用程序,帶有ToolStrip。有時候,ToolStrip圖標並沒有改變第一次鼠標點擊的方式,所以我必須點擊兩次圖標。它只是一個帶有幾個圖標和工具提示文本的標準ToolStrip,我沒有做任何特別的事情。這是常見的嗎?ToolStrip有時無法響應鼠標點擊

回答

0

如果應用程序窗口沒有獲得焦點,則必須單擊ToolStrip按鈕兩次。第一次點擊將焦點設置到窗口,第二次點擊會引發點擊事件。這是(不幸的)默認行爲,它是通過設計。 Microsoft Word顯示相同的行爲(即使.NET ToolStrip不是相同的控件)。

+5

MS Word和.NET ToolStrip按鈕之間有區別:當Word應用程序沒有焦點時,Word中的菜單和符號不會被鼠標光標高亮顯示。只有Word有重點時纔會突出顯示它們。另一方面,即使應用程序沒有焦點,.NET ToolStrip也會突出顯示它的按鈕,並假裝鼠標點擊會立即激活按鈕。 – 2009-12-12 13:32:30

1

我已經在其他開發環境(VB6)中使用過,結果是因爲第一次單擊被工具欄吸收以獲得焦點。或者,換句話說,工具欄不會響應點擊直到它有焦點。要測試這一點,請嘗試點擊工具欄的空白部分,然後單擊按鈕。如果在點擊工具欄後,您再也不必點擊按鈕兩次,那麼這可能是問題所在。我認爲他們已經解決了這個問題(這是幾年前的事情,所以請原諒黑客)是以編程方式將焦點放在MouseOver事件的工具欄上。

+0

謝謝,反正似乎這不是我的情況。如果我將焦點設置爲另一個控件(假設ToolStrip外部的按鈕),然後單擊ToolStrip按鈕,則接受點擊。 – user20353 2009-01-23 11:40:24

20

我前幾次遇到同樣的問題,我在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; 
    } 
} 
+0

這是完美的,比我嘗試過的任何替代品都要好。 – user169771 2016-10-31 03:06:40

1

您可以創建自己的類,從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