2. felev, uj tematika, C++ nyelv      A C++ Builder alkalmazása
	12. gyak	GEPESZ		  Szöveges vezérlők,
					  Pozicionálók, pozíciókijelzők. 

•	Mintaprogram szöveges vezérlőkkel 

Készítsünk a Label, Edit, Memo, ListBox és ComboBox szöveges vezérlőket 
alkalmazó programot. A program egy gépipari vállalat Központi raktárában és 
Szereldei raktárában található alkatrészek nyilvántartására szolgál. A Központi 
raktárba új alkatrészeket bevételezhetünk, onnan egy, vagy több kijelölt alkatrészt
átszállíthatunk a Szereldei raktárba, ahonnét felhasználásra szintén egy, vagy 
több alkatrészt kivételezhetünk. 
Az alkatrészek mozgását a későbbi visszakereshetőség érdekében naplózza a 
rendszer. A raktárak alkatrészkészletét megjeleníthetjük a bekerülés sorrend-
jében, vagy rendezetten. A program ablaka a következő felépítésű legyen:

Megoldás:
1. Hozzunk létre egy Raktár nevű könyvtárat, amibe mentsük le a frissen 
    létrehozott üres C++ Builder programunkat Raktar.prj projektnévvel.

2. Helyezzünk el a form-on három csoportbafoglaló panelt (GroupBox). 
    Ezek szerepe a rajtuk elhelyezendő elemek vizuális egységbe foglalása és az 
    egység nevének megjelenítése.

3. Helyezzük el a panelokon az egy-egy ListBox komponenst a raktárállomány-
    bejegyzések tárolására és megjelenítésére!

4. Helyezzük el a bal GroupBox panelon alulra az Edit komponenst!

5. Helyezzük el a három nyomógombot a hozzáadás, szállítás és felhasználás
    műveletek elvégzésére!

6. Helyezzük el a ComboBox komponenst a megjelenítés módjának
    kiválasztására!

7. Helyezzük el a Memo komponenst a naplózott események megjelenítésére!

8. Végül helyezzünk el három Label komponenst a Raktárkészlet nyilvántartás,
    Megjelenítési mód: és az Új alkatrész neve: szövegek kijelzésére. A kijelölt 
    komponenst a Ctrl  nyomvatartása mellett a nyíl billentyűkkel finoman
    pozicionálhatjuk. Pl. a Megjelenítési mód: szöveget egy vonalba állíthatjuk az
    Edit ablakban lévő szöveggel.

Az ablak a felhelyezett és méretre igazított komponensekkel:

9. Adjunk értéket a felirat (Caption) jellemzőnek a Form1, Label1, Label2,
    Label3, GroupBox1, GroupBox2, Groupbox3, Button1, Button2 és Button3
    komponensek  esetében. 

10. Nevezzük át a következő komponensek Name jellemzőjét: 
      Label2 		->   LabelMod
      Label3 		->   LabelUj
      GroupBox1   	->   GroupBoxKozpont
      GroupBox2   	->   GroupBoxSzerelde
      GroupBox3   	->   GroupBoxNaplo
      ListBox1       	->   ListBoxKozpont
      ListBox2      	->   ListBoxSzerelde
      Memo1   		->   MemoNaplo
      ComboBox1  	->   ComboBoxMod
      Edit1   		->   EditUj
      Button1   		->   ButtonHozzaad
      Button2   		->   ButtonSzallitas
      Button3  		->   ButtonFelhasznalas       értékekre!

11.  Állítsuk a form keret stílusát (BorderStyle) párbeszédablak értékre
       (bsDialog) !   

12. Változtassuk meg a Label1 felirat betűformáját (Font) félkövér, 10 méretre
      és igazítsuk középre egérrel.

13. ComboBoxMod Text jellemzőjének értékét írjuk át Normál-ra!

14. EditUj egysoros szövegszerkesztő Text jellemzőjének értékét töröljük ki.

15. A ListBoxKozpont és a ListBoxSzerelde  listavezérlőknél engedélyezzük
      a több bejegyzés kiválasztását, legyen a MultiSelect és az ExtendedSelect
      jellemzők értéke egyaránt true!

16. Töröljük a MemoNaplo  többsoros szövegszerkesztőből 
      a nevét, ehhez kattintsunk duplán a Lines jellemző sorá-
      ban lévő gombon és a megjelenő String List Editor-ban 
      töröljük a szöveget!

17. Mivel ez a MemoNaplo szövegszerkesztő most csak a 
      naplózott adatok megjelenítését fogja szolgálni, a szerkesztési lehetőséget
      tiltsuk le a ReadOnly jellemző true értékre állításával!

18. Éppenséggel a MemoNaplo szöveges vezérlő tartalma a billentyűzettel is
      görgethető, de egérrel történő kezelésre gondolva kapcsoljuk be a függőle-  
      ges görgetőlecet is a ScrollBar jellemző  ssVertical értékre állításával!

19. Mivel az eseményeket egy szöveges tárolóban naplózni kívánjuk, melyben
      az eseményeket sorszámmal azonosítjuk, ezért definiáljunk egy kinullázott
      memoszamlalo nevű változót a unit1.cpp fájl elején a TForm1 *Form1; sor 
      után:
                      int memoszamlalo = 0;

20. Hozzuk létre a Hozzáad nyomógombon való kattintás eseménykezelő  
      függvényének vázát a gombon végzett dupla kattintással!  Az eredmény:

void __fastcall TForm1::ButtonHozzaadClick(TObject *Sender)
{

}

21.  Írjuk bele a függvény blokkjába az EditUj egysoros szövegszerkesztő 
       tartalmát a ListBoxKozpont listavezérlő végéhez hozzáfűző programkódot,
       valamint naplózzuk az eseményt a MemoNaplo többsoros kijelzőben!

void __fastcall TForm1::ButtonHozzaadClick(TObject *Sender)
{ 
  AnsiString s;
  if (EditUj->Text.Length() > 0) // van valami beírva
  {   ListBoxKozpont->Items->Add(EditUj->Text);  // hozzáadás a listához
      //Naplózás:
      memoszamlalo++;    s= memoszamlalo;        // operator=( ) működik!
      s += ". Új tétel hozzáadása a Központi raktár állományához: ";
      s += EditUj->Text;
      MemoNaplo->Lines->Add(s);      // a naplót most soronként kezeljük
  }
}

22. Hozzuk létre a Szállítás nyomógomb eseménykezelő függvényének vázát a
      gombon duplán kattintva, majd írjuk bele a kiválasztott tételek átmásolását és
      az egyes bejegyzések átszállítását naplózó programsorokat:

void __fastcall TForm1::ButtonSzallitasClick(TObject *Sender)
{  
   AnsiString s;
   for (int i=0; i < ListBoxKozpont->Items->Count; i++)
   if ( ListBoxKozpont->Selected[ i ] )
   {   ListBoxSzerelde->Items->Add(ListBoxKozpont->Items->Strings[ i ] );
       //Naplózás:
       memoszamlalo++;  s= memoszamlalo; 
       s+= ". Tétel átszállítása a Központi raktárból a Szerelde raktárába: "; 
       s+= ListBoxKozpont->Items->Strings[ i ];
       MemoNaplo->Lines->Add(s);
   }
   // Átszállított elem törlése a Központi raktárból. 
   // Nem törölhettük fent,  mert elrontaná az indexeket és elemszámot,
   // vagy nem a felsőt szállítaná át először...
   for (int i = ListBoxKozpont->Items->Count-1; i >= 0; i--)
   if (ListBoxKozpont->Selected[ i ])   ListBoxKozpont->Items->Delete( i );
 }

23. Hozzuk létre a Felhasználás nyomógomb eseménykezelő függvényének 
      vázát a gombon duplán kattintva, majd írjuk bele a kiválasztott tételek
      felhasználásra való kivételezését, azaz a listából való kitörlését és ezen
      esemény naplózását elvégző programkódot:

void __fastcall TForm1::ButtonFelhasznalasClick(TObject *Sender)
{  
   AnsiString s;
   for ( int i = ListBoxSzerelde->Items->Count-1; i >= 0; i--)
   if ( ListBoxSzerelde->Selected[ i ] )
   {
      //Naplózás:
      memoszamlalo++;  s= memoszamlalo; 
      s += ". Tétel felhasználása a Szerelde raktárából: "; 
      s += ListBoxSzerelde->Items->Strings[ i ];
      MemoNaplo->Lines->Add(s);
      //Törlés:
      ListBoxSzerelde->Items->Delete( i );
   }
}

24. A lenyitható listájú ComboBoxMod komponenssel a Központi és a Szereldei
      listát szeretnénk rendezett, vagy normál módban történő megjelenítésre 
      beállítani. Ehhez a ComboBoxMod komponens Items jellemzőjét töltsük fel a 
      lenyíló menüben megjeleníteni kívánt Normál és Rendezett szövegekkel:

                     

25. Végül írjuk meg a ComboBoxMod lenyíló listán történő rendezési mód 
      választáshoz az alkatrészlisták rendezett, vagy rendezetlen megjelenítését
      beállító Sorted jellemzőknek történő értékadások programkódját a 
      ComboBoxMod komponens OnChange( ) eseménykezelő függvényében. 
      Ez a függvény a kombinált lista egysoros szövegszerkesztőjének tartalmában 
      bekövetkező módosuláskor hívódik meg. A vázát a kombinált listán való dupla
      kattintással hozhatjuk létre. A függvényt a beleírt programrészlettel a 
      következő lapon láthatjuk. 

A ComboBoxMode komponens OnChange() eseménykezelő függvénye:

void __fastcall TForm1::ComboBoxModChange(TObject *Sender)
{
    if ( ComboBoxMod->Text == "Normál” )
    {  ListBoxKozpont->Sorted= false;
       ListBoxSzerelde->Sorted= false;
    }
   else
   {   ListBoxKozpont->Sorted= true;
       ListBoxSzerelde->Sorted= true;
   }
}

Természetesen a program még tovább finomítható, pl. az új bejegyzés felvétele történhetne az Enter billentyű lenyomására is. A program futás közbeni ablakára egy példát a következő oldal ad.

A raktárkészlet nyilvántartó program futás közben:

•	Mintaprogram pozícióbeállító és kijelző vezérlőkkel  
Feladat: készítsük el az alábbi ablakkal jellemezhető C++ Builder programot! 

A programban a Korong a görgetőléccel, a csúszka vezérlővel, vagy a léptetővel gurítható jobbra, balra. 
A Csúszka a fehér Pötty közepének mindenkori magasságát jelzi, a görgetőléc tolókája a kerék 
helyével együtt mozog, miközben a folyamatállás kijelző a program indításától eltelt időt méri.

Megoldás:

1. Hozzunk létre egy új könyvtárat és mentsünk le bele Csuszka.prj néven 
    egy frissen megnyitott üres alkalmazást. 

2. Helyezzük el a szükséges vezérlőket a form-on, méretezzük és pozicio- 
    náljuk a megadott ábrának megfelelően. A form-ra egy Timer komponens 
    is felkerül, melynek feladata 5 másodpercenként meghívni az OnTimer 
    eseménykezelő függvényét és abban léptetni a folyamatállás kijelzőt. A  
    Korong és a Potty TShape komponensek, melyeknek Shape jellemzője 
    stEllipse értékű. A Korong  Brush (ecset) jellemzőjének Color   tulajdon-
    ságát clRed-re állítottuk. A fekete alap egy Shape = stRectangle értékű
    TShape komponens.

A form a komponensek felrakása után:

3. A TrackBar Orientation jellemzőjét trVertical értékre kell átírni. 

4. Szükségünk lesz néhány globális változóra, definiáljuk ezeket a 
    TForm1 *Form1       sor után:          
     int pozicio,Dx,Dy,dx,dy,R,r;
     double szog;

A pozicio a mozgás paraméterváltozója, 0-314 intervallumban vehet fel értékeket. 
Értéke megfelel a Korong által megtett útnak, mivel a Korong R sugara éppen 100. 

5.  A számításokhoz szükségünk van a sin, cos, acos függvényekre, melyek 
     a math.h headerfájlban vannak deklarálva. Szúrjuk be ezt a Unit1.h 
     include sor alá:             #include "math.h”

6. A form BorderStyle értéke bsDialog.  Edit1 ReadOnly jellemzője true.

7. A többi felirat (Caption) értelemszerű megadása mellett a form-nál is írjuk 
   át : Görgetőléc, csúszka és folyamatállás kijelző demonstrációs program-ra.

8. Az ablakbeli főcím font értékét válasszuk 10-es félkövérre.

9. Nevezzünk át néhány komponenst: 
    Shape1  -->  ShapeKorong
    Shape2  -->  ShapePotty
    Shape3  -->  ShapeAlap.

10.  Bár ezek nagy részét az Object Inspector-ban is beállíthattuk volna, 
       most a form konstruktorában adjuk meg az inicializáló értékeket:

__fastcall TForm1::TForm1(TComponent* Owner)
        : TForm(Owner)
{
 Dx= 113; Dy= 120; //eltolás az ablak sarkához képest
 dx= 201; dy= 208;
 R= 100; r= 12; //sugarak
 UpDown1->Position= 157;
 UpDown1->Min= 0;
 UpDown1->Max= 314;
		 ScrollBar1->SetParams(157,1,314);
 ScrollBar1->SmallChange = 1;          //Finom lépésköz
 ScrollBar1->LargeChange = 10;        //Nagy lépésköz
 TrackBar1->Position=100;
 TrackBar1->Min= 0;
 TrackBar1->Max= 200;       // csak kijelzéshez
 TrackBar1->SelStart= r; 
 TrackBar1->SelEnd= 2*R-r;
 TrackBar1->PageSize= 4;
 TrackBar1->Frequency= 4; 
 ProgressBar1->Min= 0;
 ProgressBar1->Max= 600;      //5 perc
 ProgressBar1->Width= 600;    // 1 egység a rajzon == 1 mp
 ProgressBar1->Step= 10;        // egy lépés == 5 mp
 ProgressBar1->Position= 0;
 Timer1->Interval=5000;            //5 mp
 Timer1->Enabled= true;
}

11. A legfontosabb függvény a görgetőléc pozícióváltozására reagáló  
      OnChange() eseménykezelő:

void __fastcall TForm1::ScrollBar1Change(TObject *Sender)
{
 //Görgetőléc pozíció kiolvasása:
 pozicio= ScrollBar1->Position;
 Edit1->Text= pozicio;                         // kiíratás
 //Korong pozicionálása:
 ShapeKorong->Left= Dx+pozicio;      //Csak csúszik valójában...
 //Pötty pozicionálása:
 szog= (double)pozicio/R;
 ShapePotty->Left= dx+pozicio-(int)(R-r)*sin(szog);
 ShapePotty->Top= dy+(int)(R-r)*cos(szog);
 TrackBar1->Position= R+(int)(R-r)*cos(szog);      // csúszka
}

A Korong forgását a Potty mozgása érzékelteti. Itt állítjuk a csúszkát is a fehér Potty 
közepének magasságára.

12.  A Timer 5 másodpercenként “felüti a fejét” és meghívja az OnTimer() 
       eseménykezelő függvényét:

void __fastcall TForm1::Timer1Timer(TObject *Sender)
{
 ProgressBar1->StepIt();     // lépteti a folyamatállás kijelzőt.
}

13.  A Léptető valamelyik gombján kattintva meghívódik a Léptető OnClick()
       eseménykezelő függvénye, mely a gomb függvényében inkrementálja,
       vagy dekrementálja a mozgásparaméter pozicio változó értékét:

void __fastcall TForm1::UpDown1Click(TObject *Sender, TUDBtnType Button)
{
  if (Button == btNext) pozicio++;
  else pozicio--;
  ScrollBar1->Position= pozicio;   // kiváltja az összes tevékenységet!
}                             // mert OnChange eseményt jelent a görgetőlécnél!        

14. Végül azt az esetet programozzuk, amikor a csúszka vezérlőt mozgatjuk
      fel-le egérrel és ennek hatására kell minden másnak működnie: Korong,
      Potty, görgetőléc, Edit1 számkijelző. A csúszka (TrackBar) magassági
      helyzetét átszámítjuk pozício-értékre és ezzel aktivizáljuk a mindentudó
      OnChange függvényét a görgetőlécnek (ScrollBar1).
 
void __fastcall TForm1::TrackBar1Change(TObject *Sender)
{
 int sv;
 sv= TrackBar1->Position;
 if (sv<12) sv=12;
 if (sv>188) sv=188;
 szog= acos((double)(sv-R)/(R-r));
 pozicio= (int)(100*szog);
 ScrollBar1->Position=pozicio; // kiváltja az összes tevékenységet
}

15.  A program gyönyörűen működik, bár még tökéletesíthető. Pl. nem 
       állítottuk le a Timer-t, rábíztuk az alkalmazásra, az Edit1 ablakba nem 
       lehet beírni és ily módon pozicionálni a Korongot, billentyűzettel nem 
       vizsgáltuk a programot,stb.