VB.NET - заставляет это приложение возвращать два целых числа для настройки мыши
Мне удалось заставить этот код C# (не мой!) Работать в VB.NET, чтобы реализовать ловушку мыши в консольном приложении. Вот код VB.NET:
Imports System.Runtime.InteropServices
Imports System.Windows.Forms
Module Module1
Class InterceptMouse
Private Shared _proc As LowLevelMouseProc = AddressOf HookCallback
Private Shared _hookID As IntPtr = IntPtr.Zero
Public Shared Sub Main()
_hookID = SetHook(_proc)
Application.Run()
UnhookWindowsHookEx(_hookID)
End Sub
Private Shared Function SetHook(proc As LowLevelMouseProc) As IntPtr
Using curProcess As Process = Process.GetCurrentProcess()
Using curModule As ProcessModule = curProcess.MainModule
Return SetWindowsHookEx(WH_MOUSE_LL, proc, GetModuleHandle(curModule.ModuleName), 0)
End Using
End Using
End Function
Private Delegate Function LowLevelMouseProc(nCode As Integer, wParam As IntPtr, lParam As IntPtr) As IntPtr
Private Shared Function HookCallback(nCode As Integer, wParam As IntPtr, lParam As IntPtr) As IntPtr
Dim MouseSetting As Integer = MouseMessages.WM_LBUTTONDOWN
Dim hookStruct As MSLLHOOKSTRUCT
If nCode >= 0 AndAlso MouseSetting = CType(wParam, MouseMessages) Then
hookStruct = CType(Marshal.PtrToStructure(lParam, GetType(MSLLHOOKSTRUCT)), MSLLHOOKSTRUCT)
Console.WriteLine(hookStruct.pt.x & ", " & hookStruct.pt.y)
End If
Dim pt As New POINT
pt.x = hookStruct.pt.x
pt.y = hookStruct.pt.y
MouseCoordinates.Add(pt)
Return CallNextHookEx(_hookID, nCode, wParam, lParam)
End Function
Private Const WH_MOUSE_LL As Integer = 14
Private Enum MouseMessages
WM_LBUTTONDOWN = &H201
WM_LBUTTONUP = &H202
WM_MOUSEMOVE = &H200
WM_MOUSEWHEEL = &H20A
WM_RBUTTONDOWN = &H204
WM_RBUTTONUP = &H205
End Enum
<StructLayout(LayoutKind.Sequential)> _
Public Structure POINT
Public x As Integer
Public y As Integer
End Structure
<StructLayout(LayoutKind.Sequential)> _
Private Structure MSLLHOOKSTRUCT
Public pt As POINT
Public mouseData As UInteger
Public flags As UInteger
Public time As UInteger
Public dwExtraInfo As IntPtr
End Structure
<DllImport("user32.dll", CharSet:=CharSet.Auto, SetLastError:=True)> _
Private Shared Function SetWindowsHookEx(idHook As Integer, lpfn As LowLevelMouseProc, hMod As IntPtr, dwThreadId As UInteger) As IntPtr
End Function
<DllImport("user32.dll", CharSet:=CharSet.Auto, SetLastError:=True)> _
Private Shared Function UnhookWindowsHookEx(hhk As IntPtr) As <MarshalAs(UnmanagedType.Bool)> Boolean
End Function
<DllImport("user32.dll", CharSet:=CharSet.Auto, SetLastError:=True)> _
Private Shared Function CallNextHookEx(hhk As IntPtr, nCode As Integer, wParam As IntPtr, lParam As IntPtr) As IntPtr
End Function
<DllImport("kernel32.dll", CharSet:=CharSet.Auto, SetLastError:=True)> _
Private Shared Function GetModuleHandle(lpModuleName As String) As IntPtr
End Function
End Class
Я тогда назвал это от Sub Main:
Sub Main()
InterceptMouse.Main()
End Sub
Однако, когда я отлаживаю его, он переходит к строке Application.Run() и не переходит к следующей строке, поэтому я не вижу, что он делает за кадром. Затем он ожидает ввода пользователя и возвращает целочисленные координаты на консоли. Это не то, чего я хочу. Я хочу, чтобы этот код выполнялся в другой функции или в фоновом режиме, передавая координаты основному потоку всякий раз, когда он получает щелчок мыши, чтобы он мог обрабатывать все остальное. Проблема в том, что этот код слишком сложен для моего уровня понимания, и я действительно не знаю, как он работает. Если мне удастся хотя бы заставить консоль возвращать координаты мыши всякий раз, когда пользователь щелкает, я могу игнорировать ее и обрабатывать оставшуюся часть кода оттуда.
1 ответ
Хорошая причина? Черт возьми нет.
Мне нравится, как вы бросаете осторожность на ветер. Используйте на свой страх и риск!
Не уверен, как именно вы собираетесь использовать это в консольном приложении...
... Я немного переработал это:
Imports System.Windows.Forms
Imports System.Runtime.InteropServices
Module Module1
Private counter As Integer = 0
Private WithEvents IM As InterceptMouse
Sub Main()
IM = InterceptMouse.Instance
IM.Start()
While counter < 3
System.Threading.Thread.Sleep(100)
End While
IM.Shutdown()
Console.Write("Press Enter to Quit")
Console.ReadLine()
End Sub
Private Sub IM_MouseClick(pt As InterceptMouse.POINT) Handles IM.MouseClick
Console.WriteLine(pt.x.ToString() & ", " & pt.y.ToString())
counter = counter + 1
End Sub
Public Class InterceptMouse
Inherits ApplicationContext
Public Event MouseClick(ByVal pt As InterceptMouse.POINT)
Private Shared _IM As InterceptMouse
Public Shared ReadOnly Property Instance() As InterceptMouse
Get
If IsNothing(_IM) Then
_IM = New InterceptMouse()
End If
Return _IM
End Get
End Property
Private _proc As LowLevelMouseProc = AddressOf HookCallback
Private _hookID As IntPtr = IntPtr.Zero
Private T As System.Threading.Thread = Nothing
Private Sub New()
End Sub
Public Sub Start()
If IsNothing(T) Then
T = New Threading.Thread(AddressOf Main)
T.Start()
End If
End Sub
Private Sub Main()
_hookID = SetHook(_proc)
Application.Run(Me)
UnhookWindowsHookEx(_hookID)
T = Nothing
End Sub
Public Sub Shutdown()
If Not IsNothing(T) Then
Application.Exit()
End If
End Sub
Private Function SetHook(proc As LowLevelMouseProc) As IntPtr
Using curProcess As Process = Process.GetCurrentProcess()
Using curModule As ProcessModule = curProcess.MainModule
Return SetWindowsHookEx(WH_MOUSE_LL, proc, GetModuleHandle(curModule.ModuleName), 0)
End Using
End Using
End Function
Private Delegate Function LowLevelMouseProc(nCode As Integer, wParam As IntPtr, lParam As IntPtr) As IntPtr
Private Function HookCallback(nCode As Integer, wParam As IntPtr, lParam As IntPtr) As IntPtr
Dim MouseSetting As Integer = MouseMessages.WM_LBUTTONDOWN
Dim hookStruct As MSLLHOOKSTRUCT
If nCode >= 0 AndAlso MouseSetting = CType(wParam, MouseMessages) Then
hookStruct = CType(Marshal.PtrToStructure(lParam, GetType(MSLLHOOKSTRUCT)), MSLLHOOKSTRUCT)
Dim pt As New POINT
pt.x = hookStruct.pt.x
pt.y = hookStruct.pt.y
RaiseEvent MouseClick(pt)
End If
Return CallNextHookEx(_hookID, nCode, wParam, lParam)
End Function
Private Const WH_MOUSE_LL As Integer = 14
Private Enum MouseMessages
WM_LBUTTONDOWN = &H201
WM_LBUTTONUP = &H202
WM_MOUSEMOVE = &H200
WM_MOUSEWHEEL = &H20A
WM_RBUTTONDOWN = &H204
WM_RBUTTONUP = &H205
End Enum
<StructLayout(LayoutKind.Sequential)> _
Public Structure POINT
Public x As Integer
Public y As Integer
End Structure
<StructLayout(LayoutKind.Sequential)> _
Private Structure MSLLHOOKSTRUCT
Public pt As POINT
Public mouseData As UInteger
Public flags As UInteger
Public time As UInteger
Public dwExtraInfo As IntPtr
End Structure
<DllImport("user32.dll", CharSet:=CharSet.Auto, SetLastError:=True)> _
Private Shared Function SetWindowsHookEx(idHook As Integer, lpfn As LowLevelMouseProc, hMod As IntPtr, dwThreadId As UInteger) As IntPtr
End Function
<DllImport("user32.dll", CharSet:=CharSet.Auto, SetLastError:=True)> _
Public Shared Function UnhookWindowsHookEx(hhk As IntPtr) As <MarshalAs(UnmanagedType.Bool)> Boolean
End Function
<DllImport("user32.dll", CharSet:=CharSet.Auto, SetLastError:=True)> _
Private Shared Function CallNextHookEx(hhk As IntPtr, nCode As Integer, wParam As IntPtr, lParam As IntPtr) As IntPtr
End Function
<DllImport("kernel32.dll", CharSet:=CharSet.Auto, SetLastError:=True)> _
Private Shared Function GetModuleHandle(lpModuleName As String) As IntPtr
End Function
End Class
End Module