mwsundberg
mwsundberg

Reputation: 320

How to trigger the Windows volume display?

When the standard keyboard key to increase the volume is hit on windows, a small window appears in the upper left displaying the volume and possibly information about playing media. I am looking for a way to trigger the window without changing the volume status, preferably in an easy to integrate way with Autohotkey.

Upvotes: 8

Views: 2859

Answers (5)

no body
no body

Reputation: 1

i make a tool for display volume when i change volume with ahk command "SoundSet, -1" and "SoundSet, +1"

wish this can help.

https://github.com/uqiu/showVolume/tree/main/WpfApp1/bin/Debug/net6.0-windows

download all file in this folder, run WpfApp1.exe

it looks like this when you change volume

image

Upvotes: 0

sharp-spark
sharp-spark

Reputation: 57

Building on Anna Wang's answer (https://stackoverflow.com/a/62012058/3251466).

This will restore the volume even when it was at an odd value.

^PgDn:: ;Ctrl+Page Down
  SoundGet, original_volume
  SendInput {Volume_Down}  
  SoundSet, original_volume
return

Upvotes: 0

mwsundberg
mwsundberg

Reputation: 320

The desired behavior when used with volume control keys can be gotten by storing the current volume, sending a media key press, then updating the volume to the stored value +/- 1 (or +0, if just seeking to display the OSD).

There is an edge case when mimicking Volume_Down when the volume is <=3. The sent Volume_Down keypress triggers the mute, but this can be accommodated for by manually setting the mute to be off afterwards, or by pre-setting the volume to 4, which prevents the rounding to 0. Which method to choose depends upon if you prefer a brief blip of potentially louder sound (pre-set to 4) or a brief mute (disable mute afterwards) when the volume is lowered from <=3 values.

The following code is in AHK v2.

; Prefix with '$' so as to prevent self triggering, since internally sending Volume_Up
$Volume_Up::{
    ; Get the current volume. SoundGetVolume returns a float which often needs rounding
    volume:=Round(SoundGetVolume())
    ; Send the Volume_Up key, so the media display is triggered
    Send "{Volume_Up}"
    ; Indiscriminately set the volume manually to volume+1
    SoundSetVolume(volume+1)
}

; Much the same as above, yet when sending Volume_Down at volumes <=3 the volume
;   is rounded down to 0 which triggers mute. The volume is then set properly,
;   yet remains muted. In order to not hear a cut in the audio, you need to set
;   the volume to 4 when (1<volume<=3) so that the Volume_Down doesn't round it
;   down to 0, or disable the mute afterwards (if volume > 1). This causes a
;   brief volume spike or mute blip, respectively. Currently the volume spike option
;   is uncommented.
$Volume_Down::{
    volume:=Round(SoundGetVolume())

    ; Bumping the volume before sending the Volume_Down to prevent mute blip (if needed)
    if(1 < volume and volume <= 3){
        SoundSetVolume(4)
    }

    Send "{Volume_Down}"
    SoundSetVolume(volume-1)

    ; ; Disable accidental triggering of mute when volume >= 3 after sending Volume_Down
    ; if(volume > 1) {
    ;   SoundSetMute(0)
    ; }
}

To just trigger the OSD as the question asks the following works. Hitting a volume key then quickly resetting the volume will displays it, yet considerations need to be made if currently muted as to prevent a blip of sound. Volume keys are used since double toggling Volume_Mute causes a gap in the sound output.

; Trigger the on screen display of the volume bar by hitting Volume_Up and
;   then quickly resetting the volume. If muted and send Volume_Up, we will
;   hear audio at original volume for a brief second. To prevent this, we
;   can set the volume to 0 and send Volume_Down instead.
^PgUp::{
    volume:=Round(SoundGetVolume())
    muted:=SoundGetMute()

    ; Trigger the display with a volume key (might briefly bump the volume if unmuted)
    if (muted or volume == 0) {
        SoundSetVolume(0)
        Send "{Volume_Down}"
    } else {
        Send "{Volume_Up}"
    }

    ; Reset to the original volume and mute status
    SoundSetMute(muted)
    SoundSetVolume(volume)
}

All of the same code, yet uncommented:

$Volume_Up::{
    volume:=Round(SoundGetVolume())
    Send "{Volume_Up}"
    SoundSetVolume(volume+1)
}

$Volume_Down::{
    volume:=Round(SoundGetVolume())
    if(1 < volume and volume <= 3){
        SoundSetVolume(4)
    }
    Send "{Volume_Down}"
    SoundSetVolume(volume-1)
}

^PgUp::{
    volume:=Round(SoundGetVolume())
    muted:=SoundGetMute()
    if (muted or volume == 0) {
        SoundSetVolume(0)
        Send "{Volume_Down}"
    } else {
        Send "{Volume_Up}"
    }
    SoundSetMute(muted)
    SoundSetVolume(volume)
}

Upvotes: 1

Anna Wang
Anna Wang

Reputation: 19

I set up an autohotkey to send volume up, the volume down (For shortcut ctrl+pgdn).

^PgDn::
   Send {Volume_Up}
   Send {Volume_Down}
   return     

Upvotes: 1

Anders
Anders

Reputation: 101756

Windows 8 introduced the Media​Control class that lets Modern apps hook into the system playback control. In Windows 8.1 and 10 it was replaced by the System​Media​Transport​Controls class.

While it supports "Manual control of the System Media Transport Controls" there does not seem to be a way to show/hide the overlay and certainly not from a desktop app.

Going into undocumented territory I found the class name of the overlay and that lead me to HideVolumeOSD. Unfortunately the class names are rather generic so you probably have to look at the size of the window as well to determine if it is the volume overlay.

I don't know if just showing the window will work, Windows is not expecting it to be visible except in response to keyboard and playback events. The HideVolumeOSD app uses keybd_event (volume up/down) to trigger it but this is problematic as noted in the comments...

Upvotes: 4

Related Questions