Dobrodružství v C#

Jak odkrýt zákoutí jazyka C#

Časová náročnost (min):

Začátečník

Pokročilý

Profesionál

Použitý operační systém : Hlavní vývojový nástroj :

Další vývojový software :

Jiný software :

Windows 2000 SP4

Visual C# .NET 2003

Žádný

Žádný

 

 

 

Obsah

Obtížnost

Čas (min)

 Přidávání instancí ovládacích prvků na formulář za běhu aplikace

* Překrytí metody OnPaint formuláře

* Strukturovaná správa chyb v praxi

* Volání metody bázové třídy z odvozené třídy

 

 

Přidávání instancí ovládacích prvků na formulář za běhu aplikace

 

Integrované prostředí jazyka C# nabízí, podobně jako i další programovací nástroje Visual Studia .NET, vizuální návrhář, pomocí kterého si můžete podobu vyvíjené aplikace upravit podle svých potřeb. Zcela jistě se shodneme na tom, že přítomnost vizuálního návrháře je velice praktickým prvkem integrovaného prostředí, ovšem lze jej použít jenom v rámci režimu návrhu aplikace. Pokud ovšem budete chtít přidávat na plochu formuláře instance ovládacích prvků přímo za běhu programu, budete se muset přiklonit k psaní programového kódu. Jelikož je přidávání a potažmo i odstraňování instancí ovládacích prvků z formuláře aplikace docela běžnou záležitostí, vysvětlíme si, jak tuto úlohu splnit nejrychlejším možným způsobem. Postupujte takto:

 

  1. Spusťte Visual C# .NET 2003 a vytvořte standardní aplikaci pro Windows (Windows Application).
  2. Na plochu formuláře umístěte jednu instanci ovládacího prvku Button, kterou nechte implicitně pojmenovanou (button1).
  3. Poklepejte na přidanou instanci prvku Button, čímž nařídíte vytvoření kostry zpracovatele události Click této instance. Podobu zpracovatele události button1_Click upravte takto:

 

            //Po aktivaci metody bude na stávající formulář přidána

            //instance ovládacího prvku Button.

            private void button1_Click(object sender, System.EventArgs e)

            {

                  //Vytvoření instance třídy Button a uložení odkazu

                  //na vzniklou instanci do referenční proměnné Tlačítko_01

                  Button Tlačítko_01 = new Button();

 

                  //Nastavení návěstí vytvořené instance třídy Button.

                  Tlačítko_01.Text = "Spustit aplikaci";

 

                  //Nastavení velikosti (šířky a výšky) vytvořené instance

                  //třídy Button.

                  Tlačítko_01.Size = new Size(100, 50);

 

                  //Určení pozice (x, y) levého horního rohu vytvořené instance

                  //třídy Button (Pozice instance ovládacího prvku je určená

                  //relativně ve vztahu k formuláři).

                  Tlačítko_01.Location = new Point(10, 125);

 

                  //Přidání vytvořené instance třídy Button do kolekce

                  //ovládacích prvků formuláře. Za tímto účelem použijeme

                  //metodu Add třídy System.Windows.Forms.Control.ControlCollection.

 

                  this.Controls.Add(Tlačítko_01);

            }

 

Novou instanci ovládacího prvku, resp. třídy Button provedeme pomocí přiřazovacího příkazu a operátoru new. Pomineme-li modifikaci různých vlastností vytvořené instance, dojdeme k závěru, že veškerou práci potřebnou pro přidání nové instance na formulář, realizuje finální řádek programového kódu:

 

 

            this.Controls.Add(Tlačítko_01);

  

Klíčové slovo this představuje aktuální instanci formuláře, přesněji řečeno aktuální instanci třídy Form1. Přístup ke všem instancím ovládacích prvků, které se na formuláři nacházejí, poskytuje kolekce instancí s názvem Controls. Použijeme-li metodu Add s názvem instance, kterou chceme přidat na plochu aktivního formuláře, bude tato instance přidána právě do kolekce instancí Controls. Připomeňme, že přidání instance do kolekce Controls tuto instanci na formuláři také zviditelní (není tedy nutné dodatečně nastavovat vlastnosti Visible vytvořené instance na hodnotu True).

 

  1. Spusťte aplikaci (klávesa F5) a klepněte na instanci ovládacího prvku Button, kterou jste na formulář přidali v době návrhu. Pracuje-li programový kód, jenž je umístěn ve zpracovateli události button1_Click správně, mělo by se na ploše formuláře objevit další tlačítko s nápisem Spustit aplikaci. Výborně, dokázali jste přidat na formulář tlačítko za běhu programu. Pokud ovšem klepnete na toto tlačítko, nic se nestane. Je to proto, že událost Click vytvořené instance není asociována se žádným smysluplným zpracovatelem. Budete-li chtít, aby se po klepnutí na instanci spustila skutečná aplikace, vložte za poslední řádek zpracovatele události button1_Click tento řádek zdrojového kódu (komentáře můžete samozřejmě vynechat):

 

            //Vytvoření asociace mezi událostí Click vytvořené instance

            //třídy Button a jejím zpracovatelem.

            Tlačítko_01.Click +=new EventHandler(Tlačítko_01_Click);

 

  1. Ve verzi 2003 vám C# nabídne možnost vytvořit asociaci mezi událostí a jejím zpracovatelem velmi intuitivním způsobem (v zásadě stačí jenom potvrdit vytvoření asociace klávesou Tab). V rámci druhé aktivace klávesy Tab bude pro vás dokonce vytvořena také programová kostra zpracovatele události Tlačítko_01_Click. Kód zpracovatele této události modifikujte takto:

 

            //Programová konstrukce zpracovatele události Tlačítko_01_Click

            private void Tlačítko_01_Click(object sender, EventArgs e)

            {

                  //Vytvoření instance třídy Process, která se nachází v jmenném

                  //prostoru System.Diagnostics.

                  System.Diagnostics.Process Aplikace_01 =

                        new System.Diagnostics.Process();

                 

                  //Specifikace názvu aplikace, kterou budeme chtít spustit.

                  //Za tímto účelem použijeme vlastnost FileName.

                  Aplikace_01.StartInfo.FileName = "Notepad";

 

                  //Zavoláním metody Start spustíme vybranou aplikaci.

                  Aplikace_01.Start();

            }

 

 

Zpět na obsah

 

Překrytí metody OnPaint formuláře

 

Metoda OnPaint reaguje na událost Paint, ke které dojde vždy v okamžiku překreslení formuláře. Pokud překryjeme metodu OnPaint formuláře, budeme moci zajistit, aby se při každém překreslení plochy formuláře uskutečnil jistý fragment programového kódu. Ačkoliv lze do překryté metody OnPaint umístit jakékoliv platné programové instrukce, nejčastěji se tělo této překryté metody používá pro modifikaci grafické reprezentace formuláře jako takového. Jak jistě víte, implicitně je barva pozadí formuláře šedá, ovšem pokud překryjeme metodu OnPaint tohoto formuláře, můžeme sami určit, jakou barvu pozadí má formulář mít.

 

Pro překrytí metody OnPaint formuláře Form1 udělejte následovní:

 

  1. Spusťte Visual C# .NET 2003 a vytvořte standardní aplikaci pro Windows (Windows Application).
  2. Vyberte nabídku View a klepněte na položku Class View. Okamžitě se zviditelní dialogové okno Class View.

 

Tip

Dialogové okno Class View můžete zobrazit i prostřednictvím klávesové zkratky CTRL+SHIFT+C. Okno Class View sdílí společný region s dalšími okny (např. Solution Explorer či Resource View). 

 

  1. Rozbalujte postupně jednotlivé položky stromové struktury jmenných prostorů a tříd:

 

·          Název projektu

·          Název jmenného prostoru

·          Form1

·          Bases and Interfaces

·          Form

 

  1. Vyhledejte položku s názvem OnPaint a klepněte na ní pravým tlačítkem myši.
  2. Z kontextové nabídky vyberte položku Add a posléze klikněte na položku Override (obr. 1).

 

 

Obr. 1 – Proces překrytí metody OnPaint formuláře

 

  1. C# vytvoří programovou kostru překryté varianty metody OnPaint:

 

            protected override void OnPaint(PaintEventArgs e)

            {

                  // TODO:  Add Form1.OnPaint implementation

                  base.OnPaint (e);

            }

 

  1. Pro změnu barvy pozadí formuláře modifikujte překrytou metodu OnPaint následovně:

 

            protected override void OnPaint(PaintEventArgs e)

            {

                  //Vytvoření nové instance struktury System.Drawing.Rectangle.

                  Rectangle GObdélník = new Rectangle(new Point(0, 0),

                        new Size(this.Width, this.Height));

 

                  //Vytvoření nového grafického štětce, který je sestaven

                  //ze třídy LinearGradientBrush.

                  LinearGradientBrush GŠtětec = new LinearGradientBrush(GObdélník,

                        Color.Red, Color.Orange, LinearGradientMode.ForwardDiagonal);

                 

                  //Deklarace referenční proměnné GObjekt, do které je uložen

                  //odkaz na objekt Graphics, jenž představuje plochu, na kterou

                  //se bude kreslit. V našem případě jde o plochu aktuální instance

                  //třídy Form1.

                  Graphics GObjekt = e.Graphics;

 

                  //Aplikace metody FillRectangle, která má na starosti práce

                  //spojené s vyplněním plochy aktuální instance třídy Form1

                  //gradientní výplní.

                  GObjekt.FillRectangle(GŠtětec, GObdélník);

                 

                  //Uvolnění zdrojů, které byly alokovány příslušnými grafickými

                  //objekty.

                  GObjekt.Dispose();

                  GŠtětec.Dispose();

 

                  //Volání metody OnPaint bázové třídy. Bázovou třídou

                  //je třída Control.

                  base.OnPaint (e);

            }

 

 

  1. Jestliže spustíte aplikaci, uvidíte, že barva pozadí formuláře je opravdu jiná (obr. 2).

 

 

Obr. 2 – Změna barvy pozadí formuláře pomocí překrytí metody OnPaint

 

 

Zpět na obsah

 

Strukturovaná správa chyb v praxi

 

Pro mnoho programátorů představuje problematika správy a ošetřování chyb v jejich programech téma, které by vystačilo na opravdu dlouhou diskusi. Je nepopiratelné, že chyby se v softwarových aplikacích vyskytovaly, vyskytují a s velikou pravděpodobností se také vyskytovat budou v i budoucích etapách vývoje programování. Přestože je tato teze ryzí skutečností, snad na všech frontech se objevují zástupy programátorů, kteří se pouštějí do boje s virtuálními chybami. Cíl je jasný: Snížit počet objevitelných chyb na takovou míru, která by byla přínosná, a to jak pro programátora, tak pro samotného finálního uživatele. Ačkoliv nemáme v tuto chvíli dostatečný prostor na podrobnou charakteristiku filozofie chyb, jejich klasifikaci a specifikaci, ukážeme si, jaké nové zbraně pro boj s počítačovými štěnicemi nabízí platforma .NET Framework a potažmo i jazyk C#.

 

Zaklínadlem dnešních dnů se v rámci programování na .NET úrovni stává takzvaná strukturovaná správa chyb. Ihned ze začátku je zapotřebí zmínit skutečnost, že správa chyb je unifikovaná a pečlivě implementovaná do všech programovacích jazyků pro prostředí .NET Framework. Tedy nejenom C#, ale také Visual Basic .NET, Visual J# a řízené C++ obsahují mechanizmy, které dovolují relativně snadné a současně flexibilní „odchytávání“ chyb v softwarových aplikacích. Společná chybová politika nabírá na významu zejména při programování ve více programovacích jazycích: Je například možné generovat chybovou výjimku z aplikace napsané v C# a posléze „zachytit“ tuto výjimku třeba v řízeném C++ nebo ve Visual Basicu .NET.

 

Po formální stránce je strukturovaná správa chyb v C# prezentována programovou konstrukcí try-catch-finally. Obecně lze při práci s chybami postupovat pomocí následující struktury:

 

  1. Nejprve je nutné identifikovat tu partii programového kódu, v níž by mohlo s největší pravděpodobností dojít k chybě.
  2. Všechen potenciálně nebezpečný kód umístíme do speciálního bloku try. To znamená, že v bloku try se bude nacházet kód, o němž předpokládáme, že v něm může dojít k chybě. Nastane-li v bloku try chyba, bude C# generovat výjimku. Výjimka představuje entitu, pomocí které program signalizuje, že v některé jeho části došlo k nečekané, resp. chybové situaci.    
  3. Vygenerovanou výjimku můžeme zpracovat v bloku catch. Ve skutečnosti není nutné, aby programátoři pracovali jenom s jedním blokem catch, protože bloků tohoto typu lze vytvořit hned několik.

 

Poznámka

Počet bloků catch však zvyčejně závisí od stylu, jakým programátor přistupuje k procesu ošetřování chyb. Tudíž lze vytvořit jenom jeden generický blok catch a všechny chybové výjimky, které budou generovány, zpracovávat podle jednotného scénáře v rámci jednoho bloku catch. V praxi se ovšem určitě častěji střetnete s přítomností většího počtu catch bloků. V tomto případě může každý blok zachytávat jenom specifický typ chybových výjimek.

 

  1. Konečně, blok finally obsahuje takové programové instrukce, které musí být realizované, a to i tehdy, nebude-li generována žádná chybová výjimka. Blok finally je z tohoto pohledu vhodný zejména na jakékoliv „čístící“ operace, jako je například terminace přístupu k datům souboru a podobně.

 

V následující programové ukázce si předvedeme, jak použít strukturovanou správu chyb v praxi. Vytvoříme třídu, instance které budou sloužit jako lokální prohlížeče obrázkových souborů. Třída bude obsahovat metodu ZačítProhlížení, které bude jako argument předáno pole textových řetězců, představujících cesty ke grafickým souborům, určeným pro prohlížení. Jestliže se na lokálním pevném disku nebudou nacházet soubory s daným jménem, dojde k vygenerování chybové výjimky. Tato výjimka bude odchycena v příslušném bloku Catch a také patřičně ošetřena. Postupujte takto:

 

  1. Spusťte Visual C# .NET 2003 a vytvořte standardní aplikaci pro Windows (Windows Application).
  2. Do projektu přidejte soubor s kódem třídy (Project à Add Class).
  3. Obsah souboru s kódem třídy upravte podle uvedeného vzoru (je uveden celý výpis kódu, jenž má být uložen do souboru):

 

using System;

using System.Drawing;

using System.Windows.Forms;

 

namespace cs_1_04_dob_01

{

   /// <summary>

   /// Třída slouží pro prohlížení grafických obrázků.

   /// </summary>

   public class ProhlížečObrázků

   {

         public ProhlížečObrázků()

         {

               //Tělo konstruktoru.

         }

 

         //Definice metody ZačítProhlížení. Všimněte si, že metoda

         //pracuje s polem textových řetězců.

         public void ZačítProhlížení(string[] pole)

         {

               //Instantiace objektů tříd Form a PictureBox.

               Form frm = new Form();

               PictureBox pict = new PictureBox();

 

               //Začátek strukturované správy chyb je identifikován

               //klíčovým slovem try, za kterým se nachází blok programového

               //kódu, jenž je ohraničen složenými závorkami. Veškerý kód,

               //který se nachází uvnitř bloku try, je podroben strukturované

               //správě chyb. Dojde-li v kódu v tomto bloku k chybě, bude

               //generována chybová výjimka.

               try

               {

                     frm.Size = new Size(400, 300);

                     frm.ControlBox = false;

                     frm.FormBorderStyle = FormBorderStyle.FixedDialog;

                     pict.Location = new Point(0,0);

                     pict.Size = new Size(frm.Width, frm.Height);

                     pict.SizeMode = PictureBoxSizeMode.StretchImage;

                     frm.Controls.Add(pict);

                     frm.Show();

 

                     //Obrázky jsou načteny v cyklu, přičemž uživatel má

                     //k dispozici přesně dvě vteřiny, aby si obrázek prohlédl.

                     //Po uplynutí stanoveného časového intervalu je zobrazen

                     //další dostupný obrázek.

                     for (byte a = 0; a <= pole.GetUpperBound(0); a++)

                     {

                          Image obr = Image.FromFile(pole[a]);

                          pict.Image = obr;

                          pict.Refresh();

                          System.Threading.Thread.Sleep(2000);

                          Application.DoEvents();

                     }

               //Konec bloku try.

               }

 

               //První blok catch. Tento blok bude zapojen do činnosti

               //v případě, jestliže bude v bloku try generována výjimka

               //typu System.IO.FileNotFoundException. Abychom mohli využít

               //informace, které si výjimka s sebou nese, deklarujeme

               //referenční proměnnou x1.

               catch (System.IO.FileNotFoundException x1)

               {

                     //Výjimka FileNotFoundException vzniká v okamžiku, kdy

                     //se na disku nenachází příslušný soubor. V tomto případě

                     //zobrazíme dialogové okno se zprávou, která bude uživateli

                     //oznamovat vzniklou chybovou situaci společně s názvem

                     //chybějícího souboru.

                     MessageBox.Show("Soubor " + x1.Message + " nebyl nalezen.",

                          "Zpráva o chybě za běhu programu",

                          MessageBoxButtons.OK, MessageBoxIcon.Error);

               }//Konec prvního bloku catch.

 

               //Druhý blok catch. Zde budou zpracovávány všechny ostatní

               //výjimky, kromě té, se kterou se pracuje v prvním bloku catch.

               catch (System.Exception)

               {

                     //Ošetření všech ostatních výjimek, ke kterým může dojít.

               }//Konec druhého bloku catch.

 

               //Začátek bloku finally. Zde vložíme všechny příkazy, kterých

               //provedení není závislé na otázce, zdali došlo k chybě či nikoliv.

               finally

               {

                     frm.Close();

               }//Konec bloku finally.

         }

   }

}

 

  1. Na formulář přidejte jednu instanci ovládacího prvku Button a do zpracovatele události Click této instance přidejte tento programový kód:

 

            //Vytvoření nové instance třídy ProhlížečObrázků.

            ProhlížečObrázků x = new ProhlížečObrázků();

                 

            //Deklarace pole, které může uchovat čtyři textové řetězce.

            string[] pole_x = new string[4];

 

            //Naplnění jednotlivých prvků pole textovými řetězci.

            //Tyto řetězce představují plně kvalifikované názvy

            //k cílovým souborům s grafickými daty. Jména souborů jsou

            //Obr1.png, Obr2.png atd., přičemž všechny soubory jsou

            //uloženy na lokálním disku d.

            for(byte a = 0; a < 4; a++)

                pole_x[a] = "d:\\obr" + (a+1) + ".png";

 

            //Aktivace metody ZačítProhlížení vytvořené instance.

            //Metodě je jako argument odevzdáno pole textových řetězců.

            x.ZačítProhlížení(pole_x);

 

 

Zpět na obsah

 

Volání metody bázové třídy z odvozené třídy

 

Aktivace metody bázové třídy z podtřídy je velmi užitečná technika, pomocí které můžete ve vhodné chvíli zavolat metodu bázové třídy, a to přímo z kódu odvozené třídy. Každá odvozená třída může využívat všech dovedností, které nabízí její bázová třída, a proto není ani nejmenším problémem aktivace příslušných metod bázové třídy z prostředí odvozené třídy. Abychom mohli zavolat metodu bázové třídy, použijeme v C# klíčové slovo base, za kterým následuje tečkový operátor (.) a název metody bázové třídy, kterou chceme aktivovat:

 

base.CílováMetodaBázovéTřídy

 

Více informací přináší následující programová ukázka (je uveden výpis celé třídy):

 

using System;

using System.Diagnostics;

using System.Windows.Forms;

 

namespace cs_1_04_dob_01

{

      //Definice třídy A1.

      public class A1

      {    

            //Definice veřejné virtuální metody.

            public virtual void SpustitPoštovníhoKlienta()

            {

                  //Aktivace metody Start třídy Process z jmenného prostoru

                  //System.Diagnostics. Výsledkem práce metody je spuštění

                  //poštovního klienta.

                  Process.Start("mailto:hanja@stonline.sk");

            }

      }

 

      //Definice třídy B1 jako podtřídy bázové třídy A1.

      public class B1 : A1

      {

            //Definice metody, která překrývá metodu bázové třídy.

            //Z této překryté metody bude pomocí klíčového slova base

            //volána metoda bázové třídy.

            public override void SpustitPoštovníhoKlienta()

            {

                  //Minimalizace aktivní instance třídy Form.

                  Form.ActiveForm.WindowState = FormWindowState.Minimized;

 

                  //Aktivace metody bázové třídy pomocí klíčového slova base,

                  //tečkového operátoru a názvu cílové metody.

                  base.SpustitPoštovníhoKlienta();

            }

 

      }

}

 

Výpis kódu pracuje se dvěma třídami: A1 a B1. Třída A1 obsahuje veřejnou virtuální metodu SpustitPoštovníhoKlienta. Je-li tato metoda aktivována, dochází k nastartování aplikace, která je na cílovém počítačovém systému nakonfigurována jako poštovní klient. Třída B1 je odvozená od třídy A1, přičemž v překryté variantě metody SpustitPoštovníhoKlienta je volána metoda bázové třídy A1.

 

 

Zpět na obsah

 

 

 

Právě jste dočetli Dobrodružství v C#.

 

Pokud se chcete dozvědět více informací o programování v C#, neváhejte a navštivte i další součástí rubriky Visual C# .NET:

 

Začínáme s jazykem C# - Seriál je určen především zájemcům o studium základních a pokročilých programovacích prvků v jazyku C#. Jestliže se chcete začít učit programovat právě v jazyku C#, nebo patříte-li k programátorům, kteří přecházejí z prostředí jiného programovacího jazyka, naleznete v jednotlivých dílech seriálu vše, co budete potřebovat ke snadnému zvládnutí jazyka C#.

 

Otázky a odpovědi – Trápí-li vás nějaký programátorský problém, na jehož řešení ne a ne přijít, pak jste na správném místě. U čtenářů oblíbená forma řešení potíží stylem otázek a odpovědí si našla svůj prostor i v naší rubrice. Máte-li problém, s kterým nevíte hnout, pošlete jeho popis autorovi rubriky, jenž vyvine maximální úsilí pro rychlé vyřešení jakékoli programátorské záhady.

 

 

Autor: Ján Hanák