Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/vb.net/16.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Vb.net 如何在设置MouseHook时检测mouseclick事件?_Vb.net_Disabled Input_Mouse Hook - Fatal编程技术网

Vb.net 如何在设置MouseHook时检测mouseclick事件?

Vb.net 如何在设置MouseHook时检测mouseclick事件?,vb.net,disabled-input,mouse-hook,Vb.net,Disabled Input,Mouse Hook,我正在创建一个工具,可以捕捉屏幕上任何东西的颜色,无论是在表单内部还是表单外部。用户将使用鼠标光标点击屏幕上的任何像素。问题在于,根据他们单击的内容,它可能会单击按钮或选择并高亮显示图标。为了解决这个问题,我使用了SetWindowsHookEx方法全局禁用mouseclick事件。这很有效。但现在的问题是,我的应用程序无法检测到发生了单击事件。我曾尝试在不同的位置和不同的时刻解除鼠标的挂钩,但它要么会使鼠标处于禁用状态,要么会重新启用鼠标,并且仍然会像上面提到的那样进行不必要的点击 在用户可以

我正在创建一个工具,可以捕捉屏幕上任何东西的颜色,无论是在表单内部还是表单外部。用户将使用鼠标光标点击屏幕上的任何像素。问题在于,根据他们单击的内容,它可能会单击按钮或选择并高亮显示图标。为了解决这个问题,我使用了SetWindowsHookEx方法全局禁用mouseclick事件。这很有效。但现在的问题是,我的应用程序无法检测到发生了单击事件。我曾尝试在不同的位置和不同的时刻解除鼠标的挂钩,但它要么会使鼠标处于禁用状态,要么会重新启用鼠标,并且仍然会像上面提到的那样进行不必要的点击

在用户可以获取像素颜色的时间内,计时器正在运行。所以很明显,我别无选择,只能在像素抓取模式下保持鼠标未钩住,以便抓取像素颜色。我试过设置鼠标挂钩,然后马上将其拔下,但这也不起作用。这似乎是个难题。当然,我有一个键盘事件的ESC和输入键作为替代停止计时器和脱钩鼠标。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
或者,我也想过用不同的方法来解决这个问题。在此像素颜色抓取模式下,鼠标光标悬停在辅助窗体上的picturebox上。窗体跟随鼠标光标并将其保持在窗体的中心位置。它悬停的picturebox有一个石灰色的背景色,这是窗体的透明键,因此它是透明的,允许用户看到窗体后面的屏幕,并抓取鼠标光标指向的像素颜色


因此,有了这一点,也许我可以让它表现得好像它点击了图片盒,而不是它背后的东西。但我也没有找到解决办法。我愿意接受你可能有的任何方法。非常感谢。我曾考虑过使picturebox半透明,使其透明但不完全透明,因为这样可以防止任何点击,但这样会使其获取的像素颜色不准确。我曾经做过一个应用程序,其中一个无边界表单在整个屏幕上最大化,它的不透明度调整为屏幕亮度过滤器,并允许它被点击通过,但这与我在这里尝试做的相反。所以我想知道。

我觉得你把事情复杂化了。。。您已经有了一个检测鼠标点击的鼠标钩子,因此在钩子回调中,不要只在WM_LBUTTONDOWN上返回1,而是在其中执行get color逻辑

例如,创建一个函数来获取特定位置的颜色:

Private Function GetScreenPixelColor(ByVal Position As Point) As Color
    Using bmp As New Bitmap(1, 1)
        Using g As Graphics = Graphics.FromImage(bmp)
             g.CopyFromScreen(Position, New Point(0, 0), New Size(1, 1))
        End Using

        Return bmp.GetPixel(0, 0)
    End Using
End Function
然后,在钩子中需要做的就是调用函数并对结果颜色进行处理:

If wParam.ToInt32() = WM_LBUTTONDOWN Then
    Dim PickedColor As Color = GetScreenPixelColor(Cursor.Position)

    'Do something with PickedColor...

    UnHookMouse()
    Return 1
End If
如果要在多个场景中应用此逻辑,只需制作另一种方法即可为您完成所有操作:

Private Sub PickColor()
    Dim PickedColor As Color = GetScreenPixelColor(Cursor.Position)

    'Do something with PickedColor...
End Sub
然后在你的钩子里,你需要做的就是:

If wParam.ToInt32() = WM_LBUTTONDOWN Then
    PickColor()
    UnHookMouse()
    Return 1
End If

我想我会根据VisualVincent给出的答案添加我的解决方案

我创建了一个执行“获取像素颜色”方法的函数:

Private Sub getcolor()
        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
    End Sub
然后调用mousehook函数中的函数:

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
            getcolor()
            Return 1
        End If
        Return CallNextHookEx(WH_MOUSE_LL, nCode, wParam, lParam)
    End Function

天哪。成功了。非常感谢。我没有意识到mousehook函数正在捕获鼠标事件。非常感谢你@巴迪洛赫:这就是钩子的作用;很高兴我能帮忙!有鼠标悬停的钩子吗?@BuddyRoach:不幸的是没有。你必须构建自己的解决方案。您可以使用设置为400毫秒默认鼠标悬停时间的计时器,如果鼠标挂钩检测到移动,请停止并重新启动计时器。如果计时器滴答作响,停止它,做你想做的任何事情,因为鼠标已经悬停了400毫秒。@BuddyRoach:看看我编译的下载,找到一个易于使用的鼠标挂钩。我的项目的wiki描述了它的工作原理: