使用AutoHotkey在Adobe Reader中水平滚动


0

我想使用AutoHotkey在Adobe Reader X中水平滚动文档。发送轮消息(0x20e)不起作用,也不发送滚动消息(0x114)。我能找到的唯一方法是向滚动条箭头发送单击,但这会使滚动水平非常慢,除了使任何并发垂直滚动延迟严重。另外,我注意到我的鼠标驱动程序(UltraNav)可以在Adobe Reader X中的模态对话框下滚动,例如“打开文件”对话框,而上述三种方法都不能。那么有谁知道我的鼠标驱动程序可能正在做什么或有另一种方式?

我刚刚找到了第四种方法,它适用于大多数应用程序,前两种方法失败,即将箭头键发送到滚动条。当它确实正确响应时,它也会响应按页面滚动的{PgUp}和{PgDn}。但是,它仍然无法在模态对话框下工作,所以鼠标驱动程序对我来说仍然是一个谜,虽然它似乎滚动相同的数量。此外,此方法在Windows资源管理器中不起作用(预期);发送到滚动条的键也会被发送到主区域。例如 controlsend,%scrollbarname%,{Down},ahk_id %window% 将成功滚动滚动条,但如果可能,还会使当前选择位置向下移动。在没有发送鼠标点击的情况下,我找不到任何其他方法来控制Windows资源管理器中的水平滚动条。

编辑

看到 AutoHotkey滚动&中间点击&鼠标加速度 这是我最初的目标,Adobe Reader只是许多不了解常用滚轮消息的应用程序之一。

Answers:


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


对不起,几个月后我自己找到了一个完整的解决方案后,我忘了回答自己的问题了。有关详细信息,请参阅我的回答
user21820

我没有足够的观点来评论你的答案,但只是想表示感谢你分享你的解决方案。
Sierra Tango

当然,你是受欢迎的!如果您对我创建的其他问题有任何关于我的解决方案或完整脚本的问题,请随时问我。要通知单个用户,请输入 @<username> 评论中的任何地方。
user21820

0

您可以在滚动条的开头单击(仅按下鼠标左键,不要重新放置它),在下图中红点所在的位置。将鼠标尽可能向下移动后,在下图中绿点所在的位置。现在释放鼠标左键。滚动速度应该足够好。

enter image description here

这是完整的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)。上图中绿点的坐标。

EDITED

可以帮助你: http://ahkscript.org/boards/viewtopic.php?f=5&t=4028

从中下载新版AutoHotkey http://ahkscript.org/ (当前版本)。来自autohotkey.com的AutoHotkey已经过时了!


好吧,我没有在我的问题中提到这种方法,但它不是我想要的,因为滚动速度会随着文档的宽度而变化,并且对于宽文档来说根本不会是平滑的。我想要水平滚动,因为垂直滚轮信息适用于大多数应用程序。
user21820

顺便说一句,我正在使用AutoHotkey_L,我相信(不记得我从哪里下载)是来自ahkscript.org。 =)
user21820

@ user21820我的脚本适用于任何类型的滚动条(水平或垂直或任何其他;))只需给它正确的坐标(初始和目的地)。滚动速度足够快。如果你需要使它平滑,你可以用鼠标移动速度。目前它有价值 0。它可以达到 100 (更多的价值,更少的速度)。是的,滚动速度将随文档的宽度而变化。代码已更新。
vasili111

你不明白。当文档很长时,只需将滚动条拖动1个像素就会使其滚动许多页面。这是绝对不受欢迎的,这就是轮式消息对于垂直滚动更好的原因。对于水平滚动,它通常不是太糟糕,但我仍然不希望滚动速度随文档的宽度而变化。无论如何,因为我的第四种方法与Adobe Reader完美配合,我唯一剩下的问题是UltraNav究竟做了什么。但感谢您分享您的方法!
user21820

@ user21820在我的问题检查部分结束 EDITED 。也许它可以帮到你。
vasili111

0

简短的回答

对于Adobe Reader X中的水平滚动,请将滚动消息发送到滚动条的父级,如 sendscrolltoscrollbarparent 在代码中。许多其他方法无法正常工作。这种方法以某种方式提供非常快速的滚动,甚至比我原来的鼠标驱动器更好。

答案很长

我找到了自己的答案,却忘记了这个问题。基本上我为每个疯狂的应用程序使用了一种特殊的方法。由于篇幅太多,我为整个问题创建了一个单独的问答( AutoHotkey滚动&amp;中间点击&amp;鼠标加速度 ),这里只给出与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)
}
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.