Partilhar via


Como personalizar barras de ferramentas

A maioria dos aplicativos baseados no Windows usa controles de barra de ferramentas para fornecer aos usuários acesso conveniente à funcionalidade do programa. No entanto, as barras de ferramentas estáticas têm algumas deficiências, como pouco espaço para exibir efetivamente todas as ferramentas disponíveis. A solução para esse problema é tornar as barras de ferramentas do seu aplicativo personalizáveis pelo usuário. Em seguida, os usuários podem optar por exibir apenas as ferramentas de que precisam e podem organizá-las de uma maneira que se adapte ao seu estilo de trabalho pessoal.

Observação

As barras de ferramentas nas caixas de diálogo não podem ser personalizadas.

 

Para habilitar a personalização, inclua o sinalizador de estilo dos controlos comuns CCS_ADJUSTABLE ao criar o controlo da barra de ferramentas. Existem duas abordagens básicas para a personalização:

  • A caixa de diálogo de personalização. Esta caixa de diálogo fornecida pelo sistema é a abordagem mais simples. Ele oferece aos usuários uma interface gráfica do usuário que lhes permite adicionar, excluir ou mover ícones.
  • Ferramentas de arrastar e soltar. A implementação da funcionalidade de arrastar e soltar permite que os usuários movam ferramentas para outro local na barra de ferramentas ou as excluam arrastando-as para fora da barra de ferramentas. Ele fornece aos usuários uma maneira rápida e fácil de organizar sua barra de ferramentas, mas não permite que eles adicionem ferramentas.

Você pode implementar qualquer abordagem ou ambas, dependendo das necessidades do aplicativo. Nenhuma dessas duas abordagens de personalização fornece um mecanismo interno, como um botão Cancelar ou Desfazer, para retornar a barra de ferramentas ao seu estado anterior. Você deve usar explicitamente a API de controle da barra de ferramentas para armazenar o estado de pré-personalização da barra de ferramentas. Se necessário, você pode usar posteriormente essas informações armazenadas para restaurar a barra de ferramentas ao seu estado original.

O que precisa de saber

Tecnologias

Pré-requisitos

  • C/C++
  • Programação da interface do usuário do Windows

Instruções

Caixa de diálogo Personalização

A caixa de diálogo de personalização é fornecida pelo controle da barra de ferramentas para oferecer aos usuários uma maneira simples de adicionar, mover ou excluir ferramentas. Os usuários podem iniciá-lo clicando duas vezes na barra de ferramentas. Os aplicativos podem iniciar a caixa de diálogo de personalização programaticamente enviando ao controle da barra de ferramentas uma mensagem TB_CUSTOMIZE.

A ilustração a seguir mostra um exemplo da caixa de diálogo de personalização da barra de ferramentas.

captura de tela de uma janela com uma barra de ferramentas de três itens e uma caixa de diálogo com listas dos botões da barra de ferramentas disponíveis e atuais

As ferramentas na caixa de listagem à direita são as que estão atualmente na barra de ferramentas. Inicialmente, essa lista conterá as ferramentas que você especificar ao criar a barra de ferramentas. A caixa de listagem à esquerda contém as ferramentas que estão disponíveis para adicionar à barra de ferramentas. Seu aplicativo é responsável por preencher essa lista (exceto com o Separador, que aparece automaticamente).

O controlo da barra de ferramentas notifica a sua aplicação de que está a iniciar uma caixa de diálogo de personalização enviando à janela pai um código de notificação TBN_BEGINADJUST seguido por um código de notificação TBN_INITCUSTOMIZE. Na maioria dos casos, o aplicativo não precisa responder a esses códigos de notificação. No entanto, se você não quiser que a caixa de diálogo Personalizar Barra de Ferramentas exiba um botão Ajuda, manipule TBN_INITCUSTOMIZE retornando TBNRF_HIDEHELP.

Em seguida, o controle da barra de ferramentas coleta as informações necessárias para inicializar a caixa de diálogo enviando três séries de códigos de notificação, na seguinte ordem:

  • Um código de notificação TBN_QUERYINSERT para cada botão na barra de ferramentas para determinar onde os botões podem ser inseridos. Retorne FALSO para impedir que um botão seja inserido à esquerda do botão especificado na mensagem de notificação. Se retornares FALSO para todos os códigos de notificação TBN_QUERYINSERT, a caixa de diálogo não será exibida.
  • Um código de notificação TBN_QUERYDELETE para cada ferramenta que está atualmente na barra de ferramentas. Retorne TRUE se uma ferramenta puder ser excluída ou FALSE se não.
  • Uma série de TBN_GETBUTTONINFO códigos de notificação para preencher a lista de botões disponíveis. Para adicionar um botão à lista, preencha a estrutura deNMTOOLBARque é passada com o código de notificação e devolva TRUE. Quando não tiver mais ferramentas para adicionar, retorne FALSE. Observe que você pode retornar informações para botões que já estão na barra de ferramentas; Esses botões não serão adicionados à lista.

A caixa de diálogo é exibida e o usuário pode começar a personalizar a barra de ferramentas.

Quando a caixa de diálogo é aberta, seu aplicativo pode receber uma variedade de códigos de notificação, dependendo das ações do usuário:

  • TBN_QUERYINSERT. O usuário alterou o local de uma ferramenta na barra de ferramentas ou adicionou uma ferramenta. Retorne FALSO para impedir que a ferramenta seja inserida nesse local.
  • TBN_DELETINGBUTTON. O usuário está prestes a remover uma ferramenta da barra de ferramentas.
  • TBN_CUSTHELP. O usuário clicou no botão Ajuda.
  • TBN_TOOLBARCHANGE. O usuário adicionou, moveu ou excluiu uma ferramenta.
  • TBN_RESET. O utilizador clicou no botão Redefinir.

Depois que a caixa de diálogo for destruída, seu aplicativo receberá um código de notificação TBN_ENDADJUST.

O exemplo de código a seguir mostra uma maneira de implementar a personalização da barra de ferramentas.

// The buttons are stored in an array of TBBUTTON structures. 
//
// Constants such as STD_FILENEW are identifiers for the 
// built-in bitmaps that have already been assigned as the toolbar's 
// image list.
//
// Constants such as IDM_NEW are application-defined command identifiers.

TBBUTTON allButtons[] = 
    {
        { MAKELONG(STD_FILENEW,  ImageListID), IDM_NEW,   TBSTATE_ENABLED, 0, {0}, 0, (INT_PTR)L"New" },
        { MAKELONG(STD_FILEOPEN, ImageListID), IDM_OPEN,  TBSTATE_ENABLED, 0, {0}, 0, (INT_PTR)L"Open"},
        { MAKELONG(STD_FILESAVE, ImageListID), IDM_SAVE,  TBSTATE_ENABLED, 0, {0}, 0, (INT_PTR)L"Save"},
        { MAKELONG(STD_CUT,      ImageListID), IDM_CUT,   TBSTATE_ENABLED, 0, {0}, 0, (INT_PTR)L"Cut" },
        { MAKELONG(STD_COPY,     ImageListID), IDM_COPY,  TBSTATE_ENABLED, 0, {0}, 0, (INT_PTR)L"Copy"},
        { MAKELONG(STD_PASTE,    ImageListID), IDM_PASTE, TBSTATE_ENABLED, 0, {0}, 0, (INT_PTR)L"Paste"}
    };

// The following appears in the window's message handler.

case WM_NOTIFY: 
    {
        switch (((LPNMHDR)lParam)->code) 
        {
        
        case TBN_GETBUTTONINFO:  
            {
                LPTBNOTIFY lpTbNotify = (LPTBNOTIFY)lParam;

                // Pass the next button from the array. There is no need to filter out buttons
                // that are already used—they will be ignored.
                
                int buttonCount = sizeof(allButtons) / sizeof(TBBUTTON);
                
                if (lpTbNotify->iItem < buttonCount)
                {
                    lpTbNotify->tbButton = allButtons[lpTbNotify->iItem];
                    return TRUE;
                }
                
                else
                
                {
                    return FALSE;  // No more buttons.
                }
            }
            
            break;

            case TBN_QUERYINSERT:
            
            case TBN_QUERYDELETE:
                return TRUE; 
        }
    }

Ferramentas de arrastar e soltar

Os usuários também podem reorganizar os botões em uma barra de ferramentas pressionando a tecla SHIFT e arrastando o botão para outro local. O processo de arrastar e soltar é manipulado automaticamente pelo controle da barra de ferramentas. Ele exibe uma imagem fantasma do botão enquanto ele é arrastado e reorganiza a barra de ferramentas depois que ele é solto. Os usuários não podem adicionar botões dessa maneira, mas podem excluir um botão soltando-o da barra de ferramentas.

Embora o controle da barra de ferramentas normalmente faça essa operação automaticamente, ele também envia ao seu aplicativo dois códigos de notificação: TBN_QUERYDELETE e TBN_QUERYINSERT. Para controlar o processo de arrastar e soltar, manipule esses códigos de notificação da seguinte maneira:

  • O código de notificação TBN_QUERYDELETE é enviado assim que o usuário tenta mover o botão, antes que o botão fantasma seja exibido. Retorne FALSO para impedir que o botão seja movido. Se você retornar TRUE, o usuário poderá mover a ferramenta ou excluí-la soltando-a da barra de ferramentas. Se uma ferramenta puder ser movida, ela poderá ser excluída. No entanto, se o usuário excluir uma ferramenta, o controle da barra de ferramentas enviará ao seu aplicativo um código de notificação TBN_DELETINGBUTTON, momento em que você pode optar por reinserir o botão em seu local original, cancelando assim a exclusão.
  • O código de notificação TBN_QUERYINSERT é enviado quando o usuário tenta soltar o botão na barra de ferramentas. Para evitar que o botão que está sendo movido seja solto à esquerda do botão especificado na notificação, retorne FALSE. Esse código de notificação não é enviado se o usuário soltar a ferramenta da barra de ferramentas.

Se o usuário tentar arrastar um botão sem pressionar também a tecla SHIFT, o controle da barra de ferramentas não manipulará a operação de arrastar e soltar. No entanto, ele enviará ao seu aplicativo um código de notificação TBN_BEGINDRAG para indicar o início de uma operação de arrastar e um código de notificação TBN_ENDDRAG para indicar o fim. Se você quiser habilitar essa forma de arrastar e soltar, seu aplicativo deve manipular esses códigos de notificação, fornecer a interface de usuário necessária e modificar a barra de ferramentas para refletir quaisquer alterações.

Salvando e restaurando barras de ferramentas

No processo de personalização de uma barra de ferramentas, seu aplicativo pode precisar salvar informações para que você possa restaurar a barra de ferramentas para seu estado original. Para iniciar a gravação ou restauração de um estado da barra de ferramentas, envie ao controle da barra de ferramentas uma mensagem TB_SAVERESTORE com a wParam definida como TRUE. O valor wParam desta mensagem especifica se você está solicitando uma operação de salvamento ou restauração. Depois que a mensagem é enviada, há duas maneiras de lidar com a operação de salvamento/restauração:

  • Com controles comuns versão 4.72 e anteriores, você deve implementar um manipulador de TBN_GETBUTTONINFO. O controle da barra de ferramentas envia esse código de notificação para solicitar informações sobre cada botão à medida que ele é restaurado.
  • A versão 5.80 inclui uma opção de salvar/restaurar. No início do processo, e à medida que cada botão é guardado ou restaurado, a sua aplicação receberá um código de notificação TBN_SAVE ou TBN_RESTORE. Para usar essa opção, você deve implementar manipuladores de notificação para fornecer as informações de bitmap e estado necessárias para salvar ou restaurar com êxito o estado da barra de ferramentas.

Os estados da barra de ferramentas são salvos em um fluxo de dados que consiste em blocos de dados definidos pelo Shell alternados com blocos de dados definidos pelo aplicativo. Um bloco de dados de cada tipo é armazenado para cada botão, juntamente com um bloco opcional de dados globais que os aplicativos podem colocar no início do fluxo. Durante o processo de salvamento, o manipulador de TBN_SAVE adiciona os blocos definidos pelo aplicativo ao fluxo de dados. Durante o processo de restauração, o manipulador de TBN_RESTORE lê cada bloco e fornece ao Shell as informações necessárias para reconstruir a barra de ferramentas.

Como lidar com uma notificação de TBN_SAVE

O primeiro código de notificação TBN_SAVE é enviado no início do processo de gravação. Antes de qualquer botão ser salvo, os membros da estrutura NMTBSAVE são definidos conforme mostrado na tabela a seguir.

Membro Cenário
iItem –1
cbData A quantidade de memória necessária para dados definidos pelo Shell.
cButtons O número de botões.
pData A quantidade calculada de memória necessária para dados definidos pelo aplicativo. Normalmente, você inclui alguns dados globais, além de dados para cada botão. Adicione esse valor a cbData e aloque memória suficiente para pData para armazenar tudo.
corrente atual O primeiro byte não utilizado no fluxo de dados. Se você não precisar de informações da barra de ferramentas global, defina pCurrent = pData para que ele aponte para o início do fluxo de dados. Se você precisar de informações da barra de ferramentas global, armazene-as em pDatae, em seguida, defina pCurrent para o início da parte não utilizada do fluxo de dados antes de retornar.

 

Se você quiser adicionar algumas informações da barra de ferramentas global, coloque-as no início do fluxo de dados. Avance pCurrent até ao final dos dados globais para que aponte para o início da parte não utilizada do fluxo de dados, e retorne.

Depois de retornar, o Shell começa a salvar as informações do botão. Ele adiciona os dados definidos pelo Shell para o primeiro botão em pCurrent e, em seguida, avança pCurrent para o início da parte não utilizada.

Depois que cada botão é salvo, um código de notificação TBN_SAVE é enviado e NMTBSAVE é retornado com esses membros definidos da seguinte maneira.

Membro Configuração
iItem O índice baseado em zero do número do botão.
pCurrent Um ponteiro para o primeiro byte não utilizado no fluxo de dados. Se você quiser armazenar informações adicionais sobre o botão, armazene-o no local apontado por pCurrent e atualize pCurrent para apontar para a primeira parte não utilizada do fluxo de dados depois disso.
TBBUTTON Uma TBBUTTON estrutura que descreve o botão que está a ser salvo.

 

Ao receber o código de notificação, deve extrair todas as informações específicas de botão de TBBUTTON. Lembre-se de que, ao adicionar um botão, pode usar o membro dwData de TBBUTTON para armazenar dados específicos da aplicação. Carregue os seus dados no fluxo de dados em pCurrent. Avançar pCurrent até o final dos dados, apontando novamente para o início da parte não utilizada do fluxo e retornar.

O Shell então avança para o próximo botão, adiciona as suas informações ao pData, avança pCurrent, carrega TBBUTTON, e envia outro código de notificação TBN_SAVE. Esse processo continua até que todos os botões sejam salvos.

Restaurando barras de ferramentas salvas

O processo de restauração consiste basicamente em reverter o processo de salvamento. No início, seu aplicativo receberá um código de notificação TBN_RESTORE com o membro iItem da estrutura NMTBRESTORE definido como –1. O membro cbData é definido como o tamanho de pData, e cButtons é definido como o número de botões.

O seu manipulador de notificação deve extrair as informações globais que foram colocadas no início do pData durante o salvamento, e avançar pCurrent para o início do primeiro bloco de dados definidos pelo Shell. Defina cBytesPerRecord para o tamanho dos blocos de dados usados para salvar os dados do botão. Defina cButtons para o número de botões e retorne.

O próximo NMTBRESTORE é para o primeiro botão. O membro pCurrent aponta para o início do seu primeiro bloco de dados de botão e iItem é definido como o índice do botão. Extraia esses dados e avance pCurrent. Carregue os dados em TBBUTTONe volte. Para omitir um botão da barra de ferramentas restaurada, defina o idCommand membro de TBBUTTON como zero. O Shell repetirá o processo para os botões restantes. Além das mensagens NMTBSAVE e NMTBRESTORE, também pode usar mensagens como TBN_RESET para salvar e restaurar a barra de ferramentas.

O exemplo de código a seguir salva uma barra de ferramentas antes de ser personalizada e a restaura se o aplicativo receber uma mensagem TBN_RESET.

int               i;
LPNMHDR           lpnmhdr;
static int        nResetCount;
static LPTBBUTTON lpSaveButtons;
LPARAM            lParam;

switch( lpnmhdr->code)
{
    case TBN_BEGINADJUST: // Begin customizing the toolbar.
    {
        LPTBNOTIFY  lpTB = (LPTBNOTIFY)lparam;
       
        // Allocate memory for the button information.
        
        nResetCount   = SendMessage(lpTB->hdr.hwndFrom, TB_BUTTONCOUNT, 0, 0);
        lpSaveButtons = (LPTBBUTTON)GlobalAlloc(GPTR, sizeof(TBBUTTON) * nResetCount);
      
        // In case the user presses reset, save the current configuration 
        // so the original toolbar can be restored.
        
        for(i = 0; i < nResetCount; i++)
        {
            SendMessage(lpTB->hdr.hwndFrom, 
                        TB_GETBUTTON, i, 
                        (LPARAM)(lpSaveButtons + i));
        }
    }
    
    return TRUE;
   
    case TBN_RESET:
    {
        LPTBNOTIFY lpTB = (LPTBNOTIFY)lparam;
        
        int nCount, i;
    
        // Remove all of the existing buttons, starting with the last one.
        
        nCount = SendMessage(lpTB->hdr.hwndFrom, TB_BUTTONCOUNT, 0, 0);
        
        for(i = nCount - 1; i >= 0; i--)
        {
            SendMessage(lpTB->hdr.hwndFrom, TB_DELETEBUTTON, i, 0);
        }
      
        SendMessage(lpTB->hdr.hwndFrom,      // Restore the saved buttons.
                    TB_ADDBUTTONS, 
                    (WPARAM)nResetCount, 
                    (LPARAM)lpSaveButtons);
    }
    
    return TRUE;
   
    case TBN_ENDADJUST:                // Free up the memory you allocated.
        GlobalFree((HGLOBAL)lpSaveButtons);
        
        return TRUE;
}

Usando controles da barra de ferramentas

Valores de índice de imagem de botão padrão da barra de ferramentas

demonstração dos controlos comuns do Windows (CppWindowsCommonControls)