Rolando horizontalmente no Adobe Reader usando a AutoHotkey

0

Quero usar a AutoHotkey para rolar um documento horizontalmente no Adobe Reader X. Enviar mensagens de roda (0x20e) não funciona, nem enviar mensagens de rolagem (0x114). O único método que pude encontrar é enviar cliques para as setas da barra de rolagem, mas isso torna a rolagem horizontalmente muito lenta, além de atrasar muito a rolagem vertical simultânea. Além disso, notei que o driver do mouse (UltraNav) pode rolar sob uma caixa de diálogo aparentemente modal no Adobe Reader X, como a caixa de diálogo Abrir arquivo, enquanto nenhum dos três métodos acima pode. Alguém sabe o que o driver do mouse pode estar fazendo ou tem outra maneira?

Acabei de encontrar um quarto método que funciona muito bem para a maioria dos aplicativos para os quais os dois primeiros falham, que é enviar teclas de seta para a barra de rolagem. Quando responde adequadamente, também responde a {PgUp} e {PgDn} que rola por página. No entanto, ele ainda não funciona sob uma caixa de diálogo modal, portanto, o que o driver do mouse faz permanece um mistério para mim, embora pareça rolar nas mesmas quantidades. Além disso, esse método não funciona no Windows Explorer (como esperado); as teclas enviadas para as barras de rolagem também são enviadas para a área principal. Por exemplo controlsend,%scrollbarname%,{Down},ahk_id %window%, rolará com sucesso a barra de rolagem, mas também fará com que a posição de seleção atual se mova para baixo, se possível. Não consigo encontrar outra maneira de controlar a barra de rolagem horizontal no Windows Explorer sem enviar cliques do mouse.

Editar

Consulte Rolagem do AutoHotkey, clique do meio e aceleração do mouse, que era meu objetivo original, o Adobe Reader sendo apenas um dos muitos aplicativos que não entendem as mensagens usuais da roda.

user21820
fonte

Respostas:

1

O Adobe Reader possui uma maneira estranha de lidar com a rolagem horizontal. Isto é o que eu uso para corrigir o problema:

#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

Nota: Alterei a atribuição das teclas de rolagem esquerda e direita do mouse para as teclas F, para que pudessem ser selecionadas no AutoHotKey, já que eu também uso o Logitech SetPoint

Stephan
fonte
Desculpe, esqueci de responder minha própria pergunta depois que encontrei uma solução completa sozinha alguns meses depois. Veja minha resposta para os detalhes.
precisa saber é o seguinte
Não tenho pontos suficientes para comentar sua resposta, mas gostaria de agradecer por compartilhar sua solução.
Stephan
Claro que você é bem-vindo! Se você tiver alguma dúvida sobre minha solução ou meu script completo sobre a outra pergunta que eu criei, fique à vontade para me perguntar. Para notificar um único usuário, coloque @<username>em qualquer lugar do seu comentário.
precisa saber é o seguinte
0

Você pode clicar (basta pressionar o botão esquerdo do mouse, ainda não o relia) no início da barra de rolagem, no local em que o ponto vermelho está na imagem abaixo. Depois de mover o mouse o mais para baixo possível, no local em que o ponto verde está na imagem abaixo. Agora solte o botão esquerdo do mouse. A velocidade de rolagem deve ser boa o suficiente.

insira a descrição da imagem aqui

Aqui está o código de script completo do AutoHotkey:

CoordMode, Mouse, Screen
InitX := 
InitY :=
DestX := 
DestY :=
Click, Left, Down, %InitX%, %InitY%
Mousemove, %DestX%, %DestY%, 0
Click, Left, Up

As variáveis ​​InitX e InitY devem conter pontos iniciais das coordenadas (x e y, respectivamente). Coordenadas do ponto vermelho que estão na imagem acima.

As variáveis ​​DestX e DestY devem conter coordenadas (x e y, respectivamente) para os pontos de destino. Coordenadas do ponto verde que está na imagem acima.

EDITADO :

Que isso possa ajudá-lo: http://ahkscript.org/boards/viewtopic.php?f=5&t=4028

Faça o download da nova versão do AutoHotkey em http://ahkscript.org/ (versão atual). AutoHotkey de autohotkey.com está desatualizado!

vasili111
fonte
Bem, eu não mencionei esse método na minha pergunta, mas não é o que eu quero, pois a velocidade de rolagem varia de acordo com a largura do documento e não seria suave para documentos largos. E eu queria rolagem horizontal porque as mensagens de roda vertical funcionam bem para a maioria dos aplicativos.
user21820
A propósito, estou usando o AutoHotkey_L, que acredito (não me lembro de onde eu baixei) é do ahkscript.org. =)
user21820
@ user21820 O meu script funcionará com qualquer tipo de barra de rolagem (horizontal ou vertical ou qualquer outra;)) apenas dê as coordenadas corretas (inicial e destino). A velocidade de rolagem será rápida o suficiente. Se precisar torná-lo suave, você pode jogar com a velocidade do mouse. Atualmente, tem valor 0. Pode subir para 100(mais valor, menos velocidade). E sim, a velocidade de rolagem varia com a largura do documento. Código atualizado.
vasili111
Você não entende. Quando o documento é longo, basta arrastar a barra de rolagem em 1 pixel para fazer com que ele role várias páginas. Isso é absolutamente indesejável, e é por isso que as mensagens de roda são melhores para rolagem vertical. Para rolagem horizontal, geralmente não é tão ruim, mas ainda não quero que a velocidade de rolagem varie com a largura do documento. De qualquer forma, desde que meu quarto método funciona perfeitamente com o Adobe Reader, minha única pergunta restante é o que exatamente o UltraNav faz. Mas obrigado por compartilhar seu método!
user21820
@ user21820 No final da minha pergunta, verifique a seção EDITADA . Talvez possa ajudá-lo.
precisa saber é o seguinte
0

Resposta curta

Para rolagem horizontal no Adobe Reader X, envie mensagens de rolagem para o pai da barra de rolagem, como no sendscrolltoscrollbarparentcódigo. Muitas outras maneiras não funcionariam corretamente. De alguma forma, esse método fornece rolagem muito rápida, ainda melhor do que o driver do mouse original.

Resposta longa

Eu tinha encontrado minhas próprias respostas, mas havia esquecido essa pergunta. Basicamente, usei um método idiossincrático para cada aplicação maluca. Como existem muitas, criei uma pergunta e uma resposta separadas para todo o lote ( rolagem AutoHotkey e clique do meio e aceleração do mouse ) e forneço apenas as partes relevantes para o Adobe Reader aqui.

O processo deve ser assim. Primeiro você chama gettarget, que assume que a posição do mouse está armazenada mx,mye encontra o destino correto para os eventos de rolagem com base no que está atualmente sob o mouse. Em seguida, você liga várias vezes scrollapós adicionar o valor para o qual deseja rolar sx,sy.

Para o Adobe Reader, até a rolagem vertical depende do envio de mensagens de roda para o lugar certo, o que não é consistente e, portanto, acabei codificando para os dois casos principais, que rolam na área de exibição do documento e na área de marcadores. Para descobrir qual é o caso, verifico se o pai do controle sob o mouse tem um descendente chamado AVL_AVView4ou não. Se isso acontecer, é a pessoa certa para a qual enviar as mensagens de roda vertical executadas por sendwheel. Mas para rolagem horizontal, verifica-se que o envio de mensagens de rolagem para o controle pai da barra de rolagem correta funciona nos dois locais, executados por sendscrolltoscrollbarparent. A barra de rolagem correta é aquela chamada scrollbar1descendente do pai do controle sob o mouse.

Código

#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)
}
user21820
fonte
0

Minha solução:

#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

Você pode aumentar o número 20 para rolar mais devagar

Feiran Zhang
fonte