Component skriftlig del 1

Først i en tre del serier som dekker komponent skriver i Delphi.
Denne artikkelen opprinnelig dukket opp i Delphi DeveloperCopyright Pinnacle Publishing, Inc. Alle rettigheter reservert.
Denne første delen viser noen av de beste tilnærminger til bygningen komponenter, og samtidig gir tips om de bestemmer seg for den beste basen klassen til å arve fra, ved hjelp av virtuelle erklæringer, prosessen med overordnede, og så on.The første to ting å spørre deg selv er hvorfor du bør gjøre bruk av komponent skriving, og når du skulle ha behov for å skrive en komponent. Det første spørsmålet er enkelt å svare på, faktisk, det har mange svar

Brukervennlighet:. Innkapslet koden betyr at du kan bare slippe den samme komponenten på ulike former igjen og igjen uten å skrive en eneste kodelinje

Debugging. Sentralisert kode gjør det enkelt å reparere en hel applikasjon (eller et sett av applikasjoner) ved å feste en feil i en enkelt komponent og rekompileres.

Penger: Det er mange selskaper som er bare altfor glad for å betale for privilegiet av å ikke finne opp hjulet.
Det andre spørsmålet er ikke så vanskelig å svare heller. Når du finner deg selv å måtte skrive den samme koden mer enn en gang er det en god idé å skrive en komponent, særlig hvis koden utfører forskjellig basert på gitte parameters.How komponenter er createdThe første trinnet er å bestemme hvilken base klasse du trenger å utlede komponenten fra. Når du kommer fra en annen klasse du arver eiendom /metode og hendelse som denne komponenten eier. Nedenfor er et eksempel på hvordan du skal bestemme hvilken klasse du skal arve fra når du skriver din egen komponent. (Klikk for full størrelse) Når det gjelder metode A og metode B, anta at komponenten i spørsmålet er TMemo. Metode
Løsning
A
Derive fra TMemo
B
Utled fra TCustomMemo
C
Derive fra TCustomControl
D
Derive fra TGraphicControl
E
Derive fra TComponent
Dette kan virke litt komplisert, så la meg forklare prosessen A
. Når du bare trenger å legge til ekstra funksjonalitet til en eksisterende komponent du kommer fra den komponenten. Dette vil automatisk gi nye komponenten alle eksisterende funksjonalitet og egenskaper av eksisterende komponent B
. Noen ganger vil du ikke bare trenger å legge til funksjonalitet, men du må ta det på samme tid. Standarden praksis når du skriver en komponent er først til å skrive en TCustomXXXXX komponent der alle eiendommer /hendelser og metoder er erklært innenfor det vernede delen av komponenten. Selve komponent blir deretter utledet fra dette basisklassen. . Trikset er derfor ikke å skjule funksjonalitet, men å utlede komponenten fra "custom" versjon av komponenten og bare publisere de egenskapene du ønsker å beholde (effektivt fjerne uønskede egenskaper /hendelser) C
: Any komponent som må få fokus må et vindu håndtak. TWinControl er der dette håndtaket er først introdusert. TCustomControl er rett og slett en TWinControl med sin egen Canvas eiendom D
. TGraphicControl har ikke et vindu håndtak og kan derfor ikke motta fokus. Komponenter som TLabel er hentet fra denne basen klassen E
. Noen komponenter er ikke skapt for å forbedre GUI interaktivitet, men for å gjøre livet ditt enklere. Alt stammer fra TComponent er bare synlig på design-time. En typisk bruk av denne type komponent er for databasetilkoblinger, tidtakere etc.Once vi har bestemt hva vår base klasse skal være, er neste skritt å opprette komponenten. Fra Component-menyen, velg Ny Component og du vil se følgende dialogboks.
Ancestor typen
Dette er basen typen som vi trenger for å stige ned fra
klasse navn
Dette er klassen navnet på vår nye komponenten (prefiks med bokstaven "T")
Palette side
Dette er som fane på den komponenten paletten du ønsker yourcomponent skal vises på, inn i en ikke-eksisterende fane tellDelphi at du ønsker en ny fane opprettet.
Skrive noen codeAlready det er tid for oss til å skrive noe. Dette første eksemplet vil ha noen nytte i det hele tatt, bortsett fra å demonstrere noen grunnleggende begreper i komponent writing.First av alt, velger Component fra hoved Delphi-menyen og velg deretter Ny Component. Skriv TComponent som "Ancestor type" og TFirstComponent som navnet på komponenten. Neste klikk "Install" button.At dette punktet kan du enten installere den nye komponenten i en eksisterende pakke (en pakke har en samling av komponenter) eller installere i en ny pakke. Klikk "inn nye pakken" og klikk på "Browse" button.Once du har valgt en sti og filnavn for den nye pakken, og gikk inn i en beskrivelse klikk "OK". Ved neste dialogboks (spør om du ønsker å rekompilere pakken) klikk "Ja". Når pakken er kompilert og installert, lagre pakken og unit.At dette punktet har vi angitt vår base klasse, og også vår nye klassenavnet. Vi har opprettet en ny pakke for å inneholde vår komponent og har blitt presentert med et skjelett klassestrukturen ved Delphi.If du ser på kildekoden levert av Delphi du vil nå se Privat, beskyttet, Public, og Publisert sections.EncapsulationEncapsulation er en enkelt konsept å forstå, men svært viktig komponent skriving. Innkapsling er gjennomført med bruk av fire reserverte ord: Privat
, Beskyttet
, Offentlig
, og Publisert
, vil du se Delphi har inkludert disse delene automatisk i kildekoden for den nye komponenten. Seksjon
Tilgjengelighet
private metoder, egenskaper og hendelser vises i denne delen vil bare beaccessible til enheten komponenten er containedwithin. Komponenter i samme enhet kan få tilgang til hverandres private elementer.
Beskyttede metoder, egenskaper og hendelser vises i denne delen vil alsoaccessible noen klasse ned fra denne klassen.
offentlige metoder, egenskaper og hendelser erklært her tilgjengelig fra hvor som helst.
Publisert Denne delen lar deg å erklære eiendommer /hendelser som vil vises i theobject inspektør. Disse innstillingene er design tid valuesthat lagres med prosjektet. (Ikke alle typer aresupported, arrays for eksempel ikke er).
Begynner å skrive vår componentDelphi nå behov for å vite alt om vår nye komponenten. Skriv inn følgende kode i komponenten kildekode. privat
{felleserklæringer}
FStartTime, FStopTime: DWORD; beskyttet
{Beskyttede erklæringer}
funksjon
GetElapsedTime: string; virtuell
; offentlig
{offentlige erklæringer}
prosedyre
Hjem; virtuell
; prosedyre
Stopp; virtuell
; eiendom
Starttime: DWORD Les
FStartTime; eiendom
stopptid: DWORD Les
FStopTime; eiendom
ElapsedTime: string Les
GetElapsedTime; publisert
{Publisert erklæringer}
end
;
Det vi har gjort her er lagt til to variabler FStartTime og FStopTime (det er standard å preceed variabelnavn med bokstaven F). Det finnes to metoder for å kontrollere disse variablene, start og stopp. Vi har lagt en GetElapsedTime funksjon som vil returnere FStopTime - FStartTime som en streng. Endelig har vi lagt tre read-only properties.Press SKIFT-CTRL-C og Delphi vil automatisk fullføre koden for klassen din (eller klikk på høyre museknapp og velg "Complete klasse på markøren"). Neste skriv inn følgende kode for hver respektive metode. {TFirstComponent}
funksjon
TFirstComponent.GetElapsedTime: string; begynne
Resultat: = IntToStr (FStopTime - FStartTime); end
; prosedyren
TFirstComponent.Start; begynne
FStartTime: = GetTickCount; end
; prosedyre
TFirstComponent.Stop; begynne
FStopTime: = GetTickCount; end
; end
.
Test driveSave enheten, og åpne pakken (Fil, Åpne prosjekt fra menyen, og velg "Delphi Package" for filtypen), når pakken er åpent klikker du på " Kompiler "-knappen. Du kan også åpne pakken din ved å velge Component fra hovedmenyen og deretter installere pakker. Velg pakken og klikk deretter på "Edit" button.You kan nå slippe en TFirstComponent på et skjema, faktisk, kan du slippe så mange du vil. Legg til to knapper (btnStart og btnStop) og legg til følgende kode i form, og deretter kjøre test app ". prosedyre
TForm1.btnStartClick (Sender: TObject); begynne
FirstComponent1.Start; end
; prosedyre
TForm1.btnStopClick (Sender: TObject); begynne
FirstComponent1.Stop; Caption: = FirstComponent1.ElapsedTime; end
;
å klikke på "Start" -knappen vil markere starttidspunktet (GetTickCount er en WinAPI kommando som returnerer antall millisekunder siden Windows startet) .Clicking "Stop" knappen vil markere stopp tid, og endre tittelen for den form.Virtual, Dynamic, abstrakt og OverrideYou kanskje lagt merke til virtuell
erklæring etter start, stopp og GetElapsedTime. Følgende øvelsen vil forklare sine uses.Create en ny komponent, utlede denne komponenten fra TFirstComponent (navn det TSecondComponent) og installere den. De virtuelle og dynamisk identifikatorer er en komponent forfatter måte å fortelle Delphi at metoden kan erstattes i en etterkommer klasse. Hvis vi Styr en metode i en klasse, vil vår nye koden kjøres i stedet for den opprinnelige koden. beskyttet
{Beskyttede erklæringer}
funksjon
GetElapsedTime: string; styre
;
Vi deretter implementere koden ovenfor som følger. funksjon
TSecondComponent.GetElapsedTime: string; Var
S: string; begynne
S: = arvet
GetElapsedTime; Resultat: = S + 'millisekunder eller' + Format ( '.% 2f sekunder', [(stopptid - Starttime) /1000]); end
;
Vår nye koden kalles nå til erstatning for den opprinnelige GetElapsedTime, selv samtaler gjennomføres i TFirstComponent å GetElapsed tid vil nå kalle vår nye koden (hvis vi har opprettet en forekomst av TSecondComponent som er ). Den opprinnelige koden startes gjennom bruk av Arvet command.Note: Hvis du ikke "overstyring" en base metode (fordi basen ikke ble erklært som virtuell
eller fordi du har glemt). TSecondComponent vil kalle den nye koden, mens noen kode implementert i TFirstComponent vil likevel fortsette å kalle den opprinnelige koden fra TFirstComponent.The Abstract identifikator forteller Delphi ikke kan forvente noen kode for den navngitte metoden. Du bør ikke opprette en forekomst av et objekt med abstrakte metoder i dem (som TStrings). Standarden praksis er å skape en etterkommer av en slik klasse, og for å overstyre alle abstrakte metoder (for eksempel TStringList gjør) .Dynamic Vs Virtual er bare et spørsmål om hastighet Vs størrelse. En dynamisk metode vil resultere i hver forekomst av en klasse som krever mindre minne, mens en Virtual metoden vil kjøre fortere på bekostning av litt ekstra memory.There er noen enkle trinn for å legge til hendelser i komponenten. Hendelser tillate komponenten til å kommunisere med søknaden, for å varsle det når noe viktig har skjedd. En hendelse er bare en lese /skrive-hotellet, i stedet for å være en enkel variabel type (for eksempel streng, heltall etc) det er en prosedyre eller function.Create en ny komponent, stige ned den fra TSecondComponent og gi den navnet TThirdComponent. Lagre enheten, installere komponenten, og legg til følgende kode. skriv
TState = (stStarted, stStopped); TStateChangeEvent = prosedyre
Avsender: TObject; Stat: TState) av
objekt
; TThirdComponent = class product: (TSecondComponent) privat
{felleserklæringer}
FState: TState; FOnStart, FOnStop: TNotifyEvent; FOnStateChange: TStateChangeEvent; beskyttet
{Beskyttede erklæringer}
offentlig
{offentlige erklæringer}
konstruktør
Lag (AOwner: TComponent); styre
; destructor
Destroy; styre
; prosedyre
Hjem; styre
; prosedyre
Stopp; styre
; eiendom
State: TState Les
FState; publisert
{Publisert erklæringer}
eiendom
onStart: TNotifyEvent Les
FOnStart skrive
FOnStart; eiendom
OnStateChange: TStateChangeEvent Les
FOnStateChange skrive
FOnStateChange; eiendom
OnStop: TNotifyEvent Les
FOnStop skrive
FOnStop; end
;

Hendelser er rett og slett prosedyrer eller funksjoner (sjelden) som tilhører en klasse (derav "objekt" -klausulen du ser i TStateChangeEvent). For eksempel er TNotifyEvent en standard hendelsestype implementert av Delphi som bare passerer objektet som utløste hendelsen, er det alltid godt å sende "Self" (Sender: TObject) som første parameter for enhver hendelse som den samme hendelsen koden kan være brukes for flere components.TNotifyEvent er definert som skriv
TNotifyEvent = prosedyre product: (Sender: TObject) objekt
;
Å kalle en hendelse fra i en komponent er bare en sak for å sjekke om arrangementet har blitt tildelt, og hvis så, kaller det. Jeg har overstyrt start og stopp metoder for TSecondComponent for å utløse disse hendelsene, som så. prosedyre
TThirdComponent.Start; begynne
arvet
; //Dette krever TSecondComponent.Start
FState: = stStarted; hvis
Assigned (onStart)
onStart (Selv); hvis
Assigned (OnStateChange)
OnStateChange (Selv, State); end
; prosedyre
TThirdComponent.Stop; begynne
arvet
; //Dette krever TSecondComponent.Stop
FState: = stStopped; hvis
Assigned (OnStop)
OnStop (Selv); hvis
Assigned (OnStateChange)
OnStateChange (Selv, State); end
; konstruktør
TThirdComponent.Create (AOwner: TComponent); < B> begynne
arvet
; //Dette er var du initialiserer egenskaper, og skape
//og objekter komponenten kan bruke internt
FState: = stStopped; end
; destructor
TThirdComponent.Destroy; begynne
//Dette er hvor du vil ødelegge //noen opprettet gjenstander
arvet; end
;
rekompilere pakken (ikke glem å lagre pakken når du legger til en ny komponent). Ved å slippe den nye komponenten på skjemaet vil du legge merke til at det er tre arrangementer. onStart
, OnStop
, og OnStateChange
. Hvis du ser på Demo3 vil du se hvordan jeg har brukt disse hendelsene. onStart
setter bildeteksten til "Startet" OnStop
viser medgått tid OnStateChange
aktiverer /deaktiverer relevant start /Stopp-knappen prosedyre
TForm1.ThirdComponent1Start (Sender: TObject); begynne
Caption: = 'start'; end
; prosedyre
TForm1.ThirdComponent1Stop (Sender: TObject); begynne
Caption: = ThirdComponent1.ElapsedTime; end
; prosedyre
TForm1.ThirdComponent1StateChange (Sender: TObject; stat: TState ); begynne
btnStart.Enabled: = ThirdComponent1.State = stStopped; btnStop.Enabled: = ThirdComponent1.State = stStarted; end
;
Standards in komponent writingFinally vi vil dekke noen flere punkter om komponent skriving, inkludert noen eksisterende metoder for grunnkomponenter og standarder for skriving. Opprette og ødelegge din komponent:
objekter er skapt gjennom en konstruktør og ødelagt gjennom en destructor. Hensikten med å overstyre en konstruktør er tredelt


    For å lage gjenstander som den inneholder i seg selv (underobjekter)

    For å initialisere verdiene av klassen (eiendommer etc)

    for å heve et unntak og stoppe klasse skapes.

    det er standard å ringe arvet konstruktør fra i din egen konstruktøren slik at foreldre-klassen kan utføre sine initialisations, selv om det ikke er nødvendig å gjøre dette for å skape komponenten. (Din komponent er opprettet så snart konstruktøren er ferdig, blir det ikke skapt ved å ringe arvet konstruktøren) Hensikten med å overstyre en destructor er rett og slett å frigjøre noen ressurser som ble tildelt i løpet av levetiden til komponent. Ring arvet bare etter at du har frigjort disse resources.Standard komponenter: Paint product::. Du kan overstyre denne metoden for å gi din egen tilpassede tegning av komponenten Loaded
    : Dette kalles av Delphi så snart alle eiendommene er ferdig blir satt når det er skapt sin overordnede form. Du kan overstyre denne metoden for å utføre handlinger som er avhengige av en gruppe av eiendommer blir satt ugyldig product::.. Når en eiendom er endret som påvirker det visuelle inntrykket av en komponent du bør kalle denne metoden < i> ComponentState
    : Denne eiendommen er svært nyttig når du trenger å sjekke om komponenten i dag eksisterer på design /løpe tid, eller om dens egenskaper blir nå lest av en streaming process.Encapsulating komponenten properlyIt er standard å skrive din komponent som TCustomMyClass og deretter utlede komponenten fra den base klasse. Den "custom" komponent du skriver vil ha de fleste (om ikke alle) av sine egenskaper /metoder erklærte i sin Beskyttet section.When du stige fra "custom" class du bare redeclare dine egenskaper innen det offentlige eller Publisert seksjoner. skriv
    TCustomMyClass = class product: (TComponent) privat
    FSomeString: string
    ; beskyttet
    prosedyre
    SetSomeString ( konst
    Verdi: string); virtuell
    ; eiendom
    SomeString: string Les
    FSomeString skrive
    SetSomeString; end
    ; TMyClass = class product: (TCustomMyClass) publisert
    eiendom
    SomeString; end
    ;
    Dette er god praksis som det tillater andre å utlede sine egne komponenter basert på din samtidig gir dem til å fjerne visse properties.Note hvordan SetSomeString har blitt erklært som virtuell innenfor verneområdet . Dette er også god etikette som det lar ned klasser for å svare på endringer i eiendomsverdier ved å overstyre den prosedyre som skiller dem. Dette gjelder også for hendelser, hvor du ser en OnStateChange arrangementet vil du ofte finne en DoStateChange metode, for eksempel: skriv
    TCustomMyClass = class product: (TComponent) privat
    FOnStateChange : TStateChangeEvent; beskyttet
    prosedyre
    DoStateChange (State: TState); virtuell
    ; publisert
    eiendom
    OnStateChange: TStateChangeEvent Les
    FOnStateChange skrive
    FOnStateChange; end
    ; prosedyre
    TCustomMyClass.DoStateChange (State: TState); begynne
    hvis
    Assigned (OnStateChange)
    OnStateChange (Selv, State); end
    ;
    I stedet for å skrive "Hvis tildelte (OnStateChange) og deretter" kode hver gang de statlige endringer, vil du bare kalle "DoStateChange (newstate)". Bortsett fra å være mindre å skrive, gjør det også underordnede klasser for å overstyre DoStateChange og utløse nødvendige koden som svar på en event.SummaryIn denne første artikkelen vi har sett bruk av komponent skriftlig. Vi har også sett hvordan å skrive våre komponenter, og hva opprinnelige klassen å basere våre komponenter på. Videre diskuterte vi Virtual /Dynamiske metoder, og hvordan du bruker dem for å gjennomføre "komponent etikette" .I den andre delen av denne artikkelen vil vi lære å skrive egendefinerte egenskaper, slik som binære data, samlinger, sett, og utvides sub -properties.NEXT aRTIKKEL > > kilde~~POS=TRUNC koden~~POS=HEADCOMP til å følge denne artikkelen kan lastes ned ved å klikke her
    .