Some MOUSE Routines - TerryRitchie - 06-04-2024
I was updating my mouse library to incorporate a windows API call and was having a heck of a time. So I wrote this little program to get everything straight in my head before incorporating the changes. I thought others might find the code useful.
Note: This will only work with Windows.
If you run the code let me know if you find any of the values off. Everything tests ok with my Windows 7 Pro machine but I know some changes related to DPI were introduced with Windows 10 that may cause these to be inaccurate. Please let me know if this is the case.
Code: (Select All)
'MOUSE test
TYPE TYPE_IPOINT ' 2D x,y point definition
x AS LONG ' x long integer coordinate
y AS LONG ' y long integer coordinate
END TYPE
DECLARE DYNAMIC LIBRARY "user32"
'get current mouse x/y position
'http://allapi.mentalis.org/apilist/GetCursorPos.shtml
FUNCTION GetCursorPos% (lpPoint AS TYPE_IPOINT)
'system window metrics in pixels
'https://learn.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-getsystemmetrics
FUNCTION GetSystemMetrics% (BYVAL nIndex AS INTEGER)
END DECLARE
DIM GetXY AS INTEGER ' dummy variable to use with API function call
DIM Mouse AS TYPE_IPOINT ' absolute mouse location on dekstop
DIM CaptionHeight AS INTEGER ' program window caption height
DIM BorderHeight AS INTEGER ' program window border height
DIM BorderWidth AS INTEGER ' program window border width
DIM WindowX1 AS INTEGER ' location of program window on desktop
DIM WindowY1 AS INTEGER ' (everything including borders)
DIM WindowX2 AS INTEGER
DIM WindowY2 AS INTEGER
DIM ClientX1 AS INTEGER ' location of client window on desktop
DIM ClientY1 AS INTEGER ' (the SCREEN statement)
DIM ClientX2 AS INTEGER
DIM ClientY2 AS INTEGER
DIM CaptionX1 AS INTEGER ' location of client window caption on desktop
DIM CaptionY1 AS INTEGER ' (the _TITLE bar)
DIM CaptionX2 AS INTEGER
DIM CaptionY2 AS INTEGER
DIM ClientMouseX AS INTEGER ' relative mouse location on client window
DIM ClientMouseY AS INTEGER
DIM WindowMouseX AS INTEGER ' relative mouse location on program window
DIM WindowMouseY AS INTEGER
DIM CaptionMouseX AS INTEGER ' relative mouse location on program window's caption
DIM CaptionMouseY AS INTEGER
DIM ProgramTitle AS STRING ' program title to display
DIM OldTitle AS STRING ' the old program title (to reduce flickering)
'+-----------------+
'| Begin main code |
'+-----------------+
SCREEN _NEWIMAGE(800, 600, 32) ' create client window
'+---------------------------------------------------------------+
'| Get the program window's caption height and border dimensions |
'| |
'| Note: This would need to go into the loop to pick up theme |
'| changes made by user. |
'+---------------------------------------------------------------+
CaptionHeight = GetSystemMetrics(4) ' caption height (from windows)
BorderHeight = GetSystemMetrics(33) - GetSystemMetrics(6) ' sizing border width - window border width (from windows)
BorderWidth = GetSystemMetrics(32) - GetSystemMetrics(5) ' sizing border height - window border height (from windows)
DO
'+---------------------------------------------------------------+
'| Calculate absolute x,y locations of program window on desktop |
'+---------------------------------------------------------------+
WindowX1 = _SCREENX
WindowY1 = _SCREENY
WindowX2 = WindowX1 + BorderWidth * 2 + _WIDTH - 1
WindowY2 = WindowY1 + CaptionHeight + BorderHeight * 2 + _HEIGHT - 1
'+--------------------------------------------------------------+
'| Calculate absolute x,y locations of client window on desktop |
'+--------------------------------------------------------------+
ClientX1 = _SCREENX + BorderWidth
ClientY1 = _SCREENY + CaptionHeight + BorderHeight
ClientX2 = ClientX1 + _WIDTH - 1
ClientY2 = ClientY1 + _HEIGHT - 1
'+-----------------------------------------------------------------------+
'| Calculate absolute x,y locations of program window caption on desktop |
'+-----------------------------------------------------------------------+
CaptionX1 = ClientX1
CaptionY1 = _SCREENY + BorderHeight
CaptionX2 = ClientX2
CaptionY2 = CaptionY1 + CaptionHeight
'+-----------------------------------------------------+
'| Get absolute mouse location on desktop |
'| |
'| Calculate relative mouse location on program window |
'| Calculate relative mouse location on client window |
'+-----------------------------------------------------+
GetXY = GetCursorPos(Mouse) ' absolute mouse location on desktop
WindowMouseX = Mouse.x - WindowX1 ' relative mouse location on program window
WindowMouseY = Mouse.y - WindowY1
ClientMouseX = Mouse.x - ClientX1 ' relative mouse location on client window
ClientMouseY = Mouse.y - ClientY1
CaptionMouseX = Mouse.x - CaptionX1
CaptionMouseY = Mouse.y - CaptionY1
LOCATE 2, 1 ' print some variables
PRINT " Mouse Locations:"
PRINT
PRINT " ABSOLUTE DESKTOP X ="; Mouse.x
PRINT " ABSOLUTE DESKTOP Y ="; Mouse.y
PRINT
PRINT " RELATIVE WINDOW X ="; WindowMouseX
PRINT " RELATIVE WINDOW Y ="; WindowMouseY
PRINT
PRINT " RELATIVE CAPTION X ="; CaptionMouseX
PRINT " RELATIVE CAPTION Y ="; CaptionMouseY
PRINT
'+-------------------------------------------------------------------------------------------------+
'| Note: _MOUSEX and _MOUSEY won't even be needed and probably should be avoided because of delays |
'| caused by calling the API and then clearing the buffer with WHILE _MOUSEINPUT: WEND |
'+-------------------------------------------------------------------------------------------------+
WHILE _MOUSEINPUT: WEND
PRINT " RELATIVE CLIENT X ="; ClientMouseX, "_MOUSEX ="; _MOUSEX; " ", "These values should equal"
PRINT " RELATIVE CLIENT Y ="; ClientMouseY, "_MOUSEY ="; _MOUSEY; " ", "when pointer is in client"
PRINT
PRINT " Program window coordinates on desktop: ("; WindowX1; ","; WindowY1; ") - ("; WindowX2; ","; WindowY2; ")"
PRINT
PRINT " Client window coordinates on desktop: ("; ClientX1; ","; ClientY1; ") - ("; ClientX2; ","; ClientY2; ")"
PRINT
PRINT " Caption window coordinates on desktop: ("; CaptionX1; ","; CaptionY1; ") - ("; CaptionX2; ","; CaptionY2; ")"
PRINT
IF MouseWithin(Mouse.x, Mouse.y, ClientX1, ClientY1, ClientX2, ClientY2) THEN
ProgramTitle = "In CLIENT Area "
ELSEIF MouseWithin(Mouse.x, Mouse.y, CaptionX1, CaptionY1, CaptionX2, CaptionY2) THEN
ProgramTitle = "In CAPTION Area "
ELSEIF MouseWithin(Mouse.x, Mouse.y, WindowX1, WindowY1, WindowX2, WindowY2) THEN
ProgramTitle = "On WINDOW Border "
ELSE
ProgramTitle = "Mouse OUTSIDE of program"
END IF
PRINT " "; ProgramTitle
IF OldTitle <> ProgramTitle THEN
_TITLE ProgramTitle
OldTitle = ProgramTitle
END IF
LOOP UNTIL _KEYDOWN(27)
SYSTEM
FUNCTION MouseWithin% (mx AS INTEGER, my AS INTEGER, x1 AS INTEGER, y1 AS INTEGER, x2 AS INTEGER, y2 AS INTEGER)
'Quick and dirty rectangular collision routine
MouseWithin% = 0
IF mx >= x1 AND mx <= x2 AND my >= y1 AND my <= y2 THEN MouseWithin% = -1
END FUNCTION
RE: Some MOUSE Routines - eoredson - 06-05-2024
I got this mouse source and used it in QB64PE 32-bit on Windows 10 and it seems to work.
It is brilliant code when detecting the mouse in Client/Caption/Border/Outside areas.. Did not know that could be done!
Erik.
RE: Some MOUSE Routines - TerryRitchie - 06-05-2024
(06-05-2024, 03:22 AM)eoredson Wrote: I got this mouse source and used it in QB64PE 32-bit on Windows 10 and it seems to work.
It is brilliant code when detecting the mouse in Client/Caption/Border/Outside areas.. Did not know that could be done!
Erik. Thank you for testing it. I can't take credit for the API calls. One of our API gurus on the forum showed me that a while back.
|