Share via


Anpassen von Symbolleisten

Die meisten Windows-basierten Anwendungen verwenden Symbolleistensteuerelemente, um Benutzern einen bequemen Zugriff auf die Programmfunktionalität zu ermöglichen. Statische Symbolleisten weisen jedoch einige Mängel auf, z. B. zu wenig Platz, um alle verfügbaren Tools effektiv anzuzeigen. Die Lösung für dieses Problem besteht darin, die Symbolleisten Ihrer Anwendung benutzerdefinierbar zu machen. Dann können Benutzer auswählen, dass nur die tools angezeigt werden, die sie benötigen, und sie können sie so organisieren, dass sie ihrem persönlichen Arbeitsstil entsprechen.

Hinweis

Symbolleisten in Dialogfeldern können nicht angepasst werden.

 

Um die Anpassung zu aktivieren, fügen Sie beim Erstellen des Symbolleistensteuerelements das flag CCS_ADJUSTABLE allgemeinen Steuerelementstil ein. Es gibt zwei grundlegende Ansätze für die Anpassung:

  • Das Anpassungsdialogfeld. Dieses vom System bereitgestellte Dialogfeld ist der einfachste Ansatz. Es bietet Benutzern eine grafische Benutzeroberfläche, die es ihnen ermöglicht, Symbole hinzuzufügen, zu löschen oder zu verschieben.
  • Ziehen und Ablegen von Tools. Durch die Implementierung von Drag-and-Drop-Funktionen können Benutzer Tools an eine andere Position auf der Symbolleiste verschieben oder löschen, indem Sie sie von der Symbolleiste ziehen. Es bietet Benutzern eine schnelle und einfache Möglichkeit, ihre Symbolleiste zu organisieren, erlaubt es ihnen jedoch nicht, Tools hinzuzufügen.

Je nach Den Anforderungen der Anwendung können Sie einen oder beides implementieren. Keiner dieser beiden Anpassungsansätze bietet einen integrierten Mechanismus, z. B. eine Schaltfläche Abbrechen oder Rückgängig, um die Symbolleiste in den früheren Zustand zurückzugeben. Sie müssen explizit die Symbolleistensteuerelement-API verwenden, um den Präanpassungszustand der Symbolleiste zu speichern. Bei Bedarf können Sie diese gespeicherten Informationen später verwenden, um den ursprünglichen Zustand der Symbolleiste wiederherzustellen.

Wichtige Informationen

Technologien

Voraussetzungen

  • C/C++
  • Programmierung der Windows-Benutzeroberfläche

Anweisungen

Anpassungsdialogfeld

Das Anpassungsdialogfeld wird vom Symbolleistensteuerelement bereitgestellt, um Benutzern eine einfache Möglichkeit zum Hinzufügen, Verschieben oder Löschen von Tools zu bieten. Benutzer können es starten, indem Sie auf die Symbolleiste doppelklicken. Anwendungen können das Anpassungsdialogfeld programmgesteuert starten, indem dem Symbolleistensteuerelement eine TB_CUSTOMIZE Nachricht gesendet wird.

Die folgende Abbildung zeigt ein Beispiel für das Dialogfeld zur Anpassung der Symbolleiste.

Screenshot eines Fensters mit einer Symbolleiste mit drei Elementen und einem Dialogfeld mit Listen der verfügbaren und aktuellen Symbolleistenschaltflächen

Die Tools im Listenfeld auf der rechten Seite sind die Tools, die sich derzeit auf der Symbolleiste befinden. Zunächst enthält diese Liste die Tools, die Sie beim Erstellen der Symbolleiste angeben. Das Listenfeld auf der linken Seite enthält die Tools, die zur Symbolleiste hinzugefügt werden können. Ihre Anwendung ist für das Auffüllen dieser Liste verantwortlich (außer mit dem Automatisch angezeigten Trennzeichen).

Das Symbolleistensteuerelement benachrichtigt Ihre Anwendung, dass es ein Anpassungsdialogfeld startet, indem es dem übergeordneten Fenster einen TBN_BEGINADJUST Benachrichtigungscode gefolgt von einem TBN_INITCUSTOMIZE Benachrichtigungscode sendet. In den meisten Fällen muss die Anwendung nicht auf diese Benachrichtigungscodes reagieren. Wenn Sie jedoch nicht möchten, dass im Dialogfeld Symbolleiste anpassen eine Hilfeschaltfläche angezeigt wird, behandeln Sie TBN_INITCUSTOMIZE, indem Sie TBNRF_HIDEHELP zurückgeben.

Das Symbolleistensteuerelement sammelt dann die Informationen, die es zum Initialisieren des Dialogfelds benötigt, indem es drei Reihen von Benachrichtigungscodes in der folgenden Reihenfolge sendet:

  • Ein TBN_QUERYINSERT Benachrichtigungscode für jede Schaltfläche auf der Symbolleiste, um zu bestimmen, wo Schaltflächen eingefügt werden können. Geben Sie FALSE zurück, um zu verhindern, dass eine Schaltfläche links neben der in der Benachrichtigung angegebenen Schaltfläche eingefügt wird. Wenn Sie false an alle TBN_QUERYINSERT Benachrichtigungscodes zurückgeben, wird das Dialogfeld nicht angezeigt.
  • Ein TBN_QUERYDELETE Benachrichtigungscode für jedes Tool, das sich derzeit auf der Symbolleiste befindet. Gibt TRUE zurück, wenn ein Tool gelöscht werden kann, oder FALSE , wenn dies nicht der Fall ist.
  • Eine Reihe von TBN_GETBUTTONINFO Benachrichtigungscodes, um die Liste der verfügbaren Schaltflächen aufzufüllen. Um der Liste eine Schaltfläche hinzuzufügen, füllen Sie die NMTOOLBAR-Struktur ein, die mit dem Benachrichtigungscode übergeben wird, und geben Sie TRUE zurück. Wenn Sie keine weiteren Tools hinzufügen können, geben Sie FALSE zurück. Beachten Sie, dass Sie Informationen für Schaltflächen zurückgeben können, die sich bereits auf der Symbolleiste befinden. Diese Schaltflächen werden der Liste nicht hinzugefügt.

Anschließend wird das Dialogfeld angezeigt, und der Benutzer kann mit dem Anpassen der Symbolleiste beginnen.

Wenn das Dialogfeld geöffnet ist, kann Ihre Anwendung je nach den Aktionen des Benutzers eine Vielzahl von Benachrichtigungscodes erhalten:

  • TBN_QUERYINSERT. Der Benutzer hat die Position eines Tools auf der Symbolleiste geändert oder ein Tool hinzugefügt. Geben Sie FALSE zurück, um zu verhindern, dass das Tool an dieser Position eingefügt wird.
  • TBN_DELETINGBUTTON. Der Benutzer ist dabei, ein Tool aus der Symbolleiste zu entfernen.
  • TBN_CUSTHELP. Der Benutzer hat auf die Schaltfläche Hilfe geklickt.
  • TBN_TOOLBARCHANGE. Der Benutzer hat ein Tool hinzugefügt, verschoben oder gelöscht.
  • TBN_RESET. Der Benutzer hat auf die Schaltfläche Zurücksetzen geklickt.

Nachdem das Dialogfeld zerstört wurde, erhält Ihre Anwendung einen TBN_ENDADJUST Benachrichtigungscode.

Das folgende Codebeispiel zeigt eine Möglichkeit zum Implementieren der Symbolleistenanpassung.

// 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; 
        }
    }

Ziehen und Ablegen von Tools

Benutzer können die Schaltflächen auf einer Symbolleiste auch neu anordnen, indem sie die UMSCHALTTASTE drücken und die Schaltfläche an eine andere Position ziehen. Der Drag-and-Drop-Prozess wird automatisch vom Symbolleistensteuerelement verarbeitet. Es zeigt ein Geisterbild der Schaltfläche an, während sie gezogen wird, und die Symbolleiste wird neu angeordnet, nachdem sie gelöscht wurde. Benutzer können auf diese Weise keine Schaltflächen hinzufügen, aber sie können eine Schaltfläche löschen, indem sie sie von der Symbolleiste ablegen.

Obwohl das Symbolleistensteuerelement diesen Vorgang normalerweise automatisch ausführt, sendet es ihrer Anwendung auch zwei Benachrichtigungscodes: TBN_QUERYDELETE und TBN_QUERYINSERT. Um den Drag-and-Drop-Prozess zu steuern, behandeln Sie diese Benachrichtigungscodes wie folgt:

  • Der TBN_QUERYDELETE Benachrichtigungscode wird gesendet, sobald der Benutzer versucht, die Schaltfläche zu verschieben, bevor die Ghost-Schaltfläche angezeigt wird. Geben Sie FALSE zurück, um zu verhindern, dass die Schaltfläche verschoben wird. Wenn Sie TRUE zurückgeben, kann der Benutzer das Tool entweder verschieben oder löschen, indem er es von der Symbolleiste abgibt. Wenn ein Tool verschoben werden kann, kann es gelöscht werden. Wenn der Benutzer jedoch ein Tool löscht, sendet das Symbolleistensteuerelement ihrer Anwendung einen TBN_DELETINGBUTTON Benachrichtigungscode. An diesem Punkt können Sie die Schaltfläche an der ursprünglichen Position erneut einfügen, wodurch sie abgebrochen wird.
  • Der TBN_QUERYINSERT Benachrichtigungscode wird gesendet, wenn der Benutzer versucht, die Schaltfläche auf der Symbolleiste zu löschen. Um zu verhindern, dass die Schaltfläche, die verschoben wird, links neben der in der Benachrichtigung angegebenen Schaltfläche abgelegt wird, geben Sie FALSE zurück. Dieser Benachrichtigungscode wird nicht gesendet, wenn der Benutzer das Tool von der Symbolleiste abwirft.

Wenn der Benutzer versucht, eine Schaltfläche zu ziehen, ohne auch die UMSCHALTTASTE zu drücken, verarbeitet das Symbolleistensteuerelement den Drag-and-Drop-Vorgang nicht. Es sendet Ihrer Anwendung jedoch einen TBN_BEGINDRAG Benachrichtigungscode, um den Beginn eines Ziehvorgangs anzugeben, und einen TBN_ENDDRAG Benachrichtigungscode, um das Ende anzugeben. Wenn Sie diese Form des Ziehens und Ablegens aktivieren möchten, muss Ihre Anwendung diese Benachrichtigungscodes verarbeiten, die erforderliche Benutzeroberfläche bereitstellen und die Symbolleiste ändern, um alle Änderungen widerzuspiegeln.

Speichern und Wiederherstellen von Symbolleisten

Beim Anpassen einer Symbolleiste muss Ihre Anwendung möglicherweise Informationen speichern, damit Sie den ursprünglichen Zustand der Symbolleiste wiederherstellen können. Um das Speichern oder Wiederherstellen eines Symbolleistenzustands zu initiieren, senden Sie dem Symbolleistensteuerelement eine TB_SAVERESTORE Nachricht, wobei lParam auf TRUE festgelegt ist. Der lParam-Wert dieser Meldung gibt an, ob Sie einen Speicher- oder wiederherstellungsvorgang anfordern. Nachdem die Nachricht gesendet wurde, gibt es zwei Möglichkeiten, den Speicher-/Wiederherstellungsvorgang zu verarbeiten:

  • Bei allgemeinen Steuerelementen , Version 4.72 und früher, müssen Sie einen TBN_GETBUTTONINFO-Handler implementieren. Das Symbolleistensteuerelement sendet diesen Benachrichtigungscode, um Informationen zu den einzelnen Schaltflächen anzufordern, während sie wiederhergestellt wird.
  • Version 5.80 enthält eine Option zum Speichern/Wiederherstellen. Zu Beginn des Prozesses und während jede Schaltfläche gespeichert oder wiederhergestellt wird, erhält Ihre Anwendung einen TBN_SAVE oder TBN_RESTORE Benachrichtigungscode. Um diese Option verwenden zu können, müssen Sie Benachrichtigungshandler implementieren, um die Bitmap- und Zustandsinformationen bereitzustellen, die zum erfolgreichen Speichern oder Wiederherstellen des Symbolleistenzustands erforderlich sind.

Symbolleistenzustände werden in einem Datenstrom gespeichert, der aus Blöcken von Shell-definierten Daten besteht, die sich mit Blöcken anwendungsdefinierter Daten abwechseln. Für jede Schaltfläche wird ein Datenblock jedes Typs gespeichert, zusammen mit einem optionalen Block globaler Daten, die Anwendungen am Anfang des Datenstroms platzieren können. Während des Speichervorgangs fügt Ihr TBN_SAVE-Handler dem Datenstrom die von der Anwendung definierten Blöcke hinzu. Während des Wiederherstellungsvorgangs liest der TBN_RESTORE-Handler jeden Block und gibt der Shell die Informationen an, die sie zum Rekonstruieren der Symbolleiste benötigt.

Behandeln einer TBN_SAVE-Benachrichtigung

Der erste TBN_SAVE Benachrichtigungscode wird zu Beginn des Speichervorgangs gesendet. Bevor Schaltflächen gespeichert werden, werden die Elemente der NMTBSAVE-Struktur wie in der folgenden Tabelle dargestellt festgelegt.

Member Einstellung
iItem –1
cbData Die Menge an Arbeitsspeicher, die für shelldefinierte Daten benötigt wird.
cButtons Die Anzahl der Schaltflächen.
Pdata Die berechnete Menge an Arbeitsspeicher, die für anwendungsdefinierte Daten benötigt wird. In der Regel schließen Sie einige globale Daten sowie Daten für jede Schaltfläche ein. Fügen Sie diesen Wert zu cbData hinzu, und weisen Sie pData genügend Arbeitsspeicher zu, um alles aufzunehmen.
pCurrent Das erste nicht verwendete Byte im Datenstrom. Wenn Sie keine globalen Symbolleisteninformationen benötigen, legen Sie pCurrent = pData so fest, dass es auf den Anfang des Datenstroms verweist. Wenn Sie globale Symbolleisteninformationen benötigen, speichern Sie sie bei pData, und legen Sie dann pCurrent auf den Anfang des nicht verwendeten Teils des Datenstroms fest, bevor sie zurückgegeben wird.

 

Wenn Sie einige globale Symbolleisteninformationen hinzufügen möchten, platzieren Sie sie am Anfang des Datenstroms. Führen Sie pCurrent bis zum Ende der globalen Daten aus, sodass sie auf den Anfang des nicht verwendeten Teils des Datenstroms verweist, und geben Sie zurück.

Nachdem Sie zurückgegeben haben, beginnt die Shell mit dem Speichern von Schaltflächeninformationen. Es fügt die von Shell definierten Daten für die erste Schaltfläche bei pCurrent hinzu und führt dann pCurrent zum Beginn des nicht verwendeten Teils aus.

Nachdem jede Schaltfläche gespeichert wurde, wird ein TBN_SAVE Benachrichtigungscode gesendet, und NMTBSAVE wird zurückgegeben, wobei diese Elemente wie folgt festgelegt sind.

Member Einstellung
iItem Der nullbasierte Index der Schaltflächennummer.
pCurrent Ein Zeiger auf das erste nicht verwendete Byte im Datenstrom. Wenn Sie zusätzliche Informationen zur Schaltfläche speichern möchten, speichern Sie sie an der Position, auf die pCurrent verweist, und aktualisieren Sie pCurrent so, dass danach auf den ersten nicht verwendeten Teil des Datenstroms verwiesen wird.
TBBUTTON Eine TBBUTTON-Struktur , die die schaltfläche beschreibt, die gespeichert wird.

 

Wenn Sie den Benachrichtigungscode erhalten, sollten Sie alle schaltflächenspezifischen Informationen, die Sie benötigen, aus TBBUTTON extrahieren. Denken Sie daran, dass Sie beim Hinzufügen einer Schaltfläche das dwData-Member von TBBUTTON verwenden können, um anwendungsspezifische Daten zu speichern. Laden Sie Ihre Daten bei pCurrent in den Datenstrom. Führen Sie pCurrent bis zum Ende Ihrer Daten aus, und zeigen Sie erneut auf den Anfang des nicht verwendeten Teils des Datenstroms, und geben Sie zurück.

Die Shell wechselt dann zur nächsten Schaltfläche, fügt ihre Informationen zu pData hinzu, erweitert pCurrent, lädt TBBUTTON und sendet einen weiteren TBN_SAVE Benachrichtigungscode. Dieser Vorgang wird fortgesetzt, bis alle Schaltflächen gespeichert sind.

Wiederherstellen gespeicherter Symbolleisten

Der Wiederherstellungsvorgang kehrt den Speichervorgang grundsätzlich um. Zu Beginn erhält Ihre Anwendung einen TBN_RESTORE Benachrichtigungscode, wobei das iItem-Element der NMTBRESTORE-Struktur auf –1 festgelegt ist. Das cbData-Element ist auf die Größe von pData und cButtons auf die Anzahl der Schaltflächen festgelegt.

Ihr Benachrichtigungshandler sollte die globalen Informationen extrahieren, die während des Speicherns am Anfang von pData platziert wurden, und pCurrent bis zum Beginn des ersten Blocks mit von Shell definierten Daten voranbringen. Legen Sie cBytesPerRecord auf die Größe der Datenblöcke fest, die Sie zum Speichern der Schaltflächendaten verwendet haben. Legen Sie cButtons auf die Anzahl der Schaltflächen fest, und geben Sie zurück.

Der nächste NMTBRESTORE ist für die erste Schaltfläche. Das pCurrent-Element zeigt auf den Anfang Ihres ersten Blocks mit Schaltflächendaten, und iItem ist auf den Schaltflächenindex festgelegt. Extrahieren Sie diese Daten, und weiterentwickeln Sie pCurrent. Laden Sie die Daten in TBBUTTON, und geben Sie zurück. Wenn Sie eine Schaltfläche von der wiederhergestellten Symbolleiste weglassen möchten, legen Sie den idCommand-Member von TBBUTTON auf 0 fest. Die Shell wiederholt den Vorgang für die restlichen Schaltflächen. Zusätzlich zu den NMTBSAVE - und NMTBRESTORE-Nachrichten können Sie auch Nachrichten wie TBN_RESET verwenden, um eine Symbolleiste zu speichern und wiederherzustellen.

Im folgenden Codebeispiel wird eine Symbolleiste gespeichert, bevor sie angepasst wird, und wird wiederhergestellt, wenn die Anwendung eine TBN_RESET Nachricht empfängt.

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;
}

Verwenden von Symbolleistensteuerelementen

Symbolindexwerte der Symbolleisten-Standardschaltfläche

Demo allgemeiner Windows-Steuerelemente (CppWindowsCommonControls)