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.
#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
Re: Get Window Title at Specific Coordinates
Posted: 10 May 2019, 17:22
by teadrinker
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.
Re: Get Window Title at Specific Coordinates
Posted: 10 May 2019, 17:32
by jeeswg
- 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.)
Re: Get Window Title at Specific Coordinates
Posted: 10 May 2019, 17:38
by swagfag
WindowFromPoint expects the numeric value
but why? how does it expect a numeric value? it expects a POINT. a POINT is:
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
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.
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
The Windows 16-bit API is unusal because it allows you to pass the Point
structure to the WindowFromPoint functions by value. Typically, user- defined
types are passed to functions by reference because passing them by value can use
up a lot of stack space and be much slower than passing the address of the
structure. An exception was made for the Point structure in certain functions
(such as ChildWindowFromPoint and WindowFromPoint) because in 16-bit programming
the size of the structure was only 32 bits long, which is the same length as a
far address anyway.
However, on a 32-bit operating system, this structure becomes 64 bits. To
preserve compatibility, Microsoft decided that the Point structure should still
be passed by value for these two API functions in the 32-bit user dynamic link
library (DLL).
Visual Basic is not capable of passing structures by value, but the value of the
elements of the structure can be placed on the stack in the correct order.
Therefore, when passing the elements of the Point structure in 32-bit
programming, two long values should be passed. When passing the elements in
16-bit programming, two integers should be passed to the function.
Another important consideration is that 32-bit Visual Basic uses the C convention
(stdcall) of passing parameters. This convention specifies that arguments are
placed on the stack from right to left. 16-Bit Visual Basic maintains the Pascal
convention of passing parameters from left to right. (API functions are declared
using the Pascal calling convention.) As a result, the elements of the structure
must be listed in reverse order (that is, element y followed by x) when calling
the WindowFromPoint function using 32-Bit Visual Basic. When using 16-bit Visual
Basic, element x is passed to the API function before element y.
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)
Re: Get Window Title at Specific Coordinates
Posted: 12 May 2019, 07:40
by jeeswg
@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.
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.