Thread Rating:
  • 0 Vote(s) - 0 Average
  • 1
  • 2
  • 3
  • 4
  • 5
Detect when mouse leaves program window
#1
I could have swore there was a discussion about this before, either on this forum or previous forums, but my searches have come up empty.

How can I detect when the mouse pointer has left the program window?

I seem to remember someone showing how to use an API call ( @SpriggsySpriggs ?) but I didn't have the foresight to add it to my tool box of goodies.

Any suggestions?
New to QB64pe? Visit the QB64 tutorial to get started.
QB64 Tutorial
Reply
#2
(08-16-2023, 01:11 AM)TerryRitchie Wrote: I could have swore there was a discussion about this before, either on this forum or previous forums, but my searches have come up empty.

How can I detect when the mouse pointer has left the program window?

I seem to remember someone showing how to use an API call ( @SpriggsySpriggs ?) but I didn't have the foresight to add it to my tool box of goodies.

Any suggestions?

Yeah the OS should know where the mouse is, Spriggsy good call, have to decide by OS what "API" to call assuming Linux has similar function and why wouldn't it, sure @mnrvovrfc  will be here to the rescue at mention of Linux and most it's Distros ;-))

OS should also know where the QB64 screen is so by deduction if mouse isn't on QB64 screen it "has left the building".
b = b + ...
Reply
#3
I was waiting for Spriggsy to jump in here first because his API knowledge is heaps more than mine.  There's probably a better API way of doing this, but here's a quick way off the top of my head - using the GetCursorPos API. 

- Dav

Code: (Select All)

TYPE POINTAPI
    x AS LONG
    y AS LONG
END TYPE
DIM apixy AS POINTAPI 'mouse x/y for the GetCursorPos function

DECLARE DYNAMIC LIBRARY "user32"
    'get current mouse x/y position
    'http://allapi.mentalis.org/apilist/GetCursorPos.shtml
    FUNCTION GetCursorPos% (lpPoint AS POINTAPI)
END DECLARE


SCREEN 12

DO

    'poll mouse x/y
    tmp = GetCursorPos(apixy)
    ax = apixy.x: ay = apixy.y

    sx = _SCREENX: sy = _SCREENY

    CLS: PRINT "MOUSE IN"
    IF ax - sx < 0 THEN CLS: PRINT "MOUSE OUT"
    IF ax - sx > _WIDTH THEN CLS: PRINT "MOUSE OUT"
    IF ay - sy < 0 THEN CLS: PRINT "MOUSE OUT"
    IF ay - sy > _HEIGHT THEN CLS: PRINT "MOUSE OUT"
    _DISPLAY

LOOP


Find my programs here in Dav's QB64 Corner
Reply
#4
(08-16-2023, 03:22 PM)Dav Wrote: I was waiting for Spriggsy to jump in here first because his API knowledge is heaps more than mine.  There's probably a better API way of doing this, but here's a quick way off the top of my head - using the GetCursorPos API. 

- Dav

Thanks Dav. Very simple and exactly what's needed.

How about you Linux users? Any ideas how to get this functionality in Linux as well?
New to QB64pe? Visit the QB64 tutorial to get started.
QB64 Tutorial
Reply
#5
Something strange happens with your code @Dav . The mouse is detected as out before the cursor leaves the bottom of the window. The strip being missed at the bottom appears to be the exact same height as the title bar. The title bar height of the window may need to be obtained as well to compensate.

The mouse pointer is still shown within bounds while it's in the title bar, which is technically correct. The y value needs to be adjusted by the height of the title bar to remove the dead strip at the bottom and to remove the title bar area from the equation, showing the mouse only within the working area of the window.

Solve one hurdle only to introduce another, LOL. I love programming. Smile
New to QB64pe? Visit the QB64 tutorial to get started.
QB64 Tutorial
Reply
#6
Yeah I guess we will have to account for the title bar height.  There's an API called GetSystemMetrics that can be used for that kind of information:
https://learn.microsoft.com/en-us/window...temmetrics

I'm getting ready to leave, so I don't have time to whip something up with it.  I'll try to get on it when getting back home.

Here's some VB code to look at to give you an example: http://allapi.mentalis.org/apilist/7D8B6...CE469.html


- Dav

Find my programs here in Dav's QB64 Corner
Reply
#7
(08-16-2023, 06:09 PM)Dav Wrote: Yeah I guess we will have to account for the title bar height.  There's an API called GetSystemMetrics that can be used for that kind of information:
https://learn.microsoft.com/en-us/window...temmetrics

I'm getting ready to leave, so I don't have time to whip something up with it.  I'll try to get on it when getting back home.

Here's some VB code to look at to give you an example: http://allapi.mentalis.org/apilist/7D8B6...CE469.html


- Dav
I was just googling and came across that same API call. I'm like a lost puppy when it comes to working with APIs in QB64 however, something I need to learn and then create a tutorial lesson for others with the same issue.
New to QB64pe? Visit the QB64 tutorial to get started.
QB64 Tutorial
Reply
#8
Using this Microsoft guide I made the modifications to the code below:

https://learn.microsoft.com/en-us/window...temmetrics

What am I missing? No matter which parameter I send to GetSystemMetrics I always get a return value of 0.

Update: Got it!

Forgot BYVAL in the FUNCTION line: FUNCTION GetSystemMetrics% (BYVAL nIndex AS INTEGER)

It looks like the border height needs to be taken into account too.

Code: (Select All)
TYPE POINTAPI
    x AS LONG
    y AS LONG
END TYPE
DIM apixy AS POINTAPI 'mouse x/y for the GetCursorPos function
DIM CaptionHeight AS INTEGER
DIM BorderHeight AS INTEGER
DIM BoderWidth AS INTEGER
DECLARE DYNAMIC LIBRARY "user32"
    'get current mouse x/y position
    'http://allapi.mentalis.org/apilist/GetCursorPos.shtml
    FUNCTION GetCursorPos% (lpPoint AS POINTAPI)
    '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

SCREEN 12
DO
    CaptionHeight = GetSystemMetrics(4) ' caption (title bar) height in pixels
    BorderWidth = GetSystemMetrics(45) '   3D width of window border in pixels (5 for non-3D)
    BorderHeight = GetSystemMetrics(46) '  3D height of window border in pixels (6 for non-3D)
    'poll mouse x/y
    tmp = GetCursorPos(apixy)
    ax = apixy.x - BorderWidth
    ay = apixy.y - CaptionHeight - BorderHeight
    sx = _SCREENX
    sy = _SCREENY
    CLS: PRINT "MOUSE IN"
    IF ax - sx < 0 THEN CLS: PRINT "MOUSE OUT"
    IF ax - sx > _WIDTH THEN CLS: PRINT "MOUSE OUT"
    IF ay - sy < 0 THEN CLS: PRINT "MOUSE OUT"
    IF ay - sy > _HEIGHT THEN CLS: PRINT "MOUSE OUT"
    LOCATE 2, 2: PRINT "CaptionHeight:"; CaptionHeight
    LOCATE 3, 2: PRINT "BorderWidth  :"; BorderWidth
    LOCATE 4, 2: PRINT "BorderHeight :"; BorderHeight
    _DISPLAY
LOOP
New to QB64pe? Visit the QB64 tutorial to get started.
QB64 Tutorial
Reply
#9
Yep, BYVAL is needed.  Glad you got it working!

(had to come right back home, gig was cancelled at last minute)

EDIT:  By the way, there are some more calls that API can do for additional MOUSE info, like see if scroll wheels are present, or if L/R mouse buttons are currently swapped.

- Dav

Find my programs here in Dav's QB64 Corner
Reply
#10
(08-16-2023, 07:13 PM)Dav Wrote: Yep, BYVAL is needed.  Glad you got it working!

(had to come right back home, gig was cancelled at last minute)

- Dav
I just updated the code above to take into account the border width and height.
New to QB64pe? Visit the QB64 tutorial to get started.
QB64 Tutorial
Reply




Users browsing this thread: 11 Guest(s)