Активируйте ContextMenuStrip, когда форма не имеет фокуса

  1. Я могу успешно отображать ContextMenuScript (CMS) вне формы Windows.
  2. Я могу выбрать / щелкнуть элементы, используя указатель мыши.
  3. Однако ему не нравится управление с клавиатуры (стрелка вверх / вниз, выход), когда форма не сфокусирована.
  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 ответ

Решение

Вариант 1 - Использование NotifyIcon

Самое простое исправление, которое вы можете использовать, это использование невидимого NotifyIcon компонент, как он обрабатывает этот случай во внутреннем коде.

Оставьте экземпляр 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 - Использование собственного окна

А вот и исправление без использования NotifyIcon, с помощью NativeWindow, Следующий фрагмент кода заботится об активном окне, и если текущая форма активна, он не использует собственное окно, в противном случае он создает и использует собственное окно.

пример

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)

Просто имейте в виду, чтобы при закрытии / удалении формы освободить ручку окна:

If (window IsNot Nothing) Then
    window.DestroyHandle()
    window = Nothing
End If
Другие вопросы по тегам