MonitorGetPrimary() function inconsistent with v1 SysGet MonitorPrimary Topic is solved

Report problems with documented functionality
User avatar
mprost
Posts: 8
Joined: 24 Dec 2018, 02:50

MonitorGetPrimary() function inconsistent with v1 SysGet MonitorPrimary

Post by mprost » 09 Dec 2022, 04:21

[Moderator note: This thread was moved to "Bug Reports" as it was determined to be one and was reported as such.]

Hi.

I'm converting a script from v1.1.36.02 to v2.0-rc.2 and I'm experiencing inconsistent results when I try to determine the primary monitor.

This is my system's (Windows 10 21H2) current configuration (monitor 1, the one on the right, is the primary monitor):
image.png
image.png (10.96 KiB) Viewed 1145 times
image.png
image.png (6.16 KiB) Viewed 1145 times

This v1 code:

Code: Select all

SysGet, primaryMonitorNumber, MonitorPrimary
SysGet, primaryMonitorCoords, Monitor, %primaryMonitorNumber%
SysGet, primaryMonitorName, MonitorName , %primaryMonitorNumber%


MsgBox, Name: %primaryMonitorName%`nNumber: %primaryMonitorNumber%`nLeft: %primaryMonitorCoordsLeft%`nTop: %primaryMonitorCoordsTop%`nRight: %primaryMonitorCoordsRight%`nBottom: %primaryMonitorCoordsBottom%
produces the following output (which is correct):
---------------------------
primary mon v1.ahk
---------------------------
Name: \\.\DISPLAY1
Number: 1
Left: 0
Top: 0
Right: 1920
Bottom: 1200
But this v2 code:

Code: Select all

primaryMonitorNumber:=MonitorGetPrimary()
MonitorGet primaryMonitorNumber, &primaryMonitorCoordsLeft, &primaryMonitorCoordsTop, &primaryMonitorCoordsRight, &primaryMonitorCoordsBottom
primaryMonitorName:=MonitorGetName(primaryMonitorNumber)


MsgBox ("Name:" . primaryMonitorName . "`n" . "Number: " . primaryMonitorNumber . "`n" . "Left: " . primaryMonitorCoordsLeft . "`n" . "Top: " . primaryMonitorCoordsTop . "`n" . "Right: " . primaryMonitorCoordsRight . "`n" . "Bottom: " . primaryMonitorCoordsBottom)
produces this output, which is not correct (regardless of the number (2), what is not correct is the coordinates, my primary monitor is at Left: 0 Top: 0, Left: -1920 Top: 0 are the coordinates of the secondary monitor):
---------------------------
primary mon v2.ahk
---------------------------
Name:\\.\DISPLAY2
Number: 2
Left: -1920
Top: 0
Right: 0
Bottom: 1200

If I understand this previous thread correctly, it was concluded there that there was a known discrepancy between the monitor number displayed in Settings and the one that's returned by MonitorGetPrimary() function. But, shouldn't this number, whichever it is, when feeded to MonitorGet, produce the coordinates of the primary monitor (as is the case in v1)?

BTW, if I omit N in MonitorGet and MonitorGetName():

Code: Select all

primaryMonitorNumber:=MonitorGet( , &primaryMonitorCoordsLeft, &primaryMonitorCoordsTop, &primaryMonitorCoordsRight, &primaryMonitorCoordsBottom)
primaryMonitorName:=MonitorGetName()


MsgBox ("Name:" . primaryMonitorName . "`n" . "Number: " . primaryMonitorNumber . "`n" . "Left: " . primaryMonitorCoordsLeft . "`n" . "Top: " . primaryMonitorCoordsTop . "`n" . "Right: " . primaryMonitorCoordsRight . "`n" . "Bottom: " . primaryMonitorCoordsBottom)
this is the output I get:
---------------------------
primary mon v2.ahk
---------------------------
Name:\\.\DISPLAY1
Number: 1
Left: 0
Top: 0
Right: 1920
Bottom: 1200
---------------------------
OK
---------------------------
which are the correct coordinates and consistent with v1. This also shows a discrepancy between the number of the primary monitor returned by MonitorGet() with N omitted and the one returned by MonitorGetPrimary() (in other words, shouldn't MonitorGetPrimary() and MonitorGet(<no parameters>) yield the same number?).

So, is this a bug in MonitorGetPrimary() or am I doing something wrong?

Thank you.

User avatar
jNizM
Posts: 3183
Joined: 30 Sep 2013, 01:33
Contact:

Re: MonitorGetPrimary() function inconsistent with v1 SysGet MonitorPrimary

Post by jNizM » 09 Dec 2022, 05:05

Can you try this and say if it returns the right monitor?

Code: Select all

#Requires AutoHotkey v2.0-beta

MsgBox "winapi:`t" GetPrimaryMonitor() "`n`nahk:`t" MonitorGetName(p := MonitorGetPrimary()) "`t [" p "]"

GetPrimaryMonitor() ; https://devblogs.microsoft.com/oldnewthing/20070809-00/?p=25643
{
	static MONITOR_DEFAULTTOPRIMARY := 0x00000001

	;POINT := (x & 0xFFFFFFFF) | (y << 32)
	hMonitor := DllCall("user32\MonitorFromPoint", "Int64", 0, "UInt", MONITOR_DEFAULTTOPRIMARY, "Ptr")

	MONITORINFOEX := Buffer(104, 0)
	NumPut("UInt", 104, MONITORINFOEX, 0)
	DllCall("user32\GetMonitorInfo", "Ptr", hMonitor, "Ptr", MONITORINFOEX)

	return StrGet(MONITORINFOEX.Ptr + 40, 32)
}

works for me (2.0-rc.2 + Win11-22H2)
Image
[AHK] v2.0.5 | [WIN] 11 Pro (Version 22H2) | [GitHub] Profile

swagfag
Posts: 6222
Joined: 11 Jan 2017, 17:59

Re: MonitorGetPrimary() function inconsistent with v1 SysGet MonitorPrimary

Post by swagfag » 09 Dec 2022, 07:54

https://github.com/Lexikos/AutoHotkey_L/blob/c83cfa942535301740a3d8c6bf0a7c5140300395/source/lib/env.cpp#L158
this is probably wrong and should have been 0 (as can be seen a few lines below that)
jNizM wrote:
09 Dec 2022, 05:05

Code: Select all

...
	POINT := Buffer(8, 0)
	NumPut("Int", 0, POINT, 0)
	NumPut("Int", 4, POINT, 0)
	hMonitor := DllCall("user32\MonitorFromPoint", "Ptr", POINT, "UInt", MONITOR_DEFAULTTOPRIMARY, "Ptr")
...
if ure (un?)lucky this could return a monitor handle other than the one which was presumably expected (MONITOR_DEFAULTTOPRIMARY)
  • zeroinit a buffer
  • write a zero into it anyway
  • ok nevermind, overwrite the zero with a 4
  • ok now pass the address of the buffer to be chunked into two ints and reinterpreted as x/y coordinates ([in] POINT pt, by Value)

Code: Select all

DllCall("user32\MonitorFromPoint", "Int64", 0, ....

User avatar
jNizM
Posts: 3183
Joined: 30 Sep 2013, 01:33
Contact:

Re: MonitorGetPrimary() function inconsistent with v1 SysGet MonitorPrimary

Post by jNizM » 09 Dec 2022, 09:49

swagfag wrote:
09 Dec 2022, 07:54
...

Code: Select all

DllCall("user32\MonitorFromPoint", "Int64", 0, ....
Post edited
[AHK] v2.0.5 | [WIN] 11 Pro (Version 22H2) | [GitHub] Profile

User avatar
mprost
Posts: 8
Joined: 24 Dec 2018, 02:50

Re: MonitorGetPrimary() function inconsistent with v1 SysGet MonitorPrimary

Post by mprost » 09 Dec 2022, 12:03

jNizM wrote:
09 Dec 2022, 05:05
Can you try this and say if it returns the right monitor?
Hi.

Thank you for the quick response.

This code:

Code: Select all

#Requires AutoHotkey v2.0-beta

MsgBox "winapi:`t" GetPrimaryMonitor() "`n`nahk:`t" MonitorGetName(p := MonitorGetPrimary()) "`t [" p "]"

GetPrimaryMonitor() ; https://devblogs.microsoft.com/oldnewthing/20070809-00/?p=25643
{
	static MONITOR_DEFAULTTOPRIMARY := 0x00000001

	;POINT := (x & 0xFFFFFFFF) | (y << 32)
	hMonitor := DllCall("user32\MonitorFromPoint", "Int64", 0, "UInt", MONITOR_DEFAULTTOPRIMARY, "Ptr")

	MONITORINFOEX := Buffer(104, 0)
	NumPut("UInt", 104, MONITORINFOEX, 0)
	DllCall("user32\GetMonitorInfo", "Ptr", hMonitor, "Ptr", MONITORINFOEX)

	return StrGet(MONITORINFOEX.Ptr + 40, 32)
}
returns:
---------------------------
primary mon v2 test.ahk
---------------------------
winapi: \\.\DISPLAY1

ahk: \\.\DISPLAY2 [2]

lexikos
Posts: 9560
Joined: 30 Sep 2013, 04:07
Contact:

Re: MonitorGetPrimary() function inconsistent with v1 SysGet MonitorPrimary

Post by lexikos » 09 Dec 2022, 17:55

swagfag wrote:
09 Dec 2022, 07:54
https://github.com/Lexikos/AutoHotkey_L/blob/c83cfa942535301740a3d8c6bf0a7c5140300395/source/lib/env.cpp#L158
this is probably wrong and should have been 0 (as can be seen a few lines below that)
Yes, MonitorGetPrimary certainly wasn't intended to be completely identical to MonitorGetCount. It currently is.



Post Reply

Return to “Bug Reports”