28. Zprávy Windows II
  1. V další aplikaci se budeme zabývat umístěním a ovládáním aktivní ikony na pruhu úloh (pruh ve spodní části pracovní plochy Windows). Opět se jedná o již hotovou aplikaci. Stáhněte si ji a přeložte ji. Dříve než ji vyzkoušíte popíšeme si její kód.

  2. Pro práci s informační oblastí pruhu úloh se používají následující funkce a struktura Windows API (jsou definovány v shellapi.h). Funkce Shell_NotifyIcon zasílá zprávu systému. Pomocí této zprávy je možno přidávat, modifikovat nebo rušit ikony v pruhu úloh. Funkce vrací true při úspěšném provedení a false v opačném případě. Funkce má dva parametry. První parametr je identifikátor zasílané zprávy. Tento parametr může nabýt některé z následujících hodnot: NIM_ADD (přidává ikonu do informační oblasti pruhu úloh), NIM_DELETE (zruší ikonu v informační oblasti pruhu úloh) a NIM_MODIFY (provede modifikaci ikony v informační oblasti pruhu úloh). Druhý parametr je adresa struktury typu NOTIFYICONDATA. Tato struktura je definována takto:
    typedef struct _NOTIFYICONDATA { // nid
        DWORD cbSize;
        HWND hWnd;
        UINT uID;
        UINT uFlags;
        UINT uCallbackMessage;
        HICON hIcon;
        char szTip[64];
    } NOTIFYICONDATA, *PNOTIFYICONDATA;
    Struktura obsahuje informace, které systém potřebuje při provádění zpráv informační oblasti pruhu úloh. Složky struktury mají následující význam: cbSize (velikost struktury NOTIFYICONDATA), hWnd (madlo okna, které bude dostávat informační zprávy spojené s danou ikonou informační oblasti pruhu úloh), uID (aplikací definovaný identifikátor ikony pruhu úloh), uFlags (pole příznaků, které indikují platnost hodnot dalších položek této struktury; jedná se o kombinaci hodnot NIF_ICON, NIF_MESSAGE a NIF_TIP - určují platnost položek hIcon, uCallbackMessage a szTip), uCallbackMessage (aplikací definovaný identifikátor zprávy; systém používá tento identifikátor pro informační zprávy, které zasílá oknu specifikovanému hodnotou položky hWnd, kdykoliv nastane uvnitř hraničního obdélníku ikony událost myši), hIcon (madlo přidávané, modifikované nebo rušené ikony pruhu úloh) a szTip (informační text, který bude zobrazen pro ikonu pruhu úloh).
    V naší aplikaci je definována soukromá metoda TrayMessage přebírající identifikátor zasílané zprávy (NIM_ADD, NIM_DELETE nebo NIM_MODIFY). Tato metoda zjednodušuje práci s ikonami informačního pruhu úloh a má tento tvar:
    bool __fastcall TForm1::TrayMessage(DWORD dwMessage)
    {
       NOTIFYICONDATA tnd;
       PSTR pszTip;
       pszTip = TipText();
       tnd.cbSize          = sizeof(NOTIFYICONDATA);
       tnd.hWnd            = Handle;
       tnd.uID             = IDC_MYICON;
       tnd.uFlags          = NIF_MESSAGE | NIF_ICON | NIF_TIP;
       tnd.uCallbackMessage = MYWM_NOTIFY;
       if (dwMessage == NIM_MODIFY) {
         tnd.hIcon  = IconHandle();
         if (pszTip) lstrcpyn(tnd.szTip, pszTip, sizeof(tnd.szTip));
         else tnd.szTip[0] = '\0';
       }
       else {
         tnd.hIcon = NULL;
         tnd.szTip[0] = '\0';
       }
       return (Shell_NotifyIcon(dwMessage, &tnd));
    }
    Naše metoda naplní strukturu NOTIFYICONDATA a volá funkci Shell_NotifyIcon. Pro naplnění složek struktury jsou volány další soukromé metody. Např. pro zjištění informačního textu ikony je použita metoda TipText (na základě označeného voliče je použit text z příslušného editačního ovladače):
    PSTR __fastcall TForm1::TipText(void)
    {
      if (RadioButton1->Checked) return (Edit1->Text.c_str());
      else return (Edit2->Text.c_str());
    }
    Pro zjištění madla ikony se používá metoda:
    HANDLE __fastcall TForm1::IconHandle(void)
    {
      if (RadioButton1->Checked) return (Image1->Picture->Icon->Handle);
      else return (Image2->Picture->Icon->Handle);
    }
    V hlavičkovém souboru formuláře jsou definovány dvě konstanty (identifikátor zprávy a identifikátor ikony) a proměnná g_hinst:
    #define MYWM_NOTIFY   (WM_APP+100)
    #define IDC_MYICON    1006
    extern HINSTANCE g_hinst;
    Obsluha OnDestroy formuláře je tvořena příkazem:
    TrayMessage(NIM_DELETE);
    Obsluha kliknutí na značce Place on tray je tvořena příkazy:
    if (CheckBox1->Checked) {
      TrayMessage(NIM_ADD);
      TrayMessage(NIM_MODIFY);
    }
    else TrayMessage(NIM_DELETE);
    Button1->Enabled = CheckBox1->Checked;
    Obsluha kliknutí na obou voličích je tvořena příkazy:
    if (!CheckBox1->Checked) return;
    TrayMessage(NIM_MODIFY);
    Obsluha OnKeyUp obou editačních ovladačů je tvořena:
    if (!CheckBox1->Checked) return;
    TrayMessage(NIM_MODIFY);
    Obsluhu stisku tlačítka tvoří příkaz:
    Hide();
    Aplikace má také místní nabídku s volbami: Properties, Toggle State a Shutdown. Obsluhu volby Properties tvoří příkaz:
    Show();
    obsluhu Toggle State tvoří:
    ToggleState();
    a obsluhu Shutdown:
    Close();
    Formulář má další soukromou metodu ToggleState:
    void __fastcall TForm1::ToggleState(void)
    {
        if (RadioButton1->Checked)
        {
            RadioButton1->Checked = false;
            RadioButton2->Checked = true;
        }
        else
        {
            RadioButton2->Checked = false;
            RadioButton1->Checked = true;
        }
        TrayMessage(NIM_MODIFY);
    }
    Některé metody vyžadují madlo naší aplikace. Uložíme je tedy do proměnné g_hinst. Toto je provedeno ve zdrojovém souboru aplikace. Následuje výpis celého tohoto souboru:
    #include <vcl.h>
    #pragma hdrstop
    HINSTANCE g_hinst;
    USEFORM("traymain.cpp", Form1);
    USERES("trayicon.res");
    WINAPI WinMain(HINSTANCE, HINSTANCE hInstance, LPSTR, int)
    {
        Application->Initialize();
        g_hinst = hInstance;
        Application->CreateForm(__classid(TForm1), &Form1);
        Application->Run();
        return 0;
    }
    Vlastní zobrazení ikony je prováděno funkcí IconDrawItem. Tato funkce má následující obsah:
    LRESULT IconDrawItem(LPDRAWITEMSTRUCT lpdi)
    {
     HICON hIcon;
     hIcon = (HICON)LoadImage(g_hinst, MAKEINTRESOURCE(lpdi->CtlID),
             IMAGE_ICON, 16, 16, 0);
     if (!hIcon) return(FALSE);
     DrawIconEx(lpdi->hDC, lpdi->rcItem.left, lpdi->rcItem.top, hIcon,
                16, 16, 0, NULL, DI_NORMAL);
     return(TRUE);
    }
    Naše aplikace také obsahuje mapování zpráv:
    BEGIN_MESSAGE_MAP
    MESSAGE_HANDLER(WM_DRAWITEM,TMessage,DrawItem)
    MESSAGE_HANDLER(MYWM_NOTIFY,TMessage,MyNotify)
    END_MESSAGE_MAP(TForm)
    Zbývají ještě další dvě soukromé metody formuláře a to DrawItem (mapována na zprávu WM_DRAWITEM) a MyNotify (mapována na zprávu kliknutí na naší ikoně). Obsah těchto metod je:
    void __fastcall TForm1::DrawItem(TMessage& Msg)
    {
         IconDrawItem((LPDRAWITEMSTRUCT)Msg.LParam);
         TForm::Dispatch(&Msg);
    }
    void __fastcall TForm1::MyNotify(TMessage& Msg)
    {
        POINT MousePos;
        switch(Msg.LParam)
        {
            case WM_RBUTTONUP:
                if (GetCursorPos(&MousePos))
                {
                    PopupMenu1->PopupComponent = Form1;
                    SetForegroundWindow(Handle);
                    PopupMenu1->Popup(MousePos.x, MousePos.y);
                }
                else Show();
                break;
            case WM_LBUTTONUP:
                ToggleState();
                break;
            default:
                break;
        }
        TForm::Dispatch(&Msg);
    }
    Tím je popis této aplikace dokončen. Pokuste se pochopit, jak aplikace pracuje.
  3. Další aplikací, kterou se budeme zabývat je opět hotová aplikace. Stáhněte si ji. Tato aplikace se skládá ze samotného formuláře (neobsahuje žádnou komponentu). Formulář má tři obsluhy událostí (OnActivate, OnPaint a OnMouseMove) a jeho konstruktor obsahuje několik příkazů. Všechny potřebné komponenty jsou vytvořeny v obsluze OnActivate formuláře. Je zde také mapována funkce SetCursor na zprávu WM_SETCURSOR. V konstruktoru formuláře je přiřazena funkce IdleLoop události OnIdle aplikace (činnost prováděná v době nečinnosti aplikace; v našem případě se vlastně činnost aplikace provádí v době nečinnosti aplikace). Aplikaci vyzkoušejte a podívejte se, jak je naprogramována.
  4. Po vytvoření a odladění aplikace, aplikaci můžeme šířit, tj. předávat ji dalším uživatelům k používání. Spustitelný soubor aplikace může požadovat další soubory (DLL, soubory balíčků a nápovědný soubor aplikace). Registry Windows mohou obsahovat položky pro aplikaci (např. umístění požadovaných souborů). Proces kopírování aplikačních souborů na počítač a provedení požadovaného nastavení registrů může být automatizováno instalačním programem (např. pomocí InstallShield Express).

  5. Jednoduchá aplikace C++ Builderu, která se skládá pouze z jednoho souboru (EXE) se na cílovém počítači instaluje snadno. Spustitelný soubor pouze překopírujeme do počítače. Složitější aplikace skládající se z mnoha souborů požadují podstatně složitější instalační procedury. Tyto aplikace vyžadují instalační programy. K vytváření instalačních programů je možno použít např. nástroj InstallShield Express. Instalační programy vytvořené tímto nástrojem provádějí různé úlohy nutné k instalaci aplikací C++ Builderu, včetně kopírování spustitelných a dalších potřebných souborů na cílový počítač, nastavení registrů Windows a instalování BDE pro databázové aplikace.
    Mimo spustitelného souboru, může být nutno distribuovat několik dalších souborů. Pokud aplikace používá běhové balíčky, pak soubory těchto balíčků je nutno distribuovat s aplikací. S balíčky zacházíme stejně jako s DLL, překopírujeme soubory a nastavíme nutné položky v registrech Windows. Systémové běhové balíčky je vhodné instalovat do adresáře Windows\System (více aplikací může sdílet stejné balíčky). Námi vytvořené balíčky je vhodné instalovat do stejného adresáře jako aplikaci. Je nutno distribuovat pouze soubory BPL balíčků.
    Jisté komponenty C++ Builderu jsou ovladače ActiveX. Obal těchto komponent je sestaven do spustitelného souboru aplikace (nebo do běhových balíčků), ale soubory OCX těchto komponent musí být také distribuovány s aplikací. Jedná se o komponenty: ChartFX, VisualSpeller, Formula One, FirstImpression, Graph Custom a Internetovské ovladače firmy NetMasters.
    Některé komponenty ze stránky Win32 Palety komponent pracují spolehlivě až s verzí 4.70 COMCTL32.DLL. Jedná se např. o vlastnosti DisabledImages, Flat, HotImages a Images komponenty ToolBar. U dalších komponent jsou to některé jiné vlastnosti. Komponenty TCoolBar a TDateTimePicker před verzí 4.70 COMCTL32.DLL nepracovaly vůbec.
    S aplikací je také vhodné šířit soubor nápovědy (pokud existuje).
  6. Aplikace přistupující k databázím požadují složitější instalaci. Přístup k databázi je často zpracováván samostatným modulem přístupu k databázi (skládá se ze souborů, které nemohou být sestaveny do spustitelného souboru aplikace). Datové soubory musí být dostupné z aplikace. Vícevrstvové databázové aplikace vyžadují specializovanou instalaci (soubory jsou obvykle umístěny na více počítačích).

  7. Přístup k databázi pro aplikaci je prováděn různými moduly přístupu k databázi. Aplikace může použít BDE nebo moduly přístupu k databázi dalších firem. Verze Client/Server C++ Builderu také umožňuje přirozený přístup k databázovým systémům SQL.
    Pro databázové aplikace, instalační program musí provést instalaci dalších potřebných souborů a nastavit potřebné registry. Totéž platí i pro Internetovské aplikace.
  8. Přirozené prostředí Windows je ovlivněno několika faktory závisejícími na uživatelských preferencích a konfiguraci. Jedná se především o:
  9. Velikost pracovní plochy Windows a počet dostupných barev jsou konfigurovatelné a závisí na instalovaném hardware. Tyto atributy se také mohou lišit na počítači vývojáře a počítači uživatele. Vzhled aplikace (okno, objekt a velikost písma) pro konfigurace počítače s různým rozlišením obrazovky může být zpracováno několika způsoby: Problémy použitého písma je nutno řešit tak, že předpokládáme standardní písma na všech počítačích a při použití nestandardního písma, tato písma distribuujeme s aplikací.
    Když používáme funkce Windows API nebo zpřístupňujeme oblasti operačního systému, pak je možné, že některé funkce nemusí být dostupné na počítačích s jinou verzí operačního systému. Např. Služby jsou použitelné pouze pro operační systém Windows NT. Verzí operačního systému se také při šíření našich programů musíme zabývat. Je nutno alespoň specifikovat požadavky na operační systém, případně nedovolit instalačnímu programu instalaci na počítač s nevyhovujícím systémem.
28. Zprávy Windows II