Učíme se Win API - 13. - Builder.cz - Informacni server o programovani

Odběr fotomagazínu

Fotografický magazín "iZIN IDIF" každý týden ve Vašem e-mailu.
Co nového ve světě fotografie!

 

Zadejte Vaši e-mailovou adresu:

Kamarád fotí rád?

Přihlas ho k odběru fotomagazínu!

 

Zadejte e-mailovou adresu kamaráda:



C/C++

Učíme se Win API - 13.

winapi_logo

2. dubna 2002, 00.00 | V tomto pokračování se začneme zabývat prací s běžnými dialogovými prvky. Bude se jednat o edit, check-box, static a button. Naučíme se detekovat akce uživatele na těchto prvcích a reagovat na ně.

V předchozím článku jsme si ukázali, jak vytvořit ten nejjednodušší dialog, založený na standardní třídě dialogových oken. Umíme už zjistit, jakým způsobem uživatel dialog ukončil, tedy v typickém případě rozlišit stick "OK" a "Storno". V tomto pokračování se začneme zabývat prací s běžnými dialogovými prvky.

Jedním ze specifických rysů dialogového okna je, že prvky na něm umístěné definujeme ve skriptu zdrojů a nemusíme je vytvářet "ručně" pomocí CreateWindowEx. Výhodou je kromě zjednodušení kódu snadná práce s rozmístěním prvků na dialogu (pokud samozřejmě používáme nějaký vizuální editor zdrojů).

Začneme tím, že si na dialog umístíme jedno editační pole (IDC_EDIT1), tlačítko (IDC_ZOBRAZ_TEXT), prvek Static text (IDC_KOPIE) a check-box (IDC_SLEDOVAT). Identifikátory prvků uvedené v závorkách si samozřejmě můžete zvolit podle svého, pak budete muset upravit i zdrojový kód. Cílem v této fázi bude naučit se jak získat text obsahu edit-boxu, jak zjistit okamžitý stav zaškrtnutí check-boxu a jak zachytit událost, kdy dojde ke změně obsahu edit-boxu, tedy když uživatel zapíše či smaže znak. Řekněme, že budeme chtít po stisknutí tlačítka přenést aktuální obsah edit-boxu do titulku hlavního okna aplikace. Tím se také přesvědčíme o tom, že i když je otevřen modální dialog, další okna aplikace mohou běžně přijímat zprávy a reagovat na ně, i když pro uživatele jsou v té době nedostupná.

V proceduře dialogu již máme handler zprávy WM_COMMAND, kde zachytáváme stisk tlačítek "OK" a "Storno". Přidejme tedy do handleru WM_COMMAND následující case:

case IDC_ZOBRAZ_TEXT:
  GetDlgItemText(hwndDlg, IDC_EDIT1, chText, 200);
  SendMessage(g_hwndMain, WM_SETTEXT, 0, (LPARAM)chText);
  break;

To je vše co musíme udělat pro přenesení textu edit-boxu do titulku hlavního okna. Jak je vidět, pro získání textu prvku na dialogu můžeme použít funkci GetDlgItemText:

UINT GetDlgItemText(
  HWND hDlg,       // handle okna dialogu
  int nIDDlgItem,  // identifikátor prvku
  LPTSTR lpString, // buffer pro text
  int nMaxCount    // maximální počet zkopírovaných znaků
);

Samozřejmě bychom mohli použít již dříve uvedenou funkci GetWindowText. Pak bychom ale museli získat handle (HWND) prvku (edit-boxu). K získání handle kteréhokoli prvku na dialogu slouží funkce GetDlgItem:

HWND GetDlgItem(
  HWND hDlg,       // handle okna dialogu
  int nIDDlgItem   // identifikátro prvku
);

Řekněme si ještě o funkci, která nám vrátí číselnou hodnotu (pokud ji lze převést) obsahu prvku dialogu. U edit-boxu je možné a výhodné pro tento případ nastavit v editoru zdrojů vlastnost "Number" odpovídající stylu okna ES_NUMBER. Příslušnou funkcí je pak GetDlgItemInt:

UINT GetDlgItemInt(
  HWND hDlg,           // handle okna dialogu
  int nIDDlgItem,      // identifikátor prvku
  BOOL *lpTranslated,  // indikátor úspešného převodu
  BOOL bSigned         // zda jde o hodnotu se znaménkem
);

Tato funkce nám vrátí číselnou hodnotu obsahu prvku, pokud má obsah číselný smysl. Úspěšnost převodu je uložena do parametru lpTranslated.

Dále si řekneme, jak zjistíme v požadovaném okamžiku stav zaškrtnutí check-boxu. Zde zjistíme, že jednou z nejčastěji používaných funkcí je SendMessage, tedy funkce která pošle zvolenému oknu zprávu, která může sloužit k "ovládání" okna, tedy například nastavení textu, přidání řádku do list-boxu a stovky podobných. Kromě toho tato funkce vrací výsledek zpracování zprávy v příslušném okně. Mnoho zpráv je totiž dotazovacích, kterými požadujeme od cílového okna nějakou informaci, například právě stav zaškrtnutí check-boxu. V dialogových oknem můžeme místo SendMessage použít funkci SendDlgItemMessage:

LRESULT SendDlgItemMessage(
  HWND hDlg,      // handle okna dialogu
  int nIDDlgItem, // identifikátor prvku
  UINT Msg,       // kód zprávy
  WPARAM wParam,  // 1. parametr zprávy
  LPARAM lParam   // 2. parametr
);

V této funkci nemusíme uvádět handle okna, ale místi toho identifikátor prvku dialogu a systém si handle zjistí sám. Je to obdobná jako u vztahu funkcí GetWindowText a GetDlgItemText.

V případě zjištení stavu check-boxu použijeme zprávu BM_GETCHECK. Identifikátor zprávy začíná na "BM", což je ze slov "button message". Znamená to, že check-box je prvek třídy "BUTTON". Návratová hodnota zprávy (tedy to co nám vrátí funkce SendMessage nebo SendDlgItemMessage) pak může být jednou ze 3 hodnot:

  • BST_CHECKED - check-box je zaškrtnut
  • BST_UNCHECKED - check-box není zaškrtnutý
  • BST_INDETERMINATE - check-box je "zašedlý", tedy v neurčitém stavu

V této souvislosti si řekněme o "opačné" zprávě, tedy nastavení stavu check-boxu programově. Tou zprávou je BM_SETCHECK, a v parametru wParam zprávy SendDlgItemMessage uvedeme jeden z výše uvedených stavů, do kterého chceme check-box nastavit. Toto počáteční nastavení se obvykle realizuje v handleru zprávy WM_INITDIALOG, kterou obdržíme pouze jednou "na začátku" po vytvoření dialogového okna, těsně před tím, než je dialog zobrazen.

Nakonec si ukážeme, jak sledovat jakékoli změny v obsahu editačního pole. V tomto případě je posílána tzv. oznamovací (notifikační) zpráva EN_CHANGE. Tato a další oznamovací zprávy nejsou ve skutečnosti samostatnými zprávami, ale jsou posílány jako horní WORD parametru wParam zprávy WM_COMMAND. Vše si ukážeme na příkladě, ve kterém budeme změny v editačním poli "kopírovat" do prvku "static text", tedy při každé zachycení změny obsahu editu (IDC_EDIT1), zjistíme jeho obsah a ten nastavíme jako text prvku static text (IDC_KOPIE). Toto budeme provádět pouze pokud je v daném okamžiku zaškrtnut check-box (IDC_SLEDOVAT). Do handleru WM_COMMAND si přidejme násjedující kód, který vše zrealizuje:

case IDC_EDIT1:
  if ( HIWORD(wParam) == EN_CHANGE )
  {
    if(SendDlgItemMessage(hwndDlg,IDC_SLEDOVAT, BM_GETCHECK,0,0)==BST_CHECKED)
    {
      GetDlgItemText(hwndDlg, IDC_EDIT1, chText, 200);
      SetDlgItemText(hwndDlg, IDC_KOPIE, chText);
    }
  }
  break;

Výsledek "v akci" vidíte na následujícím obrázku:

Ještě si můžeme nastavit výchozí stav check-boxu na zaškrtnutý v handleru zmíněné zprávy WM_INITDIALOG:

case WM_INITDIALOG:
  SendDlgItemMessage(hwndDlg, IDC_SLEDOVAT, BM_SETCHECK, BST_CHECKED, 0);
  break;

Tolik pro toto pokračování a příště se samozřejmě budeme prvkům na dialogu dále věnovat, neboť jde o základní část většiny programů, tedy uživatelské rozhraní. Doprovodný projekt si můžete stáhnout zde: win_api_13.zip.

Obsah seriálu (více o seriálu):

Tématické zařazení:

 » Rubriky  » C/C++  

Poslat článek

Nyní máte možnost poslat odkaz článku svým přátelům:

Váš e-mail:

(Není povinný)

E-mail adresáta:

Odkaz článku:

Vzkaz:

Kontrola:

Do spodního pole opište z obrázku 5 znaků:

Kód pro ověření

 

 

 

 

Nejčtenější články
Nejlépe hodnocené články

 

Přihlášení k mému účtu

Uživatelské jméno:

Heslo: