Rolagem horizontal no Adobe Reader usando o AutoHotkey

0

Eu quero usar o AutoHotkey para rolar um documento horizontalmente no Adobe Reader X. As mensagens de roda de envio (0x20e) não funcionam, nem o envio de mensagens de rolagem (0x114). O único método que eu poderia encontrar é enviar cliques para as setas da barra de rolagem, mas isso faz com que a rolagem horizontalmente seja muito lenta, além de fazer qualquer atraso de rolagem vertical simultâneo mal. Além disso, percebo que o driver do meu mouse (UltraNav) pode rolar em 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 meu mouse pode estar fazendo ou tem outro jeito?

Acabei de encontrar um quarto método que funciona muito bem para a maioria dos aplicativos para os quais os dois primeiros falham, que é o de enviar chaves de seta para a barra de rolagem. Quando ele responde corretamente, ele também responde a {PgUp} e {PgDn} que rola por página. No entanto, ainda não funciona sob uma caixa de diálogo modal, então o que o driver de mouse faz ainda é um mistério para mim, embora pareça rolar pelas mesmas quantidades. Além disso, esse método não funciona no Windows Explorer (esperado); as chaves 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 qualquer outra maneira de controlar a barra de rolagem horizontal no Windows Explorer sem enviar cliques do mouse.

Editar

Veja Rolagem AutoHotkey & clique do meio & aceleração do mouse que era minha meta original, sendo o Adobe Reader apenas um dos muitos aplicativos que não entendem as mensagens habituais da roda.

    
por user21820 14.07.2014 / 12:15

3 respostas

0

Resposta curta

Para rolagem horizontal no Adobe Reader X, envie mensagens de rolagem para o pai da barra de rolagem, como em sendscrolltoscrollbarparent no código. Muitas outras formas não funcionariam corretamente. Esse método, de alguma forma, oferece rolagem muito rápida, ainda melhor do que o driver original do meu mouse.

Resposta longa

Eu encontrei minhas próprias respostas, mas tinha esquecido essa questão. Basicamente eu usei um método idiossincrático para cada aplicação louca. Como há muitos, criei uma pergunta e uma resposta separadas para todo o lote ( AutoHotkey rolagem & aceleração do mouse e do meio do mouse ) e apenas forneça 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 em mx,my e encontra o destino correto para os eventos de rolagem com base no que está atualmente sob o mouse. Em seguida, você chama repetidamente scroll após adicionar a quantidade para rolar para sx,sy .

Para o Adobe Reader, até mesmo 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 estão rolando a área de exibição do documento e rolando a área de marcadores . Para descobrir qual é o caso, eu verifico se o pai do controle sob o mouse tem um descendente chamado AVL_AVView4 ou não. Em caso afirmativo, esse é o caminho certo para enviar mensagens de roda verticais para, realizado por sendwheel . Mas, para a rolagem horizontal, verifica-se que o envio de mensagens de rolagem para o controle pai da barra de rolagem correta funciona em ambos os lugares, realizado por sendscrolltoscrollbarparent . A barra de rolagem correta é a chamada scrollbar1 , que é a descendência 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)
}
    
por 19.01.2016 / 11:02
1

O Adobe Reader tem uma maneira estranha de manipular a rolagem horizontal. Isso é 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: eu mudei a atribuição de teclas do meu mouse direito e esquerdo para as teclas F para que elas pudessem ser selecionadas no AutoHotKey, já que eu também uso o Logitech SetPoint

    
por 19.01.2016 / 02:43
0

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

AquiestáocódigodescriptcompletodoAutoHotkey:

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

VariáveisInitXeInitYdevemmantercoordenadas(xeyrespectivamente)pontosiniciais.Coordenadasdepontovermelhoqueestãonaimagemacima.

VariáveisDestXeDestYdevemconterascoordenadas(xey,respectivamente)dospontosdedestino.Coordenadasdopontoverdequeestãonaimagemacima.

EDITADO:

Issopodeajudarvocê: link

Baixe a nova versão do AutoHotkey do link (versão atual). AutoHotkey do autohotkey.com está desatualizado!

    
por 15.07.2014 / 20:45