65.9K
CodeProject 正在变化。 阅读更多。
Home

.NET 系统范围热键组件

starIconstarIconstarIconstarIcon
emptyStarIcon
starIcon

4.33/5 (21投票s)

2003年6月16日

CPOL

2分钟阅读

viewsIcon

260757

downloadIcon

1427

一个用于响应系统范围热键组合的组件。

引言

系统范围的热键是一种按键组合,无论哪个应用程序具有输入焦点,都会触发特定事件。 例如,如果您按下 WIN+E,则会启动一个新的资源管理器实例,或者如果您按下 CTRL+PRINTSCREEN,则当前活动的窗口会被屏幕截图到剪贴板。

Win32 API 有几个调用用于设置和响应热键 - 特别是 RegisterHotKeyUnregisterHotKey,您可以在 VB.NET 中这样声明

<DllImport("user32", EntryPoint:="RegisterHotKey", _
          SetLastError:=True, _
          ExactSpelling:=True, _
          CallingConvention:=CallingConvention.StdCall)> _
Public Function RegisterHotkey(ByVal hwnd As IntPtr, _
           ByVal Id As Int32, _
           <MarshalAs(UnmanagedType.U4)> ByVal fsModifiers As Int32, _
           <MarshalAs(UnmanagedType.U4)> ByVal vkey As Int32) As Boolean

End Function

<DllImport("user32", EntryPoint:="UnregisterHotKey", _
SetLastError:=True, _
ExactSpelling:=True, _
CallingConvention:=CallingConvention.StdCall)> _
Public Function UnregisterHotkey(ByVal hwnd As Int32, _
                            ByVal Id As Int32) As Boolean

End Function

在热键通过 API 调用 RegisterHotkey 注册后,每当按下指定的按键组合时,就会将 WM_HOTKEY Windows 消息发送到 hwnd 参数中传递给它的窗口。

指定按键组合

触发事件的键由两个参数 fsModifiersvKey 定义。

fsModifiers 是一个值,它告诉操作系统,热键组合中包含哪些修饰键 - 即 Alt、Ctrl、Shift 或 Win 键。 这个值由以下标志的组合组成

Public Enum HotkeyModifierFlags
    MOD_ALT = &H1
    MOD_CONTROL = &H2
    MOD_SHIFT = &H4
    MOD_WIN = &H8
End Enum

因此,例如,如果您想要一个热键是 CTRL+ALT+C,那么修饰符将是 MOD_ALT + MOD_CONTROL

vKey 参数是与修饰符一起定义热键组合的键的虚拟键代码。

指定唯一的热键 ID

id 参数用于区分给定窗口可以接收的多个热键。 为了确保我们处理的是唯一的 ID,我使用 API 调用 GlobalAddAtom 来返回 id。 这是这样声明的

<DllImport("kernel32", EntryPoint:="GlobalAddAtom", _
SetLastError:=True, _
ExactSpelling:=False)> _
Public Function GlobalAddAtom(<MarshalAs(UnmanagedType.LPTStr)> _
                ByVal lpString As String) As Int32

End Function

创建一个窗口来监听 WM_HOTKEY 消息

最后一个参数是一个窗口句柄,用于监听 WM_HOTKEY 消息。 在这里有两个选择 - 要么传入现有窗口的句柄并子类化它的 WndProc 以查找该消息,要么创建一个新的不可见窗口专门用于监听该消息。

第二种选择是通过创建一个派生自 System.Windows.Forms.NativeWindow 的新类来实现的,如下所示

Public Class GlobalHotkeyListener
    Inherits NativeWindow

#Region "Private member variables"
    Private windowHandle As Integer
    Private mwh As ManualResetEvent
#End Region

    Public Sub New(ByVal Id As Int32, _
              ByVal fsModifiers As Int32, _
              ByVal vkey As Int32, _
              ByRef wh As ManualResetEvent)

        '\\ Get a local copy of the wait handle

        mwh = wh
        Dim cp As CreateParams = New CreateParams()

        ' Fill in the CreateParams details.
        cp.Caption = ""
        cp.ClassName = "STATIC"

        ' Set the position on the form
        cp.X = 0
        cp.Y = 0
        cp.Height = 0
        cp.Width = 0

        '\\ Set the style and extended style flags
        cp.Style = WindowStyleBits.WS_MINIMIZE
        cp.ExStyle = WindowStyleExtendedBits.WS_EX_NOACTIVATE

        ' Create the actual window
        Me.CreateHandle(cp)

        Try
            If Not RegisterHotkey(MyBase.Handle, _
                        Id, fsModifiers, vkey) Then
                Throw New Win32Exception()
            End If
        Catch e As Exception
            System.Diagnostics.Debug.WriteLine(e.ToString)
        End Try
    End Sub

WM_HOTKEY 的监听是这样完成的

<System.Security.Permissions._
                 PermissionSetAttribute(System.Security.Permissions_
                 .SecurityAction.Demand, Name:="FullTrust")> _
    Protected Overrides Sub WndProc(ByRef m As Message)
        ' Listen for messages that are sent to the 
        ' button window. Some messages are sent
        ' to the parent window instead of the button's window.

        Select Case (m.Msg)
            Case WM_HOTKEY
                ' Respond to the hotkey message (asynchronously??)
                If Not mwh Is Nothing Then
                    mwh.Set()
                End If
        End Select

        MyBase.WndProc(m)
    End Sub

未来改进

理想情况下,这个控件应该有一个 UIEditor 派生的类,以允许选择按键组合。

© . All rights reserved.