Click here to Skip to main content
15,920,383 members
Please Sign up or sign in to vote.
1.00/5 (1 vote)
See more:
Hi.

I've created a volume control program that hides in the background and responds to the key-combo's "Ctrl + Up Arrow" and "Ctrl + Down Arrow". This is working great except I can't cancel the up and down keypresses (really messes with certain programs). Any ideas?

Here's my source code:
VB
Imports System
Imports System.Windows.Forms
Imports System.Runtime.InteropServices

Public Class Form1

    Private Const APPCOMMAND_VOLUME_MUTE As Integer = &H80000
    Private Const APPCOMMAND_VOLUME_UP As Integer = &HA0000
    Private Const APPCOMMAND_VOLUME_DOWN As Integer = &H90000
    Private Const WM_APPCOMMAND As Integer = &H319

    <DllImport("user32.dll")> Public Shared Function SendMessageW(ByVal hWnd As IntPtr, ByVal Msg As Integer, ByVal wParam As IntPtr, ByVal lParam As IntPtr) As IntPtr

    End Function

    'I'm leaving the Mute Sub in for future reference
    Private Sub Mute()
        SendMessageW(Me.Handle, WM_APPCOMMAND, Me.Handle, New IntPtr(APPCOMMAND_VOLUME_MUTE))
    End Sub

    Private Sub DecVol()
        SendMessageW(Me.Handle, WM_APPCOMMAND, Me.Handle, New IntPtr(APPCOMMAND_VOLUME_DOWN))
    End Sub

    Private Sub IncVol()
        SendMessageW(Me.Handle, WM_APPCOMMAND, Me.Handle, New IntPtr(APPCOMMAND_VOLUME_UP))
    End Sub

    Public Declare Function GetAsyncKeyState Lib "user32" (ByVal vKey As Integer) As Integer
    Dim WithEvents Tmr As New Timer
    Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
        Tmr.Interval = 100
        Tmr.Start()
    End Sub
    Private Sub Tmr_Tick(ByVal sender As Object, ByVal e As System.EventArgs) Handles Tmr.Tick
        Tmr.Stop()
        If CBool(GetAsyncKeyState(Keys.ControlKey)) And CBool(GetAsyncKeyState(Keys.Up)) Then
            IncVol()
        ElseIf CBool(GetAsyncKeyState(Keys.ControlKey)) And CBool(GetAsyncKeyState(Keys.Down)) Then

            DecVol()
        End If
        Tmr.Start()
    End Sub

    Private Sub ShowHide() Handles Me.Shown
        Me.Hide()
    End Sub

End Class
Posted
Updated 13-Feb-12 17:21pm
v2

To best of my knowledge, key up/down events (non-characters) cannot be cancelled. More exactly, none of key/down events can be cancelled by handling KeyDown or KeyUp, but key press can be cancelled by handling KeyPressed.

The P/Invoke function GetAsyncKeyState is not really needed. Instead, you can handle the above event and check Shift, Alt, or Control key status in the handler. I'm not sure about sound volume messages, but I think you can control sound volume without P/Invoked SendMessage.

You can use multimedia module "winmm.dll" directly, please see:
http://www.dreamincode.net/forums/topic/45693-controlling-sound-volume-in-c%23/[^],
http://www.geekpedia.com/tutorial176_Get-and-set-the-wave-sound-volume.html[^].

See also this article: http://www.codeguru.com/csharp/csharp/cs_graphics/sound/article.php/c10931[^].

The above method still needs using P/Invoke. This is not very good.

You can use ready-to-use Microsoft .NET class Microsoft.DirectX.AudioVideoPlayback to work in pure managed code. Please see:
http://msdn.microsoft.com/en-us/library/windows/desktop/bb324235%28v=vs.85%29.aspx[^].

—SA
 
Share this answer
 
Comments
Dave Kreskowiak 13-Feb-12 23:43pm    
He's calling this a keyboard hook, but that's not what the code is doing. His code is just peeking at the state of certain keys, not actually hooking into the keyboard messages. This design will never work the way he wants it to as is.
Casey Sheridan 14-Feb-12 10:12am    
I appreciate the help but I don't understand yet what exactly I should be changing. As far as the code not being good, I pieced together this code from a couple of other places so I'm not very good at understanding it. Code samples (preferably in vb.net) would be very helpful to me.
First, what you posted is not a keyboard hook. You're just peeking at the state of certain keys.

Second, what's with the Timer?? You may be calling this "key peek" code 10 times a second, but that's no guarantee you're going to see a key state change.

I'd tell you how to fix this, but it's not fixable. Seriously, this approach will never work. You have to scrap this and use a REAL keyboard hook. Only then will you gain the ability to "eat" the keystrokes so applications can't see them.

Start reading these[^].
 
Share this answer
 
Comments
Casey Sheridan 14-Feb-12 10:15am    
I guess I never really understood what a true hook is. Thanks for the note.

This content, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)



CodeProject, 20 Bay Street, 11th Floor Toronto, Ontario, Canada M5J 2N8 +1 (416) 849-8900