Get Window Title at Specific Coordinates

Get help with using AutoHotkey (v1.1 and older) and its commands and hotkeys
scriptor2016
Posts: 844
Joined: 21 Dec 2015, 02:34

Get Window Title at Specific Coordinates

Post by scriptor2016 » 10 May 2019, 09:40

Hi

Let's say I want to get the window title at x500, y500.

Is there an easy way to do this?

Rest assured I've spent all morning trying to find the solution but to no avail :(

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

Re: Get Window Title at Specific Coordinates

Post by swagfag » 10 May 2019, 09:47

msdn WindowFromPoint

scriptor2016
Posts: 844
Joined: 21 Dec 2015, 02:34

Re: Get Window Title at Specific Coordinates

Post by scriptor2016 » 10 May 2019, 10:05

this line activates the window at 500, 500

Code: Select all

WinActivate, % "ahk_id" DllCall("WindowFromPoint", Int,500, Int,500 )
I tried adjusting the line to get the window title, but this doesn't work:

Code: Select all

wingettitle, title, % "ahk_id" DllCall("WindowFromPoint", Int,500, Int,500 )
msgbox, %title%

scriptor2016
Posts: 844
Joined: 21 Dec 2015, 02:34

Re: Get Window Title at Specific Coordinates

Post by scriptor2016 » 10 May 2019, 10:11

actually I guess I could just do this:

Code: Select all

WinActivate, % "ahk_id" DllCall("WindowFromPoint", Int,500, Int,500 )
wingettitle, title, A
msgbox, %title%

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

Re: Get Window Title at Specific Coordinates

Post by swagfag » 10 May 2019, 10:14

i ain't sure if u can actually call this function this way
i think u need to declare a var and numput the coordinates in it but I cant test it rn

scriptor2016
Posts: 844
Joined: 21 Dec 2015, 02:34

Re: Get Window Title at Specific Coordinates

Post by scriptor2016 » 10 May 2019, 10:19

winactivate works, but not wingettitle. I'd like to do it all on that one line. I will keep trying :)

teadrinker
Posts: 4295
Joined: 29 Mar 2015, 09:41
Contact:

Re: Get Window Title at Specific Coordinates

Post by teadrinker » 10 May 2019, 10:27

Code: Select all

x := 500
y := 500

$F1::
   hWnd := DllCall("WindowFromPoint", UInt64, x|(y << 32), Ptr)
   hParent := DllCall("GetAncestor", Ptr, hWnd, UInt, GA_ROOT := 2, Ptr)
   WinGetTitle, title, ahk_id %hParent%
   MsgBox, % title
   Return

scriptor2016
Posts: 844
Joined: 21 Dec 2015, 02:34

Re: Get Window Title at Specific Coordinates

Post by scriptor2016 » 10 May 2019, 10:31

thanks teadrinker, that seems to do the trick!

User avatar
jeeswg
Posts: 6902
Joined: 19 Dec 2016, 01:58
Location: UK

Re: Get Window Title at Specific Coordinates

Post by jeeswg » 10 May 2019, 11:06

@anyone using DllCall: Just FYI, this change has been made to AHK v2:
AutoHotkey v2 alpha (UPDATES) - Page 3 - AutoHotkey Community
https://autohotkey.com/boards/viewtopic.php?f=37&t=2120&p=275703#p275703
Disabled unquoted arg and return types for DllCall.
I'll update this script at some point:
DllCall converter/cleaner (e.g. x32 to x64/x32 two-way compatible) - AutoHotkey Community
https://autohotkey.com/boards/viewtopic.php?f=6&t=31365
homepage | tutorials | wish list | fun threads | donate
WARNING: copy your posts/messages before hitting Submit as you may lose them due to CAPTCHA

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

Re: Get Window Title at Specific Coordinates

Post by swagfag » 10 May 2019, 13:34

@teadrinker
https://blogs.msdn.microsoft.com/oldnewthing/20101230-00/?p=11873/
last paragraph :lol:

Code: Select all

x := y := 500
CWP_ALL := 0x0000
CWP_SKIPINVISIBLE := 0x0001
CWP_SKIPDISABLED := 0x0002
CWP_SKIPTRANSPARENT := 0x0004
hwnd := DllCall("ChildWindowFromPointEx"
	, "Ptr", DllCall("GetDesktopWindow", "Ptr")
	, "UInt64", (x & 0xFFFFFFFF) | (y << 32)
	, "UInt", CWP_SKIPINVISIBLE | CWP_SKIPDISABLED | CWP_SKIPTRANSPARENT
	, "Ptr")
and x seems to break on negative coords if u dont mask it off

that aside, these functions behave very weirdly. its says it accepts a POINT BY VALUE, what?? but i tried

Code: Select all

VarSetCapacity(P, 8, 0)
NumPut(500, &P, 0, "Int")
NumPut(500, &P, 4, "Int")
; ... and passing it BY VALUE
, "Ptr", P
but it didnt work. it only checked (0, 0) on my 2 monitor (-1920, 1920) setup, which is the topleft corner of my rhs main monitor

teadrinker
Posts: 4295
Joined: 29 Mar 2015, 09:41
Contact:

Re: Get Window Title at Specific Coordinates

Post by teadrinker » 10 May 2019, 15:30

I would prefer to tell the script "what" to do, rather than "how", if this does not affect performance. The code with WindowFromPoint() and GetAncestor(GA_ROOT) looks more clear.
swagfag wrote:these functions behave very weirdly
Compare the following two winapi functions:
WindowFromPoint:
HWND WindowFromPoint(
POINT Point
);
GetCursorPos:
BOOL GetCursorPos(
LPPOINT lpPoint
);
In the last case you need using VarSetCapacity.

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

Re: Get Window Title at Specific Coordinates

Post by swagfag » 10 May 2019, 16:11

if it wants a pointer, u do:

Code: Select all

VarSetCapacity(P, 8, 0)
NumPut(500, &P, 0, "Int")
NumPut(500, &P, 4, "Int")
; ...
, "Ptr", &P
so then, if it wants the struct itself, by value, u should be able to do:

Code: Select all

VarSetCapacity(P, 8, 0)
NumPut(500, &P, 0, "Int")
NumPut(500, &P, 4, "Int")
; ... 
, "Ptr", P
except it doesnt work in this case

teadrinker
Posts: 4295
Joined: 29 Mar 2015, 09:41
Contact:

Re: Get Window Title at Specific Coordinates

Post by teadrinker » 10 May 2019, 17:00

Compare:

Code: Select all

x := 500
y := 500
POINT := x|(y << 32)
MsgBox, % Format("{:#x}", POINT)
and

Code: Select all

x := 500
y := 500
VarSetCapacity(POINT, 8, 0)
NumPut(x, POINT, "Int")
NumPut(y, POINT, 4, "Int")
MsgBox, % POINT
u should be able to do
You do not consider AHK syntax.
In this case

Code: Select all

x := 500
y := 500
POINT := x|(y << 32)
hWnd := DllCall("WindowFromPoint", UInt64, POINT, Ptr)
MsgBox, % Format("{:#x}", hWnd)
POINT is just a string.

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

Re: Get Window Title at Specific Coordinates

Post by swagfag » 10 May 2019, 17:17

tbh i have no clue what ure trying to convey here. u cant msgbox POINT(the struct, ie VarSetCapacity). yeah, so?
imagine u were writing this in c++:

Code: Select all

#include <iostream>

struct POINT {
	long x;
	long y;
};

void myWindowFromPoint(POINT P) {
	std::cout << P.x << "," << P.y << "\n";
}

int main() {
	POINT P = { 500, 500 };
	myWindowFromPoint(P); // <<<<<<<<<<<<<<< here, u pass P BY VALUE, aka in AHK should be DllCall("WindowFromPoint", "Ptr", P, "Ptr") (NOT &P !!), where P is initialized with VarSetCapacity and filled with NumPut
	
	// what u DONT do is this
	//                                   V
	// myWindowFromPoint((400 & 0xFFFFFFFF) | (500 << 32)); which would end up being DllCall("WindowFromPoint", "UInt64", (x & 0xFFFFFFFF) | (y << 32), "Ptr") in AHK, for whatever reason apparently
	
	return 0;
}
so why then, do u have to do exactly what ure not supposed to do (ie the bitshifting stuff) in AHK for it to work properly
Last edited by swagfag on 10 May 2019, 17:27, edited 2 times in total.

teadrinker
Posts: 4295
Joined: 29 Mar 2015, 09:41
Contact:

Re: Get Window Title at Specific Coordinates

Post by teadrinker » 10 May 2019, 17:22

imagine u were writing this in c++
But we writing this not in c++, we use AHK. In this case WindowFromPoint expects the numeric value, and DllCall accepts that value as a string.

User avatar
jeeswg
Posts: 6902
Joined: 19 Dec 2016, 01:58
Location: UK

Re: Get Window Title at Specific Coordinates

Post by jeeswg » 10 May 2019, 17:32

- The definition specifies a struct, not a pointer to a struct,
- If it wanted a pointer to a struct, you could use VarSetCapacity and NumPut, and pass the address.
- In this case, you must pass an 8-byte integer directly as a value.
- You can form that 8-byte integer by using bitshift and bitwise-or on the x/y values. Alternatively, a MakeUInt64 function would be useful.
- This situation is rare, and so I mention it explicitly, as 'Point' functions, here:
jeeswg's DllCall and structs tutorial - AutoHotkey Community
https://autohotkey.com/boards/viewtopic.php?f=7&t=63708
- (It appears that for 32-bit dll calls, you could pass 2 Ints, instead of 1 UInt64, but this doesn't work for 64-bit.)
homepage | tutorials | wish list | fun threads | donate
WARNING: copy your posts/messages before hitting Submit as you may lose them due to CAPTCHA

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

Re: Get Window Title at Specific Coordinates

Post by swagfag » 10 May 2019, 17:38

WindowFromPoint expects the numeric value
but why? how does it expect a numeric value? it expects a POINT. a POINT is:

Code: Select all

typedef struct tagPOINT
{
    LONG  x;
    LONG  y;
} POINT, *PPOINT, NEAR *NPPOINT, FAR *LPPOINT;
its a struct of size 8 bytes(64 bits) that contains two 32bit signed integers.
what it certainly isnt, is ONE UNsigned 64bit integer. so why then does AHK have to pass that for it to work properly. theres no method to this madness, whatsoever!

im not sold on the string thing. u can just as easily do

Code: Select all

hWnd := DllCall("WindowFromPoint", "UInt64", (400 & 0xFFFFFFFF) | (500 << 32), "Ptr")
MsgBox, % Format("{:#x}", hWnd)
and it will work. here what were passing is decidedly not a string

@jeeswg
It appears that for 32-bit dll calls, you could pass 2 Ints, instead of 1 UInt64
:shock: jesus christ
these functions just keep getting weirder still

teadrinker
Posts: 4295
Joined: 29 Mar 2015, 09:41
Contact:

Re: Get Window Title at Specific Coordinates

Post by teadrinker » 11 May 2019, 16:00

swagfag wrote:

Code: Select all

hWnd := DllCall("WindowFromPoint", "UInt64", (400 & 0xFFFFFFFF) | (500 << 32), "Ptr")
MsgBox, % Format("{:#x}", hWnd)
and it will work. here what were passing is decidedly not a string
What were passing IS a string. Look:

Code: Select all

MsgBox, % (400 & 0xFFFFFFFF) | (500 << 32) " — it's just a string"
swagfag wrote: how does it expect a numeric value? it expects a POINT
Ok, it expects a POINT, AHK accepts a string, interprets it as Int64 numeric value, then passes this value to WindowFromPoint, WindowFromPoint interprets the value as POINT, which was expected. :lol:

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

Re: Get Window Title at Specific Coordinates

Post by swagfag » 12 May 2019, 06:48

Code: Select all

MsgBox, % (400 & 0xFFFFFFFF) | (500 << 32) " — it's just a string"
yes, this is a string but only because u concatenated a string to it, converting a whole thing into a string. (400 & 0xFFFFFFFF) | (500 << 32) by itself isnt a string, its purely numeric, it should be of type __int64.
im not sure whether DllCall's Arg1, 2, ..., N are universally treated as strings, or if it depends on the type specified preceding it. the docs dont say, i dont think
WindowFromPoint interprets the value as POINT, which was expected.
yes, so far it is clear that WindowFromPoint treats the number(or number-like string) as a POINT struct passed by value.
what isnt clear is why its doing it and how its doing it.
https://jeffpar.github.io/kbarchive/kb/138/Q138518/
the relevant section
so then how does a 64bit int that looks like this 0xYYYYYYYYXXXXXXXX, get converted to a struct with 2 32bit ints in it, correctly. what exactly happens during this conversion?

also im curious if there are any winapi function function that take in, say, a RECT by value, or some other larger-than-64 struct. if so, then u couldnt possibly make the bitshift thing work in that case, so how then would u make it work(assuming the existence of such functions)

User avatar
jeeswg
Posts: 6902
Joined: 19 Dec 2016, 01:58
Location: UK

Re: Get Window Title at Specific Coordinates

Post by jeeswg » 12 May 2019, 07:40

@swagfag: If you look at the MessageBox Winapi function, it expects HWND and LPCTSTR, which are 8 or 4 byte numbers in x64/x32, and UINT, which is a 4-byte number. POINT is just an 8-byte number, the fact that it's a 'struct', or is composed of 2 4-byte numbers, doesn't matter.

I have only seen one Winapi function that asks to pass a number by value, where the value's size is greater than 8 bytes, it is MagSetWindowSource, and it expects a 16-byte RECT. In x32 I split the RECT as 4 Ints, in x64 I pass the address.

MagSetWindowSource is mentioned here:
jeeswg's DllCall and structs tutorial - AutoHotkey Community
https://autohotkey.com/boards/viewtopic.php?f=7&t=63708

x64 calling convention | Microsoft Docs
https://docs.microsoft.com/en-us/cpp/build/x64-calling-convention?view=vs-2017
Structs and unions of size 8, 16, 32, or 64 bits, and __m64 types, are passed as if they were integers of the same size. Structs or unions of other sizes are passed as a pointer to memory allocated by the caller.

Re. DllCall and strings. E.g. to pass UInt64 0xFFFFFFFFFFFFFFFF to DllCall, use the Int64: -1, or a string: "18446744073709551615" or "0xFFFFFFFFFFFFFFFF" or "-1".
DllCall() - Syntax & Usage | AutoHotkey
https://autohotkey.com/docs/commands/DllCall.htm
For parameters of type UInt64, large unsigned values may be passed as strings.
homepage | tutorials | wish list | fun threads | donate
WARNING: copy your posts/messages before hitting Submit as you may lose them due to CAPTCHA

Post Reply

Return to “Ask for Help (v1)”