Compartilhar via


Tabelas de aceleradores

Os aplicativos geralmente definem atalhos de teclado, como CTRL+O para o comando Abrir Arquivo. Você pode implementar atalhos de teclado manipulando mensagens WM_KEYDOWN individuais, mas as tabelas de aceleradores fornecem uma solução melhor que:

  • Requer menos codificação.
  • Consolida todos os atalhos em um arquivo de dados.
  • Dá suporte à localização em outros idiomas.
  • Permite que atalhos e comandos de menu usem a mesma lógica de aplicativo.

Uma tabela aceleradora é um recurso de dados que mapeia combinações de teclado, como CTRL+O, para comandos de aplicativo. Antes de vermos como usar uma tabela de aceleradores, precisaremos de uma introdução rápida aos recursos. Um recurso é um blob de dados integrado a um binário de aplicativo (EXE ou DLL). Os recursos armazenam dados necessários para o aplicativo, como menus, cursores, ícones, imagens, cadeias de caracteres de texto ou dados de aplicativo personalizados. O aplicativo carrega os dados do recurso do binário em tempo de execução. Para incluir recursos em um binário, faça o seguinte:

  1. Crie um arquivo de definição de recurso (.rc). Esse arquivo define os tipos de recursos e seus identificadores. O arquivo de definição de recurso pode incluir referências a outros arquivos. Por exemplo, um recurso de ícone é declarado no arquivo .rc, mas a imagem de ícone é armazenada em um arquivo separado.
  2. Use o RC (Compilador de Recursos do Microsoft Windows) para compilar o arquivo de definição de recurso em um arquivo de recurso compilado (.res). O compilador RC é fornecido com o Visual Studio e também o SDK do Windows.
  3. Vincule o arquivo de recurso compilado ao arquivo binário.

Essas etapas são aproximadamente equivalentes ao processo de compilação/link para arquivos de código. O Visual Studio fornece um conjunto de editores de recursos que facilitam a criação e a modificação de recursos. (Essas ferramentas não estão disponíveis nas edições Express do Visual Studio.) Mas um arquivo .rc é simplesmente um arquivo de texto e a sintaxe está documentada no MSDN, portanto, é possível criar um arquivo .rc usando qualquer editor de texto. Para obter mais informações, consulte Sobre arquivos de recurso.

Definindo uma tabela aceleradora

Uma tabela de aceleradores é uma tabela de atalhos de teclado. Cada atalho é definido por:

  • Um identificador numérico. Esse número identifica o comando do aplicativo que será invocado pelo atalho.
  • O caractere ASCII ou o código de chave virtual do atalho.
  • Teclas modificadoras opcionais: ALT, SHIFT ou CTRL.

A tabela de aceleradores em si tem um identificador numérico, que identifica a tabela na lista de recursos do aplicativo. Vamos criar uma tabela de aceleradores para um programa de desenho simples. Este programa terá dois modos, modo de desenho e modo de seleção. No modo de desenho, o usuário pode desenhar formas. No modo de seleção, o usuário pode selecionar formas. Para este programa, gostaríamos de definir os seguintes atalhos de teclado.

Atalho Comando
CTRL+M Alternar entre modos.
F1 Alterne para o modo de desenho.
F2 Alterne para o modo de seleção.

 

Primeiro, defina identificadores numéricos para a tabela e para os comandos do aplicativo. Esses valores são arbitrários. Você pode atribuir constantes simbólicas para os identificadores definindo-as em um arquivo de cabeçalho. Por exemplo:

#define IDR_ACCEL1                      101
#define ID_TOGGLE_MODE                40002
#define ID_DRAW_MODE                  40003
#define ID_SELECT_MODE                40004

Neste exemplo, o valor IDR_ACCEL1 identifica a tabela de aceleradores e as próximas três constantes definem os comandos do aplicativo. Por convenção, um arquivo de cabeçalho que define constantes de recurso geralmente é nomeado resource.h. A próxima listagem mostra o arquivo de definição de recurso.

#include "resource.h"

IDR_ACCEL1 ACCELERATORS
{
    0x4D,   ID_TOGGLE_MODE, VIRTKEY, CONTROL    // ctrl-M
    0x70,   ID_DRAW_MODE, VIRTKEY               // F1
    0x71,   ID_SELECT_MODE, VIRTKEY             // F2
}

Os atalhos do acelerador são definidos dentro das chaves. Cada atalho contém as entradas a seguir.

  • O código de chave virtual ou caractere ASCII que invoca o atalho.
  • O comando do aplicativo. Observe que constantes simbólicas são usadas no exemplo. O arquivo de definição de recurso inclui resource.h, em que essas constantes são definidas.
  • O palavra-chave VIRTKEY significa que a primeira entrada é um código de chave virtual. A outra opção é usar caracteres ASCII.
  • Modificadores opcionais: ALT, CONTROL ou SHIFT.

Se você usar caracteres ASCII para atalhos, um caractere minúsculo será um atalho diferente de um caractere maiúsculo. (Por exemplo, digitar 'a' pode invocar um comando diferente de digitar 'A'.) Isso pode confundir os usuários, portanto, geralmente é melhor usar códigos de chave virtual, em vez de caracteres ASCII, para atalhos.

Carregando a tabela aceleradora

O recurso para a tabela de aceleradores deve ser carregado antes que o programa possa usá-lo. Para carregar uma tabela de aceleradores, chame a função LoadAccelerators .

    HACCEL hAccel = LoadAccelerators(hInstance, MAKEINTRESOURCE(IDR_ACCEL1));

Chame essa função antes de inserir o loop de mensagem. O primeiro parâmetro é o identificador do módulo. (Esse parâmetro é passado para sua função WinMain . Para obter detalhes, consulte WinMain: o ponto de entrada do aplicativo.) O segundo parâmetro é o identificador de recurso. A função retorna um identificador para o recurso. Lembre-se de que um identificador é um tipo opaco que se refere a um objeto gerenciado pelo sistema. Se a função falhar, ela retornará NULL.

Você pode liberar uma tabela de aceleradores chamando DestroyAcceleratorTable. No entanto, o sistema libera automaticamente a tabela quando o programa é encerrado, portanto, você só precisa chamar essa função se estiver substituindo uma tabela por outra. Há um exemplo interessante disso no tópico Criando aceleradores editáveis do usuário.

Traduzindo traços de teclas em comandos

Uma tabela de aceleradores funciona traduzindo traços de tecla em mensagens WM_COMMAND . O parâmetro wParam de WM_COMMAND contém o identificador numérico do comando. Por exemplo, usando a tabela mostrada anteriormente, o traço de tecla CTRL+M é convertido em uma mensagem WM_COMMAND com o valor ID_TOGGLE_MODE. Para fazer isso acontecer, altere o loop de mensagem para o seguinte:

    MSG msg;
    while (GetMessage(&msg, NULL, 0, 0))
    {
        if (!TranslateAccelerator(win.Window(), hAccel, &msg))
        {
            TranslateMessage(&msg);
            DispatchMessage(&msg);
        }
    }

Esse código adiciona uma chamada à função TranslateAccelerator dentro do loop de mensagem. A função TranslateAccelerator examina cada mensagem de janela, procurando mensagens de tecla para baixo. Se o usuário pressionar uma das combinações de teclas listadas na tabela de aceleradores, TranslateAccelerator enviará uma mensagem de WM_COMMAND para a janela. A função envia WM_COMMAND invocando diretamente o procedimento de janela. Quando TranslateAccelerator converte com êxito um traço de chave, a função retorna um valor diferente de zero, o que significa que você deve ignorar o processamento normal da mensagem. Caso contrário, TranslateAccelerator retornará zero. Nesse caso, passe a mensagem da janela para TranslateMessage e DispatchMessage, normalmente.

Veja como o programa de desenho pode lidar com a mensagem WM_COMMAND :

    case WM_COMMAND:
        switch (LOWORD(wParam))
        {
        case ID_DRAW_MODE:
            SetMode(DrawMode);
            break;

        case ID_SELECT_MODE:
            SetMode(SelectMode);
            break;

        case ID_TOGGLE_MODE:
            if (mode == DrawMode)
            {
                SetMode(SelectMode);
            }
            else
            {
                SetMode(DrawMode);
            }
            break;
        }
        return 0;

Esse código pressupõe que SetMode seja uma função definida pelo aplicativo para alternar entre os dois modos. Os detalhes de como você lidaria com cada comando obviamente dependem do seu programa.

Avançar

Definindo a imagem do cursor