Skapa dina egna Delphi-procedurer och funktioner. Skapa ett About-formulär i Delphi

Innan du skapar din komponent måste du välja en förfader för den. Vem kan vara förfader till din komponent?

Används vanligtvis som förfäder till TComponent, TControl, TWinControl, TGraphicControl, TCustomXXXXXX, såväl som alla komponenter i komponentpaletten.
Låt oss ta till exempel TOpenDialog-komponenten, som finns på sidan Dialoger i komponentpaletten. Den gör sitt jobb bra, men den har ett litet besvär. Varje gång du använder den måste du ändra värdet på Options-egenskapen varje gång. Och som regel är det samma åtgärder.
OpenDialog1.Options:= OpenDialog1.Options + ;

så att filen vi försöker öppna med den här dialogrutan faktiskt finns på disken.
Vi har redan valt en uppgift för oss själva, allt som återstår är att skapa en komponent. Vi skapar ett tomrum för komponenten genom att välja kommandot Component/New Component... från menyn och välja i dialogrutan
Ancestor typ: TOpenDialog
Klassens namn: TOurOpenDialog
Palettsida: Vårt test
Vi klickade på Ok och vi har nu en mall för vår framtida komponent.

Vi åsidosätter konstruktorn för denna komponent, dvs. i det offentliga avsnittet infoga raden:

konstruktor Skapa(AÄgare: TComponent); åsidosätta;

Genom att klicka på den här raden Ctrl + Shift + C skapas en mall för denna metod, i vilken vi infogar följande rader:

ärvt Skapa(AOwner); (Ring den ärvda konstruktören)
Alternativ:= Alternativ + ; (Vi utför de åtgärder vi behöver)

Observera: Kombinationer Ctrl-tangenter+ Skift + upp/ned-pilar låter dig flytta mellan en metoddeklaration och dess implementering.

Installerar den skapade komponenten Component/Install Component...
Installera i nytt paket
Paketfilnamn: C:Program FilesBorlandDelphi4LibOurTest.dpk
Paketbeskrivning: Vårt testade paket

Gillar du inte att vår komponent har samma ikon som standarden? Låt oss sedan skapa vår egen åt honom.
För att göra detta måste vi anropa Tools/Image Editor. Skapa en ny *.dcr-fil.
Infoga bilden av resurs/ny/bitmapp i den. Ställ in bildstorleken till 24x24 pixlar. Och sedan - din kreativitet...
Observera: färgen på prickarna som stämmer överens med färgen på prickarna i det nedre vänstra hörnet av bilden kommer att betraktas som TRANSPARANT!
När du har skapat din ritning byter du namn på den från Bitmap1 till TOurOpenDialog och sparar filen som OurOpenDialog.dcr.
Ta bort komponenten från paketet och installera den igen (endast i det här fallet kommer en länk till *.dcr-filen att läggas till).
Kompilera, installera och lycka till!

enhet OurOpenDialog; gränssnitt använder Windows, meddelanden, SysUtils, klasser, grafik, kontroller, formulär, dialogrutor; typ TOurOpenDialog = klass(TOpenDialog) privat(Privata deklarationer) skyddad offentlig(Offentliga deklarationer) konstruktör Create(AOwner: TComponent); åsidosätta; publiceras slutet; procedur Registrera; genomförande procedur Registrera; Börja RegisterComponents("Sampler", ); slutet; (TOurOpenDialog) konstruktör TOurOpenDialog.Create(AOwner: TComponent); Börja ärvt Skapa(AÄgare); (Anropa den ärvda konstruktorn) Options:= Options + ; (Vi utför de åtgärder vi behöver) slutet; slutet.

En komponentdeklaration består av avsnitt som t.ex privat, skyddad, offentlig och publicerad. Vad menar dem?
Dessa är synlighetsdirektiv.
Allt som deklareras i avsnittet privat, endast tillgänglig i modulen där klassen deklareras (privata deklarationer). Här deklareras som regel variabler som lagrar egenskapsvärden, såväl som metoder (procedurer eller funktioner) för att komma åt dem.
Allt som deklareras i avsnittet skyddad, tillgänglig som i privatsektionen, samt till arvingar av denna klass(utvecklargränssnitt).
Här kan du deklarera metoder för att komma åt egenskapsvärden (om du vill tillåta barn till din komponent att ändra dessa metoder),
samt egenskaper, metoder och händelser (metoder för att reagera på händelser) i komponenter av typen TCustomXXX.
Allt som deklareras i avsnittet offentlig, tillgänglig för alla användare av komponenten (runtime-gränssnitt).
Metoder deklareras vanligtvis här. Endast fastigheter och händelser kan deklareras i det publicerade avsnittet (de deklareras som egenskaper).
De är tillgängliga under applikationsdesign (designfasgränssnitt).

Egenskaper

Skriv egenskaper massiv- vanliga Object Pascal-arrayer, men till skillnad från de senare kan de inte bara indexeras numeriska värden men även stränga. Tyvärr kräver denna typ av egenskap en anpassad egenskapsredigerare (i objektinspektören har egenskapsredigeraren en knapp med tre punkter [...]), så i exemplet nedan egenskapen ArrayProp meddelas i avsnitt offentlig.

typ TOurComponent = klass(Tkomponent) privat( Privata deklarationer ) FArrayProp: array av heltal; fungera GetArrayProp(aIndex: heltal): heltal; procedur SetArrayProp(aIndex: heltal; konst Värde: heltal); skyddad(Skyddade deklarationer) offentlig(Offentliga deklarationer) fast egendom ArrayProp: heltal läsa GetArrayProp skriva SetArrayProp; publiceras(Publicerade deklarationer) slutet;

Egenskapsspecifikationer

Specifierare standard anger om egenskapsvärdet ska sparas i formulärfilen eller inte. Om fastighetsvärdet matchar värdet standard- värdet i formulärfilen sparas inte, om värdena inte är lika - sparas det. Du kan kontrollera detta genom att placera komponenten på formuläret och välja Högerklicka musmenyalternativet "Visa som text". Standard anger inte det ursprungliga värdet för egenskapen till det angivna. Detta måste göras i komponentens konstruktor.

enhet Vår Komponent; gränssnitt använder Windows, SysUtils, klasser, grafik, formulär, kontroller; typ TOurComponent = klass(Tkomponent) privat( Privata deklarationer ) FMyInteger: Integer; skyddad(Skyddade deklarationer) offentlig(Offentliga deklarationer) konstruktör Create(AOwner: TComponent); åsidosätta; publiceras(Publicerade deklarationer) fast egendom MyInteger: Heltal läsa FMyInteger skriva FMyInteger standard 10; slutet; genomförande konstruktör TOurComponent.Create(AOwner: TComponent); Börja ärvt Skapa(AÄgare); FINteger:= 10; slutet; slutet.

Specifierare nodefaultåsidosätter standardegenskapsvärdet. Denna specificering används vanligtvis för att åsidosätta standardvärdet för en ärvd egenskap.
Till exempel: fast egendom AutoSize nodefault;

Specifierare lagrad anger när egenskapsvärdet ska sparas i formulärfilen. Efter lagrad kan stå Sann(spara alltid) falsk(aldrig spara) eller namnet på en funktion som returnerar ett booleskt resultat.

fast egendom OneProp: heltal läsa FOneProp skriva SetOneProp lagrad Falsk; fast egendom TwoProp: heltal läsa FTwoProp skriva SetTwoProp lagrad Sann; fast egendom ThreeProp: heltal läsa FTreeProp skriva SetThreeProp lagrad Fukt;

Och det sista:
För att lägga till en bild till en komponent för demonstration i komponentpanelen måste du: - skapa den med en storlek på 24*24 med filen name.dcr (i resursen är namnet på bilden lika med namnet på komponenten, med versaler)
- placera bilden bredvid komponenten.

Subrutiner - procedurer och funktioner i Delphi språk används för att utföra specialiserade operationer. Delphi har många standardrutiner, men du måste fortfarande skapa dina egna för att utföra ofta upprepade operationer på data som kan ändras.

I allmänhet finns det programmeringsteknik"uppifrån och ner". Programmeringsteknik"top-down" delar upp uppgiften i flera enklare, som är skrivna i form av subrutiner. Dessa delas i sin tur också upp, om nödvändigt, tills problemen som programmeraren står inför når en acceptabel nivå av komplexitet (det vill säga enkelhet!). Så det här programmeringsteknik gör det lättare att skriva program genom att skapa ett så kallat skelett, bestående av subrutindeskriptorer, som senare fylls med specifika algoritmer. En tom subrutinbeskrivning kallas annars en "stub".

OCH förfaranden, Och funktioner låter dig uppnå samma resultat. Men det finns fortfarande en skillnad.

Delphi förfarande den utför helt enkelt de nödvändiga operationerna, men returnerar inga resultat från sina åtgärder. Resultatet är de ändringar som inträffade i programmet under genomförandet av denna procedur. I synnerhet kan proceduren ändra värdena för variabler, skriva nya värden till komponentceller, skriva till en fil, etc.

Delphi funktion låter dig också göra allt ovan, men returnerar dessutom resultatet i den tilldelade till sig själv menande. Det vill säga ett funktionsanrop kan vara närvarande i uttrycket till höger om uppdragsgivaren. Så en funktion är ett mer mångsidigt objekt!

Beskrivningen av subrutinen består av nyckelord procedur eller fungera, följt av namnet på rutinen med en lista över parametrar inom parentes. När funktioner följt av ett kolon och typen av returvärde. Ett vanligt semikolon krävs nedan! Själva subrutinkoden är omgiven av "logiska parenteser" börja/sluta. För en funktion måste du tilldela den i kod till en variabel med namnet på funktionen eller en speciell reserverad variabel Resultat(helst) funktionens returvärde. Exempel:


En subrutin som beskrivs på detta sätt måste placeras i huvudprogrammet innan dess första anrop. Annars kommer du under kompileringen att få ett meddelande om att "okänd identifierare..." Det är inte alltid bekvämt att hålla reda på detta. Det finns en väg ut - placera endast subrutintiteln där beskrivningar av alla programdata placeras.

Parametrar är en kommaseparerad lista med identifierare, följt av ett kolon och typen. If listor med identifierare olika typer flera, de är åtskilda av ett semikolon. Allt är detsamma som vid en vanlig databeskrivning. Dessa är de så kallade formell alternativ. När du anropar en subrutin ersätts de av faktisk- kommaseparerade data av samma typ som de formella.
Parametrar i subrutinbeskrivningen kan vara frånvarande, sedan arbetar den med data direkt från huvudprogrammet.

Nu måste vi introducera begreppet lokal data. Detta är data - variabler, konstanter, subrutiner som används och existerar endast vid anropet av denna subrutin. De bör också beskrivas i denna subrutin. Platsen för deras beskrivning är mellan titeln och början av det logiska blocket - nyckelordet Börja. Namn lokal data kan matcha namnen global. I det här fallet används en lokal variabel och ändrar den kommer inte att påverka på en global med samma namn.
Ganska lika lokala typer, variabler, konstanter och lokala procedurer och funktioner kan introduceras, vilka kan beskrivas och användas endast inom en given subrutin.

Nu ett exempel. Låt oss skriva ett program för att summera två tal. Den kommer att bestå av ett formulär där det kommer att finnas en knapp (komponent Knapp), genom att klicka på vilken vår subrutin kommer att exekveras, och två inmatningsrader (komponenter Redigera), där vi kommer in i operanderna. Låt oss börja från förfarandet.

var
Form1: TForm1;
A, B, Summa: Heltal;
procedur Sum(A, B: heltal);

genomförande

($R *.dfm)

procedur
Börja
A:=StrToInt(Edit1.Text);
B:=StrToInt(Edit2.Text);
Summa(A, B);
Caption:=IntToStr(Summa);
slutet;

procedur Sum(A, B: heltal);
Börja
Summa:=A+B;
slutet;

Vår procedur finns efter knappklickshanteraren, där den kallas. Och programmet fungerar just för att procedurhuvudet ingår i databeskrivningsblocket. Men fortfarande driften av summering i I detta fall Det är gjort något otydligt.
Låt oss nu göra samma sak med funktioner.

var
Form1: TForm1;
A, B, Summa: Heltal;
fungera

genomförande

($R *.dfm)

procedur TForm1.Button1Click(Avsändare: TObject);
Börja
A:=StrToInt(Edit1.Text);
B:=StrToInt(Edit2.Text);
Summa:=Summa(A, B); // Enligt min mening är det nu mer tydligt var allt kommer ifrån
Caption:=IntToStr(Summa);
slutet;

fungera Sum(A, B: Heltal): Heltal;
Börja
Resultat:=A+B;
slutet;

Det finns funktioner i att använda stora datastrukturer som parametrar, till exempel arrayer som består av flera tusen (eller fler) element. Vid överföring av stora datamängder till en subrutin kan det bli stora utgifter för systemresurser och tid. Därför används överföring av andra element än värdena själva (överföring "efter värde", som i tidigare exempel), och referenser till namnet på en variabel eller konstant (passerande "vid namn"). Detta uppnås genom att infoga ett nyckelord före parametrarna som vi vill skicka med namn var.

fungera Sum(A, B: heltal; var Arr: array av heltal): heltal;

Om vi ​​tittar på beskrivningen av vår subrutin och beskrivningen av knappklickshanteraren (detta är också en subrutin!), som skapades av Delphi, ser vi att namnet på hanteraren (Button1Click) föregås av TForm1. Som vi vet, i Delphi, separerar en punkt ett objekt och dess attribut (egenskaper och metoder). Så Delphi skapar Button1Click som en metod på Form1-objektet. Dessutom brevet T innan objektet indikerar att Button1Click inte bara är en metod för objektet, utan en metod för objektets klass. Låt oss inte bry oss om det här för tillfället, men vi ska bara göra detsamma. Genom att beskriva vår procedur eller funktion som en metod för klassen TForm1 får vi möjlighet att använda klassobjekt i den utan att ange dess namn, vilket är mycket bekvämare. Det vill säga, om vi i vår subrutin använder några komponenter placerade på formuläret (till exempel Button1), så skriver vi

Button1.Width:=100; //Knappbredd
men inte
Form1.Button1.Width:=100;

Det blir också möjligt att använda inbyggda variabler, såsom parametern Sender. I varje hanterare pekar detta objekt på källan, det vill säga objektet som anropar den givna rutinen. Till exempel i vårt summeringsförfarande Avsändare = Knapp1. Efter att ha analyserat denna variabel kan du besluta om vissa åtgärder.

Efter att ha beskrivit subrutinen som en klassmetod måste vi placera dess beskrivning på samma plats där Delphi placerar dem - i beskrivningen av klassen TForm1. Se själv var beskrivningen av Button1Click-proceduren finns. För detta, med markören inuti Button1Click-rutinen, klicka CTRL+Skift och markörkontrollknappen " Upp" eller " Ner" samtidigt. Det kommer att ske en övergång till beskrivningen av subrutinen (för att gå tillbaka, upprepa denna åtgärd igen). Placera beskrivningen av din subrutin bredvid ny linje. Observera att TForm1 inte längre skrivs.

Rekursion- viktigt och kraftfullt egenskapen hos procedurer och funktioner i Delphi. Rekursion Detta är förmågan hos en subrutin att referera till sig själv under drift. Utan rekursion skulle du behöva använda loopar, vilket gör programmet svårare att läsa. Ett rekursivt anrop till en subrutin klargör omedelbart innebörden av vad som händer. Naturligtvis måste du se till att subrutinen måste ha ett villkor, när den är uppfylld stannar ytterligare rekursion, annars kommer subrutinen att gå in i en loop.

Ofta, när man arbetar med stor mängd filer eller bara för organisation, är det nödvändigt att distribuera filer till separata kataloger och underkataloger. För att automatisera processen är det bekvämt för programmet att vid behov självständigt kunna skapa de kataloger det behöver för att lagra filer. Delphi har en uppsättning funktioner för att stödja denna uppgift.

Skapa en mapp

Du kan skapa en mapp i Delphi med hjälp av CreateDir-funktionen eller MkDir-proceduren. Du kan också använda ForceDirectories-funktionen. De två första kommandona skapar en ny mapp korrekt. Skillnaderna ligger i hur de beter sig om det är omöjligt att skapa en mapp.

ForceDirectories(ExtractFilePath(Application.ExeName) + "/folder1/folder2/newfolder" );

Ta bort en mapp

När du tar bort en mapp är det viktigt att tänka på om den innehåller bilagor eller inte. Om mappen är tom används funktionen RemoveDir, där sökvägen till mappen som ska raderas anges, i likhet med skapande. Funktionen, när den körs, returnerar även True om raderingen lyckades och False om raderingen misslyckades.

if RemoveDir("minmapp") då
ShowMessage( "Mappen har raderats.")
annan
ShowMessage( "Fel: mappen har inte tagits bort.");

Om mappen inte är tom kan du använda anpassad funktion, som sekventiellt tar bort alla bifogade filer, och sedan tomma mappar. För Delphi miljöer 2010 kan du använda följande metod:

TDirectory.Delete("myfolder" , True);

I det här fallet bör IOUtils-biblioteket läggas till i beskrivningsavsnittet.

använder IOUtils;

Om detta inte är möjligt bör du använda nästa funktion, beskriven i DelphiWorld. Parametern anger sökvägen till mappen som ska raderas. Om raderingen lyckas (inklusive alla bilagor) kommer funktionen att returnera True om raderingen misslyckas, returnerar den False.

// Funktion för att radera en katalog med bilagor.
function MyDirectoryDelete(dir: sträng): Boolean;
var
fos: TSHFileOpStruct;
Börja
ZeroMemory(@fos, SizeOf(fos));
med fos börjar
wFunc:= FO_DELETE;
fFlags:= FOF_SILENT eller FOF_NOCONFIRMATION
pFrom:= PChar(dir + #0);
slutet ;
Resultat:= (0 = ShFileOperation(fos));
slutet ;

// Anropa raderingsfunktionen i programmet.
Börja om MyDirectoryDelete("minmapp") då
ShowMessage( "Mappen har raderats.")
annan
ShowMessage( "Fel: mappen har inte tagits bort.");
slutet ;

Du måste lägga till ShellApi-biblioteket i beskrivningsavsnittet här.

använder
ShellApi;

Kontrollerar att det finns en katalog

För att kontrollera att det finns en katalog, använd funktionen DirectoryExists. Parametern indikerar också hela eller relativ väg till mappen. Om angiven mapp existerar kommer funktionen att returnera True, annars False.

om DirectoryExists("minmapp") då
ShowMessage( "Mappen finns.")
annan
ShowMessage( "Det finns ingen sådan mapp.");


Utveckla dina egna komponenter

Om du inte är nöjd med standardkomponenterna som följer med Delphi, då är det dags för dig att prova på att skapa din egen. Vi börjar med enkla först och går gradvis över till mer komplexa. Så, låt oss börja.

Innan du skapar din komponent är det viktigt att välja rätt förfader för den. Vem kan vara förfader till din komponent? Används vanligtvis som förfäder till TComponent, TControl, TWinControl, TGraphicControl, TCustomXXXXXX, såväl som alla komponenter i komponentpaletten. Låt oss ta till exempel TOpenDialog-komponenten, som finns på sidan Dialoger i komponentpaletten. Den gör sitt jobb bra, men den har ett litet besvär. Varje gång du använder den måste du ändra värdet på Options-egenskapen varje gång. Och som regel är det samma åtgärder.


Genom att klicka på den här raden Ctrl + Shift + C skapas en mall för denna metod, i vilken vi infogar följande rader:


Installerar den skapade komponenten Component/Install Component...

  • Installera i nytt paket
  • Paketfilnamn: C:\Program Files\Borland\Delphi4\Lib\OurTest.dpk
  • Paketbeskrivning: Vårt testade paket

Gillar du inte att vår komponent har samma ikon som standarden? Låt oss sedan skapa vår egen åt honom. För att göra detta måste vi anropa Tools/Image Editor. Skapa en ny *.dcr-fil. Infoga bilden av resurs/ny/bitmapp i den. Ställ in bildstorleken till 24x24 pixlar. Och sedan - din kreativitet... Observera: färgen på prickarna som matchar färgen på prickarna i det nedre vänstra hörnet av bilden kommer att betraktas som TRANSPARANT!

När du har skapat din ritning byter du namn på den från Bitmap1 till TOurOpenDialog och sparar filen som OurOpenDialog.dcr. Ta bort komponenten från paketet och installera den igen (endast i det här fallet kommer en länk till *.dcr-filen att läggas till).

Kompilera, installera och lycka till!

Publiceringsdatum

Alla formulär behöver inte skapas när ansökan startar. Vissa är bättre skapade medan programmet körs.

I vilket fall är det bättre att skapa en form dynamiskt?

Jag vill lyfta fram två huvudpunkter.

  1. Om formuläret sällan används och det är stor sannolikhet att det inte kommer att anropas alls. Ett exempel skulle vara fönstret "Om".
  2. Om antalet instanser av vårt fönster kan vara fler än en.

Som alltid kommer jag att visa dig hur du skapar ett formulär dynamiskt med ett exempel.

Ett exempel på dynamisk formskapande.

  1. Klicka på huvudmenyn "Arkiv".
  2. Sen ny.

Själva programmet skissade upp klassen för den framtida formen. Därför att Vi kommer att skapa ett fönster genom att trycka på en knapp, jag föreslår att du tar bort följande kodrader.

var Form2: TForm2; // Om du gav formuläret ett namn, kommer denna kodavsnitt att variera

Vi organiserar deklarationen lokalt, inne i knapphanteraren. Låt oss spara den resulterande modulen.

Låt oss nu gå tillbaka till huvudform. Låt oss ansluta den nyskapade modulen till den: Arkiv->Använd enhet...-> Välj den du behöver (du kan helt enkelt lägga till den i avsnittet Användningar).

Låt oss skapa två knappar. Vi kommer att skapa ett nytt fönster på två olika sätt:

procedure TForm1.Button1Click(Avsändare: TObject); var Form2: TForm2; börja Form2:= TForm2.Create(Application); Form2.Caption:= "Nytt formulär, metod 1"; Form2.Visa; slutet;

procedur TForm1.Button2Click(Avsändare: TObject); var Form2: TForm2; börja Application.CreateForm(TForm2,Form2); Form2.Caption:= "Nytt formulär, metod 2"; Form2.Visa; slutet;

Tja, allt är väldigt enkelt, men om du fortfarande har några frågor, skriv i kommentarerna. Jag svarar en gång.