A Delphi programozási nyelv Kovács Péter 2011. április 14.
A Delphiről általában Adatbázis alkalmazások készítése Vezérelv: Legyen látható (és elkészíthető) tervezési időben, ami csak lehet! Vizuális tervezés és kódgenerálás szervesen összekapcsolódik Komponens: egy osztály, amely valamely látható vagy nem látható erőforrás interfészét valósítja meg
Rapid Application Development Teljes integritás Automatikus kódgenerálás és kódszinkronizáció Integrált debugger Gyors és intelligens fordító Újrahasznosíthatóság
Egyebek Ami kimaradt: ActiveX komponensek Broker Technologies makrórögzítő a gyakran használt tevékenységek automatizálására ActiveX komponensek kliensoldali fejlesztés Broker Technologies szerveroldali fejlesztés
Adatbázis-kezelés Borland Database Engine – Adatbázis Motor Database Wizard – Egyszerű karbantartó program készítése Database Desktop – Adatbázis böngésző Database Explorer QuickReport – Report készítő
Nyomkövetés Beépített debugger lehetőségei: Hibák típusai: A program végrehajtásának ellenőrzése A változók értékének figyelése Az adatok értékének változtatása nyomkövetés közben Hibák típusai: Fordítási idejű hibák Logikai hibák Futási idejű hibák
Fordítók Borland cég CodeGear részlege Embarcadero (http://embarcadero.com/) Lazarus: Delphi-szerű fejlesztő környezet (http://lazarus.freepascal.org/)
Szabványos könyvtárak Régebben: RTL (futási idejű könyvtár) VCL (vizuális komponenskönyvtár) CLX (platformfüggetlen komponenskönyvtár) Újabb verziók: egységesen VCL
Könyvtári egységek System SysUtils Types Windows Messages Classes
Párhuzamosság TThread absztrakt osztály Execute() virtuális metódus Create konstruktor CreateSuspended Boolean típusú paraméterrel type TMyThread = class(TThread) protected procedure Execute; override; end;
Párhuzamosság Egyprocesszoros gépen ne használjunk 16 szálnál többet Priority attribútum: tpIdle, tpLowest, tpLower, tpNormal, tpHigher, tpHighest, tpTimeCritical Suspend, Resume, WaitFor thread := TMyThread.Create(false); thread.WaitFor; // bevárjuk thread.Free; // felszabadítjuk
Párhuzamosság Terminated logikai tag Synchronize metódus Lock – Unlock metóduspár, pl. TCanvas TCriticalSection osztály
Kritikus szakaszok var CriticalSection: TCriticalSection; begin CriticalSection := TCriticalSection.Create; … CriticalSection.Enter; … CriticalSection.Leave; … CriticalSection.Free; end;
Mutexek var MyMutex: TMutex; begin MyMutex := TMutex.Create(nil, false, ''); … MyMutex.Acquire; … MyMutex.Release; … MyMutex.Free; end;
Szemafor var MySemaphore: TSemaphore; begin MySemaphore := TSemaphore.Create(nil, 5, 5, ''); … MySemaphore.Acquire; … MySemaphore.Release; … MySemaphore.Free; end;
Komponensek dinamikus létrehozása GUI építő eszközzel „felhúzunk” a formra egy komponenst -> a form konstruktorába bekerül egy hívás a komponens konstruktorára, és utasítások, melyek beállítják a propertyket name property: a komponensre mutató globális változó neve Dinamikus komponensek: name property helyett tároló konténereken keresztül érjük el
Komponensek megkülönböztetése Különböző típusú komponensek tárolása megengedett, csak közös ős kell Ha tömbben tároljuk a komponenseket, a megkülönböztetésükre használhatjuk a Tag propertyt Az igazi megoldás a származtatás: az azonosításra szolgáló adattagot bővíthetjük többdimenziós tömbre
Komponensek megkülönböztetése type TMyImage = class(TImage) posX: Integer; posY: Integer; end; var … kep: array[1..8,1..5] of TMyImage; kep[i].Tag := i; kep[i][j].posX := i; kep[i][j].posY := j;
Komponensek dinamikus megszüntetése kep[i].Free; … kep[i] := TImage.Create(self); Csak akkor törlődik a komponens, ha más referencia nem mutat rá!
Végtelen engedélyezett hosszúságú lista bevitele Komplex adatszerkezetből szeretnénk egy listányit bevinni Ne legyenek felesleges, üres mező-együttesek Két megoldás: Gomb hatására új mező-együttes jelenik meg Mezők kitöltöttségének függvényében mezők megszüntetése és létrehozása
Végtelen engedélyezett hosszúságú lista bevitele
Végtelen engedélyezett hosszúságú lista bevitele type TFormPanel = class(TPanel) edit: TEdit; box: TCheckBox; combo: TComboBox; id: Integer; procedure Create(…); end;
Végtelen engedélyezett hosszúságú lista bevitele procedure TForm1.Button1Click(Sender: TObject); var a: TFormPanel; begin a := TFormPanel.Create(self); list.Add(a); end;
Végtelen engedélyezett hosszúságú lista bevitele
Végtelen engedélyezett hosszúságú lista bevitele procedure TForm1.FirstEditChange(Sender: TObject); begin if (sender as TEdit).Text <> '' then begin … end; // add new row end; procedure TForm1.SecondEditChange(Sender: TObject); begin if (sender as TEdit).Text = '' then begin … end; // delete last row end;
Grafikai alapok Eszközkörnyezet: a vászon, amire rajzolunk Az API szintjén bonyolult lenne használni TCanvas osztály Canvas.Brush.Color := clRed; Canvas.Pen.Color := clBlue; Canvas.Ellipse(20, 20, 120, 120); Felszabadítja a nem használt erőforrásokat
TCanvas tulajdonságok Brush ecsetszín vagy minta ClipRect a canvas jelenlegi vágó téglalapja CopyMode meghatározza a rajzolás módját Font a canvas ezzel a betűvel rajzol Handle a canvas leíró tulajdonság (Windows API direkt hívásához) Pen meghatározza a vonalak stílusát PenPos a rajzolás pozíciója (x,y koordináta) Pixels egy tömb a canvas pixeleiből
TCanvas eljárások Arc a jelenlegi tollal ívet rajzolhatunk BrushCopy képet jelenít meg áttetsző háttérrel CopyRect képszeletet másol megadott helyre Draw a memóriából másol egy képet Ellipse ellipszis FloodFill kitölt egy területet az ecsettel
TCanvas eljárások LineTo vonalat húz megadott koordinátába MoveTo beállítja a jelenlegi rajzpozíciót Pie körszeletet rajzol Polygon kitöltött sokszög rajzolása Polyline vonal rajzolása koordinátatömbből Rectangle kitöltött téglalap
TCanvas eljárások RoundRect lekerekített sarkú téglalap StretchDraw kép másolása a memóriából TextExtent paraméterként megadott szöveg mérete pixelben TextWidth TextHeight paraméterként megadott szöveg szélessége, magassága pixelben TextOut szöveget rajzol megadott helyre TextRect szöveget rajzol téglalapon belülre
GDI objektumok Graphics Device Interface Objektumok: Toll Ecset Betű Paletta Bitkép Terület (region)
Tollak Color a vonal színe Handle a toll leíró tulajdonsága (GDI közvetlen meghívásához) Mode meghatározza a vonalrajzolás módját Style a toll stílusa Width a toll szélessége pixelben
Ecsetek Bitmap kép beállítása az ecset háttereként Color az ecset színe Handle az ecset leírója (közvetlen GDI híváshoz) Stlye az ecset stílusa
Képek megjelenítése var Bitmap: TBitmap; begin Bitmap := TBitmap.Create; Bitmap.LoadFromFile('hatter.jpg'); Canvas.Draw(0, 0, Bitmap); Bitmap.Free; end; Kép méretének megváltoztatása: StretchDraw Kép részekre bontott megjelenítése: CopyRect
Standard dialógusok Előnyei: Hátrányai: A felhasználónak minden alkalmazásnál ugyanaz az ablak jelenik meg A programozónak is egyszerűbb ezeket használnia Hátrányai: Egy bizonyos határon túl nem lehet őket megváltoztatni Ha magyar nyelvű programot angol Windows alatt futtatunk, akkor keveredik a két nyelv
OpenDialog, SaveDialog Fájlok kiválasztására szolgálnak megnyitáshoz, illetve mentéshez Események: OnShow OnClose OnCanClose OnFolderChange OnSelectionChange OnTypeChange Metódusok: Execute
További dialógusablakok OpenPictureDialog, SavePictureDialog A dialógusablak része a kép előnézetét mutató felület is (csak .bmp, .ico, .wmf vagy .emf kiterjesztésű képeknél látható) FontDialog Események: OnApply Metódusok: Execute
PrinterSetupDialog, PrintDialog A nyomtató beállításait megjelenítő dialógusablakot nyit meg Execute metódus PrintDialog Tulajdonságok: Másolatok száma (Copies) Leválogatás módja (Collage) Kinyomtatandó oldalak száma (MinPage, MaxPage)
FindDialog, ReplaceDialog Kizárólag adatok bevitelére szolgálnak Események: OnFind OnReplace Metódusok: Execute CloseDialog
DDE technológia Dynamic Data Exchange Ma már kicsit elavult DDE szerver: információt nyújt más alkalmazásoknak A DDE kliens felelős a kapcsolat kialakításáért Téma: a kommunikáció pontosabb definiálása Elem: az átadott adatok legpontosabb identifikációja
DDE technológia DdeServerConv: a szerver témája DdeServerItem: a szerver témájának egy eleme DdeClientItem: a kliens témájának egy eleme DdeClientConv: a kliens témája SetLink: megpróbál kapcsolatot kialakítani CloseLink: befejezi az aktuális konverzációt ExecuteMacro: parancsot küld a szervernek
OLE technológia Object Linking and Embedding Szerkeszthetünk bitmapeket anélkül, hogy külön le kellene programoznunk OLE 1.0 1990 DDE koncepcióján alapul képes több aktív kapcsolatot fenntartani két dokumentum között OLE 2.0 Új funkciók: drag-and-drop technika, helyben történő aktiválás, OLE strukturált tárolás
OLE technológia OLE szerver: saját gépen futó alkalmazás, mely más alkalmazások részére felkínálja szolgáltatásait Lehetőséget ad más alkalmazásban definiált objektum megjelenítésére a saját programunkban Beszúrás (Embedding): az objektum fizikailag is az alkalmazásba kerül Csatolás (Linking): az alkalmazásba nem lesz fizikailag beszúrva az objektum, csak egy hivatkozás rá
A Delphi és az OLE Az OleContainer komponens jelképezi az OLE szervereket a Delphiben létrehozott alkalmazásokban Metódusok: InsertObjectDialog CreateObject CreateObjectFromFile CreateObjectFromInfo CreateLinkToFile
OLE objektum beolvasása procedure TForm1.CreateObjectClick(Sender: TObject); begin OleContainer1.CreateObjectFromFile (ExpandFileName('teszt.doc'), false); end; procedure TForm1.LoadFromFileClick(Sender: TObject); begin OleContainer1.LoadFromFile('teszt.doc'); end;
OLE objektum mentése procedure TForm1.SaveToFileClick(Sender: TObject); begin OleContainer1.SaveToFile('teszt.doc'); end; procedure TForm1.SaveAsDocumentClick(Sender: TObject); begin OleContainer1.SaveAsDocument('teszt.doc'); end;
Menük összekapcsolása Ha elhelyezünk egy MainMenu komponenst a formon, akkor az objektum szerkesztésekor ebben megjelennek az OLE szerverhez tartozó menüpontok De mi van akkor, ha az alkalmazásunkban is szeretnénk saját menüt kialakítani? GroupIndex tulajdonság 0, 2, 4… GroupIndex esetén az alkalmazás főmenüjének menüpontjai mindig láthatók lesznek 1, 3, 5… GroupIndex esetén az OLE szerver menüjével felül lesznek írva
DLL-ek A Windowsban kétféle futtatható állomány létezik: Programok (EXE fájlok) Dinamikus csatolású könyvtárak (Dynamic Link Libraries, DLL fájlok) A DLL fájlok közvetlenül nem futtathatók, mégis tartalmaznak programkódot, és tartalmazhatnak erőforrásokat is DLL-ek előnyei: Több program használhatja ugyanazt a DLL-t Ekkor a DLL csak egyszer töltődik be a memóriába A Delphiben készített DLL-eket más programozási nyelven készült alkalmazásokban is felhasználhatjuk
DLL készítése library dll_pelda uses SysUtils, Classes, Math; function lnko(a,b: integer): integer; stdcall; var i: integer; begin i := min(a,b); while (a mod i > 0) or (b mod i > 0) do dec(i); result := i; end; exports lnko; begin beep(); end.
Statikus importálás Akkor töltjük be a DLL-t a memóriába, amikor az azt használó program első példánya elindul Minden további alkalmazás a már betöltött könyvtár alprogramjait használja Az alprogram neve alapján: function lnko(a,b: integer):integer; stdcall; external 'dll_pelda.dll'; Átnevezéssel: function LegnagyobbKozosOszto(a,b: integer):integer; stdcall; external 'dll_pelda.dll' name 'lnko';
Dinamikus importálás Az alkalmazás futása során betöltjük a DLL-t a memóriába LoadLibrary() Ha már nincs rá szükség, felszabadítjuk FreeLibrary() A hivatkozáshoz szükségünk van a DLL-függvény vagy eljárás belépési pontjának címére GetProcAddress()
MDI alkalmazások Multiple Document Interface Főform: szülő ablak Azon belül megjelenő formok: gyermek ablakok Például: Szövegszerkesztők Fejlesztő programok Internetes böngészők
MDI alkalmazások
MDI működése a Windowsban Delphi MDI sablonban több funkció van, ami eleve működik MDI alkalmazások felépítése a Windowsban: Az alkalmazás fő ablaka: keret vagy tároló MDI ügyfél: az MDI keretablak teljes területét befedi (a keret gyermeke) Gyermekablakok: nem közvetlenül a keretablakba helyeződnek, hanem az MDI ügyfél gyermekei
Keret- és gyermekablakok procedure TMainForm.NewElement1Click(Sender: TObject); var ChildForm: TChildForm; begin WindowMenu := Window1; Inc(counter); ChildForm := TChildForm.Create(Self); ChildForm.Caption := ChildForm.Caption + ' ' + IntToStr(counter); ChildForm.Show; end;
Keret- és gyermekablakok Megnyitás, kis méret, teljes méret: OK Bezárás helyett lekicsinyíti az ablakokat Ahhoz, hogy valóban eltűnjön egy ablak, az OnClose esemény Action paraméterét caFree-re kell állítani: procedure TChildForm.FormClose(Sender: TObject; var Action: TCloseAction); begin Action := caFree; end;
Ablak menü felépítése A Delphinek van előre elkészített MDI sablonja Windows menü elemei: Cascade (lépcsőzetes elrendezés) Tile (mozaikszerű elrendezés) Arrange Icons (ikonok elrendezése) Jobb megoldás: Helyezzünk a formra egy ActionList komponenst, és rendeljük hozzá az előre meghatározott, kész MDI műveleteket Majd hozzuk létre a Windows menüben a megfelelő almenüket, és állítsuk be az action tulajdonságukat
Különböző gyermekablakok procedure TChildOther.AddCircle1Click(Sender: TObject); var x,y: integer; begin randomize; x := random(300); y := random(300); Canvas.Ellipse(x-20, y-20, x+20, y+20); end; procedure TChildOther.Clear1Click(Sender: TObject); begin Refresh; end;
Különböző gyermekablakok Állítsuk be az előbb definiált formot gyermekformnak Mivel MDI alkalmazásnál egy gyermekablaknak nem lehet saját menüje, ezért ez zavart okoz Megoldás: állítsuk be a menükhöz tartozó GroupIndexet File menü a MainFormon: 1 Circle menü a ChildOther formon: 2 Window menü a MainFormon: 3
Különböző gyermekablakok Ha egy TChildOther típusú gyermekablak aktív, akkor megjelenik a hozzá tartozó menü:
Különböző gyermekablakok Ha másik típusú ablakra váltunk, akkor a menü eltűnik:
Vége Köszönöm a figyelmet!