我想使用 AutoHotkey 在 Adobe Reader X 中水平滚动文档。发送滚轮消息 (0x20e) 不起作用,发送滚动消息 (0x114) 也不起作用。我能找到的唯一方法是向滚动条箭头发送点击,但这会使水平滚动非常慢,此外还会使任何并发的垂直滚动严重滞后。此外,我注意到我的鼠标驱动程序 (UltraNav) 可以在 Adobe Reader X 中明显模态的对话框(例如“打开文件”对话框)下滚动,而上述三种方法都不能。那么有人知道我的鼠标驱动程序可能在做什么或有其他方法吗?
我刚刚发现了第四种方法,它对于前两种方法无法实现的大多数应用程序来说效果很好,即向滚动条发送箭头键。当它正确响应时,它还会响应按页滚动的 {PgUp} 和 {PgDn}。但是,它在模式对话框下仍然不起作用,因此鼠标驱动程序的作用对我来说仍然是个谜,尽管它似乎滚动了相同的量。此外,此方法在 Windows 资源管理器中不起作用(预期);发送到滚动条的键也会发送到主区域。例如,controlsend,%scrollbarname%,{Down},ahk_id %window%
将成功滚动滚动条,但如果可能,还会导致当前选择位置向下移动。我找不到任何其他不发送鼠标点击来控制 Windows 资源管理器中水平滚动条的方法。
编辑
看AutoHotkey 滚动、中键单击和鼠标加速这是我最初的目标,Adobe Reader 只是众多无法理解通常的滚轮信息的应用程序之一。
答案1
Adobe Reader 处理水平滚动的方式很奇怪。以下是我用来修复此问题的方法:
#IfWinActive, ahk_exe Acrobat.exe
F13::
While GetKeyState("F13") {
Send, {Shift down}{WheelUp}
Sleep, 100
}
Send, {Shift up}
Return
F14::
While GetKeyState("F14") {
Send, {Shift down}{WheelDown}
Sleep, 100
}
Send, {Shift up}
Return
#IfWinActive
注意:我将鼠标左键和右键的按键分配更改为 F 键,以便可以在 AutoHotKey 中拾取它们,因为我还使用 Logitech SetPoint
答案2
您可以单击(仅按下鼠标左键,不要松开)滚动条的开始处,即下图中红点所在的位置。然后将鼠标尽可能向下移动,即下图中绿点所在的位置。现在松开鼠标左键。滚动速度应该足够快。
以下是完整的 AutoHotkey 脚本代码:
CoordMode, Mouse, Screen
InitX :=
InitY :=
DestX :=
DestY :=
Click, Left, Down, %InitX%, %InitY%
Mousemove, %DestX%, %DestY%, 0
Click, Left, Up
变量 InitX 和 InitY 应保存坐标(分别为 x 和 y)初始点。上图中红点的坐标。
变量 DestX 和 DestY 应保存目标点的坐标(分别为 x 和 y)。上图中绿点的坐标。
已编辑:
希望这能帮到你:http://ahkscript.org/boards/viewtopic.php?f=5&t=4028
从以下位置下载新版本的 AutoHotkeyhttp://ahkscript.org/(当前版本)。autohotkey.com 上的 AutoHotkey 已经过时了!
答案3
简短回答
对于 Adobe Reader X 中的水平滚动,请向滚动条的父级发送滚动消息,如sendscrolltoscrollbarparent
代码中所示。许多其他方法都无法正常工作。这种方法不知何故提供了非常快的滚动速度,甚至比我原来的鼠标驱动程序还要好。
长答案
我找到了自己的答案,但忘记了这个问题。基本上,我对每一个疯狂的申请都使用了一种独特的方法。由于申请太多,我为所有申请都创建了一个单独的问题和答案(AutoHotkey 滚动、中键单击和鼠标加速),这里只给出与Adobe Reader相关的部分。
过程应该像这样。首先调用gettarget
,它假设鼠标位置存储在 中mx,my
,并根据鼠标下方的当前位置找到滚动事件的正确目标。然后scroll
在添加要滚动到 的量后重复调用sx,sy
。
对于 Adobe Reader,即使是垂直滚动也依赖于将滚轮消息发送到正确的位置,这是不一致的,因此我最终对两种主要情况进行了硬编码,即滚动文档显示区域和滚动书签区域。为了找出是哪种情况,我检查鼠标下的控件的父级是否有一个名为的后代AVL_AVView4
。如果有,那么这就是发送垂直滚轮消息的正确方法,由执行sendwheel
。但对于水平滚动,事实证明,在两个地方向正确滚动条的父控件发送滚动消息都有效,由执行sendscrolltoscrollbarparent
。正确的滚动条是scrollbar1
鼠标下控件的父级的后代。
代码
#commentflag // ; Change to C++ comment style
global mx,my
global sx:=0
global sy:=0
global ctrl,window,parent
global methodx
global methody
global scrollbarx
global scrollbary
global max16bit:=32767
gettarget()
{
ctrl:=getctrlat(mx,my)
window:=getwindow(ctrl)
class:=getclass(window)
parent:=getparent(ctrl)
parentname:=getnameatroot(parent)
if( class=="AcrobatSDIWindow" )
{
if( regexmatch(parentname,"AVL_AVView")==1 )
{
ctrl:=getdescendant(parent,"AVL_AVView4")
if( ctrl=="" )
{
ctrl:=getdescendant(parent,"AVL_AVView1")
}
methodx:="scrolltoscrollbarparent"
scrollbarx:="scrollbar1"
methody:="wheel"
}
}
}
scroll:
critical on
tx:=sx
ty:=sy
sx-=tx
sy-=ty
rx:=0
ry:=0
if( tx!=0 )
{
txi:=rtoz(tx)
rx:=tx-txi
if( txi!=0 )
{
if( methodx=="scrolltoscrollbarparent" )
{
sendscrolltoscrollbarparent(scrollbarx,"h",txi)
}
}
}
if( ty!=0 )
{
if( methody=="wheel" )
{
sendwheel("v",-ty)
}
}
sx:=rx
sy:=ry
return
sendwheel(dir,amount)
{
t:=a_tickcount
msg:=( dir=="v" ? 0x20a : 0x20e )
flags:=getkeystate("Ctrl")<<3|getkeystate("Shift")<<2
amount*=120
while( amount>max16bit )
{
sendmessage msg,max16bit<<16|flags,mx|my<<16,,ahk_id %ctrl%,,,,timelimit
amount-=max16bit
if( a_tickcount-t>=timelimit )
{
return
}
}
while( amount<-max16bit )
{
sendmessage msg,-max16bit<<16|flags,mx|my<<16,,ahk_id %ctrl%,,,,timelimit
amount+=max16bit
if( a_tickcount-t>=timelimit )
{
return
}
}
sendmessage msg,round(amount)<<16|flags,mx|my<<16,,ahk_id %ctrl%,,,,timelimit
}
sendscrolltoscrollbarparent(name,dir,amount)
{
sb:=getdescendant(parent,name)
sbp:=getparent(sb)
t:=a_tickcount
msg:=( dir=="v" ? 0x115 : 0x114 )
flag:=( amount<0 ? 0 : 1 )
loop % abs(amount)
{
sendmessage msg,flag,sb,,ahk_id %sbp%,,,,timelimit
if( a_tickcount-t>=timelimit )
{
return
}
}
}
rtoz(r)
{
return ( r>0 ? floor(r) : ceil(r) )
}
getparent(handle)
{
return dllcall("GetParent","uint",handle)
}
getname(root,handle)
{
local CH,CN,S,P
WinGet, CH, ControlListHwnd, ahk_id %root%
WinGet, CN, ControlList, ahk_id %root%
setformat integerfast,h
handle+=0
handle.=""
setformat integerfast,d
LF:= "`n", CH:= LF CH LF, CN:= LF CN LF, S:= SubStr( CH, 1, InStr( CH, LF handle LF ) )
StringReplace, S, S,`n,`n, UseErrorLevel
StringGetPos, P, CN, `n, L%ErrorLevel%
Return SubStr( CN, P+2, InStr( CN, LF, 0, P+2 ) -P-2 )
}
getdescendant(handle,name)
{
local CH,CN,S,P
WinGet, CH, ControlListHwnd, ahk_id %handle%
WinGet, CN, ControlList, ahk_id %handle%
setformat integerfast,h
handle+=0
handle.=""
setformat integerfast,d
LF:= "`n", CH:= LF CH LF, CN:= LF CN LF, S:= SubStr( CN, 1, InStr( CN, LF name LF ) )
StringReplace, S, S,`n,`n, UseErrorLevel
StringGetPos, P, CH, `n, L%ErrorLevel%
Return SubStr( CH, P+2, InStr( CH, LF, 0, P+2 ) -P-2 )*1
}
getnameatroot(handle)
{
return getname(dllcall("GetAncestor","uint",handle,"uint",2),handle)
}
getnameaschild(handle)
{
return getname(getparent(handle),handle)
}
getclass(handle)
{
local class
wingetclass class,ahk_id %handle%
return class
}
getwindow(handle)
{
return dllcall("GetAncestor","uint",handle,"uint",2)
}
getctrlat2(x,y,first,current)
{
/*
Pushes the following invisible container controls to the back because they are in front of their contents for no reason
SysTabControl32 : The usual class that contains tabbed panes ( Mouse properties , ... )
Static : A class occasionally used to contain tabbed panes ( Programmer's Notepad Options > Fonts and Colours > Advanced , ... )
Button : A typical class used to contain a List Box ( Outlook Contact > Properties > General > Members , ... )
Executes WindowFromPoint again to access the contents of such container controls
*/
local handle,class,style
class:=getclass(current)
winget style,style,ahk_id %current%
if( class=="SysTabControl32" or class=="Static" or ( class=="Button" and (style&0x7)==0x7 ) )
{
dllcall("SetWindowPos","uint",current,"uint",1,"int",0,"int",0,"int",0,"int",0,"uint",0x3) // push it to the back where it belongs
handle:=dllcall("WindowFromPoint","int",x,"int",y)
//handle:=DllCall( "WindowFromPoint", "int64", (my << 32) | (mx & 0xFFFFFFFF), "Ptr") // for negative 64-bit
if( handle==first )
{
return first
}
return getctrlat2(x,y,first,handle)
}
return current
}
getctrlat(x,y)
{
local handle
handle:=dllcall("WindowFromPoint","int",x,"int",y)
//handle:=DllCall( "WindowFromPoint", "int64", (my << 32) | (mx & 0xFFFFFFFF), "Ptr") // for negative 64-bit
return getctrlat2(x,y,handle,handle)
}
答案4
我的解决方案:
#IfWinActive, ahk_exe Acrobat.exe
WheelLeft::
Send,{shift down}
sleep,20
Send,{WheelUp}
sleep,20
Send,{shift up}
return
WheelRight::
Send,{shift down}
sleep,20
Send,{WheelDown}
sleep,20
Send,{shift up}
return
#IfWinActive
你可以增加数字 20 来减慢滚动速度