Partilhar via


Tabelas Aceleradoras

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 aceleração fornecem uma solução melhor que:

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

Um de tabela acelerador de é um recurso de dados que mapeia combinações de teclado, como CTRL+O, para comandos de aplicativo. Antes de vermos como usar uma tabela aceleradora, precisaremos de uma rápida introdução aos recursos. Um recurso é um blob de dados que é construído em um binário de aplicativo (EXE ou DLL). Os recursos armazenam dados necessários para o aplicativo, como menus, cursores, ícones, imagens, cadeias de texto ou quaisquer dados personalizados do aplicativo. 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). Este 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 do ícone é armazenada em um arquivo separado.
  2. Use o Microsoft Windows Resource Compiler (RC) 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. Visual Studio fornece um conjunto de editores de recursos que facilitam a criação e 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, então é possível criar um arquivo .rc usando qualquer editor de texto. Para obter mais informações, consulte Sobre arquivos de recursos.

Definindo uma tabela de aceleração

Uma tabela aceleradora é 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 própria tabela aceleradora tem um identificador numérico, que identifica a tabela na lista de recursos do aplicativo. Vamos criar uma tabela aceleradora 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 Alterne entre os modos.
F1 Mude para o modo de desenho.
F2 Mude para o modo de seleção.

 

Primeiro, defina identificadores numéricos para a tabela e para os comandos do aplicativo. Estes valores são arbitrários. Você pode atribuir constantes simbólicas para os identificadores definindo-os 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 do acelerador 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 é chamado 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 encaracoladas. Cada atalho contém as seguintes entradas.

  • O código de chave virtual ou caractere ASCII que invoca o atalho.
  • O comando application. Observe que constantes simbólicas são usadas no exemplo. O arquivo de definição de recurso inclui resource.h, onde essas constantes são definidas.
  • A 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, por isso geralmente é melhor usar códigos de chave virtual, em vez de caracteres ASCII, para atalhos.

Carregando a tabela do acelerador

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

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

Chame essa função antes de inserir o loop de mensagem. O primeiro parâmetro é o identificador para o módulo. (Este parâmetro é passado para o seu 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 aceleradora chamando DestroyAcceleratorTable. No entanto, o sistema libera automaticamente a tabela quando o programa é encerrado, então 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 pelo usuário.

Traduzindo pressionamentos de teclas em comandos

Uma tabela aceleradora funciona traduzindo pressionamentos de teclas 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 pressionamento de tecla CTRL+M é convertido em uma mensagem de WM_COMMAND com o valor ID_TOGGLE_MODE. Para que isso aconteça, altere o loop da 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 da janela, procurando mensagens com chave para baixo. Se o usuário pressionar uma das combinações de teclas listadas na tabela do acelerador, TranslateAccelerator enviará uma mensagem WM_COMMAND para a janela. A função envia WM_COMMAND invocando diretamente o procedimento da janela. Quando TranslateAccelerator traduz com êxito um pressionamento de teclas, 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.

Aqui está 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;

Este código assume que SetMode é 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.

Seguinte

Definindo a imagem do cursor