Visual Basic em Português

Página pessoal de Jorge Paulino sobre o Visual Basic (VB.NET, ASP.NET, VB6, VBA) e algumas noticias de tecnologia

VB.NET: Criando HotKeys (teclas de atalho)

Em diversos programas é usual existirem combinações de teclas que executam determinadas tarefas. Estas combinações, normalmente designadas por HotKeys, simplificam a utilização da aplicação. Por exemplo, a combinação CTRL+A abre o Form A, Shift+B imprimir o relatório B, etc. Esta funcionalidade é bastante prática e simples de implementar mas apenas funciona quando o Form está seleccionado (com focus).


Para criar uma ou mais HotKeys que funcionem mesmo sem a aplicação estar seleccionada, utilizasse a função RegisterHotKey(). Deste modo é possível detectar e manipular sempre que uma tecla ou uma combinação de teclas é executada.

Existem combinações que podem ser sobrepostas (por exemplo CTRL+C, ALT+TAB, etc) e por isso é preciso bastante cuidado ao utilizar este código. A má ou incorrecta utilização pode prejudicar o correcto funcionamento do sistema operativo. O objectivo não é desabilitar combinações de teclas mas sim criar combinações ou atalhos que permitam, por exemplo, abrir uma aplicação que está escondida ou que se encontra no "system tray".

O seguinte exemplo mostra como criar algumas HotKeys. Algumas servem apenas para mostrar as implicações caso exista uma má utilização. No final é necessário fazer o processo inverso, ou seja, remover a HotKey do registo, utilizando a função UnregisterHotKey().

   

    ' Cria uma nova lista que guarda os ID's registados
    Private RegistedIDs As New List(Of Integer)

    ' Declara um evento que irá indicar o número do ID registado
    Public Event HotkeyPressedID(ByVal ID As Integer)

    Public Enum HotKeyModifiers
        None = 0
        Alt = 1
        Control = 2
        Shift = 4
        Windows = 8
    End Enum

    ' API's para registar e remover o registo das hotkeys
    Private Declare Function RegisterHotKey Lib "user32" (ByVal handle As IntPtr, ByVal ID As Integer, ByVal fsModifiers As Integer, ByVal vk As Integer) As Boolean
    Private Declare Function UnregisterHotKey Lib "user32" (ByVal handle As IntPtr, ByVal ID As Integer) As Boolean


   
''' <summary>
    ''' Regista (ou tenta) um HotKey usando a respectiva API
    ''' </summary>
    ''' <param name="ID">Número único do registo</param>
    ''' <param name="Modifiers">Indicação do modifier</param>
    ''' <param name="KeyCombo">Indicação da tecla</param>
    Public Function RegisterHotKey(ByVal ID As Integer, ByVal Modifiers As HotKeyModifiers, ByVal KeyCombo As Integer) As Boolean

        ' Caso consiga registar a hotkey
        If RegisterHotKey(Me.Handle, ID, Modifiers, KeyCombo) Then   

            ' Adiciona à lista dos ID's registados
            RegistedIDs.Add(ID)
            Return True
        End If

    End Function

    ''' <summary>
    ''' Subrotina que executa uma acção de acordo com a combinação efectuada
    ''' </summary>
    ''' <param name="ID">Número do ID registado</param>
    Private Sub RegisterHotKeyExample_HotkeyPressedID(ByVal ID As Integer) Handles Me.HotkeyPressedID

        Select Case ID
            Case 0
                Me.TextBox1.AppendText(Now & " - Ctrl+Shift+F" & vbNewLine)
            Case 1
                Me.TextBox1.AppendText(Now & " - Windows+T" & vbNewLine)
            Case 2
                Me.TextBox1.AppendText(Now & " - Alt+Tab bloqueado" & vbNewLine)
            Case 3
                Me.TextBox1.AppendText(Now & " - Letra ‘a’ bloqueada" & vbNewLine)
            Case 4
                Me.TextBox1.AppendText(Now & " - Letra ‘b’ bloqueada" & vbNewLine)
        End Select

    End Sub

    ' Overrides ao WndProc e detecção se a combinação foi efectuada
    Protected Overrides Sub WndProc(ByRef m As System.Windows.Forms.Message)
        Const WM_HOTKEY As Integer = &H312

        ' Caso seja uma HotKey
        If m.Msg = WM_HOTKEY Then
            RaiseEvent HotkeyPressedID(m.WParam.ToInt32)
        End If   

        MyBase.WndProc(m)

    End Sub

   

    Private Sub RegisterHotKeyExample_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load

        ' No evento Form Load são registadas algumas teclas. Os ID's 2,3 e 4 servem
        ' apenas para mostrar que é preciso ter algum cuidado a utilizar este código  

        ' Ctrl-Shift-F
        RegisterHotKey(0, HotKeyModifiers.Control Or HotKeyModifiers.Shift, Keys.F)

        ' Windows+T
        RegisterHotKey(1, HotKeyModifiers.Windows, Keys.T)

        ' Alt+Tab (que irá apenas desabilitar esta combinação)
        RegisterHotKey(2, HotKeyModifiers.Alt, Keys.Tab)

        ' Desabilita as teclas ‘a’ e ‘b’
        RegisterHotKey(3, HotKeyModifiers.None, Keys.A)
        RegisterHotKey(4, HotKeyModifiers.None, Keys.B)

    End Sub


   
' MUITO IMPORTANTE: Garantir sempre que as teclas saem do registo, caso
    ' contrário o sistema operativo pode não funcionar correctamente
    Private Sub RegisterHotKeyExample_FormClosing(ByVal sender As Object, ByVal e As System.Windows.Forms.FormClosingEventArgs) Handles Me.FormClosing

        ' Ciclo nos ID's registados
        For Each ID As Integer In RegistedIDs
            UnregisterHotKey(Me.Handle, ID)
        Next

    End Sub


Cada número da HotKey tem de ser único e a combinação de teclas não pode estar a ser utilizada por outra thread. Caso aconteça o resultado do registo é falso e a combinação não é registada.

   

Este exemplo mostra numa caixa de texto a informação da HotKey pressionada, mas é apenas ilustrativo. Existem diversas combinações que podem ser utilizadas que podem melhorar a funcionalidade da aplicação.   

Exemplo do artigo: DOWNLOAD DO FICHEIRO

   

PS: Como sempre, qualquer dúvida, comentário ou correcção ao artigo é sempre bem vinda!

14 comentários:

Nazgulled disse...

Penso que não haja grande necessidade de usar a API do Windows, complicando assim a coisa.

Usando o ProcessCmdKey pode-se fazer hotkeys muito facilmente. O único contra é que são hotkeys locais (ao programa) e não globais no sistema.

Mas isso já vai das intenções de cada um.

jpaulino disse...

Olá Nazgulled,

Em primeiro lugar obrigado pela visita ao meu blog.

O problema é mesmo esse ... podes criar teclas locais mas se quiseres criar uma tecla que funcione em qualquer lugar, ou seja, sem que aplicação tenha focus ? E se quiseres alterar o funcionamento de teclas de sistema (por exemplo o CTRL+C, CTRL+V) ? Tens de usar API’s!

Este é um dos métodos mas existem outros (semelhantes) mas todos com recurso a API’s.

celio cantalice disse...

CAra parabens pelo bolg é show de boloa! Embora desenvolvida pela gigante Microsoft, encontrar literatura gratuita na web é muito dificil e nem todo mundo tem 250 pau pra darem livros!!! parabens!!!

Jorge disse...

Olá Celio Cantalice,

Obrigado pela visita e fico satisfeito que o blog seja do seu interesse!

Um abraço,
Jorge Paulino

Bruno disse...

Gostava de saber como fazer uma combinacao de 2 teclas para atalho mas num projecto criado por mim. dentro de uma form, clicando em Ctrl+L acontessa algo. com uma tecla consigo mas cpm 2 já nao..

Se algume me podesse ajudar agradecia.

Obrigado

jpaulino disse...

Olá Bruno,

Dentro do form é mais simples e basta utilizar algo do género:

Private Sub Form1_KeyDown(ByVal sender As Object, ByVal e As System.Windows.Forms.KeyEventArgs) Handles Me.KeyDown
If e.Control AndAlso e.KeyCode = Keys.L Then
MessageBox.Show("Teste")
End If
End Sub

Não esquecer de colocar a propriedade do form KeyPreview = True.

Bruno disse...

Olá jpaulino

Muito obrigado funciona na perfeição. Nao conhecia " AndAlso ".

Quero pedir desculpa mas não pude vir aqui mais cedo.

Quero tambem deixar a mensagem de que este Blog já me ajudou por diversas vezes e gostaria que fosse actualizado mais vezes. Mas compreendo que nem sempre seja possivel.

Obrigado

Anónimo disse...

Galera,

Preciso bloquear a combinação CTRL + "a". sem perder a funçao do CTRL + ALT + DEl e outras do CTRL.

Pois tenho um aplicativo que utiliza a combinação CTRL + 'a' e estão burlando o sistema.

Agradeço a ajuda!!!

Thiago disse...

Olá, o codigo fonte nao está funcionando no windows 7 porque? o meu é o windows 7 64bits ultimate

Thiago disse...

N verdde eu no estou conseguindo loquer o ALT+TB

Jorge Paulino disse...

Algumas combinações não funcionam desta forma. Existem outras soluções que se podem tentar.

Exempli: http://www.dreamincode.net/forums/topic/56460-disable-ctrl-alt-del-altf4-and-alt-tab/

Thiago disse...

Meu unico problema está em Bloquear o ALT+TAB O resto está perfeito.

Anónimo disse...

Queria saber como bloquear as teclas ALT+TAB e o ALT+ESC.. Isso está estragando meu sistema de geranciamento de lan. Então, quem puder, envie email para pesquisas.onlyne@gmail.com dizendo EXATAMENTE o que fazer pra bloquear essas teclas agradeço. Não sei usar programações e etc, por isso peço ajuda pra fazer isso EXATAMENTE no windows 7 (mas acho que se souberem em qualquer windows, já vai se de rande ajuda). Mandem no título BLOQUEIO DE TECLAS ALT+TAB. Não mandem links ou afins, pois nã ovai me ajudar em nada pq não vou clicar. Por favor, quem puder ajudar nisso agradeço. ISSO É URGENTE!!

Jorge Paulino disse...

Olá,

Coloque a questão no fórum da comunidade, onde sou moderador, Portugal-a-Programar.

Certamente terá uma resposta ;)

Cumprimentos,
Jorge Paulino

Mensagens Recentes



Microsoft Office Especialist

Membro da Comunidade
Experts-Exchange


Administ. da Comunidade
Portugal-a-Programar



Twitter

Artigos no CodeProject

Artigos no CodeProject

Subscrever Novidades

Endereço de Email:

Delivered by FeedBurner

Seguidores

Histórico