1. Úvod
Asi mi dáte za pravdu, že Stavový řádek (StatusBar) je stejně důležitá součást
aplikace jako například Nástrojová lišta (ToolBar). Avšak pokud prostudujeme knihovnu MFC zjistíme, že Stavový
řádek nemá zdaleka takové grafické možnosti jako zmíněná Nástrojová lišta.
Ukažme si tedy jakým způsobem můžeme sami vykreslit obsah panelu ve stavovém
řádku.

2. Stavový řádek vs. MFC
Standardní stavový řádek je zobrazen na
předcházejícím obrázku. Takto jej můžete vidět například v MDI aplikaci, která
je vygenerovaná pomocí AppWizardu. Tento řádek se skládá ze čtyř panelů.
|
Tento panel nemá
prostorový rámeček a slouží pro zobrazení nápovědy k položkám menu a
tlačítkům v nástrojové liště. Standardně zabírá zbývající plochu celého
stavového řádku. |
|
Indikátor klávesy Caps Lock,
pokud je klávesa zapnutá je zobrazen text "CAP". |
|
Indikátor klávesy Num Lock,
pokud je klávesa zapnutá je zobrazen text "NUM". |
|
Indikátor klávesy Scroll Lock,
pokud je klávesa zapnutá je zobrazen text "SCRL". |
Stavový řádek je v
knihovně MFC reprezentován třídou CStatusBar.
Tato třída umožňuje vytvářet panely a nastavovat jim text. Za vytvoření řádku je
obvykle odpovědná třída CMainFrame. V
implementačním souboru (.CPP) této třídy je ještě umístěno pole, které definuje
jednotlivé panely. Podívejme se na následující zdrojový kód.
static UINT indicators[] =
{
ID_SEPARATOR, // status line indicator
ID_INDICATOR_CAPS,
ID_INDICATOR_NUM,
ID_INDICATOR_SCRL,
};
|
Pole určuje počet panelů ve stavovém řádku a
každému panelu přiřazuje jednoznačný identifikátor (ID). Jak uvidíme později
přidání panelu se provede přidáním položky do tohoto pole. Vytvoření stavového řádku se provádí v metodě OnCreate ve třídě CMainFrame.
int CMainFrame::OnCreate(LPCREATESTRUCT lpCreateStruct)
{
...
if (!m_wndStatusBar.Create(this) ||
!m_wndStatusBar.SetIndicators(indicators,
sizeof(indicators)/sizeof(UINT)))
{
TRACE0("Failed to create status bar\n");
return -1; // fail to create
}
...
}
|
Jak je vidět z ukázky
zdrojového kódu, nejdříve se volá metoda Create, která Stavový řádek vytvoří a následně jsou vytvořeny
panely voláním metody SetIndicators.
3. Stavový řádek vs. MFC
Naším prvním úkolem bude vložení nového
panelu do Stavové řádky. Pokud ještě nemáte připravený projekt, tak pomocí AppWizardu vygenerujte MDI aplikaci (není
třeba měnit žádné nastavení). Do tabulky řetězců (string table) vložíme novou položku jejíž jméno bude ID_INDICATOR_NEW.

V
implementačním souboru třídy CMainFrame rozšíříme pole indicators o nově vzniklé ID.
static UINT indicators[] =
{
ID_SEPARATOR, // status line indicator
ID_INDICATOR_NEW, // Nový panel
ID_INDICATOR_CAPS,
ID_INDICATOR_NUM,
ID_INDICATOR_SCRL,
};
|
Pokud přeložíte a spustíte bude Stavová lišta
vypadat následovně. Všimněte si, že šířka vloženého panelu je odvozena od
šířky textu.

Nastavení textu v panelu
provedeme pomocí metody SetPaneText ze třídy CStatusBar. Pokud chceme zjistit jaký text se v panelu nachází použijeme
metodu GetPaneText.
BOOL SetPaneText( int nIndex, LPCTSTR lpszNewText,
BOOL bUpdate = TRUE );
CString GetPaneText( int nIndex ) const;
|
3. Vykreslení panelu
Protože třída CStatusBar nám nedává možnost změnit vizuální vzhled panelu
(kromě změny prostorového rámečku), zkusíme si obsah panelu vykreslit sami. Pomocí ClassWizardu vygenerujte novou
třídu CMyStatusBar, která bude dědit ze
třídy CStatusBar. V této třídě
implementujte virtuální metodu DrawItem. Tato metoda je automaticky
volána pro vykreslení jednoho panelu. V našem případě
vykreslíme panel přidaný v předchozí kapitole (jeho index je 1).
class CMyStatusBar : public CStatusBar
{
...
virtual void DrawItem(LPDRAWITEMSTRUCT lpdis);
...
};
void CMyStatusBar::DrawItem(LPDRAWITEMSTRUCT lpdis)
{
ASSERT(lpdis->itemID == 1);
CDC* pdc = CDC::FromHandle(lpdis->hDC);
CRect rcItem(lpdis->rcItem);
int nBkMode = pdc->SetBkMode(TRANSPARENT);
COLORREF nBkColor = pdc->GetBkColor();
pdc->FillSolidRect(rcItem, RGB(255, 0, 0));
pdc->DrawText(GetPaneText(1),
rcItem, DT_SINGLELINE|DT_CENTER|DT_VCENTER);
pdc->SetBkMode(nBkMode);
pdc->SetBkColor(nBkColor);
}
|
Pokud máme třídu správně připravenou, můžeme
přistoupit k její u použití. Ve třídě CMainFrame změníme typ proměnné m_wndStatusBar.
class CMainFrame : public CMDIFrameWnd
{
...
protected: // control bar embedded members
CMyStatusBar m_wndStatusBar;
CToolBar m_wndToolBar;
...
};
|
Posledním krokem je nastavení
speciálního stylu, který zajistí volání metody DrawItem tímto stylem je SBT_OWNERDRAW, který se nastavuje každému panelu zvlášť. My tento styl
nastavíme našemu novému panelu. Nastavení se provádí v metodě OnCreate ve třídě CMainFrame.
int CMainFrame::OnCreate(LPCREATESTRUCT lpCreateStruct)
{
...
UINT nID, nStyle;
int cxWidth;
m_wndStatusBar.GetPaneInfo(1, nID, nStyle, cxWidth);
m_wndStatusBar.SetPaneInfo(1, nID, nStyle|SBT_OWNERDRAW,
cxWidth);
return 0;
}
|
Pokud vše správně
naprogramujete a přeložíte měl by Stavový řádek vypadat následovně.

|