How can I read cursor position on a second screen?

Nick Buckenham 41 Reputation points
2021-06-29T17:31:56.357+00:00

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?

VB
VB
An object-oriented programming language developed by Microsoft that is implemented on the .NET Framework. Previously known as Visual Basic .NET.
2,668 questions
0 comments No comments
{count} votes

Accepted answer
  1. Castorix31 83,206 Reputation points
    2021-06-30T09:31:14.217+00:00

    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 additional answer

Sort by: Most helpful
  1. David Lowndes 4,711 Reputation points
    2021-06-29T20:38:42.813+00:00

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