我正在创建一个工具,它可以抓取屏幕上任何内容的颜色,无论是在表单内部还是在表单外部。用户将使用他们的鼠标光标通过单击来抓取屏幕上的任何像素。问题在于,根据他们点击的内容,它可能会点击一个按钮或选择并突出显示一个图标。为了解决这个问题,我使用了 SetWindowsHookEx() 方法来全局禁用 mouseclick 事件。这行得通。但现在的问题是我的应用程序无法检测到点击事件已经发生。我曾尝试在不同的位置和不同的时刻解开鼠标,但它要么禁用鼠标,要么重新启用鼠标,但仍会继续执行上面提到的不需要的点击。
在用户可以获取像素颜色期间,计时器正在运行。所以很明显,我别无选择,只能在“像素抓取模式”下保持鼠标脱钩,以便继续抓取像素颜色。我试过设置鼠标钩,然后马上解开它,但这也不起作用。这似乎是一个问题 22。当然,我有一个用于 ESC 和 ENTER 键的键盘事件作为停止计时器和解开鼠标的替代方法。用于“取消”操作的 ESC 键和用于获取像素颜色并停止计时器的 ENTER 键。但我希望鼠标点击执行相同的功能而不点击/激活其他任何东西。这是我的代码。
Private Structure MSLLHOOKSTRUCT
Public pt As Point
Public mouseData As Int32
Public flags As Int32
Public time As Int32
Public extra As IntPtr
End Structure
Private mHook As IntPtr = IntPtr.Zero
Private Const WH_MOUSE_LL As Int32 = &HE
Private Const WM_RBUTTONDOWN As Int32 = &H204
Private Const WM_LBUTTONDOWN As Int32 = &H201
<MarshalAs(UnmanagedType.FunctionPtr)> Private mProc As MouseHookDelegate
Private Declare Function SetWindowsHookExW Lib "user32.dll" (ByVal idHook As Int32, ByVal HookProc As MouseHookDelegate, ByVal hInstance As IntPtr, ByVal wParam As Int32) As IntPtr
Private Declare Function UnhookWindowsHookEx Lib "user32.dll" (ByVal hook As IntPtr) As Boolean
Private Declare Function CallNextHookEx Lib "user32.dll" (ByVal idHook As Int32, ByVal nCode As Int32, ByVal wParam As IntPtr, ByRef lParam As MSLLHOOKSTRUCT) As Int32
Private Declare Function GetModuleHandleW Lib "kernel32.dll" (ByVal fakezero As IntPtr) As IntPtr
Private Delegate Function MouseHookDelegate(ByVal nCode As Int32, ByVal wParam As IntPtr, ByRef lParam As MSLLHOOKSTRUCT) As Int32
Public Function SetHookMouse() As Boolean
If mHook = IntPtr.Zero Then
mProc = New MouseHookDelegate(AddressOf MouseHookProc)
mHook = SetWindowsHookExW(WH_MOUSE_LL, mProc, GetModuleHandleW(IntPtr.Zero), 0)
End If
Return mHook <> IntPtr.Zero
End Function
Public Sub UnHookMouse()
If mHook = IntPtr.Zero Then Return
UnhookWindowsHookEx(mHook)
mHook = IntPtr.Zero
End Sub
Private Function MouseHookProc(ByVal nCode As Int32, ByVal wParam As IntPtr, ByRef lParam As MSLLHOOKSTRUCT) As Int32
'Label1.Text = "Message=" & wParam.ToInt32.ToString & " X=" & lParam.pt.X.ToString & " Y=" & lParam.pt.Y.ToString
If wParam.ToInt32 = WM_LBUTTONDOWN Then
Return 1
End If
Return CallNextHookEx(WH_MOUSE_LL, nCode, wParam, lParam)
End Function
Private Sub Timer2_Tick(sender As Object, e As EventArgs) Handles Timer2.Tick
Using bmp2 As New Bitmap(1, 1)
Using g As Graphics = Graphics.FromImage(bmp2)
g.CopyFromScreen(Cursor.Position,
New Point(0, 0), New Size(1, 1))
End Using
firsty = bmp2.GetPixel(0, 0).ToArgb
ToolStripButton7.BackColor = Color.FromArgb(firsty)
Form4.PictureBox1.BackColor = Color.FromArgb(firsty)
Form4.PictureBox5.BackColor = Color.FromArgb(firsty)
Form4.PictureBox4.BackColor = Color.FromArgb(firsty)
Form4.PictureBox3.BackColor = Color.FromArgb(firsty)
Panel3.BackColor = Color.FromArgb(firsty)
Me.Invalidate()
Dim CodeCodeInHex As String = bmp2.GetPixel(0, 0).ToArgb().ToString("X")
CodeCodeInHex = CodeCodeInHex.Remove(0, 2)
BGCOLOR.Text = "#" & CodeCodeInHex
Form4.Label1.Text = "#" & CodeCodeInHex
Label3.Text = "#" & CodeCodeInHex
End Using
SetHookMouse()
UnHookMouse()
Select Case MouseButtons
Case MouseButtons.Left
Cursor = Cursors.Default
Form4.Close()
SplitContainer3.SplitterDistance = SplitContainer3.Width - SPLITC3
Me.TopMost = True
ColorDialog1.Color = Color.FromArgb(firsty)
ToolStripTextBox1.Text = ColorDialog1.Color.A & ", " & ColorDialog1.Color.R & ", " & ColorDialog1.Color.G & ", " & ColorDialog1.Color.B
Panel2.Visible = False
If CSSToolbarToolStripMenuItem.Checked = True Then
Else
SplitContainer3.Panel2Collapsed = True
End If
Timer2.Stop()
Me.TopMost = False
Case MouseButtons.Right
Case MouseButtons.Middle
Case MouseButtons.Left + MouseButtons.Right
End Select
End Sub
或者,我也考虑过用不同的方法来解决这个问题。在此像素颜色抓取模式下,鼠标光标悬停在辅助窗体上的图片框上。表单跟随鼠标光标并保持在表单的死点。它悬停的图片框具有 Lime 的背景色,这是表单的透明度键,从而使其透明,允许用户看到表单后面的屏幕并抓住鼠标光标指向的像素颜色。
因此,有了这一点,也许我可以以某种方式让它表现得好像它点击了图片框,而不是它背后的东西。但我也没有找到解决方案。我对您可能拥有的任何方法持开放态度。谢谢你。我曾考虑让图片框半透明,使其透明但不完全,因为它会阻止任何点击,但这会使它抓取的像素颜色不准确。我曾经做过一个应用程序,其中一个无边框表单在整个屏幕上最大化,它的不透明度调整为“屏幕亮度过滤器”并允许点击它,但这与我在这里尝试做的相反. 所以我想知道。