Přizpůsobení panelů nástrojů
Většina aplikací založených na Windows používá ovládací prvky panelu nástrojů, které uživatelům poskytují pohodlný přístup k funkcím programu. Statické panely nástrojů ale mají určité nedostatky – například příliš málo místa pro efektivní zobrazení všech dostupných nástrojů. Řešením tohoto problému je, aby panely nástrojů vaší aplikace byly uživatelsky přizpůsobitelné. Uživatelé se pak můžou rozhodnout zobrazit jenom nástroje, které potřebují, a mohou je uspořádat způsobem, který vyhovuje jejich osobním pracovnímu stylu.
Poznámka
Panely nástrojů v dialogových oknech nelze přizpůsobit.
Pokud chcete povolit přizpůsobení, při vytváření ovládacího prvku panelu nástrojů zahrňte příznak stylu CCS_ADJUSTABLE běžných ovládacích prvků. Existují dva základní přístupy k přizpůsobení:
- Dialogové okno přizpůsobení. Toto systémové dialogové okno je nejjednodušším přístupem. Poskytuje uživatelům grafické uživatelské rozhraní, které jim umožňuje přidávat, odstraňovat nebo přesouvat ikony.
- Přetahování nástrojů Implementace funkce přetažení umožňuje uživatelům přesunout nástroje na jiné místo na panelu nástrojů nebo je odstranit přetažením mimo panel nástrojů. Poskytuje uživatelům rychlý a snadný způsob uspořádání panelu nástrojů, ale neumožňuje jim přidávat nástroje.
V závislosti na potřebách aplikace můžete implementovat buď jeden přístup, nebo oba. Žádný z těchto dvou přístupů k přizpůsobení neposkytuje integrovaný mechanismus, například tlačítko Storno nebo Zpět, aby se panel nástrojů vrátil do předchozího stavu. K uložení stavu předběžného určení panelu nástrojů je nutné explicitně použít rozhraní API ovládacího prvku panelu nástrojů. V případě potřeby můžete později pomocí uložených informací obnovit panel nástrojů do původního stavu.
Co potřebujete vědět
Technologie
Požadavky
- C/C++
- Programování uživatelského rozhraní systému Windows
Instrukce
Dialogové okno Přizpůsobení
Dialogové okno přizpůsobení poskytuje ovládací prvek panelu nástrojů, který uživatelům umožňuje jednoduše přidávat, přesouvat nebo odstraňovat nástroje. Uživatelé ho můžou spustit poklikáním na panel nástrojů. Aplikace mohou programově spustit dialogové okno přizpůsobení odesláním zprávy TB_CUSTOMIZE ovládacímu prvku panelu nástrojů.
Následující obrázek znázorňuje příklad dialogového okna přizpůsobení panelu nástrojů.
Nástroje v seznamu vpravo jsou ty, které jsou aktuálně na panelu nástrojů. Zpočátku bude tento seznam obsahovat nástroje, které zadáte při vytváření panelu nástrojů. Seznam vlevo obsahuje nástroje, které jsou k dispozici pro přidání na panel nástrojů. Vaše aplikace zodpovídá za naplnění daného seznamu (kromě oddělovače, který se zobrazí automaticky).
Ovládací prvek panelu nástrojů upozorní vaši aplikaci, že spouští dialogové okno přizpůsobení, odesláním nadřazenému oknu kódu oznámení TBN_BEGINADJUST, následovanému kódem oznámení TBN_INITCUSTOMIZE. Ve většině případů aplikace nemusí na tyto kódy oznámení reagovat. Pokud ale nechcete, aby dialogové okno Přizpůsobit panel nástrojů zobrazilo tlačítko Nápověda, zpracujte zprávu TBN_INITCUSTOMIZE vrácením TBNRF_HIDEHELP.
Ovládací prvek panelu nástrojů pak shromažďuje informace potřebné k inicializaci dialogového okna odesláním tří řad kódů oznámení v následujícím pořadí:
- Kód oznámení TBN_QUERYINSERT pro každé tlačítko na panelu nástrojů, který určuje, kam se dají tlačítka vložit. Vraťte FALSE, aby se zabránilo vložení tlačítka vlevo od tlačítka uvedeného v oznamovací zprávě. Pokud vrátíte FALSE, všem kódům oznámení TBN_QUERYINSERT, dialogové okno se nezobrazí.
- Kód oznámení TBN_QUERYDELETE pro každý nástroj, který je aktuálně na panelu nástrojů. Pokud lze nástroj odstranit, vraťte TRUE, jinak vraťte FALSE.
- Řada kódů oznámení TBN_GETBUTTONINFO k naplnění seznamu dostupných tlačítek. Chcete-li přidat tlačítko do seznamu, vyplňte NMTOOLBAR strukturu, která je předána s kódem oznámení a vrátíte TRUE. Pokud nemáte další nástroje k přidání, vraťte FALSE. Všimněte si, že můžete vrátit informace pro tlačítka, která jsou již na panelu nástrojů; tato tlačítka nebudou přidána do seznamu.
Zobrazí se dialogové okno a uživatel může začít přizpůsobovat panel nástrojů.
Po otevření dialogového okna může vaše aplikace přijímat různé kódy oznámení v závislosti na akcích uživatele:
- TBN_QUERYINSERT. Uživatel změnil umístění nástroje na panelu nástrojů nebo přidal nástroj. Vraťte FALSE, aby nástroj nebyl vložen do daného umístění.
- TBN_DELETINGBUTTON. Uživatel se chystá odebrat nástroj z panelu nástrojů.
- TBN_CUSTHELP. Uživatel kliknul na tlačítko Nápověda.
- TBN_TOOLBARCHANGE. Uživatel přidal, přesunul nebo odstranil nástroj.
- TBN_RESET. Uživatel kliknul na tlačítko Obnovit.
Po zničení dialogového okna aplikace obdrží TBN_ENDADJUST kód oznámení.
Následující příklad kódu ukazuje jeden způsob implementace přizpůsobení panelu nástrojů.
// 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;
}
}
Přetahování a upouštění nástrojů
Uživatelé můžou také změnit uspořádání tlačítek na panelu nástrojů stisknutím klávesy SHIFT a přetažením tlačítka do jiného umístění. Proces přetažení je automaticky zpracován ovládacím prvkem panelu nástrojů. Při přetahování se zobrazí stínový obrázek tlačítka a po přetažení přeuspořádá panel nástrojů. Uživatelé tímto způsobem nemůžou přidávat tlačítka, ale můžou tlačítko odstranit tak, že ho přejdou mimo panel nástrojů.
I když ovládací prvek panelu nástrojů obvykle tuto operaci provádí automaticky, odešle také aplikaci dva kódy oznámení: TBN_QUERYDELETE a TBN_QUERYINSERT. Chcete-li řídit proces přetahování, zpracujte následujícím způsobem tyto kódy oznámení:
- Kód oznámení TBN_QUERYDELETE je odeslán, jakmile se uživatel pokusí tlačítko přesunout, ještě předtím než se zobrazí duchové tlačítko. Vraťte FALSE, abyste zabránili přesunutí tlačítka. Pokud vrátíte TRUE, uživatel bude moci nástroj přesunout nebo jej odstranit odstraněním z panelu nástrojů. Pokud je možné nástroj přesunout, můžete ho odstranit. Pokud však uživatel nástroj odstraní, ovládací prvek panelu nástrojů odešle aplikaci kód oznámení TBN_DELETINGBUTTON, v jakém okamžiku můžete zvolit opětovné vložení tlačítka do původního umístění, čímž odstranění zrušíte.
- Kód oznámení TBN_QUERYINSERT se odešle, když se uživatel pokusí tlačítko na panelu nástrojů vypustit. Chcete-li zabránit tomu, aby se tlačítko, které se přesouvá, dostalo na levou stranu tlačítka uvedeného v oznámení, vraťte FALSE. Tento kód oznámení se neodesílá, pokud uživatel nástroj odstraní z panelu nástrojů.
Pokud se uživatel pokusí přetáhnout tlačítko bez stisknutí klávesy SHIFT, ovládací prvek panelu nástrojů nezpracuje operaci přetažení. Aplikace však odešle kód oznámení TBN_BEGINDRAG označující začátek operace přetažení a kód oznámení TBN_ENDDRAG, který bude indikovat konec. Pokud chcete tuto formu přetažení povolit, musí aplikace zpracovávat tyto kódy oznámení, poskytovat potřebné uživatelské rozhraní a upravit panel nástrojů tak, aby odrážel všechny změny.
Ukládání a obnovování panelů nástrojů
V procesu přizpůsobení panelu nástrojů může vaše aplikace potřebovat uložit informace, abyste mohli panel nástrojů obnovit do původního stavu. Chcete-li zahájit ukládání nebo obnovení stavu panelu nástrojů, odešlete ovládacímu prvku panelu nástrojů TB_SAVERESTORE zprávu s parametrem wParam nastaveným na hodnotu TRUE. Hodnota wParam této zprávy určuje, jestli požadujete operaci uložení nebo obnovení. Po odeslání zprávy existují dva způsoby zpracování operace uložení nebo obnovení:
- U běžných ovládacích prvků verze 4.72 a starších je nutné implementovat obslužnou rutinu TBN_GETBUTTONINFO. Ovládací prvek panelu nástrojů odešle tento kód oznámení, aby požádal o informace o každém tlačítku při jeho obnovení.
- Verze 5.80 obsahuje možnost uložení/obnovení. Na začátku procesu a po uložení nebo obnovení každého tlačítka obdrží aplikace TBN_SAVE nebo TBN_RESTORE kód oznámení. Chcete-li použít tuto možnost, musíte implementovat obslužné rutiny oznámení, které poskytují rastrové obrázky a informace o stavu stavu potřebné k úspěšnému uložení nebo obnovení stavu panelu nástrojů.
Stavy panelu nástrojů se ukládají do datového proudu, který se skládá z bloků dat definovaných prostředím, které se střídají s bloky dat definovaných aplikací. Jeden datový blok každého typu se ukládá pro každé tlačítko spolu s volitelným blokem globálních dat, který můžou aplikace umístit na začátek datového proudu. Během procesu uložení přidá obslužná rutina TBN_SAVE do datového proudu bloky definované aplikací. Během procesu obnovení obslužná rutina TBN_RESTORE čte každý blok a poskytuje prostředí informace, které potřebuje k rekonstrukci panelu nástrojů.
Zpracování oznámení TBN_SAVE
První TBN_SAVE kód oznámení se odešle na začátku procesu uložení. Před uložením tlačítek jsou členy struktury NMTBSAVE nastaveny, jak je znázorněno v následující tabulce.
Člen | Nastavení |
---|---|
iPoložka | –1 |
cbData | Množství paměti potřebné pro data definovaná prostředím. |
cButtons | Počet tlačítek. |
pData | Vypočítané množství paměti potřebné pro data definovaná aplikací Obvykle zahrnete některá globální data a data pro každé tlačítko. Přidejte danou hodnotu do cbData a přidělte dostatek paměti pro pData k uložení všech. |
pCurrent | První nepoužitý bajt v datovém streamu. Pokud nepotřebujete informace o globálním panelu nástrojů, nastavte pCurrent = pData tak, aby odkazoval na začátek datového proudu. Pokud potřebujete informace o globálním panelu nástrojů, uložte je na pDataa před vrácením nastavte pCurrent na začátek nepoužívané části datového proudu. |
Pokud chcete přidat některé informace o globálním panelu nástrojů, umístěte je na začátek datového streamu. Posuňte pCurrent na konec globálních dat, aby odkazoval na začátek nepoužívané části datového streamu, a vraťte se.
Jakmile se vrátíte, shell začne ukládat informace o tlačítku. Přidá data definovaná prostředím pro první tlačítko na pCurrent a pak přejde pCurrent na začátek nepoužívané části.
Po uložení každého tlačítka se odešle kód oznámení TBN_SAVE a vrátí se NMTBSAVE, přičemž jsou tito členové nastaveni následujícím způsobem.
Člen | Nastavení |
---|---|
iPoložka | Index čísla tlačítka začínající od nuly. |
pCurrent | Ukazatel na první nepoužitý bajt v datovém streamu Pokud chcete uložit další informace o tlačítku, uložte ho do umístění, na které odkazuje pCurrent a aktualizujte pCurrent tak, aby odkazoval na první nepoužívané části datového proudu. |
TBBUTTON | Struktura TBBUTTON popisující tlačítko, které se ukládá. |
Když obdržíte kód oznámení, měli byste extrahovat všechny informace specifické pro tlačítko, které potřebujete z TBBUTTON. Mějte na paměti, že když přidáte tlačítko, můžete použít člena dwData ze struktury TBBUTTON k uchování dat specifických pro aplikaci. Načtěte data do datového streamu na pCurrent. Přeneste pCurrent na konec vašich dat, znovu ho nastavte tak, aby ukazoval na začátek nepoužité části streamu, a vraťte se.
Prostředí pak přejde na další tlačítko, přidá své informace do pData, přepne pCurrent, načte TBBUTTONa odešle další TBN_SAVE kód oznámení. Tento proces pokračuje, dokud nebudou uložena všechna tlačítka.
Obnovení uložených panelů nástrojů
Proces obnovení v podstatě obrátí proces uložení. Na začátku aplikace obdrží kód oznámení TBN_RESTORE s iItem členem struktury NMTBRESTORE nastavenou na –1. cbData člen je nastaven na velikost pDataa cButtons je nastaven na počet tlačítek.
Obslužná rutina oznámení by měla extrahovat globální informace, které byly umístěny na začátku pData během ukládání, a posunout pCurrent na začátek prvního bloku dat definovaných systémem Shell. Nastavte cBytesPerRecord na velikost datových bloků, které jste použili k uložení dat tlačítka. Nastavte cButtons na počet tlačítek a vraťte se.
Další NMTBRESTORE je pro první tlačítko. Člen pCurrent odkazuje na začátek prvního bloku dat tlačítek a iItem je nastaven na index tlačítka. Extrahujte tato data a pokračujte dále pCurrent. Načtěte data do TBBUTTONa pokračujte. Pokud chcete vynechat tlačítko z obnoveného panelu nástrojů, nastavte idCommand člen TBBUTTON na nulu. Shell zopakuje proces pro zbývající tlačítka. Kromě NMTBSAVE a NMTBRESTORE zprávy můžete také použít zprávy, jako je TBN_RESET k uložení a obnovení panelu nástrojů.
Následující příklad kódu uloží panel nástrojů před přizpůsobením a obnoví ho, pokud aplikace obdrží TBN_RESET zprávu.
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;
}
Související témata
-
hodnoty indexu obrázků v panelu nástrojů pro standardní tlačítka
-
ukázka běžných ovládacích prvků Windows (CppWindowsCommonControls)