一种使用RegisterHotkey 安装系统范围的热键的方法,该热键激活一个程序,该程序在任何屏幕中捕获光标下的颜色。
当注册为热键的键盘键被按下时,将通知注册它的窗口(或线程),无论窗口是否具有焦点、最小化或在另一个屏幕中。
按下热键时,使用Screen.FromPoint()方法识别光标所在的屏幕。
有关与 Screen 对象和 Screens/VirtualScreen 坐标相关的方法的更多信息,请参阅Using SetWindowPos with multiple monitors 中的答案。
然后使用CreateDC函数获取Cursor位置对应的Screen的设备上下文,并使用GetPixel函数获取Cursor下像素的Color。
在任何时候都不会创建位图。
注意事项:
- 必须使用UnregisterHotKey 函数取消注册已注册的热键。
- CreateDC 函数创建的句柄必须使用DeleteDC 函数释放。
- 按下热键时,WM_HOTKEY 消息将发送到注册它的窗口(或线程)。我们需要重写 WndProc 以接收通知。请参阅 MSDN 文档中与
WM_HOTKEY 消息相关的注释,了解由 wParam 和 lParam 表示的值的解释。
- 如果热键对应于我们注册的热键,则会调用一个动作(此处名为
HotkeyPressed)。光标下的颜色设置为 PicureBox 控件的背景颜色(此处命名为PicureBox1)。
- 由于提到了 F12 键,请注意此键由调试器(当前调试器或内核模式调试器)保留,因此不应使用它。当然,它可以与键修饰符(Control、Alt、Shift)相关联。
- 如果注册了更多热键,则必须增加/更改相应的标识符(此处为名为
myHotkeyID 的字段)。
在选择的表单中插入以下代码。
热键 (F11) 在 Form.Load() 事件中注册,在 Form.FormClosed() 事件中取消注册。
Imports System.Runtime.InteropServices
Imports System.Security
Imports System.Security.Permissions
Private Const WM_HOTKEY As Integer = &H312
Private myHotkeyID As Integer = 327680
Private myHotkeyModifiers As RegHotkeyModifiers = 0
Private currentScreen As Screen
Private cursorPosition As Point = Point.Empty
Friend Shared HotkeyPressed As Action
Public Sub New()
InitializeComponent()
HotkeyPressed =
Sub()
currentScreen = Screen.FromPoint(cursorPosition)
Me.PictureBox1.BackColor = PixelColorFromScreen(currentScreen, cursorPosition)
End Sub
End Sub
Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load
Dim result = RegisterHotKey(Me.Handle, myHotkeyID, myHotkeyModifiers, Keys.F11)
End Sub
Private Sub Form1_FormClosed(sender As Object, e As FormClosedEventArgs) Handles MyBase.FormClosed
UnregisterHotKey(Me.Handle, myHotkeyID)
End Sub
<SecurityCritical>
<SecurityPermission(SecurityAction.Demand, Flags:=SecurityPermissionFlag.UnmanagedCode)>
Protected Overrides Sub WndProc(ByRef m As Message)
Select Case m.Msg
Case WM_HOTKEY
If CType(m.WParam, Integer) > 0 Then
Dim keyPressed As Keys = CType(CType(m.LParam, Integer) >> 16, Keys)
Dim modifiers = CInt(m.LParam) And &HFF
If myHotkeyID = CInt(m.WParam) AndAlso CInt(myHotkeyModifiers) = modifiers Then
Select Case keyPressed
Case Keys.F11
cursorPosition = Cursor.Position
HotkeyPressed()
End Select
End If
End If
Exit Select
End Select
MyBase.WndProc(m)
End Sub
Win32 函数声明和辅助方法:
<Flags>
Friend Enum RegHotkeyModifiers As UInteger
MOD_ALT = &H1
MOD_CONTROL = &H2
MOD_SHIFT = &H4
MOD_WIN = &H8 ' WINDOWS key was held down. Reserved for use by the operating system.
MOD_NOREPEAT = &H4000 ' Keyboard auto-repeat does not yield multiple hotkey notifications.
End Enum
<DllImport("user32.dll")>
Friend Shared Function RegisterHotKey(hWnd As IntPtr, ActionHotkeyId As Integer, fsModifiers As RegHotkeyModifiers, VirtualKey As Integer) As Boolean
End Function
<DllImport("user32.dll")>
Friend Shared Function UnregisterHotKey(hWnd As IntPtr, ActionHotkeyId As Integer) As Boolean
End Function
<DllImport("gdi32.dll", SetLastError:=True, CharSet:=CharSet.Auto)>
Friend Shared Function CreateDC(lpszDriver As String, lpszDevice As String, lpszOutput As String, lpInitData As IntPtr) As IntPtr
End Function
<DllImport("gdi32.dll", SetLastError:=True, EntryPoint:="DeleteDC")>
Friend Shared Function DeleteDC(<[In]> hdc As IntPtr) As Boolean
End Function
<DllImport("gdi32.dll", SetLastError:=True)>
Friend Shared Function GetPixel(hdc As IntPtr, nXPos As Integer, nYPos As Integer) As UInteger
End Function
Friend Function CreateDCFromDeviceName(deviceName As String) As IntPtr
Return CreateDC(deviceName, Nothing, Nothing, IntPtr.Zero)
End Function
Private Function PixelColorFromScreen(screen As Screen, position As Point) As Color
Dim screenDC As IntPtr = CreateDCFromDeviceName(screen.DeviceName)
Dim pixel As UInteger = GetPixel(screenDC, position.X, position.Y)
Try
Return Color.FromArgb(CType(pixel And &HFF, Integer),
CType(pixel And &HFF00, Integer) >> 8,
CType(pixel And &HFF0000, Integer) >> 16)
Finally
DeleteDC(screenDC)
End Try
End Function