windowswindows-10autohotkeyvolume

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.


Solution

  • 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)
    }