AutoHotKey_Lで、音量ミキサーをもう少し便利に。
WindowsVista以降の音量ミキサーを、特にキーボードで操作しやすくするAHKスクリプト Ver.1.1。
Ver.1.0。#v打鍵で画面幅いっぱいに音量ミキサー呼び出し。上下、PageUp/Down、Home/Endキーで音量調整。ソフトウェアごとの音量は、左端のマスターボリュームの値が上限となるよう制限。左右キーで対象ソフトウェア変更。ツールチップとタイトルバーで音量の概略を表示。
Ver.1.1。音量ミキサー起動中は、Vol.Up/Down、Muteキーでも音量ミキサーを操作するように。数字キーで対象デバイスを変更できるように。Spaceキーで対象をミュートに。対象の切り替え順が、見た目通りになるように修正。
ver.1.2b。アイテムが10個以上あると正常動作しないのを修正。
; 音量ミキサー最大化呼び出し
#v::
Run, SndVol.exe, , , svpid
winWait, 音量ミキサー, , 10
if ErrorLevel
return
WinGetPos, , , , WH
WinMove, , , 0, A_ScreenHeight - WH, A_ScreenWidth
return
$Volume_Mute::
IfWinExist, 音量ミキサー ahk_class #32770
{
VM_Mute()
return
}
Send, {Volume_Mute}
return
$Volume_Down::
IfWinExist, 音量ミキサー ahk_class #32770
{
VM_LvUD(0)
return
}
Send, {Volume_Down}
return
$Volume_Up::
IfWinExist, 音量ミキサー ahk_class #32770
{
VM_LvUD(1)
return
}
Send, {Volume_Up}
return
;--------------------------------------------------------------------------------------
; 音量ミキサー
;--------------------------------------------------------------------------------------
#IfWinActive 音量ミキサー ahk_class #32770
1::VM_DevChange(1)
2::VM_DevChange(2)
Up::
ControlGetFocus, ACtrl
IfInString, ACtrl, msctls_trackbar32
VM_LvUD(1)
else
Send, {Up}
return
Down::
ControlGetFocus, ACtrl
IfInString, ACtrl, msctls_trackbar32
VM_LvUD(0)
else
Send, {Down}
return
PGUP::VM_LvUD(1, 20)
PGDN::VM_LvUD(0, 20)
Home::VM_LvUD(1, 100)
End::VM_LvUD(0, 100)
Right::VM_FocusMove(1)
Left::VM_FocusMove(0)
Space::
ControlGetFocus, ACtrl
IfInString, ACtrl, msctls_trackbar32
VM_Mute()
else
Send, {Space}
return
VM_DevChange(DevNum) {
SetKeyDelay, -1, 1
DevVolNN := VM_GetDevTrkNN()
DevNN := DevVolNN * 2 - 1
ControlFocus, ToolbarWindow32%DevNN%
ControlSend, ToolbarWindow32%DevNN%, {Space}{Down %DevNum%}{Enter}
Sleep, 300
VM_FocusMove(-1)
}
VM_LvUD(Direct = 1, MP = 1) {
DevVolCNN := "msctls_trackbar32" VM_GetDevTrkNN()
ControlGetFocus, AVolCNN
if AVolCNN {
IfNotInString, AVolCNN, msctls_trackbar32
return
} else
AVolCNN := DevVolCNN
SendMessage, 0x400, , , %AVolCNN% ; TBM_GETPOS
AVolNum := ErrorLevel
if (AVolCNN != DevVolCNN) {
SendMessage, 0x400, , , %DevVolCNN% ; TBM_GETPOS
DevVolNum := ErrorLevel
} else
DevVolNum := 0
if Direct {
if (AVolNum - MP > DevVolNum)
VM_SetLv(AVolCNN, AVolNum - MP)
else ; DevVolより音量が大きくなる場合
VM_SetLv(AVolCNN, DevVolNum)
} else {
VM_SetLv(AVolCNN, AVolNum + MP)
}
VM_LvView(AVolCNN, DevVolCNN)
}
VM_SetLv(AVolCNN, VolNum) {
ControlGet, AVolHwnd, Hwnd, , %AVolCNN%
SendMessage, 0x405, 0x1, %VolNum%, %AVolCNN% ; TBM_SETPOS
ParCNN := "#32770" RegExReplace(AVolCNN, "^msctls_trackbar32(\d+)$", "$1")
ControlGet, ParHwnd, Hwnd, , %ParCNN%
if ParHwnd
SendMessage, 0x115, 0x4,%AVolHwnd%, , ahk_id %ParHwnd% ; WM_VSCROLL
else
SendMessage, 0x115, 0x4,%AVolHwnd% ; WM_VSCROLL
}
VM_Mute() {
DevVolNN := VM_GetDevTrkNN()
ControlGetFocus, AVolCNN
if !AVolCNN
AVolCNN := "msctls_trackbar32" DevVolNN
if !RegExMatch(AVolCNN, "^msctls_trackbar32(\d+)$", $)
return
else if ($1 == DevVolNN)
MuteCNN := "ToolbarWindow32" $1 * 2 + 1
else
MuteCNN := "ToolbarWindow32" $1 * 2
ControlClick, %MuteCNN%, , , , , NA
}
VM_FocusMove(Direct = 1) {
DevVolNN := VM_GetDevTrkNN()
ControlGetFocus, AVolCNN
if (-1 == Direct) || !RegExMatch(AVolCNN, "^(msctls_trackbar32|ToolbarWindow32)(\d+)$", $) {
ControlFocus, msctls_trackbar32%DevVolNN%
VM_LvView("msctls_trackbar32" DevVolNN, "msctls_trackbar32" DevVolNN)
return
} else if ("msctls_trackbar32" == $1) {
AVolNN := $2
} else if !Mod($2, 2) {
AVolNN := $2 // 2
} else {
if ($2 > DevVolNN * 2)
AVolNN := $2 // 2
else
AVolNN := $2 // 2 + 1
}
VolList := VM_GetTrkNNList(DevVolNN)
if Direct {
if RegExMatch(VolList, AVolNN "`n(\d+)", $)
if RegExMatch(VolList, "(?:^|`n)" AVolNN "`n(\d+)", $)
TrgVolNN := $1
else
TrgVolNN := DevVolNN
} else {
RegExMatch(VolList, "(\d+)(?:\n" AVolNN "|$)", $)
TrgVolNN := $1
}
ControlFocus, msctls_trackbar32%TrgVolNN%
VM_LvView("msctls_trackbar32" TrgVolNN, "msctls_trackbar32" DevVolNN)
}
VM_GetDevTrkNN() {
WinGet, CList, ControlList, 音量ミキサー ahk_class #32770
Sort, CList, P18 R
Sort, CList, N P18 R
Loop, Parse, CList, `n
return SubStr(A_LoopField, 18)
}
VM_GetTrkNNList(DevVolNN) {
static BefPosXList, Result
Loop, %DevVolNN% {
ControlGetPos, CX, , , , msctls_trackbar32%A_Index%
PosXList .= CX "`n"
}
if (BefPosXList == PosXList)
return Result
BefPosXList := PosXList
Result := ""
Loop, %DevVolNN%
Result .= A_Index "`n"
Sort, Result, F VM_TrkPosXComp
StringTrimRight, Result, Result, 1
return Result
}
VM_TrkPosXComp(NN1, NN2) {
ControlGetPos, CX1, , , , msctls_trackbar32%NN1%
ControlGetPos, CX2, , , , msctls_trackbar32%NN2%
if (CX1 > CX2)
return 1
else if (CX1 < CX2)
return -1
else
return 0
}
VM_LvView(AVolCNN, DevVolCNN) {
SendMessage 0x400, , , %AVolCNN% ; TBM_GETPOS
AVolNum := ErrorLevel
AVolLv := 100 - AVolNum
SendMessage 0x400, , , %DevVolCNN% ; TBM_GETPOS
DevVolLv := 100 - ErrorLevel
WinGetTitle, AWTitle
TitleBuf := RegExReplace(AWTitle, "(.*?) Vol:[\d/ ]+?$", "$1") " Vol:" DevVolLv
LoopCnt := RegExReplace(DevVolCNN, "^msctls_trackbar32(\d+)$", "$1") - 1
Loop, %LoopCnt% {
SendMessage, 0x400, , , msctls_trackbar32%A_Index% ; TBM_GETPOS
TitleBuf .= " / " 100 - ErrorLevel
}
WinSetTitle, %TitleBuf%
IfWinActive, 音量ミキサー ahk_class #32770
{
ControlGetPos, CX, CY, , CH, %AVolCNN%
TY := CY + (CH - 24) / 100 * AVolNum - 24
ToolTip, Vol:%AVolLv% / %DevVolLv%, %CX%, %TY%, 10 ; ToolTip番号は適当に
SetTimer, VM_LvCheck, 100
} else {
ToolTip, Vol:%AVolLv% / %DevVolLv%, , , 10 ; ToolTip番号は適当に
SetTimer, VM_LvCheck, 3000
}
}
VM_LvCheck:
IfWinNotActive, 音量ミキサー ahk_class #32770
{
ToolTip, , , , 10 ; ToolTip番号は適当に
IfWinNotExist, 音量ミキサー ahk_class #32770
SetTimer, VM_LvCheck, Off
}
return
デバイス変更は力技。
Vol.キーで音量変更した場合、音量ミキサー非表示でもツールチップを表示しようと思ったのだが、音量ミキサーの目盛りと実際の音量が一定でなかったので断念。