27. Zprßvy Windows I
  1. DalÜφ aplikace ukazuje jak vytvo°it obsluhu pro zprßvu Win32. Tento p°φklad pou₧φvß makra mapovßnφ zprßv definovanß v SYSDEFS.H k obslou₧enφ zprßvy WM_GETMINMAXINFO. ZaΦneme v²voj novΘ aplikace. Rozm∞ry formulß°e zm∞nφme na 350 x 350. Na formulß° umφstφme Φty°i komponenty Label (v₧dy dv∞ vedle sebe) a zm∞nφme texty lev²ch komponent na èφ°ka a V²Üka. Texty prav²ch komponent zm∞nφme na 350. Dßle vytvo°φme obsluhu udßlosti OnResize formalß°e. Obsluha bude obsahovat p°φkazy:

  2. Label2->Caption = IntToStr(Width);
    Label4->Caption = IntToStr(Height);
    Kdy₧ nynφ aplikaci spustφme a m∞nφme velikost formulß°e, pak zobrazenΘ texty nßs informujφ o rozm∞rech formulß°e.  My ale po₧adujeme, aby rozm∞ry formulß°e bylo mo₧no m∞nit pouze v n∞jakΘm intervalu, nap°. mezi 300 a 400 body.
    Zprßva WM_GETMINMAXINFO je zaslßna oknu, kdy₧ je m∞n∞na velikost nebo pozice okna. Aplikace m∙₧e pou₧φt tuto zprßvu k p°epsßnφ minimßlnφ a maximßlnφ implicitnφ velikosti a pozice okna. Parametrem zprßvy je ukazatel na strukturu MINMAXINFO, kterß obsahuje implicitnφ hodnoty okna. Tyto implicitnφ hodnoty m∙₧eme p°epsat. Struktura MINMAXINFO je deklarovßna takto:
    typedef struct tagMINMAXINFO {
        POINT ptReserved;
        POINT ptMaxSize;
        POINT ptMaxPosition;
        POINT ptMinTrackSize;
        POINT ptMaxTrackSize;
    } MINMAXINFO;
    Slo₧ky struktury majφ tento v²znam:
     
    Slo₧ka V²znam
    ptReserved Rezervovßno
    ptMaxSize Specifikuje maximalizovanou Üφ°ku (point.x) a maximalizovanou v²Üku (point.y) okna.
    ptMaxPosition Specifikuje pozici levΘho okraje maximalizovanΘho okna (point.x) a pozici hornφho okraje maximalizovanΘho okna (point.y).
    ptMinTrackSize Specifikuje minimßlnφ Üφ°ku (point.x) a minimßlnφ v²Üku (point.y) okna.
    ptMaxTrackSize Specifikuje maximßlnφ Üφ°ku (point.x) a maximßlnφ v²Üku (point.y) okna.

    Vytvo°φme tedy ve°ejnou virtußlnφ metodu formulß°e nazvanou RestrictSize s nßsledujφcφm obsahem:
    void __fastcall TForm1::RestrictSize(TMessage& Msg)
    {
         ((POINT far *)Msg.LParam)[3].x = 300;
         ((POINT far *)Msg.LParam)[3].y = 300;
         ((POINT far *)Msg.LParam)[4].x = 400;
         ((POINT far *)Msg.LParam)[4].y = 400;
         TForm::Dispatch(&Msg);
    }
    a budeme se sna₧it namapovat zprßvu WM_GETMINMAXINFO na naÜi metodu RestrictSize, kterß zajistφ, ₧e Üφ°ka a v²Üka formulß°e se musφ pohybovat mezi 300 a 400. Pokud formulß° p°ijme zprßvu WM_GETMINMAXINFO, pak naÜe metoda zm∞nφ informace zprßvy o maximßlnφm a minimßlnφm rozm∞ru okna a volßnφm Dispatch je tato upravenß zprßva p°edßna souΦasnΘ obsluze udßlosti objektu formulß°e. Nßsleduje v²pis deklarace typu formulß°e, ve kterΘm je uvedeno po₧adovanΘ mapovßnφ:
    class TForm1 : public TForm
    {
    __published: // IDE-managed Components
            TLabel *Label1;
            TLabel *Label3;
            TLabel *Label2;
            TLabel *Label4;
            void __fastcall FormResize(TObject *Sender);
    private: // User declarations
    public:  // User declarations
            virtual __fastcall TForm1(TComponent* Owner);
            void virtual __fastcall RestrictSize(TMessage& Msg);
    // Toto mapovßnφ mapuje zprßvu WM_GETMINMAXINFO na funkci RestrictSize
    BEGIN_MESSAGE_MAP
    MESSAGE_HANDLER(WM_GETMINMAXINFO,TMessage,RestrictSize)
    // Zde lze p°idat dalÜφ mapovanΘ zprßvy.
    END_MESSAGE_MAP(TForm)
    };
    Nynφ, kdy₧ aplikaci p°elo₧φme a spustφme, vidφme, ₧e velikost okna lze m∞nit pouze v zadan²ch mezφch. Obdobn∞ je mo₧no provΘst mapovßnφ dalÜφch zprßv Windows. K mapovßnφ jsou pou₧ita makra BEGIN_MESSAGE_MAP, MESSAGE_HANDLER a END_MESSAGE_MAP.

  3. DalÜφ aplikace, se kterou se nynφ seznßmφme, je aplikace zobrazujφcφ seznam proces∙ b∞₧φcφch na naÜem poΦφtaΦi a umo₧≥ujφcφ zruÜenφ vybranΘho procesu. Jednß se op∞t o hotovou aplikaci. Aplikaci si stßhn∞te a vyzkouÜejte jak pracuje. Nynφ se podφvßme jak tato aplikace je vytvo°ena. Nejprve zaΦneme jednoduÜÜφmi Φinnostmi. VoliΦe ve spodnφ Φßsti formulß°e pouze urΦujφ barvu textu v komponent∞ ListBox. Obsluha udßlosti OnClick pro vÜechny Φty°i voliΦe je tvo°ena p°φkazy:

  4. TRadioButton *rbp =(TRadioButton*) Sender;
    ListBox1->Font->Color=rbp->Font->Color;
    Obsluhu udßlosti OnTimer ΦasovaΦe (pohybuje Üipkou na panelu nßstroj∙) tvo°φ (i je globßlnφ prom∞nnß deklarovanß na zaΦßtku zdrojovΘho souboru formulß°e):
    switch(i){
      case 0:{
        Image1->Picture->Bitmap->LoadFromResourceName(0,
                                     (AnsiString)"BITMAP_5");
        Image1->Refresh();
        i=1;
        return;
      }
      case 1:{
        Image1->Picture->Bitmap->LoadFromResourceName(0,
                                     (AnsiString)"BITMAP_2");
        Image1->Refresh();
        i=2;
        return;
      }
      case 2:{
        Image1->Picture->Bitmap->LoadFromResourceName(0,
                                     (AnsiString)"BITMAP_3");
        Image1->Refresh();
        i=3;
        return;
      }
      case 3:{
        Image1->Picture->Bitmap->LoadFromResourceName(0,
                                     (AnsiString)"BITMAP_4");
        Image1->Refresh();
        i=4;
        return;
      }
      case 4:{
       Image1->Picture->Bitmap->LoadFromResourceName(0,
                                     (AnsiString)"BITMAP_1");
        Image1->Refresh();
        i=0;
        return;
      }
    }
    Obsluha volby File | Exit je tvo°ena p°φkazem
    PostQuitMessage(0);
    Funkce API PostQuitMessage p°edßvß Windows po₧adavek na ukonΦenφ. Parametr funkce urΦuje ukonΦujφcφ k≤d aplikace. Funkce zasφlß zprßvu WM_QUIT front∞ zprßv vlßkna. Kdy₧ vlßkno zφskß zprßvu WM_QUIT ze svΘ fronty zprßv, ukonΦφ sv∙j cyklus zprßv a vracφ °φzenφ Windows.
    Volba Help | About zobrazφ okno s informacemi o programu. Obsluha tΘto volby nepot°ebuje ₧ßdnΘ vysv∞tlenφ.
    Obsluha stisku levΘho tlaΦφtka na palet∞ nßstroj∙ je tvo°ena p°φkazy (tato obsluha je vyvolßna i p°i volb∞ File | List Pids a File | Refresh List):
    long lp=0;
    ListBox1->Enabled=true;
    ListBox1->Clear();
    EnumWindows((WNDENUMPROC)EnumProc,lp);
    SpeedButton2->Enabled=true;
    SpeedButton3->Enabled=true;
    V tΘto obsluze je volßna funkce EnumWindows. Popis tΘto funkce bude uveden pozd∞ji. Obsluhu stisku druhΘho tlaΦφtka tvo°φ (ListBox je vyprßzdn∞n a zakßzßna dv∞ tlaΦφtka):
    ListBox1->Clear();
    SpeedButton3->Enabled=false;
    SpeedButton1->Enabled=false;
    Obsluhu stisku t°etφho tlaΦφtka tvo°φ p°φkazy (je zde volßna obsluha stisku prvnφho tlaΦφtka a poslednφ tlaΦφtko zakßzßno):
    SpeedButton4Click(0);
    SpeedButton1->Enabled=false;
    Obsluha udßlosti OnShow formulß°e tvo°φ p°φkazy (prom∞nnß stat je statickß prom∞nnß s poΦßteΦnφ hodnotou 1; je deklarovßna na poΦßtku programovΘ jednotky formulß°e):
    if(stat){
      stat= 0;
      ListBox1->Items->Add((AnsiString)"Click on 'pid' Tool button above");
    }
    Tato obsluha po prvnφm zobrazenφ formulß°e zobrazφ v ListBox text Click on 'pid' Tool button above. Nynφ se ji₧ v∞nujeme funkci EnumWindows. Tato funkce prochßzφ vÜechna okna nejvyÜÜφ ·rovn∞ (nezab²vß se pod°φzen²mi okny) na obrazovce a p°edßvß madlo ka₧dΘho z nich zp∞tn∞ volanΘ funkci. EnumWindows pokraΦuje a₧ do poslednφho okna nebo dokud zp∞tn∞ volanß funkce vracφ false. Funkce mß dva parametry. Prvnφm je ukazatel na zp∞tn∞ volanou funkci a druh² urΦuje hodnotu, kterß bude p°edßna zp∞tn∞ volanΘ funkci.
    V naÜem p°φklad∞ je funkcφ EnumWindows zp∞tn∞ volßna nßsledujφcφ funkce:
    bool __stdcall EnumProc(/*HWND*/void * hWnd,/*LPARAM*/long/*lp*/)
    {
       unsigned long* pPid;       //LPDWORD
       unsigned long result;      //DWORD
       void *hg;                  //HGLOBAL
       unsigned long id;
       if(hWnd==NULL) return false;
       hg = GlobalAlloc(GMEM_SHARE,sizeof(unsigned long));
       pPid = (unsigned long *)GlobalLock(hg);
       result = GetWindowThreadProcessId(hWnd,pPid);
       if(result){
          char title[110];
          char className[95];
          char totalStr[256];
          GetClassName(hWnd,className,95);
          GetWindowText(hWnd,title,110);
          id=*pPid;
          itoa(id,totalStr,10);
          strcat(totalStr,"\t");
          if(title){
             strcat(totalStr,title);
             strcat(totalStr,"\t");
          }
          strcat(totalStr,className);
          Form1->ListBox1->Items->Add((AnsiString)totalStr);
       }
       else{
          GlobalUnlock(hg);
          GlobalFree(hg);
          return false;
       }
       GlobalUnlock(hg);
       GlobalFree(hg);
       return true;
    }
    NaÜe funkce vytvß°φ seznam spuÜt∞n²ch proces∙. Pokuste se pochopit, jak tato funkce pracuje. V naÜem programu zb²vß jeÜt∞ obsluha udßlosti OnClick okna seznamu, kterou tvo°φ p°φkazy:
    SpeedButton1->Enabled=true;
    StatusBar1->SimpleText=
      "Select 'Kill Selected PID' to terminate the process";
    a obsluha stisku poslednφho tlaΦφtka (zruÜenφ vybranΘho procesu). Obsluhu stisku poslednφho tlaΦφtka tvo°φ:
    AnsiString str;
    char *tmp;
    int i;
    i= ListBox1->ItemIndex;
    if( i != -1){
      AnsiString s;
      tmp = new char[100];
      s=ListBox1->Items->Strings[i];
      strcpy(tmp,(char*)s.c_str());
      tmp=strtok(tmp,"\t");
    }
    int id=atoi(tmp);
    delete[] tmp;
    HANDLE ps = OpenProcess(1,false,id);
    if(ps){
      if(!TerminateProcess(ps,-9)){
        ShowMessage((AnsiString)"Could not end process specified!");
      }
      else{
        ShowMessage((AnsiString)"Process successfully terminated!");
      }
    }
    else{
      ShowMessage((AnsiString)"Could not open process requested!");
    }
    Pokuste se pochopit, jak tato obsluha pracuje.
27. Zprßvy Windows I