question

NickBuckenham-3845 avatar image
0 Votes"
NickBuckenham-3845 asked NickBuckenham-3845 commented

How can I read cursor position on a second screen?

I need to monitor the Cursor.Position.X as it moves from the left side of my screen #1 (the primary screen) to the right side of screen #2, which is set up as an extension of the primary screen and to the right of it. They are both HD so my total viewing area is 3840 x 1050, and I need to continuously monitor the value of 'x' as it changes from zero to 3840.

In Visual Basic: Dim MposX as integer = Cursor.Position.X only works for the primary screen. How can I get it to continuously provide the X value numbers (1921 to 3840) when the cursor is on screen #2?

dotnet-visual-basic
5 |1600 characters needed characters left characters exceeded

Up to 10 attachments (including images) can be used with a maximum of 3.0 MiB each and 30.0 MiB total.

Castorix31 avatar image
0 Votes"
Castorix31 answered NickBuckenham-3845 commented

Maybe you can test with a Mouse Hook.

From doc :

pt
Type: POINT
The x- and y-coordinates of the cursor, in per-monitor-aware screen coordinates.

So you can check if there is a difference with or without a Manifest (PROCESS_DPI_AWARENESS enumeration)
by changing the <dpiAware> value




Test of a Mouse Hook =>

 Imports System.Runtime.InteropServices
    
 Public Class Form1
     Public Const WH_MIN As Integer = (-1)
     Public Const WH_MSGFILTER As Integer = (-1)
     Public Const WH_JOURNALRECORD As Integer = 0
     Public Const WH_JOURNALPLAYBACK As Integer = 1
     Public Const WH_KEYBOARD As Integer = 2
     Public Const WH_GETMESSAGE As Integer = 3
     Public Const WH_CALLWNDPROC As Integer = 4
     Public Const WH_CBT As Integer = 5
     Public Const WH_SYSMSGFILTER As Integer = 6
     Public Const WH_MOUSE As Integer = 7
     Public Const WH_HARDWARE As Integer = 8
     Public Const WH_DEBUG As Integer = 9
     Public Const WH_SHELL As Integer = 10
     Public Const WH_FOREGROUNDIDLE As Integer = 11
     Public Const WH_CALLWNDPROCRET As Integer = 12
     Public Const WH_KEYBOARD_LL As Integer = 13
     Public Const WH_MOUSE_LL As Integer = 14
     Public Const WH_MAX As Integer = 14
     Public Const WH_MINHOOK As Integer = WH_MIN
     Public Const WH_MAXHOOK As Integer = WH_MAX
    
     <StructLayoutAttribute(LayoutKind.Sequential, CharSet:=CharSet.Unicode)>
     Public Structure MSLLHOOKSTRUCT
         Public pt As System.Drawing.Point
         Public mouseData As Integer
         Public flags As Integer
         Public time As Integer
         Public dwExtraInfo As UInteger
     End Structure
    
     Public Delegate Function HookProc(ByVal nCode As Integer, ByVal wParam As IntPtr, ByVal lParam As IntPtr) As Integer
    
     <DllImport("User32.dll", CharSet:=CharSet.Auto, CallingConvention:=CallingConvention.StdCall)>
     Public Shared Function SetWindowsHookEx(ByVal idHook As Integer, ByVal lpfn As HookProc, ByVal hInstance As IntPtr, ByVal threadId As Integer) As Integer
     End Function
    
     <DllImport("User32.dll", CharSet:=CharSet.Auto, CallingConvention:=CallingConvention.StdCall)>
     Public Shared Function UnhookWindowsHookEx(ByVal idHook As Integer) As Boolean
     End Function
    
     <DllImport("User32.dll", CharSet:=CharSet.Auto, CallingConvention:=CallingConvention.StdCall)>
     Public Shared Function CallNextHookEx(ByVal idHook As Integer, ByVal nCode As Integer, ByVal wParam As IntPtr, ByVal lParam As IntPtr) As Integer
     End Function
    
     Shared hHook As Integer = 0
     Private MouseLLProcedure As HookProc
    
     Public Sub New()
         InitializeComponent()
     End Sub
    
     Private Shared Label1 As Label = New Label()
    
     Public Shared Function MouseLLProc(ByVal nCode As Integer, ByVal wParam As IntPtr, ByVal lParam As IntPtr) As Integer
         If (nCode >= 0) Then
             Dim pMSLLHOOKSTRUCT As MSLLHOOKSTRUCT = New MSLLHOOKSTRUCT()
             pMSLLHOOKSTRUCT = CType(Marshal.PtrToStructure(lParam, pMSLLHOOKSTRUCT.[GetType]()), MSLLHOOKSTRUCT)
             Label1.Text = pMSLLHOOKSTRUCT.pt.ToString()
         End If
    
         Return If(nCode < 0, CallNextHookEx(hHook, nCode, wParam, lParam), 0)
     End Function
    
     Private Sub Form1_Load(ByVal sender As Object, ByVal e As EventArgs) Handles MyBase.Load
         Label1.Size = New Size(100, 32)
         Label1.Location = New Point(150, 150)
         Label1.BorderStyle = BorderStyle.Fixed3D
         Label1.BackColor = Color.Black
         Label1.ForeColor = Color.Yellow
         Label1.Font = New Font("Arial", 8.0F, FontStyle.Bold, GraphicsUnit.Point)
         Label1.TextAlign = ContentAlignment.MiddleCenter
         Me.Controls.Add(Label1)
         Me.ClientSize = New System.Drawing.Size(400, 400)
         MouseLLProcedure = New HookProc(AddressOf MouseLLProc)
         hHook = SetWindowsHookEx(WH_MOUSE_LL, MouseLLProcedure, CType(0, IntPtr), 0)
         CenterToScreen()
     End Sub
    
     Private Sub Form1_FormClosing(ByVal sender As Object, ByVal e As FormClosingEventArgs) Handles MyBase.FormClosing
         If hHook <> 0 Then UnhookWindowsHookEx(hHook)
     End Sub
    
 End Class

· 1
5 |1600 characters needed characters left characters exceeded

Up to 10 attachments (including images) can be used with a maximum of 3.0 MiB each and 30.0 MiB total.

I think I will just tuck all of this away for a rainy day, there obviously isn't a simple solution. Thanks guys, Nick

0 Votes 0 ·
DavidLowndes-6766 avatar image
0 Votes"
DavidLowndes-6766 answered DavidLowndes-6766 commented

Use the Win32 API GetCursorPos. I'm not aware of a .NET equivalent so you may need to PInvoke it.

· 4
5 |1600 characters needed characters left characters exceeded

Up to 10 attachments (including images) can be used with a maximum of 3.0 MiB each and 30.0 MiB total.

In that case, it ought to work!

0 Votes 0 ·

I'm purely a Visual Basic person ... PInvoke has provided this:

 <System.Runtime.InteropServices.StructLayout(Runtime.InteropServices.LayoutKind.Sequential)>
 Public Structure POINTAPI
     Dim x As Integer
     Dim y As Integer
 End Structure

 <DllImport("user32.dll", ExactSpelling:=True, SetLastError:=True)> _
 Public Shared Function GetCursorPos(ByRef lpPoint As POINTAPI) As <MarshalAs(UnmanagedType.Bool)> Boolean
 End Function

 Private Declare Function GetCursor Lib "user32.dll" () As IntPtr

but quite how to use it isn't clear to me. Any further advice?

0 Votes 0 ·
Show more comments