发表回复 
利用ACC控制酷狗音乐
2019-11-20, 09 : 14 (这个帖子最后修改于: 2019-11-21 22 : 06 by feiyue.)
Heart 利用ACC控制酷狗音乐
最近在玩ACC,发现它可以操作各种不规则窗口,
所以把以前后台控制酷狗音乐的脚本改进了一下。Shy


代码: (全选)
;-----------------------------------
;  利用ACC控制酷狗音乐 - By FeiYue
;
;  注:热键可以改为自己喜欢的
;-----------------------------------
#NoEnv


F5::酷狗音乐("上一首")

F6::酷狗音乐("下一首")

F7::酷狗音乐("播放/暂停")

F8::酷狗音乐("我喜欢")

^!F5::  ; 采集包含指定文字的按钮的对象路径

ToolTip, 正在采集,请稍等……, 5, 5
Clipboard:=s:=JEE_AccGetTextAll(WinExist("A"), "下一首|上一首|播放|我喜欢")
SoundBeep
ToolTip
MsgBox, 4096,, 已复制内容`n`n%s%
s=
return


酷狗音乐(命令)
{
    DetectHiddenWindows, On
    WinGet, List, List, ahk_exe KuGou.exe
    Loop, %List%
    {
        WinExist("ahk_id " . id:=List%A_Index%)
        WinGetPos,,, w, h
        WinGetTitle, tt
        WinGetText, tx
        WinGet, cs, ControlList
        ok:=(w>100 && h>100)+(tt!="")+(tx!="")+(cs!="")
        if (A_Index=1 or ok>ok_max)
            ok_max:=ok, okid:=id
    }
    路径:={ "上一首"    : "4.3.7.13.1"
          , "播放/暂停" : "4.3.7.13.3"
          , "下一首"    : "4.3.7.13.2"
          , "我喜欢"    : "4.3.7.27.5" }  ; 有的版本是4.3.7.26.5
    Try if (List) and (path:=路径[命令])
    {
        if (命令!="我喜欢" or Acc_Get("Name",path,0,"ahk_id " okid)="我喜欢")
            Acc_Get("DoAction", path, 0, "ahk_id " okid)
        return
    }
    ;---------------------------------------------
    ; 旧的方式可能需要借助AU3_Spy调整各按钮的X坐标
    ;---------------------------------------------
    if (List) and WinExist("ahk_id " okid)
    {
        WinGetPos,,, w, h
        if (w<500)  ; 不显示音乐库
            坐标:={ "上一首"    : 30
                  , "播放/暂停" : 65
                  , "下一首"    : 98
                  , "我喜欢"    : 148 }
        else
            坐标:={ "上一首"    : 33
                  , "播放/暂停" : 93
                  , "下一首"    : 153
                  , "我喜欢"    : 618 }
        SetControlDelay, -1
        ControlClick, % "x" Round(坐标[命令]) " y" Round(h-35),,,,, NA Pos
    }
}

;==================================================

; Acc.ahk - thanks Sean, jethrow, jeeswg
Acc_Get(Cmd, ChildPath="", ChildID=0, WinTitle="", WinText="", ExcludeTitle="", ExcludeText="")
{
    static properties := {Action:"DefaultAction", DoAction:"DoDefaultAction", Keyboard:"KeyboardShortcut"}
    AccObj := IsObject(WinTitle) ? WinTitle
           :  Acc_ObjectFromWindow( WinExist(WinTitle, WinText, ExcludeTitle, ExcludeText), 0 )
    if ComObjType(AccObj, "Name") != "IAccessible"
        ErrorLevel := "Could not access an IAccessible Object"
    else
    {
        StringReplace, ChildPath, ChildPath, _, %A_Space%, All
        AccError:=Acc_Error(), Acc_Error(true)
        Loop Parse, ChildPath, ., %A_Space%
            try
            {
                if A_LoopField is digit
                    Children:=Acc_Children(AccObj), m2:=A_LoopField ; mimic "m2" output in else-statement
                else
                    RegExMatch(A_LoopField, "(\D*)(\d*)", m)
                    , Children:=Acc_ChildrenByRole(AccObj, m1), m2:=(m2?m2:1)
                if Not Children.HasKey(m2)
                    throw
                AccObj := Children[m2]
            }
            catch
            {
                ErrorLevel:="Cannot access ChildPath Item #" A_Index " -> " A_LoopField, Acc_Error(AccError)
                if Acc_Error()
                    throw Exception("Cannot access ChildPath Item", -1, "Item #" A_Index " -> " A_LoopField)
                return
            }
        Acc_Error(AccError)
        StringReplace, Cmd, Cmd, %A_Space%, , All
        properties.HasKey(Cmd)? Cmd:=properties[Cmd]:
        try
        {
            if (Cmd = "Location")
                AccObj.accLocation(ComObj(0x4003,&x:=0), ComObj(0x4003,&y:=0)
                , ComObj(0x4003,&w:=0), ComObj(0x4003,&h:=0), ChildId)
                , ret_val := "x" NumGet(x,0,"int") " y" NumGet(y,0,"int")
                . " w" NumGet(w,0,"int") " h" NumGet(h,0,"int")
            else if (Cmd = "Object")
                ret_val := AccObj
            else if Cmd in Role,State
                ret_val := Acc_%Cmd%(AccObj, ChildID+0)
            else if Cmd in ChildCount,Selection,Focus
                ret_val := AccObj["acc" Cmd]
            else
                ret_val := AccObj["acc" Cmd](ChildID+0)
        }
        catch
        {
            ErrorLevel := """" Cmd """ Cmd Not Implemented"
            if Acc_Error()
                throw Exception("Cmd Not Implemented", -1, Cmd)
            return
        }
        return ret_val, ErrorLevel:=0
    }
    if Acc_Error()
        throw Exception(ErrorLevel,-1)
}

Acc_ObjectFromWindow(hWnd, idObject = -4)
{
    Acc_Init()
    If DllCall("oleacc\AccessibleObjectFromWindow"
    , "Ptr", hWnd, "UInt", idObject&=0xFFFFFFFF, "Ptr", (VarSetCapacity(IID,16)
    +NumPut(idObject==0xFFFFFFF0?0x0000000000020400:0x11CF3C3D618736E0,IID,"Int64")
    +NumPut(idObject==0xFFFFFFF0?0x46000000000000C0:0x719B3800AA000C81,IID,8,"Int64"))*0
    +&IID, "Ptr*", pacc)=0
        Return ComObjEnwrap(9,pacc,1)
}

Acc_Init()
{
    Static h
    If (!h)
        h:=DllCall("LoadLibrary","Str","oleacc","Ptr")
}

Acc_GetRoleText(nRole)
{
    nSize := DllCall("oleacc\GetRoleText", "Uint", nRole, "Ptr", 0, "Uint", 0)
    VarSetCapacity(sRole, (A_IsUnicode?2:1)*nSize)
    DllCall("oleacc\GetRoleText", "Uint", nRole, "str", sRole, "Uint", nSize+1)
    Return sRole
}

Acc_GetStateText(nState)        ; Here not required
{
    nSize := DllCall("oleacc\GetStateText", "Uint", nState, "Ptr", 0, "Uint", 0)
    VarSetCapacity(sState, (A_IsUnicode?2:1)*nSize)
    DllCall("oleacc\GetStateText", "Uint", nState, "str", sState, "Uint", nSize+1)
    Return    sState
}

Acc_Error(p="") {
    static setting:=0
    return p=""?setting:setting:=p
}

Acc_Children(Acc)
{
    if ComObjType(Acc,"Name") != "IAccessible"
        ErrorLevel := "Invalid IAccessible Object"
    else
    {
        Acc_Init(), cChildren:=Acc.accChildCount, Children:=[]
        if DllCall("oleacc\AccessibleChildren", "Ptr",ComObjValue(Acc), "Int",0
        , "Int",cChildren, "Ptr",VarSetCapacity(varChildren,cChildren*(8+2*A_PtrSize),0)*0
        +&varChildren, "Int*",cChildren)=0
        {
            Loop %cChildren%
                i:=(A_Index-1)*(A_PtrSize*2+8)+8, child:=NumGet(varChildren,i)
                , Children.Insert(NumGet(varChildren,i-8)=9?Acc_Query(child):child)
                , NumGet(varChildren,i-8)=9?ObjRelease(child):
            return Children.MaxIndex()?Children:
        } else
            ErrorLevel := "AccessibleChildren DllCall Failed"
    }
    if Acc_Error()
        throw Exception(ErrorLevel,-1)
}

Acc_ChildrenByRole(Acc, Role)
{
    if ComObjType(Acc,"Name")!="IAccessible"
        ErrorLevel := "Invalid IAccessible Object"
    else
    {
        Acc_Init(), cChildren:=Acc.accChildCount, Children:=[]
        if DllCall("oleacc\AccessibleChildren", "Ptr",ComObjValue(Acc)
        , "Int",0, "Int",cChildren, "Ptr",VarSetCapacity(varChildren
        , cChildren*(8+2*A_PtrSize),0)*0+&varChildren, "Int*",cChildren)=0
        {
            Loop %cChildren%
            {
                i:=(A_Index-1)*(A_PtrSize*2+8)+8, child:=NumGet(varChildren,i)
                if NumGet(varChildren,i-8)=9
                    AccChild:=Acc_Query(child), ObjRelease(child)
                    , Acc_Role(AccChild)=Role?Children.Insert(AccChild):
                else
                    Acc_Role(Acc, child)=Role?Children.Insert(child):
            }
            return Children.MaxIndex()?Children:, ErrorLevel:=0
        } else
            ErrorLevel := "AccessibleChildren DllCall Failed"
    }
    if Acc_Error()
        throw Exception(ErrorLevel,-1)
}

Acc_Query(Acc) ; thanks Lexikos - www.autohotkey.com/forum/viewtopic.php?t=81731&p=509530#509530
{
    try return ComObj(9, ComObjQuery(Acc,"{618736e0-3c3d-11cf-810c-00aa00389b71}"), 1)
}

Acc_Role(Acc, ChildId=0)
{
    try return ComObjType(Acc,"Name")="IAccessible"
        ? Acc_GetRoleText(Acc.accRole(ChildId)):"invalid object"
}

JEE_AccGetTextAll(hWnd:=0, RegEx="", vSep:="`r`n", vIndent:="`t", vOpt:="")
{
    vLimN := 20, vLimV := 20
    Loop, Parse, vOpt, % " "
    {
        vTemp := A_LoopField
        if (SubStr(vTemp, 1, 1) = "n")
            vLimN := SubStr(vTemp, 2)
        else if (SubStr(vTemp, 1, 1) = "v")
            vLimV := SubStr(vTemp, 2)
    }

    oMem := {}, oPos := {}
    oMem[1, 1] := Acc_ObjectFromWindow(hWnd, OBJID_WINDOW:=0x0)
    oPos[1] := 1, vLevel := 1
    VarSetCapacity(vOutput, 1000000*2)

    Loop
    {
        if !vLevel
            break
        if !oMem[vLevel].HasKey(oPos[vLevel])
        {
            oMem.Delete(vLevel)
            oPos.Delete(vLevel)
            vLevelLast := vLevel, vLevel -= 1
            oPos[vLevel]++
            continue
        }
        oKey := oMem[vLevel, oPos[vLevel]]

        vName := "", vValue := ""
        if IsObject(oKey)
        {
            vRoleText := Acc_GetRoleText(oKey.accRole(0))
            try vName := oKey.accName(0)
            try vValue := oKey.accValue(0)
        }
        else
        {
            oParent := oMem[vLevel-1,oPos[vLevel-1]]
            vChildId := IsObject(oKey) ? 0 : oPos[vLevel]
            vRoleText := Acc_GetRoleText(oParent.accRole(vChildID))
            try vName := oParent.accName(vChildID)
            try vValue := oParent.accValue(vChildID)
        }
        if (StrLen(vName) > vLimN)
            vName := SubStr(vName, 1, vLimN) "..."
        if (StrLen(vValue) > vLimV)
            vValue := SubStr(vValue, 1, vLimV) "..."
        vName := RegExReplace(vName, "[`r`n]", " ")
        vValue := RegExReplace(vValue, "[`r`n]", " ")

        vAccPath := ""
        if IsObject(oKey)
        {
            Loop, % oPos.Length() - 1
                vAccPath .= (A_Index=1?"":".") oPos[A_Index+1]
        }
        else
        {
            Loop, % oPos.Length() - 2
                vAccPath .= (A_Index=1?"":".") oPos[A_Index+1]
            vAccPath .= " c" oPos[oPos.Length()]
        }

        ; 稍作修改只返回匹配指定正则字符串的路径
        if (vName~=RegEx) or (vValue~=RegEx)
            vOutput .= vAccPath "`t" JEE_StrRept(vIndent, vLevel-1)
            . vRoleText " [" vName "][" vValue "]" vSep

        oChildren := Acc_Children(oKey)
        if !oChildren.Length()
            oPos[vLevel]++
        else
        {
            vLevelLast := vLevel, vLevel += 1
            oMem[vLevel] := oChildren
            oPos[vLevel] := 1
        }
    }
    return SubStr(vOutput, 1, -StrLen(vSep))
}

JEE_StrRept(vText, vNum)
{
    if (vNum > 0)
        return StrReplace(Format("{:" vNum "}", ""), " ", vText)
}
查找这个用户的全部帖子
表示感谢 引用并回复 移动视图置页面顶端
发表回复 


论坛跳转:


联系我们 | Autohotkey 中文站 | 回到顶部 | 回到正文区 | 精简(归档)模式 | RSS 聚合