Hlavní
Hlavní strana
Seznam článků
Nejčtenější články
Progres e-mailem
Visual C++ FAQ

Seriály
COM
ISAPI

banner2.gif (2546 bytes)

Nenechte si ujít
Neobdélníková okna
Tisk bez Preview
MFC a DLL
Logo v MDI ploše
Kouzla s kombo-boxem
Výjimky v C++

banner.gif (3305 bytes)

Speciální panel ve stavové řádce Jan Odvárko
11.10.1999
[Hlavní stránka]  |  [Rubrika]

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.

jo_270999_statusbar_obr1.jpg (2672 bytes)

 

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ů.

  • Ready

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.

  • CAP

Indikátor klávesy Caps Lock, pokud je klávesa zapnutá je zobrazen text "CAP".

  • NUM

Indikátor klávesy Num Lock, pokud je klávesa zapnutá je zobrazen text "NUM".

  • SCRL

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.

jo_270999_statusbar_obr2.jpg (23448 bytes)

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.

jo_270999_statusbar_obr3.gif (5681 bytes)

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(25500));
  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ě.

jo_270999_statusbar_obr4.gif (1918 bytes)

 


Podobné články: Dynamický stavový řádek, Kouzla s kombo-boxem díl 4., Kouzla s kombo-boxem díl 5.,

Kdo Otázka nebo připomínka

Prohlížení příspěvků nebo nový příspěvek

O firmě... Kontakt Ostatní