Search code examples
vb.netwinformstreeviewonkeydownbeep

Why does windows play a beep sound on KeyDown, but not on DoubleClick?


I hope this is going to be a real quick question: I have a TreeView on a Windows form.

I run this code to open directories, displayed in a tree view:

Private Sub OpenFolder()
    Try
        System.Diagnostics.Process.Start(SelectedDir)
    Catch ex As Exception
        MessageBox.Show("Mappen " & SelectedDir & " kan ikke åbnes!")
    End Try
End Sub

When I call OpenFolder() from the KeyDown event:

Private Sub TreeViewDir_KeyDown(sender As Object, e As KeyEventArgs) Handles TreeViewDir.KeyDown
    If e.KeyCode = Keys.Enter Then
        OpenFolder()
        e.SuppressKeyPress = True
    ElseIf e.KeyCode = Keys.Delete Then
        DeleteFolder()
        e.SuppressKeyPress = True
    End If
End Sub

..I get a windows error sound. But no error message. What is driving me up the walls, is that this sub fires the function without any problems at all.

Private Sub TreeViewDir_DoubleClick(sender As Object, e As EventArgs) Handles TreeViewDir.DoubleClick
    OpenFolder()
End Sub

The error sound plays when the folder opens, but again, only on KeyDown. Can someone tell me why this happens only on the KeyDown event and what I'm doing wrong here?


Solution

  • First, let me point out that your OpenFolder() method isn't responsible for that beep sound, the KeyPress event is. This is a standard behavior of Windows when a key is pressed where it has no job to do.

    Now, setting SuppressKeyPress to true, should, in fact, prevent the KeyPress event from firing and therefore, no beep sound should be played. However, in some cases when you execute some code in the KeyDown event, it takes time for the keystroke to be suppressed and therefore causing the beep sound.

    To get around this, you can simply subscribe to the KeyPress event and set e.Handled to true:

    Private Sub TreeViewDir_KeyPress(sender As Object, e As KeyPressEventArgs) Handles TreeViewDir.KeyPress
        If e.KeyChar = ChrW(Keys.Enter) Then e.Handled = True
    End Sub
    

    Another solution, if you don't want to use KeyDown, is to allow some time for the keystroke to be suppressed, by delaying the execution of your method:

    Private Async Sub TreeViewDir_KeyDown(sender As Object, e As KeyEventArgs) Handles TreeViewDir.KeyDown
        '   ^^^^^ ⟸ Don't forget the Async keyword.
    
        If e.KeyCode = Keys.Enter Then
            e.SuppressKeyPress = True   ' This is first
            Await Task.Delay(100)       ' Followed by a small delay
            OpenFolder()                ' Then call the method.
        End If
    End Sub