12.07.2015 Aufrufe

DELPHI-Programmierung: Spezielle Techniken

DELPHI-Programmierung: Spezielle Techniken

DELPHI-Programmierung: Spezielle Techniken

MEHR ANZEIGEN
WENIGER ANZEIGEN

Erfolgreiche ePaper selbst erstellen

Machen Sie aus Ihren PDF Publikationen ein blätterbares Flipbook mit unserer einzigartigen Google optimierten e-Paper Software.

<strong>DELPHI</strong>-<strong>Programmierung</strong>:<strong>Spezielle</strong> <strong>Techniken</strong>Ausarbeitung von York YannikosInhalt• Der Sender-Parameter• Der Parent- / Owner-Parameter• Debugging• Exceptions• Streams• ActionLists / ActionManager• Threads• Run-time Type Information (RTTI)• Kurze Einführung in PackagesDer Sender-ParameterSender ist ein Parameter vom Typ TObject (Sender: TObject). Er kann jedes Objektbeinhalten, dass ein Event auslösen kann. Bei einem Event-Aufruf steht im Sender-Parameterdas Objekt, das den Event ausgelöst hat, sozusagen die „Absender-Adresse“.Beispiel-Code:procedure Form1.ButtonClick(Sender: TObject);beginif Sender is StopButton thenStop(Sender);end;Diese Prozedur überprüft, ob der Button, der geklickt wurde und die Prozedur aufgerufen hat,ein StopButton ist. Falls ja, dann wird der StopButton auf „Stop“ gesetzt.Der Sender kann von Prozedur zu Prozedur weitergegeben werden, beinhaltet jedoch immerdas Objekt, das den ersten Event ausgelöst hat. Dabei kann Sender auf die Poperties vonObjekten zugreifen.Beispiel-Code:procedure TForm1.PanelClick(Sender: TObject);beginPanel1.Color := TPanel(Sender).Color;end;Mit dieser Prozedur wird die Farbe eines Panels (Panel1) auf die gleiche Farbe gesetzt, wiedie des beliebigen anderen Panels, auf das geklickt wurde, und das somit den Event ausgelösthat.


(siehe Programm1, Form1)Leider gibt es beim Sender Einschränkungen. Zum Beispiel lässt sich eine ähnlicheButtonClick-Prozedur nicht auf z.B. ein MainMenu anwenden, da die Prozedur einen Buttonals Event-Auslöser erwartet, und keinen Klick auf ein MainMenu.(siehe Programm1, Form2)Eine gute Lösung bieten hier die Tags.Tag ist eine Property von TComponents, das sich im Klassenbaum nur zwei Stufen unterTObjects befindet. Folglich hat jede Delphi-Komponente Tag als Property. Tag ist vom TypInteger und kann beliebig gesetzt werden. Durch ihn lassen sich Komponenten gutmiteinander verknüpfen.(siehe Programm1, Form3: procedure TForm3.SpeedButtonClick(Sender: TObject);)Diese SpeedButton-Prozedur lässt sich auf Buttons sowie auf MainMenus usw. anwenden:Zunächst werden ein MainMenu und ein PopupMenu eingefügt, mit jeweils vier MenuItems.Jedem Item wird dann der entsprechende SpeedButton zugeordnet: MenuItem1 bekommt dengleichen Tag wie SpeedButton1, MenuItem2 den gleichen wie SpeedButton2 usw. Hierbei istunwichtig, welchen Tag man konkret nimmt, wichtig ist nur, dass der Tag-Integerwert bei denKomponenten, die miteinander verknüpft werden sollen, gleich ist.Mit dem ersten IF wird abgefragt, ob das Objekt, das den Event ausgelöst hat (Sender), einSpeedButton ist. Falls ja, wird der Zustand in sein Gegenteil überführt (zweites IF), also von„gedrückt“ in „nicht gedrückt“ und andersherum. Ist der Sender kein SpeedButton, so werdenmit einer FOR-Schleife alle Komponenten des Formulars durchlaufen. Wenn eineKomponente „gefunden“ wurde, die ein SpeedButton ist, so wird anschließend der Tag vomSpeedButton mit dem des Senders verglichen. Ist der Tag der gleiche, so wird dieserSpeedButton, dem der Sender über den Tag zugeordnet ist, wie gehabt in seinen gegenteiligenZustand überführt.Der Parent- / Owner-ParameterDer Parent-Parameter eines Objektes gibt seinen Halter (oder „Container“) an:Zum Beispiel ist CheckBox1 innerhalb von GroupBox1 Child vonGroupBox1, und GroupBox1 ist Parent von CheckBox1.Koordinaten von Objekten werden relativ zu ihrem Parent angegeben.Der Owner-Parameter gibt den „Verantwortlichen“ für die Erstellung und Vernichtung einesObjektes an. Zum Beispiel ist in Delphi das Formular der Owner aller seiner Komponenten.Sobald also ein Objekt zerstört wird, das Owner von anderen Objekten ist, so werden allediese anderen Objekte ebenfalls zerstört (zum Beispiel beim Schließen eines Formulars).


Der Vorteil ist, dass nicht alle Objekte einzeln zerstört werden müssen.Im Controls array eines Objektes werden diejenigen anderen Objekte gespeichert, derenParent das gewählte Objekt ist. Ownership wird hingegen im Components array gespeichert(alle Objekte, deren Owner das gewählte Objekt ist).Programm2 listet zu jeder Komponente deren Owner und Parent auf und zeigt an, für welcheanderen Komponenten die gewählte der Parent (siehe Controls-Feld) bzw. der Owner (sieheComponents-Feld) ist.Debugging (to debug: ent„fehlern“, Fehler beseitigen)Der Begriff Debugging beschreibt Methoden, effizient Fehler zu finden und zu beseitigen.Dazu werden spezielle Tools benötigt, sogenannge Debugger.Währende der Software-Entwicklung mit Delphi arbeitet man stets in einem der folgendendrei Modi:• Entwurfsmodus• Laufzeitmodus• UnterbrechungsmodusDer Unterbrechungsmodus kann durch folgende Ausführungsmethoden erreicht werden:MethodeProgramm ausführen bis zur Cursorposition im CodeEinzelne Anweisungen ausführenGesamte Routine ausführenBis zum Haltepunkt ausführenShortcutF4F7F8Doppelklick oder F5 im CodeMan kann in Delphi mit folgenden Arten von Haltepunkten arbeiten:• nicht-bedingte• bedingte• Boolesche Ausdrücke• DurchlaufszählerNicht-bedingte Haltepunkte bewirken, dass das Programm sofort in den Unterbrechungsmodusspringt, sobald der Haltepunkt erreicht wurde.Bedingte Haltepunkte überprüfen beim Erreichen des Haltepunktes, ob eine gewisseBedingung erfüllt ist (Booelsche Ausdrücke: true / false) oder ob der Haltepunkt eine gewisseAnzahl oft durchlaufen wurde (Durchlaufszähler).Mit einem Booleschen Ausdruck kann man zum Beispiel prüfen, ob eine Variable einengewissen Wert hat, wenn der Haltepunkt erreicht wurde, um dann in Abhängigkeit davon inden Unterbrechungsmodus zu springen oder nicht.


ExceptionsBei der Fehlerbehandlung sind die Exceptions ein gutes Hilfsmittel. Sie dienen dazu,Ausnahmesituationen im Laufzeitmodus zu kontrollieren. Hierzu wird voher im Quelltext eingeschützter Bereich erstellt, in dem eventuelle Ausnahmen (Exceptions) auftreten können.Anschließend wird ein Bereich erstellt, der Anweisungen enthält, wie sich das Programm beiAuftreten einer Exception verhalten soll. Somit wird gewährleistet, dass das Programm beiFehlern nicht unkontrolliert abstürzt sondern mit einer Exception abgefangen wird.Es gibt zwei Arten von Exceptions:• try – except• try – finallyBeispiel-Code für try – except:{ ungeschützte Anweisungen }try// hier beginnt der geschützte Bereich{ Anweisungen, die eine Exception auslösen können }except// hier endet der geschützte Bereich undbeginnt der Exceptions-Anweisungsblock{ Anweisungen zur Behandlung von Exceptions; werden nurausgeführt, wenn Exception auftritt }end;// hier endet der Exceptions-Anweisungsblock{ weitere ungeschützte Anweisungen }Beispiel-Code für try – finally:{ ungeschützte Anweisungen }try{ Anweisungen, die eine Exception auslösen können }finally{ Anweisungen, die sowohl bei einer als auch bei keinerException ausgeführt werden }end;{ weitere ungeschützte Anweisungen }


Beispiel-Code für eine Verschachtelung:trytry{ ... }except{ ... }end;finally{ ... }end;Programm3 enthält Exceptions, um eine Division durch 0 abzufangen. Im Quelltext wirdbeim letzten Beispiel noch kurz angeschnitten, wie eigene Exception-Meldungen angezeigtwerden können.Hinweis:Unter Tools ► Debugger-Optionen… ► Sprach-Exceptions den Haken bei „Bei Delphi-Exceptions stoppen“ wegnehmen, sonst laufen die Exceptions nicht richtig.StreamsStreams bieten eine gute Möglichkeit, Daten zu lesen und zu schreiben. Dabei wird Zugriffauf verschiedene Datentypen wie Speicher, Strings, Sockets, Dateien, etc. ermöglicht.Die Oberklasse aller Streams ist TStream.Alle Unterklassen spezifizieren Zugriff auf bestimmte Datentypen:• TFileStream• TStringStream• TMemoryStreamBeispiel-Code für einen Streams:procedure TForm1.CopyFileClick(Sender: TObject);varstream1,stream2:TStream;beginstream1 := TFileStream.Create(From.Text,fmOpenRead);trystream2 := TFileStream.Create(To.Text,fmCreate);trystream2.CopyFrom(Stream1,Stream1.Size);finallystream2.Free;finallystream1.Freeend;


Hier wird zunächst stream1 erstellt, der die schon vorhandene Datei From.Text zum Lesenöffnet. Anschließend wird stream2 erstellt, der eine neue Datei To.Text erstellt und zumSchreiben öffnet. Dann wird der Inhalt von stream1 in stream2 geschrieben, bevor schließlichdie streams zerstört werden.Letztendlich wurde mit der Datei To.Text einfach eine Kopie der Datei From.Text erstellt.Weitere Moduskonstanten für TFileStream.Create und ihre Wirkung:KonstantefmOpenReadfmOpenWritefmOpenReadWritefmShareExclusivefmShareDenyWritefmShareDenyReadfmShareDenyNonefmCreateWirkungöffnet Datei zum Lesenöffnet Datei zum Schreibenöffnet Datei zum Lesen und Schreibenöffnet Datei für den ausschließlichen Zugriff derAnwendungverhindert, dass andere Anwendungen in die Dateischreibenverhindert, dass andere Anwendungen die Datei lesenoder in sie schreiben könnenerlaubt anderen Anwendungen das Lesen und dasSchreiben in die Dateierstellt eine neue Datei und öffnet sie zum SchreibenStreams ermöglichen es außerdem, Objekte als ganzes in einer Datei zu speichern und/oderauszulesen. Zum Beispiel können so Objekte während der Laufzeit in einer Datei gespeichert,anschließend vom Formular gelöscht, und schließlich wiederhergestellt werden.(siehe Programm4)ActionLists / ActionManagerActionsLists erlauben es, mehrere Elemente auf die gleiche Aktion zugreifen zu lassenDie Aktionen können individuell erstellt werden:Zum Beispiel Copy/Paste als Menüeintrag und als Symbol in einer Symbolleiste (dafür istdann nur eine Aktion nötig: Copy/Paste)


Die durch ActionLists verknüpften Objekte nehmen die Eigenschaften der Aktionskomponentean. Außerdem ist die Realisierung von Prozeduren und Events für verschiedeneKomponenten einfach und erfordert daher keinen großen Programmieraufwand. Man kannsowohl eigene als auch vorgegebene Aktionen benutzen. ActionLists werden über dieKomponentenliste in das Formular eingefügt. Anschließend kann per Rechtsklick derActionList-Editor aufgerufen werden, mit dem eigene Aktionen erstellt, geändert odergelöscht werden können. Jede Aktion umfasst dabei die Ereignisse OnExecute und OnUpdate.Mit OnExecute wird definiert, welche Anweisungen nach dem Ausführen der Aktionabgearbeitet werden; mit OnUpdate kann eine Prozedur festgelegt werden, die bei einem„Update“ der Komponente, die die Aktion benutzt (also zum Beispiel beim Schreiben in einEdit-Feld), aufgerufen wird.(siehe Programm5, Form1: Edit-Feld, Exit-Button, Next-Button)Erstelle Aktionen werden im ObjektInspektor unter den Ereignissen als „Action“ angezeigt.Folgende Befehle können im Edit-Feld eingegeben werden:• next• quit• smileDer ActionManager ist eine weitere Komponente, mit der schnell und einfach zum BeispielSymbolleisten erstellt werden können (in Verbindung mit ActionToolBars). Der ToolBarweist man den ActionManager im ObjektInspektor zu. Wie auch die ActionList ist derActionManager auf der Komponentenliste zu finden. Mit ihm lassen sich ebenfalls Aktionenverwalten und Icons und Shortcuts zuweisen. Hierfür wird nur noch eine einfache ImageListhinzugefügt, die man dem ActionManager im ObjektInspektor unter „Images“ zuweist.(siehe Programm5, Form2)ThreadsThreads kann man als „Pfade“ bezeichnen, an dem ein Prozess abläuft. Jeder Prozess bestehtaus mindestens einem Thread (primärer Thread).Frage: Warum sollte man weitere Threads erstellen?• Pro: Ausnutzung von Rechenzeit• Contra: Verwaltungsaufwand steigt (laut Borland sollten maximal 16 Threads benutztwerden)Für Threads wird die Laufzeit in „Zeitscheiben“ eingeteilt, d.h., jeder Thread bekommt seineeigene Zeit zur Verfügung gestellt. Außerdem werden Threads nach Priorität behandelt.Es gibt zwei Arten von Multithreading:• synchronisiert• unsysnchronisiert


Beim synchronisierten Multithreading erfolgt ein gleichzeitiger Zugriff auf dieselben Daten,was leicht zu Problemen führt. Die Lösung dafür sind Critial Sections (siehe unten).Beim unsynchronisierten Multithreading arbeiten die Threads völlig unabhängig voneinanderjedoch erfolgt durch keinen Thread Zugriff auf globale Variablen. Deshalb wird in der Regelsynchrones Multithreading verwendet.Kritische Abschnitte (Critical Sections) sind Programmabschnitte, in denen nur ein Threadzur Zeit arbeiten darf. Während der Arbeit dieses einen Threads ist der Abschnitt für alleanderen Threads gesperrt. Sobald der Thread seine Arbeit beendet hat, gibt er ein Signal zurFreigabe des Abschnittes. Critical Sections werden zum Beispiel beim Ändern von globalenVariablen eingesetzt.Wenn zwei Threads auf das Signal des jeweils anderen warten, um die Arbeit zu starten, dannist ein sogenannter Deadlock entstanden. Deadlocks können bei synchronem Multithreadingentstehen, wenn zum Beispiel ein Thread eine Critical Section nach beendeter Arbeit nicht alsfrei signalisiert.In Delphi gibt es die Klasse TThread. Allerdings ist es nicht möglich, eine Instanz dieserKlasse zu bilden. Folglich muss eine Unterklasse definiert werden:MyThread = class(TThread)private{ Objekte, auf die der Thread zugreifen soll,alle VCL-Inhalte }protectedprocedure Execute; override;{ Methoden, die der Thread durchlaufen soll }publicconstructor Create( ... );end;Ein gutes Beispiel ist Programm6, das von Borland als Demonstration von Threads erstelltwurde.Run-time Type Information (RTTI)Delphis RTTI liefert Informationen über Objekte während der Laufzeit. Durch sie ist eineinfacher Zugriff auf Properties und Typenaufzählungen (enumerated types) von Objektenmöglich.Zur Nutzung der RTTI muss im Implementation-Bereich im Code die Unit TypInfoeingebunden werden:{ ... }ImplementationUses TypInfo;{ ... }(siehe Programm7, Form1: enumerated types)


Während der Laufzeit ist nur der Zugriff auf public / published Properties möglich.Die Property Color zum Beispiel wird von TControl an TMemo, TEdit, … published vererbt.Jedoch ist Color in TControl protected, was dazu führt, dass während der Laufzeit die Farbenvon Memo-, Edit-Feldern, … nicht verändert werden kann.Durch das einbinden der Unit TypInfo werden hierfür Spezialmethoden (SetOrdProp,SetStrProp, SetMethodProp, …) zur Verfügung gestellt, die die entsprechenden Properties beiausreichend gegebenen Informationen ändern können. Damit wird der Zugriff auf allepublished Properties sichergestellt, unabhängig von der Sichtbarkeit der vererbten Properties.In Programm7, Form2 wird obiges demonstriert. Setzten Sie dazu im ObjektInspektor vonDelphi das OnClick-Ereignis von Button2 („Setze Farbe“) auf ButtonClickWorks. Dasvoreingestellte Ereignis steht auf ButtonClickGehtNicht: Ein Blick in diese Prozedurverdeutlicht noch einmal das Problem.Ein Klick auf den Button „Setze Hints“ verteilt Hints auf alle Komponenten während derLaufzeit; nach Auswahl eines Objektes in der ComboBox werden alle seine Propertieswährend der Laufzeit aufgelistet.Kurze Einführung in PackagesPackages dienen dazu, kompilierte Units einzukapseln. Dadurch wird ein externer Zugriff aufdie Programme und VCL innerhalb der Packages ermöglicht.Der Vorteil ist, dass Packages auf Units und andere Packages verweisen und deshalb keinCode muss integriert werden muss. Mit Packages ist die Grundlage zur Komponentenentwicklunggeschaffen.Packages werden in Delphi mit Klick auf Datei ► Neu ► Package erstellt. Hier können dieerforderlichen Units oder Komponenten hinzugefügt oder entfernt werden, das Package kanncompiled oder installiert werden.Quellenverzeichnis• Doberenz, Kowalski - Borland Delphi 4, Grundlagen und Profiwissen• Delphi-Hilfe zu SysUtils• Swan - Die Delphi 4 Bibel• Artikel Return To Sender von Douglas Horn• Artikel RTTI von Cary Jensen• Artikel Parentage and Ownership von Robert Vivrette► Alle Programme sind mit Delphi 6 erstellt worden.

Hurra! Ihre Datei wurde hochgeladen und ist bereit für die Veröffentlichung.

Erfolgreich gespeichert!

Leider ist etwas schief gelaufen!