How can I get the client dimensions of the monitor the mouse is in and the mouse's coordinates? Topic is solved

Get help with using AutoHotkey (v2 or newer) and its commands and hotkeys
IMTheNachoMan
Posts: 59
Joined: 01 Mar 2022, 17:07
Contact:

How can I get the client dimensions of the monitor the mouse is in and the mouse's coordinates?

19 Sep 2023, 10:25

I am trying to make a GUI show up centered under a mouse.

I need to know the client area of the monitor the mouse is in because if the mouse is too far to the edge, then I have to offset the GUI coordinates.
niCode
Posts: 305
Joined: 17 Oct 2022, 22:09

Re: How can I get the client dimensions of the monitor the mouse is in and the mouse's coordinates?

19 Sep 2023, 11:45

Does this work for you?

Code: Select all

clientArea := GetClientAreaOfMonitor()

ToolTip('Top: ' clientArea.top '`nBottom: ' clientArea.bottom '`nLeft: ' clientArea.left '`nRight: ' clientArea.right)


GetClientAreaOfMonitor()
{
    monitor := MonitorFromMouse()                                                   ; get monitor mouse is on
    MonitorGetWorkArea(monitor, &left, &top, &right, &bottom)                       ; get edge coordinates of client area
    return {left: left, top: top, right: right, bottom: bottom}                     ; return as object
}


MonitorFromMouse()
{
    DllCall('GetCursorPos', 'UInt64*', &point_struct:=0)                            ; get mouse position struct
    monFromMouse := DllCall('MonitorFromPoint', 'Int64', point_struct, 'UInt', 2)   ; return monitor handle number mouse is on
    return ConvertHandleToNumber(monFromMouse)                                      ; convert handle to monitor number and return it
}


ConvertHandleToNumber(handle)
{
    monCallback   := CallbackCreate(__EnumMonitors, 'Fast', 4)                      ; fast-mode, 4 parameters
    monHandleList := ''                                                             ; initialize monitor handle number list

    if EnumerateDisplays(monCallback)                                               ; enumerates all monitors
    {
        loop parse, monHandleList, '`n'                                             ; loop list of monitor handle numbers
            if A_LoopField = handle                                                 ; if the handle number matches the monitor the mouse is on
                return A_Index                                                      ; set monFromMouse to monitor number
    }

    __EnumMonitors(hMonitor, hDevCon, pRect, args) {                                ; callback function for enumeration DLL
        monHandleList .= hMonitor '`n'                                              ; add monitor handle number to list
        return true                                                                 ; continues enumeration
    }
}

EnumerateDisplays(callback) => DllCall('EnumDisplayMonitors', 'Ptr', 0, 'Ptr', 0, 'Ptr', callback, 'UInt', 0)
IMTheNachoMan
Posts: 59
Joined: 01 Mar 2022, 17:07
Contact:

Re: How can I get the client dimensions of the monitor the mouse is in and the mouse's coordinates?

19 Sep 2023, 13:33

niCode wrote:
19 Sep 2023, 11:45
Does this work for you?
Yes. It does. Thank you. I didn't realize it would be so complex.

One follow up question, where can I read up on this object format?

Code: Select all

{left: left, top: top, right: right, bottom: bottom}
I didn't know AHK 2 supported that. Can I do nesting with this? And arrays? I can't find any information on this format when I look at the documentation for objects.
niCode
Posts: 305
Joined: 17 Oct 2022, 22:09

Re: How can I get the client dimensions of the monitor the mouse is in and the mouse's coordinates?

19 Sep 2023, 14:16

It's an object literal and you can read more about it here: Object Literal

You can indeed add arrays and nest other objects if you want/need to.

Code: Select all

someObject := {
    top: 5,
    bottom: 72,
    name: 'bob',
    petAges: [2, 4],

    secondObject: { name: 'george',
                    age: 34 }
}

MsgBox('top: ' someObject.top
        '`nbottom: ' someObject.bottom
        '`nname: ' someObject.name
        '`nage of pet 1: ' someObject.petAges[1]
        '`nage of pet 2: ' someObject.petAges[2]
        '`nnested object name: ' someObject.secondObject.name
        '`nnested object age: ' someObject.secondObject.age
)
niCode
Posts: 305
Joined: 17 Oct 2022, 22:09

Re: How can I get the client dimensions of the monitor the mouse is in and the mouse's coordinates?

19 Sep 2023, 14:26

IMTheNachoMan wrote:
19 Sep 2023, 13:33
I didn't realize it would be so complex.
I don't think it necessarily has to be. When I was trying to determine what monitor a window (not mouse) was on, I wasn't able to find nor create a completely accurate way without the complication. There were some outlier situations that would come up now and again that wouldn't be 100% accurate. For some reason, I adopted the complicated way for getting the mouse position and took the code from my class to supply to you. So it probably can be made much simpler, this was just what I had at hand.
just me
Posts: 9525
Joined: 02 Oct 2013, 08:51
Location: Germany

Re: How can I get the client dimensions of the monitor the mouse is in and the mouse's coordinates?  Topic is solved

20 Sep 2023, 03:35

Using built-in functions:

Code: Select all

#Requires AutoHotkey v2.0
clientArea := GetClientAreaOfMonitor()

MsgBox('Number: '   clientArea.Num .
       '`nLeft: '   clientArea.Left .
       '`nTop: '    clientArea.Top .
       '`nRight: '  clientArea.Right .
       '`nBottom: ' clientArea.Bottom)

GetClientAreaOfMonitor() {
   Local MonitorCount := MonitorGetCount()
   If MonitorCount = 1
      Return {Num: 1, Left: 0, Top: 0, Right: A_ScreenWidth, Bottom: A_ScreenHeight}
   Local X, Y, L, T, R, B
   Local CMM := A_CoordModeMouse
   A_CoordModeMouse := "Screen"
   MouseGetPos(&X, &Y)
   A_CoordModeMouse := CMM
   Loop MonitorCount {
      MonitorGet(A_Index, &L, &T, &R, &B)
      If (X >= L) && (X <= R) && (Y >= T) && (Y <= B)
         Return {Num: A_Index, Left: L, Top: T, Right: R, Bottom: B}
   }
   Return False
}
Another option:

Code: Select all

#Requires AutoHotkey v2.0
#Warn
MonitorGetFromMouse(&N, &L, &T, &R, &B)

MsgBox('Number: ' N '`nLeft: ' L '`nTop: ' T '`nRight: ' R '`nBottom: ' B)

MonitorGetFromMouse(&N?, &L?, &T?, &R?, &B?) {
   Local CMM := A_CoordModeMouse, X, Y
   A_CoordModeMouse := "Screen"
   MouseGetPos(&X, &Y)
   A_CoordModeMouse := CMM
   Loop MonitorGetCount() {
      N := A_Index
      MonitorGet(A_Index, &L, &T, &R, &B)
      If (X >= L) && (X <= R) && (Y >= T) && (Y <= B)
         Return True
   }
   N := L := T := R := B := 0
   Return False
}

Return to “Ask for Help (v2)”

Who is online

Users browsing this forum: Bing [Bot], gekunfei, songdg and 42 guests