【问题标题】:Autohotkey - How to adjust volume only of a specific program?Autohotkey - 如何仅调整特定程序的音量?
【发布时间】:2016-07-18 09:29:32
【问题描述】:

我想控制特定程序的音量,而不是整个主音量。

我发现 THIS 线程的代码仅用于从 Volume Mixer 控制 Windows Media Player 的音量。

这是整个脚本:

SetTitleMatchMode, 3
SndVolWasStarted = 0

;Turn off SndVol after 1 second 
Loop {
  Sleep, 10
  If SndVolWasStarted = 1
  {
    GetKeyState, StateF1, F1
    GetKeyState, StateF2, F2
    If (StateF1 = "D" or StateF2 = "D")
    SndVolStartTime = %A_Now%
      Else {
        If ((A_Now - SndVolStartTime > 1) and WinExist("ahk_class #32770"))
        WinClose, ahk_class #32770
      }
    IfWinNotExist, ahk_class #32770
    SndVolWasStarted = 0
  }
}

;Hotkey to decrease volume
F1::
IfWinExist, Windows Media Player 
{
  IfWinNotExist, ahk_class #32770
  {
    Run, "%A_WinDir%\System32\SndVol.exe" -r 88888888
    WinWait, ahk_class #32770
    SndVolWasStarted = 1
  }
  ToolbarWindowNumber = 322
  msctls_trackbarNumber = 321
  Loop {
    ControlGetText, ControlName, ToolbarWindow%ToolbarWindowNumber%, ahk_class #32770
    If ControlName = Mute for Windows Media Player
    {
      ControlSend, msctls_trackbar%msctls_trackbarNumber%, {Down}, ahk_class #32770 ; Use {Down 2} to change sound level faster
      Break
    } Else {
      If ToolbarWindowNumber < 328
      {
        ToolbarWindowNumber := ToolbarWindowNumber + 2
        msctls_trackbarNumber := msctls_trackbarNumber + 1
      } Else {
        If ToolbarWindowNumber = 328
        {
          ToolbarWindowNumber = 3210
          msctls_trackbarNumber := msctls_trackbarNumber + 1
        } Else {
          If ToolbarWindowNumber < 3242
          {
            ToolbarWindowNumber := ToolbarWindowNumber + 2
            msctls_trackbarNumber := msctls_trackbarNumber + 1
          } Else {
            MsgBox, 16, AutoHotkey, ERROR: Application's volume control was not found!`nThis could occur if the Volume Mixer has more than 20 opened applications
            Break
          }
        }
      }
    }
  }
}
Return

;Hotkey to increase volume
F2::
IfWinExist, Windows Media Player
{
  IfWinNotExist, ahk_class #32770
  {
    Run, "%A_WinDir%\System32\SndVol.exe" -r 88888888
    WinWait, ahk_class #32770
    SndVolWasStarted = 1
  }
  ToolbarWindowNumber = 322
  msctls_trackbarNumber = 321
  Loop {
    ControlGetText, ControlName, ToolbarWindow%ToolbarWindowNumber%, ahk_class #32770
    If ControlName = Mute for Windows Media Player
    {
      ControlSend, msctls_trackbar%msctls_trackbarNumber%, {Up}, ahk_class #32770 ; Use {Up 2} to change sound level faster
      Break
    } Else {
      If ToolbarWindowNumber < 328
      {
        ToolbarWindowNumber := ToolbarWindowNumber + 2
        msctls_trackbarNumber := msctls_trackbarNumber + 1
      } Else {
        If ToolbarWindowNumber = 328
        {
          ToolbarWindowNumber = 3210
          msctls_trackbarNumber := msctls_trackbarNumber + 1
        } Else {
          If ToolbarWindowNumber < 3242
          {
            ToolbarWindowNumber := ToolbarWindowNumber + 2
            msctls_trackbarNumber := msctls_trackbarNumber + 1
          } Else {
            MsgBox, 16, AutoHotkey, ERROR: Application's volume control was not found!`nThis could occur if the Volume Mixer has more than 20 opened applications
            Break
          }
        }
      }
    }
  }
}
Return

我试过了,它可以在 Windows Media Player 上运行,但我无法让它在 Google Chrome 上运行。

我在IfWinExist, Windows Media Player上改了一段代码,改成IfWinExist, Google Chrome,但没有调整Chrome的音量。

我正在运行 Windows 10 64 位

【问题讨论】:

  • 这个答案对你有用吗?如果是,请采纳答案。

标签: autohotkey


【解决方案1】:
  1. 全部替换IfWinExist, Windows Media Player
    IfWinExist ahk_class Chrome_WidgetWin_1
  2. 全部替换If ControlName = Mute for Windows Media Player
    if (ControlName ~= "Mute for.*- Google Chrome")

您可以使用 Autohotkey Window Spy 实用程序来查找值。右键单击任务栏托盘通知区域中的任意 AHK 图标,然后选择“Window Spy”。


或使用很棒的nircmd 实用程序:

^#Up::run nircmd changeappvolume focused +0.1
^#Down::run nircmd changeappvolume focused -0.1
^#Numpad0::run nircmd muteappvolume focused 2

Ctrl+Win+Up = 提高活动应用的音量
Ctrl+Win +Down = 降低活动应用程序的音量
Ctrl+Win+Numpad 0 = 静音/取消静音活动应用

focused 替换为应用程序的exe 名称以控制特定应用程序,例如chrome.exe, vlc.exe

【讨论】:

  • 将脚本更改为:hastebin.com/ewizedidov.cmake 然后出现此消息 i.snag.gy/SznsOt.jpg
  • 那是因为 Chrome 没有播放任何东西,所以它没有被列出。只需删除 msgbox 行。
  • Chrome 和 Windows Media Player 可以工作,但 VLC 等其他人怎么样...IfWinExist 旁边会放什么代码?
  • 您可以使用 Autohotkey Window Spy 实用程序来查找值。
  • 你也知道如何静音/取消静音吗?
【解决方案2】:

我在使用 nircmd 时遇到了一些烦人的延迟。这是我的解决方案:

ShiftAppVolume( appName, incr ),与:

  • appName:目标 .exe 的名称。如果为空(例如,""),则使用活动窗口的应用程序。

  • incr:作为主音量比率的增量(例如,0.04-0.20)。如果是0,则该函数充当应用程序的切换静音/取消静音。

您可以“超过”主音量的 100%:然后主音量会自动增加,而其他应用程序会相应降低以保持恒定水平。 (该功能还确保有一个应用程序处于 100%,因此,如果您增加然后降低应用程序的级别,则主音量不会无缘无故地保持高。)

ShiftAppVolume( appName, incr )
{
    if !appName
    {
        WinGet, activePID, ID, A
        WinGet, activeName, ProcessName, ahk_id %activePID%
        appName := activeName        
    }
    
    IMMDeviceEnumerator := ComObjCreate( "{BCDE0395-E52F-467C-8E3D-C4579291692E}", "{A95664D2-9614-4F35-A746-DE8DB63617E6}" )
    DllCall( NumGet( NumGet( IMMDeviceEnumerator+0 ) + 4*A_PtrSize ), "UPtr", IMMDeviceEnumerator, "UInt", 0, "UInt", 1, "UPtrP", IMMDevice, "UInt" )
    ObjRelease(IMMDeviceEnumerator)

    VarSetCapacity( GUID, 16 )
    DllCall( "Ole32.dll\CLSIDFromString", "Str", "{77AA99A0-1BD6-484F-8BC7-2C654C9A9B6F}", "UPtr", &GUID)
    DllCall( NumGet( NumGet( IMMDevice+0 ) + 3*A_PtrSize ), "UPtr", IMMDevice, "UPtr", &GUID, "UInt", 23, "UPtr", 0, "UPtrP", IAudioSessionManager2, "UInt" )

    DllCall( NumGet( NumGet( IAudioSessionManager2+0 ) + 5*A_PtrSize ), "UPtr", IAudioSessionManager2, "UPtrP", IAudioSessionEnumerator, "UInt" )
    ObjRelease( IAudioSessionManager2 )
    
    DllCall( NumGet( NumGet( IAudioSessionEnumerator+0 ) + 3*A_PtrSize ), "UPtr", IAudioSessionEnumerator, "UIntP", SessionCount, "UInt" )
    levels := []
    maxlevel := 0
    targets := []
    t := 0
    ISAVs := []
    Loop % SessionCount
    {
        DllCall( NumGet( NumGet( IAudioSessionEnumerator+0 ) + 4*A_PtrSize ), "UPtr", IAudioSessionEnumerator, "Int", A_Index-1, "UPtrP", IAudioSessionControl, "UInt" )
        IAudioSessionControl2 := ComObjQuery( IAudioSessionControl, "{BFB7FF88-7239-4FC9-8FA2-07C950BE9C6D}" )
        ObjRelease( IAudioSessionControl )
        
        DllCall( NumGet( NumGet( IAudioSessionControl2+0 ) + 14*A_PtrSize ), "UPtr", IAudioSessionControl2, "UIntP", PID, "UInt" )
        
        PHandle := DllCall( "OpenProcess", "uint", 0x0010|0x0400, "Int", false, "UInt", PID )
        if !( ErrorLevel or PHandle = 0 )
        {
            name_size = 1023
            VarSetCapacity( PName, name_size )
            DllCall( "psapi.dll\GetModuleFileNameEx" . ( A_IsUnicode ? "W" : "A" ), "UInt", PHandle, "UInt", 0, "Str", PName, "UInt", name_size )
            DllCall( "CloseHandle", PHandle )
            SplitPath PName, PName
            
            if incr
            {
                t += 1
                
                ISimpleAudioVolume := ComObjQuery(IAudioSessionControl2, "{87CE5498-68D6-44E5-9215-6DA47EF883D8}")
                DllCall( NumGet( NumGet( ISimpleAudioVolume+0 ) + 4*A_PtrSize ), "UPtr", ISimpleAudioVolume, "FloatP", level, "UInt" )  ; Get volume
                
                if ( PName = appName )
                {
                    level += incr
                    targets.push( t )
                    DllCall( NumGet( NumGet( ISimpleAudioVolume+0 ) + 5*A_PtrSize ), "UPtr", ISimpleAudioVolume, "Int", 0, "UPtr", 0, "UInt" )  ; Unmute
                }
                ISAVs.push( ISimpleAudioVolume )
                levels.push( level )
                maxlevel := max( maxlevel, level )
            }
            else
            {
                if ( PName = appName )
                {
                    ISimpleAudioVolume := ComObjQuery(IAudioSessionControl2, "{87CE5498-68D6-44E5-9215-6DA47EF883D8}")
                    DllCall( NumGet( NumGet( ISimpleAudioVolume+0 ) + 6*A_PtrSize ), "UPtr", ISimpleAudioVolume, "IntP", muted )  ; Get mute status
                    maxlevel := maxlevel or muted
                    ISAVs.push( ISimpleAudioVolume )
                }
            }
        }
        ObjRelease(IAudioSessionControl2)
    }
    ObjRelease(IAudioSessionEnumerator)
    
    if incr
    {
        if ( maxlevel = 0.0 ) or ( maxlevel = 1.0 )
        {
            for i, t in targets
                DllCall( NumGet( NumGet( ISAVs[t]+0 ) + 3*A_PtrSize ), "UPtr", ISAVs[t], "Float", levels[t], "UPtr", 0, "UInt" )
        }
        else
        {
            VarSetCapacity( GUID, 16 )
            DllCall( "Ole32.dll\CLSIDFromString", "Str", "{5CDF2C82-841E-4546-9722-0CF74078229A}", "UPtr", &GUID)
            DllCall( NumGet( NumGet( IMMDevice+0 ) + 3*A_PtrSize ), "UPtr", IMMDevice, "UPtr", &GUID, "UInt", 7, "UPtr", 0, "UPtrP", IEndpointVolume, "UInt" )

            DllCall( NumGet( NumGet( IEndpointVolume+0 ) + 9*A_PtrSize ), "UPtr", IEndpointVolume, "FloatP", MasterLevel ) ; Get master level
            DllCall( NumGet( NumGet( IEndpointVolume+0 ) + 7*A_PtrSize ), "UPtr", IEndpointVolume, "Float", MasterLevel * maxlevel, "UPtr", 0, "UInt" ) ; Set master level
            ObjRelease( IEndpointVolume )
            
            for i, ISimpleAudioVolume in ISAVs
                DllCall( NumGet( NumGet( ISimpleAudioVolume+0 ) + 3*A_PtrSize ), "UPtr", ISimpleAudioVolume, "Float", min( 1.0, levels[i] / maxlevel ) , "UPtr", 0, "UInt" )  ; Set volume
        }        
    }
    else
    {
        for i, ISimpleAudioVolume in ISAVs
            DllCall( NumGet( NumGet( ISimpleAudioVolume+0 ) + 5*A_PtrSize ), "UPtr", ISimpleAudioVolume, "Int", !maxlevel, "UPtr", 0, "UInt" )  ; Toggle mute status
    }
    ObjRelease( IMMDevice )
    for i, ISimpleAudioVolume in ISAVs
        ObjRelease(ISimpleAudioVolume)
}

如果您想受到当前主音量的限制(即,一旦您的应用程序处于 100% 相对水平,尝试增加将无效),您可以使用:

ShiftAppVolumeTopped( appName, incr )
{
    if !appName
    {
        WinGet, activePID, ID, A
        WinGet, activeName, ProcessName, ahk_id %activePID%
        appName := activeName        
    }
    
    IMMDeviceEnumerator := ComObjCreate( "{BCDE0395-E52F-467C-8E3D-C4579291692E}", "{A95664D2-9614-4F35-A746-DE8DB63617E6}" )
    DllCall( NumGet( NumGet( IMMDeviceEnumerator+0 ) + 4*A_PtrSize ), "UPtr", IMMDeviceEnumerator, "UInt", 0, "UInt", 1, "UPtrP", IMMDevice, "UInt" )
    ObjRelease(IMMDeviceEnumerator)

    VarSetCapacity( GUID, 16 )
    DllCall( "Ole32.dll\CLSIDFromString", "Str", "{77AA99A0-1BD6-484F-8BC7-2C654C9A9B6F}", "UPtr", &GUID)
    DllCall( NumGet( NumGet( IMMDevice+0 ) + 3*A_PtrSize ), "UPtr", IMMDevice, "UPtr", &GUID, "UInt", 23, "UPtr", 0, "UPtrP", IAudioSessionManager2, "UInt" )
    ObjRelease( IMMDevice )

    DllCall( NumGet( NumGet( IAudioSessionManager2+0 ) + 5*A_PtrSize ), "UPtr", IAudioSessionManager2, "UPtrP", IAudioSessionEnumerator, "UInt" )
    ObjRelease( IAudioSessionManager2 )
    
    DllCall( NumGet( NumGet( IAudioSessionEnumerator+0 ) + 3*A_PtrSize ), "UPtr", IAudioSessionEnumerator, "UIntP", SessionCount, "UInt" )
    Loop % SessionCount
    {
        DllCall( NumGet( NumGet( IAudioSessionEnumerator+0 ) + 4*A_PtrSize ), "UPtr", IAudioSessionEnumerator, "Int", A_Index-1, "UPtrP", IAudioSessionControl, "UInt" )
        IAudioSessionControl2 := ComObjQuery( IAudioSessionControl, "{BFB7FF88-7239-4FC9-8FA2-07C950BE9C6D}" )
        ObjRelease( IAudioSessionControl )
        
        DllCall( NumGet( NumGet( IAudioSessionControl2+0 ) + 14*A_PtrSize ), "UPtr", IAudioSessionControl2, "UIntP", PID, "UInt" )
        
        PHandle := DllCall( "OpenProcess", "uint", 0x0010|0x0400, "Int", false, "UInt", PID )
        if !( ErrorLevel or PHandle = 0 )
        {
            name_size = 1023
            VarSetCapacity( PName, name_size )
            DllCall( "psapi.dll\GetModuleFileNameEx" . ( A_IsUnicode ? "W" : "A" ), "UInt", PHandle, "UInt", 0, "Str", PName, "UInt", name_size )
            DllCall( "CloseHandle", PHandle )
            SplitPath PName, PName
            if ( PName = appName )
            {
                ISimpleAudioVolume := ComObjQuery(IAudioSessionControl2, "{87CE5498-68D6-44E5-9215-6DA47EF883D8}")
                DllCall( NumGet( NumGet( ISimpleAudioVolume+0 ) + 6*A_PtrSize ), "UPtr", ISimpleAudioVolume, "IntP", muted )  ; Get mute status
                if incr
                {
                    DllCall( NumGet( NumGet( ISimpleAudioVolume+0 ) + 4*A_PtrSize ), "UPtr", ISimpleAudioVolume, "FloatP", level, "UInt" )  ; Get volume
                    DllCall( NumGet( NumGet( ISimpleAudioVolume+0 ) + 3*A_PtrSize ), "UPtr", ISimpleAudioVolume, "Float", max( 0.0, min( 1.0, level + incr ) ) , "UPtr", 0, "UInt" )  ; Set volume
                    if muted
                        DllCall( NumGet( NumGet( ISimpleAudioVolume+0 ) + 5*A_PtrSize ), "UPtr", ISimpleAudioVolume, "Int", !muted , "UPtr", 0, "UInt" )  ; Unmute
                }
                else
                {
                    DllCall( NumGet( NumGet( ISimpleAudioVolume+0 ) + 5*A_PtrSize ), "UPtr", ISimpleAudioVolume, "Int", !muted , "UPtr", 0, "UInt" )  ; Set volume
                }
                ObjRelease(ISimpleAudioVolume)
            }
        }
        ObjRelease(IAudioSessionControl2)
    }
    ObjRelease(IAudioSessionEnumerator)
}

信用到期:这些解决方案是通过扩展 this proposition 创建的,以及来自 GeekDude's AppVolume 的其他提示。后者是您也可以直接在代码中使用的类。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2021-04-19
    • 1970-01-01
    • 2011-04-18
    • 2023-03-09
    • 2016-10-31
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多