PDA

Показать полную графическую версию : Проблема с активацией микшера Windows


Сергей Красиков
05-04-2020, 12:22
Добрый день, помогите дописать код будильника.
В скрипте реализован запуск аудиофайла с последовательной регулировкой в цикле громкости системы через 50 сек. (сброс до нуля) и через следующие 10 сек. (увеличение). И так до завершения воспроизведения трека. Появилась необходимость прописать сброс контекстных меню, которые я сам вызываю ПКМ, когда он (этот чёртов будильник) будит меня ( :) ), т.к. при их наличии микшер активируется, но громкость не регулируется.
Что найдено на данный момент. Решено пойти по пути сброса всех окон или выполнить нажатие ЛКМ, таким образом убрать вызванное меню. Насколько я понял, язык VBS сам не умеет эмулировать клик по кнопкам мыши, поэтому было найдено решение применить приложение Excel через объект и использовать его в попытке переместить курсор в нужное место и там кликнуть по ЛКМ, тем самым решить проблему. Но вот беда, в первой части повторения в цикле микшер успешно понижает громкость, а после эмуляции клика, микшер вызывается, но не активируется.

Вот проблемный кусок кода (полный скрипт прикреплю в файле):
Set obj_sh = CreateObject("WScript.Shell")
pause = 100
wmp_vol = 70
WScript.Sleep pause
With obj_sh
For iter_cycl = 1 to 1
WScript.Sleep 5000
Set volmix = .Exec("%SystemRoot%\System32\SndVol.exe")
.AppActivate "Volume Mixer"
WScript.Sleep pause
For vol_cycl = 1 to iter_cycl + 1
.SendKeys "{PGDN}"
Next
WScript.Sleep pause
volmix.Terminate
Set volmix = Nothing
WScript.Sleep 1000
'------------------------
Set object = CreateObject("shell.application")
object.MinimizeAll
Set object = Nothing
On Error Resume Next
Set excel = WScript.CreateObject("Excel.Application")
x = "0"
y = "0"
excel.ExecuteExcel4Macro ("CALL(""user32"",""SetCursorPos"",""JJJ""," & x & "," & y & ")")
excel.ExecuteExcel4Macro ("CALL(""User32"",""mouse_event"",""JJJJJJ""," & "2" & ")")
WScript.Sleep pause
excel.ExecuteExcel4Macro ("CALL(""User32"",""mouse_event"",""JJJJJJ""," & "4" & ")")
WScript.Sleep pause
Set excel = Nothing
On Error GoTo 0
'--------------------------
Set volmix = .Exec("%SystemRoot%\System32\SndVol.exe")
.AppActivate "Volume Mixer"
WScript.Sleep pause
For vol_cycl = 1 to iter_cycl + 1
.SendKeys "{PGUP}"
Next
WScript.Sleep pause
volmix.Terminate
Set volmix = Nothing
Next
End With
Set obj_sh = Nothing

А может имеется более лаконичное решение? Спасибо.

iglezz
05-04-2020, 13:18
Для изменения громкости можно эмулировать нажатия мультимедийных клавиш:
' Увеличить громкость:
obj_sh.SendKeys(chr(&hAF))

' Уменьшить громкость:
obj_sh.SendKeys(chr(&hAE))
Можно использовать команды setsysvolume (https://www.nirsoft.net/utils/nircmd2.html#setsysvolume) и changesysvolume (http://www.nirsoft.net/utils/nircmd2.html#changesysvolume) утилиты nircmd (https://www.nirsoft.net/utils/nircmd.html) через метод Run.

Iska
05-04-2020, 16:26
Сергей Красиков, не тот язык выбрали.

Например, на AutoIt:
#include <Sound.au3>

AutoItSetOption("MustDeclareVars", 1)

Local $sFileName = @ScriptDir & "\Default.mp3"
Local $aSound = _SoundOpen($sFileName)
Local $i

If @error = 2 Then
MsgBox($MB_SYSTEMMODAL, "Error", "The file does not exist")
Exit(1)
ElseIf @extended <> 0 Then
Local $iExtended = @extended ; Assign because @extended will be set after DllStructCreate().
Local $tText = DllStructCreate("char[128]")
DllCall("winmm.dll", "short", "mciGetErrorStringA", "str", $iExtended, "struct*", $tText, "int", 128)
MsgBox($MB_SYSTEMMODAL, "Error", "The open failed." & @CRLF & "Error Number: " & $iExtended & @CRLF & "Error Description: " & DllStructGetData($tText, 1) & @CRLF & "Please Note: The sound may still play correctly.")
Exit(2)
EndIf

Local $iSoundLength = _SoundLength($aSound, 2)
Local $iPercent

SoundSetWaveVolume(5)
_SoundPlay($aSound)
ProgressOn($sFileName, "Volume level: ", "Current playing position: 0%", -1, -1, 16)

While 1
For $i = 5 To 100
SoundSetWaveVolume($i)
$iPercent = Round(_SoundPos($aSound, 2) / $iSoundLength * 100, 1)
ProgressSet($iPercent, "Current playing position: " & $iPercent & "%", "Volume level: " & $i & "%")
Sleep(100)

If _SoundPos($aSound, 2) >= $iSoundLength Then
ExitLoop 2
EndIf
Next

For $i = 100 To 5 Step -1
SoundSetWaveVolume($i)
$iPercent = Round(_SoundPos($aSound, 2) / $iSoundLength * 100, 1)
ProgressSet($iPercent, "Current playing position: " & $iPercent & "%", "Volume level: " & $i & "%")
Sleep(100)

If _SoundPos($aSound, 2) >= $iSoundLength Then
ExitLoop 2
EndIf
Next

WEnd

ProgressSet(100, "Current playing position: 100%", "Volume level: 100%")

SoundSetWaveVolume(100)
_SoundStop($aSound)
_SoundClose($aSound)

ProgressOff()

Exit(0)

Сергей Красиков
05-04-2020, 17:49
Iska, я относительно неплохо знаком с VBA, поэтому VBS освоить легче. Сейчас огромными глазами смотрю на приведённый вами пример, как когда-то на Бейсик. Не, в другой раз.
iglezz, Спасибо. То, что надо!
Set obj_sh = CreateObject("WScript.Shell")

pause = 200

With obj_sh

i = 0
While i < 51
'Уменьшить громкость:
.SendKeys(chr(&hAE))
i = i + 1
Wend

WScript.Sleep pause * 5

i = 0
While i < 10
'Увеличить громкость:
.SendKeys(chr(&hAF))
i = i + 1
Wend

End With

Set obj_sh = Nothing


Таким образом удастся избавиться от сторонних приложений, чего не хотелось делать и с nircmd.

Друзья, спасибо за ответы!

Iska
05-04-2020, 18:04
Сергей Красиков, а там разницы не особо. Между VBA/WSH и AutoIt.

iglezz
05-04-2020, 18:09
Сергей Красиков,
Autoit - бейсико-подобный язык, переехать на него с VBS несложно. И для целей мелкого бытового скриптинга подходит в целом лучше - в комплекте GUI, тонна пользовательских функций, адекватная справка с примерами.




© OSzone.net 2001-2012