Vytvořte si vlastní komponenty - 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:



Komponenty

Vytvořte si vlastní komponenty

22. srpna 2001, 00.00 | Být uživatelem připravených komponent je jednoduché. Co se takhle pustit do vlastní tvorby komponent? Jak na to se dozvíte v tomto článku.

Když se ohlédnu do minulosti, není to tak dávno, co jsem byl ještě pouze uživatelem vizuálních komponent, které do mého C++ Builderu naservíroval Borland. Samozřejmě mi jejich možnosti časem přišli těsné a počal jsem nové hledat v síti internetu. Přiznejme si, brzy přišla chvíle, kdy ani tato varianta nebyla vyhovující. Přece "Co si člověk neudělá sám, to nebude fungovat!". Povzbuzen tímto heslem, pustil jsem se do výroby vlastních vizuálních komponent.

Pokud máte chuť obohatit si Paletu komponent o několik přírůstků a ještě jste na to neměli čas, ochutnejte se mnou kousíček z tohoto řemesla.

SpinPro - procentový proužek


Nejjednodušší možnou komponentou, kterou najdete v paletě Samples je komponenta CGauge. Jedná se o klasický proužek, určený ke znázornění určitého úseku nebo počtu procent. Vyzkouejme pro začátek podobnou komponentu, která bude mít pár vlastností, také bude znázorňovat stav v procentech z nějakého úseku a navíc přidejme zobrazení s barevným přechodem.

Oproti zvyklostem nezačneme nový projekt, ale zvolíme Component/New Component ...

Vybereme třídu, komponentu, od které budeme svůj výtvor odvozovat. Pro naše účely potřebujeme třídu s Canvasem. Ideální je myslím TCustomControl, dále novou třídu pojmenujeme, já ji nazval TSpinPro a zvolíme záložku, kde umístíme komponentu. Pro naše pokusy nám velmi dobře poslouží záložka Samples. Volbou OK nám Builder vytvoří kostru komponenty.

Ke spokojenosti nepotřebujeme mnoho, jelikož se jedná o nějaký rozsah, definujeme vlastnosti Min a Max, čímž si určíme minimální a maximální hranici. Dále potřebujeme aktuální pozici v tomto určeném rozsahu, takže vlastnost Pozice. Nakonec přidáme přepínač pro zobrazení obyčejného proužku a proužku s gradientem.
Editujeme hlavičkový soubor SpinPro.h

class PACKAGE TSpinPro : public TCustomControl
{
private:
  int FMin;
  int FMax;
  int FPozice;
  bool grad;

  void __fastcall NastavMin(int ACis);
  void __fastcall NastavMax(int ACis);
  void __fastcall NastavP(int ACis);
  void __fastcall NastavG(bool AGrad);
protected:
  virtual void __fastcall Paint(void);
public:
  __fastcall TSpinPro(TComponent* Owner);
__published:
  __property int Min = {read = FMin, write = NastavMin};
  __property int Max = {read = FMax, write = NastavMax};
  __property int Pozice = {read = FPozice, write = NastavP};
  __property bool Gradient = {read = grad, write = NastavG};
};

Do privátních proměnných třídy uložíme interní informace, minimální hodnotu, maximální hodnotu a pozici v tomto rozsahu (FMin, FMax, FPozice). Zajímavé je, že pro uložení do těchto proměnných využíváme s výhodou funkcí NastavMin, NastavMax ..... Oproti běžné definici třídy v C++ máme k dispozici klíčové slovo __published, položky označené tímto klíčovým slovem se chovají stejně jako při použití public, navíc jsou zobrazeny v objekt inspektoru. Do této sekce patří definice vlastností, které mají být editovatelné objekt inspektorem, tedy Min, Max a Pozice. Zda se jedná o měnitelnou vlastnost určíme pomocí __property. Toto slovíčko má tu moc, že vlastnosti můžeme přiřadit metodu pro čtení (read) nebo metodu pro zápis (write).
__property int Min = {read = FMin, write = NastavMin};
V našem případě čteme hodnotu z proměnné FMin (private) a vlastnost měníme voláním funkce NastavMin. Tento zápis je přejatý z Delphi a neobsahuje parametry volané funkce. No a konečně také property umožňuje nastavit výchozí hodnotu (default).
__property int Min = {read = FMin, write = NastavMin, default = 100};
pro náhodně zvolenou hodnotu slouží nodefault.

Tímto opustíme hlavičkový soubor a pustíme se kódování funkcí.

Jak již jsem zmínil, odvodili jsme naši komponentu od TCustomControl, abychom mohli na její plochu elegantně kreslit do Canvasu. Tato třída má definovanou metodu Paint, která reaguje na událost WM_PAINT.

void __fastcall TSpinPro::Paint() {
   Windows::TRect Okno1;  // rectangle pro proužek 
   Okno1.Left = 0;
   Okno1.Top = 0;
   Okno1.Right = (double) (Width*( (double) (FPozice-FMin)/(FMax-FMin)));  
     // výpočet šířky proužku
   Okno1.Bottom = Height;

  Canvas->Pen->Color = clBlack;
  Canvas->Rectangle(2,2, Width-1, Height-1);
  Canvas->Brush->Color = clWhite;
  Canvas->FillRect(Canvas->ClipRect);  // nejprve vyplníme bílou barvou

  if (grad == false) {
    Canvas->Brush->Color = clNavy;
    Canvas->FillRect(Okno1);  // nakreslíme proužek v barvě navy
  }

  Canvas->Font->Color = clWhite;
  Canvas->Brush->Color = clNavy; // přidáme textový popisek - počet procent
  Canvas->TextOut(Width/2-Canvas->TextWidth((AnsiString) FPozice)/2,
Height/2-Canvas->TextHeight("A")/2, AnsiString (FPozice)+ "%"); }

Takhle jednoduše se dá obsloužit celé vykreslení komponenty. Nejprve nakreslíme bílý podklad, potom vypočítáme rectangle pro proužek a nakonec ho vykreslíme. Při výpočtu rectangle je nejdůležitější šířka proužku. Tu vypočítáme jako počet procent (FPozice-FMin) z rozsahu (FMax-FMin). Komentář je myslím naprosto výstižný.

No jistě vás zajímá, proč při změně vlastnosti potřebujeme zavolat NastavMin, NastavMax atd... Stačilo by uložit hodnotu přímo do proměné. To je sice pravda, ale zase by se neprojevila navenek žádná změna, proto zavoláme funkci např. NastavMin, změníme hodnotu proměnné a vynutíme překreslení.

void __fastcall TSpinPro::NastavMin(int ACis) {
  if (ACis >= FMax)
    throw Exception("Nemůže být větší než Max");
  FMin = ACis;

  if (FPozice < FMin)
    TSpinPro::NastavP(FMin);

  TSpinPro::Paint();
}

Co je důležité v této funkci zajistit? Hlavně ošetřit chybně zadané hodnoty, když zadáme větší minimální hodnotu než je hodnota maximální (a obráceně). Pokud zadáme hodnotu mimo rozsah, vyvoláme výjimku, ohlásí se chybový MessageBox se zprávou.

Obrázek komponenty (resource)

Kdyby jste v tuto chvíli instalovali komponentu, bylo by vše v pořádku, instalace by byla úspěšná. Nicméně mělo by to jednu vadu na kráse a tou by byl symbol zobrazující komponentu - . Nic ale není ve světě programování problém, musíme jen vytvořit resource z obrázkem a zahrnout do překladu. Vše se dělá v ImageEditoru, vytvoříme nový resource soubor a do něj vložíme nový Resource/New/Bitmap. A teď to nejdůležitější bitmapa se musí jmenovat jako třída komponenty, takže ji pojmenujeme TSPINPRO. Přilinkování zajistíme direktivou

#pragma resource "SpinPro.res"

a je vymalováno, nyní stačí komponentu nainstalovat. Komponentu si stáhněte odtud (BCB1-4) .

Progress - stavový indikátor

..................

Pokud jste se prokousali až sem, jistě nepohrdnete malým bonbonkém. Pro změnu komponenta, indikátor stavu (podobná komponentě ProgressBar). Komponenta se příliš neliší od té předchozí. Má stejné vlastnosti, rozdíl je pouze ve vykreslování. Komponenta má dva režimy, jednoduchý (jednobarevný) a barevný indikátor (viz obrázek). Opět se podívejme na zjednodušenou vykreslovací funkci.

void __fastcall TProgress::Paint() {
   Windows::TRect Okno1;

  Canvas->Pen->Color = clBlack;
  Canvas->Rectangle(1,1, Width, Height);   
  Canvas->Brush->Color = clBtnFace;

  Canvas->FillRect(Canvas->ClipRect);      // vnitřek vyplníme šedou barvou
  Canvas->Pen->Color = clGray;                   // rámeček
  Canvas->MoveTo(0, 0);
  Canvas->LineTo(Width, 0);
  Canvas->MoveTo(0, 0);
  Canvas->LineTo(0, Height);
  Canvas->Pen->Color = clWhite;
  Canvas->MoveTo(0, Height-1);
  Canvas->LineTo(Width, Height-1);
  Canvas->MoveTo(Width-1, Height-1);
  Canvas->LineTo(Width-1, 0);

  int pocetproc = (FPozice.ToInt()-FMin.ToInt())/((FMax.ToInt()-FMin.ToInt())/10);  
// výpočet, kolit je potřeba vybarvit obdelníčků // vybarví předem vypočtený počet obdelníčků for (int i = 0; i < pocetproc*2; i++) { Okno1.Left = i*Width/20+2; Okno1.Top = 2; Okno1.Right = (1+i)*Width/20-2; Okno1.Bottom = Height - 2; Canvas->Brush->Color = clNavy; Canvas->FillRect(Okno1); } }

Nejprve vykreslíme obrys, část v bílé, část v šedé barvě. Pak následuje to nejdůležitější, vypočítat počet obdelníčků, které se mají zobrazit. Toho docílíme výpočtem :
int pocetproc = (FPozice.ToInt()-FMin.ToInt())/((FMax.ToInt()-FMin.ToInt())/10);
No a pak již nezbývá než postupně vykreslit všechny obdelníčky.

Pro vlastnosti a parametry jsem využil datového typu AnsiString (i když to může připadat nelogické). Vyzkoušejte použití i jiných datových typů.

To co vzniklo z mého snažení naleznete ZDE.

Doufám, že vám můj článek vypomohl při prvním oťukávání komponent. A protože jsme zdaleka nevyčerpali všechny možnosti, které se nám komponenty nabízí, určitě nepohrdnete dalším pokračováním někdy v budoucnu o využívání a obsluze událostí a zpráv.

Tématické zařazení:

 » Rubriky  » Komponenty  

 » Rubriky  » Windows  

 

 

 

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

 

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

Uživatelské jméno:

Heslo: