11-01-2022, 02:08 AM (This post was last modified: 11-01-2022, 04:57 PM by Pete.)
So what I thought should be doable with thee two commands cannot be accomplished.
Here is what the code demonstrates.
1) Sets the program screen to the top left corner of the desktop.
2) Make a screen click, which places the mouse at 0, 0 of your desktop.
3) Now carefully move the mouse around in the program screen, and after a bit, carefully move it back to the upper right corner.
Well it should be back to 0, 0, right? Well, far from it. I mean provided the mouse isn't moved past the borders of the desktop, I would think the relative coordinates should be the same at the same points the mouse originated from: 0, 0 when back at the top left side of the desktop.
Code: (Select All)
_SCREENMOVE 0, 0
_DELAY .1
_SCREENCLICK 0, 0
DO
_LIMIT 30
WHILE _MOUSEINPUT
x = x + _MOUSEMOVEMENTX
y = y + _MOUSEMOVEMENTY
WEND
LOCATE 1, 1: PRINT y; x; " ";
IF LEN(INKEY$) THEN
EXIT DO
END IF
LOOP
END
I believe I know the issue, basically `_MouseMovementX` and `_MouseMovementY` do not just report the delta between mouse X/Y in movement, they actually report movement information more directly from the mouse itself. You can read about it a bit here. The reason it doesn't accurately track your cursor is because Windows doesn't just move your cursor X units for every Y movement units reported by the mouse, rather it applies the "speed" and "acceleration" pointer settings. This distinction is good for things like games where you're hiding the cursor anyway (and thus you get more accurate info to work with), but not if you're just trying to track where the cursor is.
You can kinda see this if you go into the `Mouse Properties` and turn off `Enhance pointer precision`, that's basically the acceleration setting. When it's off the mouse position reported by your program stays more or less accurate (as far as I can tell). The distance it thinks you traveled is still wrong though because that's dependent on your "mouse pointer speed".
Very difficult for me to imagine a practical use for this keyword set. Since the difference is very little at the start, but multiplies the longer you use it, I also find it difficult to understand why the developers didn't sync it with the mouse pointer.
So unfortunately we have nothing in QB64 to locate the mouse cursor outside of the program window in the same y, x coordinates that _SCREENCLICK would be assigned to.
If it wasn't for Windows API, I'd have to do a hack where I build a transparent window over the desktop to accomplish this, but since Steve appointed me as the official API Princess, I'll go with this...
Code: (Select All)
REDIM Hold AS POINTAPI
TYPE POINTAPI
X_Pos AS LONG
Y_Pos AS LONG
END TYPE
DECLARE DYNAMIC LIBRARY "user32"
FUNCTION GetCursorPos (lpPoint AS POINTAPI)
END DECLARE
DO
_LIMIT 30
z = GetCursorPos(Hold)
LOCATE 1, 1: PRINT "Col ="; Hold.X_Pos;: LOCATE 1, 11 + 1: PRINT "Row ="; Hold.Y_Pos; " ";
IF LEN(INKEY$) THEN
EXIT DO
END IF
LOOP
END
The API makes some sense when you think of it as a way to directly make use of mouse movement, not a way to track where the cursor is. It's simply not intended for that usage, it's intended for the case where the application has hidden the cursor and is using the mouse to move a camera or etc. In that situation they don't want the cursor acceleration and speed to impact it, such settings are likely configurable within their application instead and they handle it themselves.
Potentially we could add commands for getting the absolute cursor position, it sounds fairly achievable. We'd have to work out how it fits in with the rest of the mouse stuff though, throwing it into _MouseInput might not be the best (your program would have to handle every mouse event from the system), and also we wouldn't want it easily confusable with the existing `_MouseX` and `_MouseY`.
11-01-2022, 11:58 AM (This post was last modified: 11-01-2022, 12:03 PM by Pete.)
I'd think the way _SCREENCLICK is set up would be the same method you would want to use for a y and x absolute mouse cursor position addition. Of course it opens up a small can of worms in that _MOUSEMOVEY and X would have to have absolute additions, too.
Maybe something like...
_MOUSEABSY and X
_MOUSEMOVEABSY and X
Oh well, I'm, not the GOTO guy when it comes to coming up with names. If I had Adam's job, all the animals would have been named Spot. See Spot run. See Spot fly. See Spot swim. You get the idea.
For now, I'm going to continue my project with my API solution. The project will make use of a couple more API calls, so it wouldn't have been x-platform, anyway.
Man I had to remind myself of _ScreenClick and I seem to recall _MouseMovementX (sounds like an old Disney ad campaign) wasn't working.
@Pete what did you want from or expect or need from _MouseMovementX ? (That term also drops a hint of a recent mouse presence.)
Wiki: "The _MOUSEMOVEMENTX function returns the relative horizontal position of the mouse cursor as positive or negative values."
Seems like an easy thing to code from a click by saving the mouse x, y and then calc the current location or click from the saved mouse x, y.
Do
While _MouseInput: Wend
mx = _MouseX: my = _MouseY: mb = _MouseButton(1)
If mb Then saveMx = mx: saveMy = my
Cls
Print mx, my
Print "Movements:"; mx - saveMx; my - saveMy
_Display
_Limit 30
Loop
I'm making something where I need the program window minimized and it tracks the mouse position anywhere on the Desktop at the exact coordinates a _SCREENCLICK or SCREENPRINT could be used. Our QB64 _MOUSEY and X functions, of course, only track movement in the QB64 window, not the entire desktop, and no, I don't want to make the QB64 window a desktop overlay. I could, as I could make it perfectly transparent and you'd never even know it was overlying your desktop, but I don't want that. I want the cursor to move about the desktop, the minimized program window to track it, and if I make a click, those coordinates get feed to the _SCREENPRINT command, and at that screen position on some open desktop app the text gets printed.
Now in QB64 the only keywords that track the mouse cursor outside the program window are _MOUSEMOVEMENTY and X. The problem is they apparently, according to Matt, work based on speed and direction, not on absolute pixel location. I get it "relative" but I thought releative movement out would always equal relative movement back, but they don't work that way. So for example, using those keywords to move the pointer and display the difference from the exact upper left corner of the desktop to the middle of the desktop and back will never get you back to 0, 0. Something like 20, -8. Anyway, that's spells fail for using _SCREENCLICK or _SCREENPRINT at specific desktop pixels, so those two QB64 keyword functions are out.
So for now I just created a simple Windows API call that does this for me. I didn't even have to hock my tiara Steve gave me to do it. API Princess my ASCII! I'm the Queen, and Steve knows it!