3

I have two monitors with the non-primary monitor (number 1) set to the main one's (number 2) top left like this:

enter image description here

I'll repeat: number 2 is the primary monitor.

Here's the code:

Cursor.Position = new Point(-500, -500);

What happens is that when the cursor is initially in the primary monitor (number 2), after the code is executed, the cursor moves to monitor number 1, to a location 500 pixels up from its bottom, but to its far right. Here:

enter image description here

Instead of here:

enter image description here

After running the above code twice, like so:

Cursor.Position = new Point(-500, -500);
Cursor.Position = new Point(-500, -500);

It gets to the correct place.

The problem is that this code seems like a hack and I'd like to avoid it, and get the cursor to the correct place in a "correct" way.

So how do I achieve that?

ispiro
  • 26,556
  • 38
  • 136
  • 291
  • [Using SetWindowPos with multiple monitors](https://stackoverflow.com/a/53026765/7444103) -- DpiAwareness notes. -- You didn't specify the target .Net version and DpiAwareness status of your app. – Jimi Mar 22 '22 at 21:41
  • @Jimi .NET6, and the DPI awareness seems irrelevant (note that after the second time the line is executed the cursor gets to the correct place). Also, both monitors have the same resolution. – ispiro Mar 22 '22 at 21:45
  • All right, I assume it's PerMonitorV2, default in .Net 6. See the note in [SetCursorPos](https://learn.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-setcursorpos) – Jimi Mar 22 '22 at 21:50
  • Could you also post the reported dimensions of the VirtualScreen when the app is positioned in the primary and secondary Monitor? -- *Hitting a wall*, with `SetCursorPos` is relatively *normal*. The DpiAwareness thing is about the assumed correct final position of the Pointer: it doesn't *seem right*. – Jimi Mar 22 '22 at 22:02
  • If these actually match in any contexts, try [SetPhysicalCursorPos](https://learn.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-setphysicalcursorpos) instead and see the notes in [PhysicalToLogicalPoint](https://learn.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-physicaltologicalpoint) (still behaviors related to the actual DpiAwareness of that process) – Jimi Mar 22 '22 at 22:31
  • @Jimi You are correct, it's `PerMonitorV2`. It's not `Hitting a wall`, it's passing to its other side as I've described in the question. I don't understand what you're asking about primary and secondary, but the original window is on the primary monitor. And the desired location is correct, pf course, because it does _end_ up there. – ispiro Mar 23 '22 at 11:18
  • It is *hitting a wall*, in fact you have to set the position twice to move the pointer. Did you read the notes in `SetCursorPos` (the function that is called when you set `Cursor.Position`)? A Form / Control has the Capture set on the Mouse Pointer (which is quite normal behavior). – Jimi Mar 24 '22 at 10:02

1 Answers1

2

When you have more than one screen then you have to be careful about Bounds of each screen C# provide an array of Screens and you can loop through that array to get more information about screen coordinates i.e. Screen.AllScreens

enter image description here

See the image bellow which demonstrate that only primary screen start from X:0 and Y:0 in 2D(X,Y) plane, we can adjust second screen anywhere, in my case it is has position (-1366,305) as shown. and different points ar enter image description here Each Screen has its bound from Left To Right and From Top to Bottom. You can use that bounds to go to exact position like shown in code I can move to any Point of any screen if I add its Bounds'value to Point.

   //To move on First Screen use its Bounds
    Cursor.Position = new Point(300 + Screen.AllScreens[0].Bounds.Left, 300 + Screen.AllScreens[0].Bounds.Top);
    
    //To move on Second Screen use its Bounds
    Cursor.Position = new Point(300 + Screen.AllScreens[1].Bounds.Left, 300 + Screen.AllScreens[1].Bounds.Top);
rtraees
  • 312
  • 2
  • 15