Page 2 of 3

Re: Get Window Title at Specific Coordinates

Posted: 12 May 2019, 13:00
by swagfag
sorry, i still dont understand how this is supposed to work. so we have the 8 byte(64 bit) struct POINT

Code: Select all

struct POINT {
  __int32 x;
  __int32 y;
};
which is being treated as an __int64 because "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.".
ok, suppose __int32 x = 0xXXXXXXXX; and __int32 y = 0xYYYYYYYY;, u have somewhere in memory 0xXXXXXXXX and right next to it 0xYYYYYYYY.
now, this 16 byte (64 bit) sequence of bytes in memory: .... XXXX XXXX YYYY YYYY .... is looked at and reinterpreted as the 64 bit integer: __int64 theArgument = 0xXXXXXXXXYYYYYYYY;.
that integer is then passed to WindowFromPoint and WindowFromPoint somehow knows that the high bytes are meant to be the X, whereas the low bytes represent the Y coordinate.

BUT! in the DllCall, if we're passing this number it has to be constructed the other way around: 0xYYYYYYYYXXXXXXXX, the high bytes are Y and the low - X.
???

also, presumably, these 64bit ints fit entirely into the 64bit RCX
the "rect by value" function is a nice find, gj

Re: Get Window Title at Specific Coordinates

Posted: 12 May 2019, 13:14
by jeeswg
Because it's little endian, when you store an 8-byte number, the later digits are stored at the front. When writing, the bytes are swapped. And when reading, the bytes are swapped.

Code: Select all

q:: ;test write UInt64, and read as UInts/UShorts/UChars
VarSetCapacity(vData, 8)
NumPut("0x8877665544332211", &vData, 0, "UInt64")

vOutput := ""

Loop, 2
	vNum := NumGet(&vData, (A_Index-1)*4, "UInt")
	, vOutput .= (A_Index=1?"":" ") Format("0x{:X}", vNum)
vOutput .= "`r`n"

Loop, 4
	vNum := NumGet(&vData, (A_Index-1)*2, "UShort")
	, vOutput .= (A_Index=1?"":" ") Format("0x{:X}", vNum)
vOutput .= "`r`n"

Loop, 8
	vNum := NumGet(&vData, A_Index-1, "UChar")
	, vOutput .= (A_Index=1?"":" ") Format("0x{:X}", vNum)
vOutput .= "`r`n"

Clipboard := vOutput
MsgBox, % vOutput
return

Re: Get Window Title at Specific Coordinates

Posted: 12 May 2019, 13:17
by teadrinker
swagfag wrote: (400 & 0xFFFFFFFF) | (500 << 32) by itself isnt a string, its purely numeric, it should be of type __int64.
Formally, this value is a number, but AHK stores this value in memory as a string, and you can easily verify this:

Code: Select all

MsgBox, % (400 & 0xFFFFFFFF) | (500 << 32)        . "`n"
        . Ord( (400 & 0xFFFFFFFF) | (500 << 32) ) . "`n"  ; 50 — character code of 2
        . Chr(50)                                         ; 2 — first number in 2147483648400
        
POINT := (400 & 0xFFFFFFFF) | (500 << 32)
Loop % StrLen(POINT) {
   ch := NumGet(POINT, (A_Index - 1) << !!A_IsUnicode, A_IsUnicode ? "UShort" : "UChar")
   MsgBox, % POINT                . "`n"
   . "char position: " . A_Index  . "`n"
   . "char code: "     . ch       . "`n"
   . "char: "          . Chr(ch)
}

Re: Get Window Title at Specific Coordinates

Posted: 12 May 2019, 14:28
by swagfag
jeeswg wrote:
12 May 2019, 13:14
Because it's little endian
holy batman, yes, finally, now it all makes sense. thank u

if u have the struct:

Code: Select all

struct POINT {
	__int32 x = 0xX4X3X2X1; 
	__int32 y = 0xY4Y3Y2Y1; 
}
in memory it will be laid out like this:

Code: Select all

                          |
                          V
__int32 = 0xX4 X3 X2 X1   ..
             |  |  |  +-> X1
             |  |  +----> X2
             |  +-------> X3
             +----------> X4

__int32 = 0xY4 Y3 Y2 Y1   
             |  |  |  +-> Y1
             |  |  +----> Y2
             |  +-------> Y3
             +----------> Y4
                          ..
                          |
                          V

-->> .. .. X1 X2 X3 X4 Y1 Y2 Y3 Y4 .. .. -->>
so if u store this exact byte sequence in RCX by some other means, u will trick WindowFromPoint into thinking it's working with a struct. and the means to do so, happen to be "bitshift the y coord into the high order bytes and leave the x coord in the low order bytes", (0xY4 Y3 Y2 Y1 << 32) | 0xX4 X3 X2 X1 produces 0xY4 Y3 Y2 Y1 X4 X3 X2 X1, in other words:

Code: Select all

                            |
                            V
0xY4 Y3 Y2 Y1 X4 X3 X2 X1   ..
   |  |  |  |  |  |  |  +-> X1
   |  |  |  |  |  |  +----> X2
   |  |  |  |  |  +-------> X3
   |  |  |  |  +----------> X4
   |  |  |  +-------------> Y1
   |  |  +----------------> Y2
   |  +-------------------> Y3
   +----------------------> Y4
                            ..
                            |
                            V

-->> .. .. X1 X2 X3 X4 Y1 Y2 Y3 Y4 .. .. -->>
same byte sequence as the one produced by the struct

Re: Get Window Title at Specific Coordinates

Posted: 20 Jun 2021, 06:27
by lexikos
teadrinker wrote:
12 May 2019, 13:17
Formally, this value is a number, but AHK stores this value in memory as a string, and you can easily verify this:
As people are referring to this topic, I will point out that this is technically correct, but misleading.

When you assign the result of a bitwise operator to a variable, AutoHotkey in fact stores a 64-bit integer. When you access the variable with &var or NumGet, or pass it to a command like MsgBox, a numeric string is computed and cached in the variable. Any subsequent access which needs a string will refer to this string, not the original number, which is also retained. &var and NumGet will only let you examine the string, for backward-compatibility reasons. Using Ord() does not prove anything, because Ord expects a string, and will attempt to convert whatever value you give it to a string in order to carry out its purpose.

For more details, see Concepts - Caching.

This is a little different in v2, where the caching behaviour has been changed to preserve the original type of the value, &var has been replaced with StrPtr(var), and NumGet doesn't refer to a variable's (string) content directly.

If you pass the result of (400 & 0xFFFFFFFF) | (500 << 32) directly to an int64 parameter for WindowFromPoint, it will not be converted to (or stored as) a string.



As for passing POINT by value;

The target function doesn't know where the value came from; it only has the raw binary content of the stack or register. So for an 8-byte struct, if you compose a 64-bit integer which has the right raw binary value, it is sufficient to pass this number as "int64" because DllCall takes care of the details of passing an 8-byte value. Bitwise operators aren't the only way; you could prepare the struct with NumPut, then use NumGet(struct, "int64") to get the value to pass to DllCall.

For 32-bit, int64 parameters are pushed onto the stack, occupying 8 bytes instead of the usual 4 bytes per parameter. For 64-bit, passing int64 is essentially the same, but all smaller parameters are widened to 64-bit, and the first four parameters are copied into registers as well.

Passing the x and y coordinates as individual int parameters works for 32-bit because they are simply pushed onto the stack, right to left, 4 bytes at a time. This would not work with smaller types, because each parameter would be widened to 32-bit. It also would not work for x64 because each parameter (int) would be widened to 64-bit.

For larger structs, there's no simple way to target both 32-bit and 64-bit with a single DllCall expression, because DllCall doesn't support passing values larger than int64. You would need to break the struct into individual int64 or int/uint parameters on 32-bit, and pass a single ptr on 64-bit. Fortunately, functions which take structs larger than 8 bytes by value are fairly rare.
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.
Source: x64 calling convention | Microsoft Docs
(There are other 32-bit and 64-bit platforms where some of the above may not apply; I'm referring only to the x86 and x86-64 platforms where AutoHotkey runs. I have no idea about ARM64...)

Re: Get Window Title at Specific Coordinates

Posted: 20 Jun 2021, 16:18
by teadrinker
@lexikos, thanks for clarification.

Re: Get Window Title at Specific Coordinates

Posted: 22 Jun 2021, 04:31
by Avtem
People, come on! Why do you complicate all this? There is a two-line solution to the problem (although, be aware that you need to have a sufficient variable size to store the title).

Code: Select all

varSetCapacity(title, 200, 0)
DllCall("GetWindowText", "ptr", DllCall("WindowFromPoint", "Int", 500, "Int", 500)
		, "str", title, "int", 199)	
msgbox %title%

Re: Get Window Title at Specific Coordinates

Posted: 22 Jun 2021, 06:45
by teadrinker
@Avtem
Your code doesn't work on 64 bit AHK. If you read the text above, you get why. :)

Re: Get Window Title at Specific Coordinates

Posted: 22 Jun 2021, 07:18
by Avtem
teadrinker wrote:
22 Jun 2021, 06:45
@Avtem
Your code doesn't work on 64 bit AHK. If you read the text above, you get why. :)
Hm, i think i'm running 64 bit version AHK (see the screenshot). Did you try to run my code?

Re: Get Window Title at Specific Coordinates

Posted: 22 Jun 2021, 08:40
by teadrinker
Try this:

Code: Select all

Gui, New, -Caption +Border
Gui, Margin, 0, 0
Gui, Font, s24
Gui, Add, Edit,, This text must be shown
Gui, Show, x497 y497
varSetCapacity(title, 200, 0)
DllCall("GetWindowText", "ptr", DllCall("WindowFromPoint", "Int", 500, "Int", 500)
      , "str", title, "int", 199)	
msgbox %title%
ExitApp
What the text the message box shows?

Re: Get Window Title at Specific Coordinates

Posted: 22 Jun 2021, 08:46
by emrekarahan0001
Avtem wrote:
teadrinker wrote:
22 Jun 2021, 06:45
@Avtem
Your code doesn't work on 64 bit AHK. If you read the text above, you get why. :)
Hm, i think i'm running 64 bit version AHK (see the screenshot). Did you try to run my code?
me too running 64 bit version AHK and no problem. :thumbup:

Re: Get Window Title at Specific Coordinates

Posted: 22 Jun 2021, 09:04
by teadrinker
@emrekarahan0001
Did you try my code above?

Re: Get Window Title at Specific Coordinates

Posted: 22 Jun 2021, 09:28
by teadrinker
emrekarahan0001 wrote: me too running 64 bit version AHK and no problem
Looks like there was a problem. :)

Re: Get Window Title at Specific Coordinates

Posted: 22 Jun 2021, 10:14
by emrekarahan0001
teadrinker wrote:
22 Jun 2021, 09:04
@emrekarahan0001
Did you try my code above?
Yes and your code working too :thumbup:

Re: Get Window Title at Specific Coordinates

Posted: 22 Jun 2021, 10:27
by teadrinker
Are you sure you launch it on 64 bit? This code can't show you "This text must be shown" with 64 bit AHK.

Re: Get Window Title at Specific Coordinates

Posted: 22 Jun 2021, 10:37
by emrekarahan0001
teadrinker wrote:
22 Jun 2021, 09:28
emrekarahan0001 wrote: me too running 64 bit version AHK and no problem
Looks like there was a problem. :)
yes i have a problem, but i don't know how can i explain, This is my code, if Title Turkish or English, first check which one, and then wait the true title for work
:facepalm:

Code: Select all

^z::
varSetCapacity(title, 200, 0)
DllCall("GetWindowText", "ptr", DllCall("WindowFromPoint", "Int", 500, "Int", 500)
      , "str", title, "int", 199)

   	if title = Home / Twitter - Google Chrome
   	{
   	Msgbox, English
	gosub, En
   	}
	else 
	{
	WinWait, Home / Twitter - Google Chrome
	}

   	if title = Anasayfa / Twitter - Google Chrome
   	{
   	Msgbox, Turkish
	gosub, Tr
   	}
	else 
	{
	WinWait, Anasayfa / Twitter - Google Chrome
	}

En:
   	Msgbox, Hello World
Return

Tr:
   	Msgbox, Merhaba Dünya
Return

Re: Get Window Title at Specific Coordinates

Posted: 22 Jun 2021, 10:53
by emrekarahan0001
Image
teadrinker wrote:
22 Jun 2021, 10:27
Are you sure you launch it on 64 bit? This code can't show you "This text must be shown" with 64 bit AHK.

Re: Get Window Title at Specific Coordinates

Posted: 22 Jun 2021, 11:16
by teadrinker
emrekarahan0001 wrote: WinWait, Anasayfa / Twitter - Google Chrome
As I see, you are trying to get the title from the browser. Most likely, it is open in full screen. Your code really gets the title of the window from coords 500, 0.
But what my code shows in its message box?

Re: Get Window Title at Specific Coordinates

Posted: 22 Jun 2021, 11:34
by emrekarahan0001
teadrinker wrote:
22 Jun 2021, 11:16
emrekarahan0001 wrote: WinWait, Anasayfa / Twitter - Google Chrome
As I see, you are trying to get the title from the browser. Most likely, it is open in full screen. Your code really gets the title of the window from coords 500, 0.
But what my code shows in its message box?
if title "Anasayfa / Twitter - Google Chrome"

Code: Select all

"WinWait, "Home" / Twitter - Google Chrome"
waiting....

Re: Get Window Title at Specific Coordinates

Posted: 22 Jun 2021, 11:41
by emrekarahan0001
by the way, i dont need this

Code: Select all

^z::
varSetCapacity(title, 200, 0)
DllCall("GetWindowText", "ptr", DllCall("WindowFromPoint", "Int", 500, "Int", 500)
      , "str", title, "int", 199)

   	if title = Home / Twitter - Google Chrome
   	{
   	Msgbox, English
	gosub, En
   	}
	else if title = Anasayfa / Twitter - Google Chrome
	{
   	Msgbox, Turkish
	gosub, Tr
	}

En:
   	Msgbox, Hello World
Return

Tr:
   	Msgbox, Merhaba Dünya
Return