当窗体没有焦点时激活 ContextMenuStrip

Activate ContextMenuStrip when the Form doesn't have focus

  1. 我能够在 windows 表单外成功显示 ContextMenuScript (CMS)。
  2. 我可以使用鼠标指针 Select/Click 个项目。
  3. 但是,当窗体未获得焦点时,它不喜欢键盘控制(箭头 up/down,转义)。
  4. 如果表单获得焦点并显示 CMS,则键盘可以控制它,但在未获得焦点时则不能:(.
  5. 我需要有关代码的帮助,这将有助于在不关注表单的情况下实现这一目标。

此致

   Public Const CTRL_Key As Integer = &H2
   Public Const Hot_Key As Integer = &H312
   Public Declare Function RegisterHotKey Lib "user32" (ByVal hwnd As IntPtr, ByVal id As Integer, ByVal fsModifiers As Integer, ByVal vk As Integer) As Integer
   Public Declare Function UnregisterHotKey Lib "user32" (ByVal hwnd As IntPtr, ByVal id As Integer) As Integer

   Private Sub Hot_Key_Register() Handles MyBase.Load
    RegisterHotKey(Me.Handle, 100, CTRL_Key, Keys.NumPad1)
    RegisterHotKey(Me.Handle, 200, CTRL_Key, Keys.NumPad2)
    RegisterHotKey(Me.Handle, 300, CTRL_Key, Keys.NumPad3)
   End Sub

   Protected Overrides Sub WndProc(ByRef Window_Message As Message)

    If Window_Message.Msg = Hot_Key Then
        Dim id As IntPtr = Window_Message.WParam
        Select Case (id.ToString)
            Case "100"
                CMS_01.Show(Cursor.Position.X, Cursor.Position.Y)
            Case "200"
                CMS_02.Show(Cursor.Position.X, Cursor.Position.Y)
            Case "300"
                CMS_03.Show(Cursor.Position.X, Cursor.Position.Y)
        End Select
    End If
    MyBase.WndProc(Window_Message)
   End Sub

选项 1 - 使用 NotifyIcon

您可以使用的最简单的修复方法是使用不可见的 NotifyIcon component as it handles this case in its internal code

NotifyIcon 的一个实例拖放到您的表单上,然后使用它来显示上下文菜单,将上下文菜单条分配给它的 ContextMenuStrip 属性 然后调用它的 ShowContextMenu 使用反射的私有方法。

例子

Private Sub ShowContextMenu(menu As ContextMenuStrip)
    NotifyIcon1.Visible = False
    NotifyIcon1.ContextMenuStrip = menu
    Dim m = NotifyIcon1.GetType().GetMethod("ShowContextMenu",
        Reflection.BindingFlags.NonPublic Or Reflection.BindingFlags.Instance)
    m.Invoke(NotifyIcon1, Nothing)
End Sub
Protected Overrides Sub WndProc(ByRef Window_Message As Message)
    If Window_Message.Msg = Hot_Key Then
        Dim id As IntPtr = Window_Message.WParam
        Select Case (id.ToString)
            Case "100"
                ShowContextMenu(CMS_01)
        End Select
    End If
    MyBase.WndProc(Window_Message)
End Sub

选项 2 - 使用本机 Window

这里是不使用 NotifyIcon, using NativeWindow 的修复方法。下面的一段代码关心活动​​的window,如果当前表单是活动的,它不使用原生的window,否则它创建并使用原生的window.

例子

Private window As NativeWindow
Private Sub ShowContextMenu(menu As ContextMenuStrip, p As Point)
    If (Form.ActiveForm IsNot Me) Then
        If (window Is Nothing) Then
            window = New NativeWindow()
            window.CreateHandle(New CreateParams())
        End If
        SetForegroundWindow(window.Handle)
    End If
    menu.Show(p)
End Sub

并显示菜单:

ShowContextMenu(CMS_01, Cursor.Position)

请记住在 closing/disposing 形式时释放 window 句柄:

If (window IsNot Nothing) Then
    window.DestroyHandle()
    window = Nothing
End If