script does not work in 64 bit AHK

Get help with using AutoHotkey (v1.1 and older) and its commands and hotkeys
need4speed
Posts: 143
Joined: 22 Apr 2016, 06:50

script does not work in 64 bit AHK

25 Aug 2017, 02:39

sorry if this ain't be a bug, but I don't see why this is should not work in the 64 bit Version.

to reproduce insert a long text in WordPad. the vertical scroll bar appears, after running the script WheelUP/Down are inverted in AutoHotkeyA32.exe & AutoHotkeyU32.exe. In AutoHotkeyU64.exe WheelUP/Down does not longer work.

Code: Select all

#NoTrayIcon
#SingleInstance, force
#MaxHotkeysPerInterval 250
SetTitleMatchMode, 2
CoordMode, Mouse, Screen

#If MouseIsOver("WordPad")
WheelUp::
	MouseGetPos, m_x, m_y
	hw_m_target := DllCall( "WindowFromPoint", "int", m_x, "int", m_y )
	SendMessage, 0x20A, -120 << 16, ( m_y << 16 )|m_x,, ahk_id %hw_m_target%
return

WheelDown::
	MouseGetPos, m_x, m_y
	hw_m_target := DllCall( "WindowFromPoint", "int", m_x, "int", m_y )
	SendMessage, 0x20A, 120 << 16, ( m_y << 16 )|m_x,, ahk_id %hw_m_target%
return
#If

MouseIsOver(WinTitle) {
    MouseGetPos,,, Win
    return WinExist(WinTitle . " ahk_id " . Win)
}
just me
Posts: 9450
Joined: 02 Oct 2013, 08:51
Location: Germany

Re: script does not work in 64 bit AHK

25 Aug 2017, 09:42

WindowFromPoint() has only one parameter, a POINT structure of 8 bytes. With AHK32 you have to split the structure into two parameters of 4 bytes ("Int", ..., "Int", .... With AHK64 you have to pass the 8 bytes as one parameter ("Int64", ....

Also, the defaullt return type of DllCall() is Int (4 bytes). The function you are calling returns a window handle (HWND) of type Ptr, which is 4 bytes for AHK32 and 8 bytes for AHK64 on Win x64. Without specifying the return type Ptr you will only get the lower 4 bytes of a 8 bytes handle.

This isn't a bug!
wolf_II
Posts: 2688
Joined: 08 Feb 2015, 20:55

Re: script does not work in 64 bit AHK

25 Aug 2017, 10:16

Try also without DllCall:

Code: Select all

#If MouseIsOver("WordPad")
WheelUp::
    MouseGetPos, m_x, m_y,, Ctrl
    ControlGet, hCtrl, Hwnd,, %Ctrl%, A
    SendMessage, 0x20A, -120 << 16, ( m_y << 16 )|m_x,, ahk_id %hCtrl%
return

WheelDown::
    MouseGetPos, m_x, m_y,, Ctrl
    ControlGet, hCtrl, Hwnd,, %Ctrl%, A
    SendMessage, 0x20A, 120 << 16, ( m_y << 16 )|m_x,, ahk_id %hCtrl%
return
#If
I hope that helps.
User avatar
jeeswg
Posts: 6902
Joined: 19 Dec 2016, 01:58
Location: UK

Re: script does not work in 64 bit AHK

25 Aug 2017, 11:54

Note: you should do something like this:
(vPosX & 0xFFFF)|(vPosY<<16)
(vPosX & 0xFFFFFFFF)|(vPosY<<32)
notice the use of &, to make sure that negative as well as positive values can be handled.

I did various experiments re. this which I will publish in my mathematics tutorial.

Using similar logic to this:

Code: Select all

q::
VarSetCapacity(vData, 8, 0)
NumPut(-2, vData, 0, "Int")
NumPut(-2, vData, 4, "Int")
MsgBox, % NumGet(vData, 0, "Int")
MsgBox, % NumGet(vData, 4, "Int")
MsgBox, % Format("0x{:X}", NumGet(vData, 0, "Int64")) ;0xFFFFFFFEFFFFFFFE
MsgBox, % Format("0x{:X}", (-2 & 0xFFFFFFFF)|(-2 << 32)) ;0xFFFFFFFEFFFFFFFE
MsgBox, % Format("0x{:X}", (-2)|(-2 << 32)) ;incorrect: 0xFFFFFFFFFFFFFFFE
return
@just me: Why can't you use two Ints in x64? I'm trying to figure it out ...
INT INT
INT64
Both take up 8 bytes and don't require any padding. Am I missing something?
I would have thought that both methods would work in both x32 and x64.
homepage | tutorials | wish list | fun threads | donate
WARNING: copy your posts/messages before hitting Submit as you may lose them due to CAPTCHA
need4speed
Posts: 143
Joined: 22 Apr 2016, 06:50

Re: script does not work in 64 bit AHK

25 Aug 2017, 15:29

I used "my" script without actually understanding it.
Thank you all for the code and explanations.
just me
Posts: 9450
Joined: 02 Oct 2013, 08:51
Location: Germany

Re: script does not work in 64 bit AHK

25 Aug 2017, 15:50

Hi jeeswg,

I have to correct myself a bit. All function parameters on x86 (32-bit) are passed using the stack. So it makes no difference whether you pass one Int64 or two Ints for a POINT structure.. Both will put 8 bytes onto the stack and the called function will fetch exactly this 8 bytes.

On x64 (64-bit) the first four parameters are passed using registers. The stack is only used for additional parameters. So you must pass the POINT structure which is the first parameter as one parameter.

Source: Overview of x64 Calling Conventions
User avatar
jeeswg
Posts: 6902
Joined: 19 Dec 2016, 01:58
Location: UK

Re: script does not work in 64 bit AHK

25 Aug 2017, 16:44

@need4speed: So it looks like this would work for your script:

Code: Select all

hw_m_target := DllCall( "WindowFromPoint", "int64", ( m_y << 32 )|( m_x & 0xFFFFFFFF ), "ptr" )
I might write it slightly differently like this:

Code: Select all

hw_m_target := DllCall("WindowFromPoint", "int64",(m_x&0xFFFFFFFF)|(m_y<<32), "ptr")
;or:
hWnd := DllCall("WindowFromPoint", Int64,(vPosX&0xFFFFFFFF)|(vPosY<<32), Ptr)
[EDIT:] I tested the script and it worked, although I was concerned that &0xFFFFFFF, might not work, if AHK tried to interpret &0xFFFFFFF by attempting to retrieve the address of a variable called '0xFFFFFFFF'. I.e. so in theory putting spaces around the '&' might be safer.
==================================================

@just me:
Thanks so much just me, I finally have some understanding why there is a difference.

This affects my script:
DllCall converter/cleaner (e.g. x32 to x64/x32 two-way compatible) - AutoHotkey Community
https://autohotkey.com/boards/viewtopic.php?f=6&t=31365
it suggests that all scripts, for x64/x32 compatibility, should aim to have the same number of parameters as the definition specifies, and not split them up.

Btw you noticed a lot of flaws with that initial script, in case there any more. I didn't think the script was necessarily perfect at the time, but there were more issues than expected.

==================================================

I don't 100% understand what they're talking about here, although I can sort of follow, in case there is anywhere that explains this better.

Overview of x64 Calling Conventions
https://msdn.microsoft.com/en-us/library/ms235286.aspx
The __fastcall convention uses registers for the first four arguments and the stack frame to pass additional arguments.
Parameter Passing
https://msdn.microsoft.com/en-us/library/zthk2dkh.aspx
homepage | tutorials | wish list | fun threads | donate
WARNING: copy your posts/messages before hitting Submit as you may lose them due to CAPTCHA

Return to “Ask for Help (v1)”

Who is online

Users browsing this forum: Google [Bot], Joey5, justcop, Rohwedder and 152 guests