À primeira vista, a barra de menus no Microsoft Internet Explorer 5 e posterior parece semelhante a um menu padrão. No entanto, parece bem diferente quando você começa a usá-lo.
A captura de tela a seguir mostra a barra de menus do Windows Internet Explorer com o menu Ferramentas selecionado.
A barra de menus é, na verdade, um controle de barra de ferramentas que se parece com um menu padrão. Em vez de itens de menu de nível superior, uma barra de menus tem uma série de botões somente texto que exibem um menu suspenso quando clicados. No entanto, como um tipo especializado de barra de ferramentas, uma barra de menus tem alguns recursos que os menus padrão não possuem:
- Ele pode ser personalizado usando técnicas de barra de ferramentas padrão, permitindo que o usuário mova, exclua ou adicione itens.
- Ele pode ter hot-tracking, para que os usuários saibam quando estão sobre um item de nível superior sem ter que clicar nele primeiro.
Uma barra de menus pode ser incorporada em um controle de vergalhão, dando-lhe as seguintes características:
- Pode ter uma pinça, que permite ao usuário mover ou redimensionar a banda.
- Ele pode compartilhar uma faixa no controle de vergalhão com outras bandas, como a barra de ferramentas padrão na ilustração anterior.
- Ele pode exibir uma divisa quando é coberto por uma faixa adjacente, dando ao usuário acesso aos itens ocultos.
- Ele pode ter um bitmap de plano de fundo definido pelo aplicativo.
Este tópico discute como implementar uma barra de menus. Como uma barra de menus é uma implementação especializada de um controle de barra de ferramentas, o foco será em tópicos específicos de barras de menu. Para obter uma discussão sobre como incorporar uma barra de ferramentas em um controle de vergalhão, consulte Como criar uma barra de ferramentas de estilo do Internet Explorer e Sobre controles de vergalhão.
Transformando uma barra de ferramentas em uma barra de menus
Para transformar uma barra de ferramentas em uma barra de menus:
- Crie uma barra de ferramentas simples incluindo TBSTYLE_FLAT com os outros sinalizadores de estilo de janela. O estilo TBSTYLE_FLAT também permite o rastreamento a quente. Com esse estilo, a barra de menus se parece muito com um menu padrão até que o usuário ative um botão. Em seguida, o botão parece se destacar da barra de ferramentas e pressionar quando é clicado, assim como um botão padrão. Como o hot-tracking está habilitado, tudo o que é necessário para ativar um botão é que o cursor passe o mouse sobre ele. Se o cursor se mover para outro botão, ele será ativado e o botão antigo desativado.
- Crie botões de estilo de lista incluindo TBSTYLE_LIST com os outros sinalizadores de estilo de janela. Esse estilo cria um botão mais fino que se parece mais com um item de menu de nível superior padrão.
- Torne os botões somente texto definindo o membro iBitmap da estrutura TBBUTTON do botão como I_IMAGENONE e o membro iString como o texto do botão.
- Dê a cada botão o estilo BTNS_DROPDOWN. Quando o botão é clicado, o controle da barra de ferramentas envia ao aplicativo uma notificação TBN_DROPDOWN para solicitar que ele exiba o menu do botão.
- Incorpore a barra de menus em uma faixa de vergalhão. Habilite pinças e divisas, conforme discutido em Como criar uma barra de ferramentas estilo do Internet Explorer.
- Implemente um manipulador de TBN_DROPDOWN para exibir o menu suspenso do botão quando ele for clicado. O menu suspenso é um tipo de menu pop-up. Ele é criado usando a função TrackPopupMenu , com seu canto superior esquerdo alinhado com o canto inferior esquerdo do botão.
- Implemente a navegação pelo teclado, para que a barra de menus seja totalmente acessível sem um mouse.
- Implemente o hot-tracking do menu. Com os menus padrão, uma vez que o menu de um item de menu de nível superior tenha sido exibido, mover o cursor sobre outro item de nível superior exibe automaticamente seu menu e recolhe o menu do item anterior. O controle da barra de ferramentas rastreará o cursor e alterará a imagem do botão, mas exibirá automaticamente o novo menu. Seu aplicativo deve fazê-lo explicitamente.
A maioria desses itens é simples de implementar e é discutida em outros lugares. Consulte Como criar uma barra de ferramentas no estilo do Internet Explorer, Sobre controles da barra de ferramentas ou Sobre controles de vergalhão para obter uma discussão geral sobre como usar barras de ferramentas e controles de vergalhão. Consulte Menus para obter uma discussão sobre como lidar com menus pop-up. Os dois últimos itens, navegação pelo teclado e hot-tracking de menu, são discutidos no restante deste tópico.
Manipulando a navegação com o menu Hot-Tracking desativado
Os usuários podem optar por navegar na barra de menus com o mouse, o teclado ou uma mistura de ambos. Para implementar a navegação na barra de menus, seu aplicativo deve lidar com notificações da barra de ferramentas e monitorar o mouse e o teclado. Esta tarefa pode ser dividida em duas partes distintas: com e sem hot-tracking de menu. Esta seção discute como lidar com a navegação quando nenhum menu é exibido e o rastreamento a quente de menu não está habilitado.
Navegação do mouse
Se o hot-tracking do menu estiver desativado, você poderá tratar uma barra de menus como uma barra de ferramentas normal. Se o usuário estiver navegando com um mouse, tudo o que seu aplicativo precisa fazer é manipular a notificação TBN_DROPDOWN. Quando essa notificação for recebida, exiba o menu suspenso apropriado e habilite o rastreamento a quente do menu. A partir de então, você estará no regime de hot-tracking do menu discutido em Handling Navigation with Menu Hot-Tracking Enabled.
Conforme discutido em Navegação mista, você também precisa lidar com a notificação TBN_HOTITEMCHANGE para acompanhar o botão ativo. Essa notificação é irrelevante se o usuário estiver navegando apenas com o mouse, mas é necessária quando a navegação do mouse e do teclado são mistos.
Navegação pelo teclado
Como observado na seção anterior, o usuário pode fazer uma série de operações de navegação com o teclado quando o hot-tracking do menu está desativado. Os controles da barra de ferramentas oferecem suporte à navegação pelo teclado somente se tiverem foco. Eles também não lidam com todos os pressionamentos de teclas que são necessários para barras de menu. A solução mais simples para lidar com a navegação pelo teclado é processar os eventos de pressionamento de teclas relevantes explicitamente.
Se o hot-tracking do menu estiver desabilitado, seu aplicativo deverá manipular esses eventos de pressionamento de tecla da seguinte maneira:
- A tecla F10. Ative o primeiro botão com TB_SETHOTITEM.
- As teclas SETA PARA A ESQUERDA e SETA PARA A DIREITA. Ative o botão adjacente com TB_SETHOTITEM. Se o usuário tentar navegar para fora de qualquer extremidade da barra de menus, ative o primeiro botão na extremidade oposta.
- A tecla ESCAPE. Desative o botão ativo com TB_SETHOTITEM. A barra de menus deve ser retornada ao estado que tinha antes de ativar o primeiro botão.
- Uma tecla aceleradora ALT-Key. Use a mensagem TB_MAPACCELERATOR para determinar a qual botão o caractere Chave corresponde. Exiba o menu suspenso do botão e ative o rastreamento a quente do menu.
- A tecla SETA PARA BAIXO. Se um botão estiver ativo, mas nenhum menu tiver sido exibido, exiba o menu do botão e habilite o rastreamento a quente do menu.
- A tecla ENTER. Desative o botão ativo com TB_SETHOTITEM. A barra de menus deve ser retornada ao estado que tinha antes de ativar o primeiro botão.
Navegação mista
Os manipuladores de navegação do teclado descritos na seção anterior basicamente fazem duas tarefas: manter o controle do botão ativo e exibir o menu apropriado quando um botão é selecionado. Esses manipuladores são suficientes, desde que o usuário navegue apenas com o teclado. No entanto, os usuários geralmente misturam navegação de teclado e mouse. Por exemplo, eles podem ativar o primeiro botão com a tecla F10, usar o mouse para ativar um botão diferente e, em seguida, abrir seu menu com a tecla SETA PARA BAIXO. Se você estiver monitorando apenas pressionamentos de tecla para manter o controle da tecla ativa, você exibirá o menu errado. Você também deve manipular a notificação TBN_HOTITEMCHANGE para manter o controle preciso do botão ativo.
Manipulando a navegação com o Menu Hot-Tracking ativado
Quando o hot-tracking do menu está ativado, seu aplicativo deve alterar a maneira como ele responde à navegação do usuário. Para replicar o comportamento dos menus padrão, você deve implementar os seguintes recursos explicitamente.
Com navegação do mouse:
- Se o usuário mover o cursor sobre outro botão, esse menu aparecerá imediatamente e o menu anterior desaparecerá.
- O hot-tracking do menu permanece ativo até que o usuário selecione um comando ou clique em um ponto que não faça parte da região do menu. Qualquer ação desativa o hot-tracking do menu até que outro botão seja clicado.
- Se o cursor se mover para fora do menu, o menu suspenso atual permanecerá até que o cursor volte a se mover ou o usuário clique em um ponto fora da área coberta pelo menu. Se o cursor retornar a um botão diferente do que está sendo exibido no momento, o menu antigo será recolhido e o novo menu será exibido.
Com navegação pelo teclado:
A tecla SETA PARA A DIREITA move o foco para a direita. Se o item tiver um submenu, exiba o submenu. Se o item não tiver um submenu, recolha o menu e quaisquer submenus, ative o botão seguinte com TB_SETHOTITEM e exiba o menu do botão adjacente. Se o último botão estiver ativo quando essa mensagem for recebida, exiba o menu do primeiro botão.
A tecla SETA PARA A ESQUERDA move o foco para a esquerda. Se o item for um submenu, recolha-o e mude o foco para o menu pai. Se o item não for um submenu, recolha o menu, ative o botão seguinte com TB_SETHOTITEM e exiba o menu desse botão.
A tecla ESCAPE faz o backup da tela em uma etapa.
- Se um submenu for exibido, ele será recolhido e o foco mudará para o menu pai.
- Se o menu de um botão for exibido, ele será recolhido e o rastreamento a quente do menu será desativado. O botão do item permanece ativo.
- Se nenhum menu for exibido, mas um botão estiver ativo, o botão será desativado e o rastreamento a quente do menu será desativado.
As teclas SETA PARA CIMA e SETA PARA BAIXO são usadas apenas para navegar dentro de um menu específico.
A tecla ENTER inicia o comando associado a um item de menu. Se o item de menu tiver um submenu, a tecla ENTER o exibirá.
Assim como acontece com o estojo desativado de rastreamento a quente do menu, seu aplicativo deve ser capaz de lidar com mouse, teclado e navegação mista. No entanto, o fato de um menu ser exibido significa que as mensagens terão que ser tratadas de forma um pouco diferente.
Processamento de mensagens para hot-tracking de menu
O hot-tracking do menu requer que um menu seja exibido o tempo todo, além do breve intervalo necessário para alternar para um novo menu. No entanto, o menu suspenso que é exibido por TrackPopupMenu é modal. Seu aplicativo continuará a receber algumas mensagens diretamente, incluindo WM_COMMAND, TBN_HOTITEMCHANGE e mensagens normais relacionadas ao menu, como WM_MENUSELECT. No entanto, ele não receberá mensagens de teclado ou mouse de baixo nível diretamente. Para manipular mensagens como WM_MOUSEMOVE, você deve definir um gancho de mensagem para interceptar mensagens que são direcionadas para o menu.
Quando um menu suspenso for exibido, defina o gancho da mensagem chamando a função SetWindowsHookEx com o parâmetro idHook definido como WH_MSGFILTER. Todas as mensagens destinadas ao menu serão passadas para o seu MessageProc. Por exemplo, o fragmento de código a seguir define um gancho de mensagem que interceptará as mensagens que estão indo para um menu suspenso. MsgHook
é o nome do procedimento de gancho e hhookMsg
é o identificador do procedimento.
hhookMsg = SetWindowsHookEx(WH_MSGFILTER, MsgHook, HINST_THISDLL, 0);
As mensagens de menu são identificadas definindo o parâmetro nCode do procedimento de gancho como MSGF_MENU. O parâmetro lParam apontará para uma estrutura MSG com a mensagem. Os detalhes de quais mensagens precisam ser tratadas e como são discutidos no restante deste tópico.
Seu aplicativo deve passar todas as mensagens para o próximo gancho de mensagem chamando a função CallNextHookEx. Você também deve enviar mensagens do mouse diretamente para o controle da barra de ferramentas, certificando-se de converter quaisquer coordenadas de ponto para o espaço de coordenadas do cliente da barra de ferramentas. Enviar as mensagens diretamente garante que o controle da barra de ferramentas receba as mensagens apropriadas do mouse. Por exemplo, a barra de ferramentas precisa receber WM_MOUSEMOVE mensagens para rastrear seus botões.
Quando um novo botão é ativado, seu aplicativo deve recolher o menu suspenso antigo com uma mensagem WM_CANCELMODE e exibir um novo menu. Ele também deve recolher o menu suspenso quando o foco é retirado da barra de menus com navegação pelo teclado ou clicando fora da área do menu. Sempre que você recolher um menu, você deve liberar seu gancho de mensagem usando a função UnhookWindowsHookEx. Se você precisar exibir outro menu suspenso, crie um novo gancho de mensagem. Quando um comando é iniciado, o menu será recolhido automaticamente, mas você deve liberar explicitamente o gancho da mensagem.
O exemplo de código a seguir libera o gancho de mensagem que foi definido no exemplo anterior.
UnhookWindowsHookEx(hhookMsg);
Navegação do mouse
Quando uma barra de ferramentas normal controla botões hot-tracks, ela realça o botão ativo e envia ao aplicativo uma notificação TBN_HOTITEMCHANGE cada vez que um novo botão é ativado. Seu aplicativo é responsável por exibir o menu suspenso apropriado. Ela deverá:
- Manipule a notificação TBN_HOTITEMCHANGE para acompanhar o botão ativo. Quando o botão ativo for alterado, feche o menu antigo e crie um novo.
- Manipule a notificação TBN_DROPDOWN que é enviada quando um botão é clicado. Em seguida, ele deve recolher o menu e desativar o hot-tracking do menu. O botão permanece ativo.
- Manipule as mensagens de WM_LBUTTONDOWN, WM_RBUTTONDOWN e WM_MOUSEMOVE no procedimento de gancho de mensagem para acompanhar a posição do mouse. Se o mouse for clicado fora da área de menu, feche o menu suspenso atual, desative o hot-tracking do menu e retorne a barra de menus ao seu estado de pré-ativação.
- Quando um comando de menu for iniciado, desative o hot-tracking do menu. O menu será recolhido automaticamente, mas você deve liberar explicitamente o gancho da mensagem.
Você também deve manipular mensagens relacionadas ao menu, como a mensagem WM_INITMENUPOPUP que é enviada quando um item de menu precisa exibir um submenu. Para obter uma discussão sobre como lidar com essas mensagens, consulte Menus.
Navegação pelo teclado
Seu aplicativo deve processar mensagens do teclado no procedimento de gancho de mensagem e agir naquelas que afetam o rastreamento a quente do menu. As seguintes teclas pressionadas devem ser manipuladas:
- A tecla ESCAPE. A tecla ESCAPE faz com que a tela suba um nível. Se um submenu estiver sendo exibido, ele deverá ser recolhido. Se o menu principal de um botão for exibido, recolha-o e desative o hot-tracking do menu. O botão permanece ativo.
- A tecla SETA PARA A DIREITA. Se o item tiver um submenu, exiba-o. Se o item não tiver um submenu, recolha o menu e quaisquer submenus, ative o botão seguinte com TB_SETHOTITEM e exiba seu menu. Se o último botão estava ativo quando essa notificação foi recebida, exiba o menu do primeiro botão.
- A tecla SETA PARA A ESQUERDA. Se o item estiver em um submenu, recolha-o e mude o foco para o menu pai. Se o item não for um submenu, feche o menu, ative o botão adjacente com TB_SETHOTITEM e exiba seu menu. Se o primeiro botão estava ativo quando essa notificação foi recebida, exiba o menu do último botão.
- As teclas SETA PARA CIMA e SETA PARA BAIXO. Essas teclas são usadas para navegar dentro de um menu, mas não afetam diretamente o rastreamento a quente do menu.
- Uma tecla aceleradora ALT-Key. Use a mensagem TB_MAPACCELERATOR para determinar a qual botão o caractere Chave corresponde. Se ele corresponder a um botão diferente do atualmente ativo, recolha o menu suspenso atual, ative o novo botão com TB_SETHOTITEM e exiba o menu do botão adjacente. Se o caractere Chave corresponder ao botão exibido no momento, feche o menu suspenso e desative o rastreamento a quente do menu. O botão deve permanecer ativo.