Im Frühjahr 2001 wurde an der Universität der Bundeswehr München mit der Entwicklung eines modularen Fahrzeugsimulators für den Einsatz in Lehre und angewandter Forschung/Entwicklung begonnen. Projektname ist das Akronym „MASTER“, welches für Modular Advanced Simulator for Education and Research steht. Das Projekt ist eingeteilt in drei Entwicklungsphasen (siehe Abbildung 1.1). Ziel der ersten Phase ist der Aufbau eines Entwicklungssimulators mit einem Experimentalcockpit. In Phase 2 wird der Simulator erweitert um ein reales Cockpit und um einen Simulatordom. In der dritten Phase ist es geplant, den bisherigen Simulator mit einer Bewegungsplattform auszustatten. Ein besonderes Merkmal dieses Simulators ist es, daß der Simulatordom mit unterschiedlichen, austauschbaren Cockpitmodulen betrieben werden kann. Dies ermöglicht die Simulation sowohl für Land- als auch Luftfahrzeuge. Das Projekt ist so strukturiert, daß ein Großteil der Entwicklung im Rahmen von Studentenprojekten durchgeführt werden kann. Hierbei sollen die in verschiedenen Vorlesungen erworbenen Fähigkeiten an einem realen Projekt angewandt werden.
Die Rechnertopologie des Simulators ist entsprechend seines modularen Gesamtaufbaus strukturiert. Gemäß den Simulatorkomponenten Bedienerstation, Experimentalcockpit, EAV-Modul, Simulatorcockpit, Simulatordom und Bewegungsplattform lassen sich auch rechnerseitig einzelne „Funktionseinheiten“ definieren, zwischen denen im aktiven Simulatorbetrieb Informationen teilweise in Echtzeit ausgetauscht werden müssen.
Es ist beabsichtigt die genannten Rechnermodule weitgehend auf der Basis bestehender PC-Technologie auszuführen. Wo immer möglich, soll die Implementierung der Software unter Verwendung von Standards erfolgen. Damit kann eine weitgehende Flexibilität und Interoperabilität der einzelnen Simulatorkomponenten erreicht werden.
Im Rahmen dieser Arbeit soll für den im Aufbau befindlichen Simulator ein Navigationsdisplay konzipiert und auf der Basis von ActiveX-Steuerelementen in C++ implementiert werden
Inhaltsverzeichnis
1 Einleitung
2 ActiveX
2.1 Softwarekomponenten
2.2 Anforderungen an Softwarekomponenten
2.3 COM als Basis
2.4 ActiveX-Steuerelemente
3 Erstellung eines ActiveX-Steuerelementes
3.1 Erstellen eines ActiveX-Steuerelementes mit dem Assistenten
3.2 Testcontainer für ActiveX-Steuerelemente
3.3 Eigenen Programmcode einfügen
3.3.1 Vordefinierte Eigenschaften
3.3.2 Benutzerdefinierte Eigenschaften
3.3.3 Member-Variablen
3.3.4 Member-Funktionen
3.3.5 Ereignisse
3.4 Hinweise zur Implementierung
4 ActiveX-Steuerelement MASTER_Seg7
4.1 Beschreibung
4.2 Implementierung
4.2.1 Entwurf auf dem Papier
4.2.2 Zeichnen des Elementes
4.2.3 Berechnung der Farbe für inaktive Segmente
4.2.4 Berechnung der einzelnen Digits
4.3 Eigenschaften und Methoden
4.3.1 void AboutBox()
4.3.2 short GetAnzahlDigits()
4.3.3 void SetAnzahlDigits(short anzahl)
4.3.4 OLE_COLOR GetBackColor()
4.3.5 void SetBackColor(OLE_COLOR backcolor) .
4.3.6 OLE_COLOR GetForeColor()
4.3.7 void SetForeColor(OLE_COLOR forecolor)
4.3.8 double GetValue()
4.3.9 void SetValue(double value)
4.3.10 short GetDarstellung()
4.3.11 void SetDarstellung(short darstellung)
5 ActiveX-Steuerelement MASTER_Map
5.1 Beschreibung
5.2 Implementierung
5.2.1 Zeichnen des Elementes
5.2.2 Karte und zugehörige Koordinaten
5.2.3 Umrechnen der WGS84-Position in Pixelkoordinaten .
5.2.4 Richtung des Flugzeugs
5.3 Eigenschaften und Methoden
5.3.1 void AboutBox()
5.3.2 OLE_COLOR GetBackColor()
5.3.3 void SetBackColor(OLE_COLOR backcolor)
5.3.4 OLE_COLOR GetForeColor()
5.3.5 void SetForeColor(OLE_COLOR forecolor)
5.3.6 double GetZoom()
5.3.7 void SetZoom(double zoom)
5.3.8 CString GetFile()
5.3.9 void SetFile(LPCTSTR file)
5.3.10 BOOL GetTrack()
5.3.11 void SetTrack(BOOL track )
5.3.12 BOOL GetCenter()
5.3.13 void SetCenter(BOOL center)
5.3.14 BOOL GetTiming()
5.3.15 void SetTiming(BOOL timing)
5.3.16 long GetMapXScroll()
5.3.17 void SetMapXScroll(long xscroll )
5.3.18 long GetMapYScroll()
5.3.19 void SetMapYScroll(long yscroll )
5.3.20 void PixPosition(long xpos, long ypos)
5.3.21 void WGS84Position(double laenge, double breite, double ti- me)
5.3.22 void ClearTrack()
5.3.23 long GetMapWidth()
5.3.24 long GetMapHeight()
5.3.25 long GetTimingInterval()
5.3.26 SetTimingInterval(long interval )
5.4 Ereignisse
5.4.1 void MousePosition(double laenge, double breite)
5.4.2 void PositionChanged(long xtop, long ytop)
6 ActiveX-Steuerelement MASTER_FlightScala
6.1 Beschreibung
6.2 Implementierung
6.2.1 Zeichnen des Elementes
6.2.2 Skalaeinteilung
6.3 Eigenschaften und Methoden
6.3.1 void AboutBox()
6.3.2 OLE_COLOR GetBackColor()
6.3.3 void SetBackColor(OLE_COLOR backcolor) .
6.3.4 OLE_COLOR GetForeColor()
6.3.5 void SetForeColor(OLE_COLOR forecolor)
6.3.6 double GetZoom()
6.3.7 void SetZoom(double zoom)
6.3.8 BOOL GetTrack()
6.3.9 void SetTrack(BOOL track )
6.3.10 BOOL AutoScroll()
6.3.11 void AutoScroll(BOOL scroll )
6.3.12 long GetScrollPosition()
6.3.13 void SetScrollPosition(long scrollpos) . .
6.3.14 void ClearTrack()
6.3.15 long GetScrollWidth()
6.3.16 BOOL GetTiming()
6.3.17 void SetTiming(BOOL timing)
6.3.18 long GetTimingInterval()
6.3.19 SetTimingInterval(long interval )
6.3.20 void Position(double hoehe, double zeit )
6.3.21 short AnzahlHLinien()
6.3.22 void AnzahlHLinien(short anzahl )
6.4 Ereignisse
6.4.1 void MousePosition(double hoehe)
7 Applikation MASTER_Navigator
7.1 Beschreibung
7.2 Implementierung
7.2.1 ActiveX-Steuerelemente einfügen
7.2.2 Erstellen der Bedienoberfläche
7.2.3 Laden und Speichern der Einstellungen .
7.2.4 Laden der Karte
7.2.5 Manuelles Eingeben der Position
7.2.6 Starten und Anhalten der Navigation
7.2.7 Abfragen des Shared Memory und Zurückschreiben der Zeit
8 Zusammenfassung und Ausblick
A Projekt MASTER_Seg7
A.1 Projekt-Dateien
A.2 Arbeitsbereich
B Projekt MASTER_Map
B.1 Projekt-Dateien
B.2 Arbeitsbereich
C Projekt MASTER_FlightScala
C.1 Projekt-Dateien
C.2 Arbeitsbereich
D Projekt MASTER_Navigator
D.1 Projekt-Dateien
D.2 Initialisierungsdatei
E Karten
E.1 Karten
E.2 .ini-Dateien
F Hilfsprogramme
Literaturverzeichnis
Abbildungsverzeichnis
1.1 Entwicklungsphasen des Simulators
1.2 Rechnertopologie
1.3 MASTER_Navigator
2.1 Softwarekomponente
2.2 Hierarchie einiger COM-Schnittstellen
2.3 Die ActiveX-Schnittstelle Invoke
2.4 Wechselwirkungen zwischen ActiveX-Container und Steuerelement
2.5 CLSID in der Registrierungsdatenbank
2.6 Klassennamen in der Registrierungsdatenbank .
3.1 Neues Projekt
3.2 Assistent Schritt 1 von 2
3.3 Assistent Schritt 2 von 2
3.4 Informationen zum neuen Projekt
3.5 Testcontainer
3.6 vordefinierte Eigenschaft hinzufügen
3.7 ID-Tabelle für Eigenschaftsseiten
3.8 benutzerdefinierte Eigenschaft hinzufügen
3.9 Ereignis hinzufügen
4.1 MASTER_Seg7 Anzeigearten
4.2 Entwurf der 7-Segment-Anzeige
4.3 MASTER_Seg7 Eigenschaftsseite Format
4.4 MASTER_Seg7 Eigenschaftsseite Farben
5.1 MASTER_Map Anzeige
5.2 Koordinatensysteme
5.3 MASTER_Map Eigenschaftsseite Karte
6.1 MASTER_FlightScala Anzeige
6.2 MASTER_FlightScala Eigenschaftsseite Scala
7.1 MASTER_Navigator Bedienoberfläche
7.2 Steuerelemente im Projekt MASTER_Navigator .
7.3 Aufbau des Shared Memory
7.4 Prinzipschaltbild
ABBILDUNGSVERZEICHNIS
A.1 MASTER_Seg7 Arbeitsbereich
B.1 MASTER_Map Arbeitsbereich
C.1 MASTER_FlightScala Arbeitsbereich
E.1 Kartenausschnitt München
E.2 Kartenausschnitt EG5
F.1 Hilfsprogramm shmKoordinaten
F.2 Hilfsprogramm shmZeitlesen
Tabellenverzeichnis
2.1 Auf COM basierende Technologien
4.1 Koordinaten der einzelnen Segmente
4.2 Segmente der einzelnen Ziffern
Kapitel 1
Einleitung
Im Frühjahr 2001 wurde an der Universität der Bundeswehr München mit der Entwick- lung eines modularen Fahrzeugsimulators für den Einsatz in Lehre und angewandter Forschung/Entwicklung begonnen. Projektname ist das Akronym „MASTER“, wel- ches für Modular Advanced Simulator for Education and Research steht. Das Projekt
Abbildung in dieser Leseprobe nicht enthalten
Abbildung 1.1: Entwicklungsphasen des Simulators
ist eingeteilt in drei Entwicklungsphasen (siehe Abbildung 1.1). Ziel der ersten Phase ist der Aufbau eines Entwicklungssimulators mit einem Experimentalcockpit. In Pha- se 2 wird der Simulator erweitert um ein reales Cockpit und um einen Simulatordom. In der dritten Phase ist es geplant, den bisherigen Simulator mit einer Bewegungs- plattform auszustatten. Ein besonderes Merkmal dieses Simulators ist es, daß der Si- mulatordom mit unterschiedlichen, austauschbaren Cockpitmodulen betrieben werden kann. Dies ermöglicht die Simulation sowohl für Land- als auch Luftfahrzeuge. Das Projekt ist so strukturiert, daß ein Großteil der Entwicklung im Rahmen von Studenten- projekten durchgeführt werden kann. Hierbei sollen die in verschiedenen Vorlesungen erworbenen Fähigkeiten an einem realen Projekt angewandt werden.
Die Rechnertopologie des Simulators ist entsprechend seines modularen Gesamt- aufbaus strukturiert. Gemäß den Simulatorkomponenten Bedienerstation, Experimen- talcockpit, EAV-Modul, Simulatorcockpit, Simulatordom und Bewegungsplattform las- sen sich auch rechnerseitig einzelne „Funktionseinheiten“ definieren, zwischen denen im aktiven Simulatorbetrieb Informationen teilweise in Echtzeit ausgetauscht werden müssen (siehe Abbildung 1.2). Es ist beabsichtigt die genannten Rechnermodule weit-
Abbildung in dieser Leseprobe nicht enthalten
Abbildung 1.2: Rechnertopologie
gehend auf der Basis bestehender PC-Technologie auszuführen. Wo immer möglich, soll die Implementierung der Software unter Verwendung von Standards erfolgen. Damit kann eine weitgehende Flexibilität und Interoperabilität der einzelnen Simulatorkomponenten erreicht werden.[6]
Im Rahmen dieser Arbeit soll für den im Aufbau befindlichen Simulator ein Navigationsdisplay konzipiert und auf der Basis von ActiveX-Steuerelementen in C++ implementiert werden (siehe Abbildung 1.3).
Abbildung in dieser Leseprobe nicht enthalten
Abbildung 1.3: MASTER_Navigator
Kapitel 2 ActiveX
2.1 Softwarekomponenten
Sowohl im Maschinenbau als auch in der Architektur gibt es Standardbauteile und Standardverfahren, um eine Konstruktionsaufgabe durchzuführen. Die Verfahren sind den betreffenden Ingenieuren bzw. Architekten wohlbekannt; für Bauteile gibt es Ka- taloge, in denen diese verzeichnet sind. In der Softwaretechnik gibt es praktisch keine Standardbauteile. Viele Softwareentwickler haben ihre eigenen Bauteile; mit den gän- gigen Methoden der Wiederverwendung schaffen sich diese Programmierer im Laufe der Zeit ihre eigenen Bauteillager, sie verwenden also Programmcode wieder. Dies ist ganz im Sinne der Wiederverwendung. Allerdings ist der dabei betrachtete Kontext nicht zufriedenstellend: Jeder Programmierer kann nur seine eigenen Bauteile (oder die seines Teams, seiner Firma) wiederverwenden. Wechselt er zu einer anderen Fir- ma, so muß er plötzlich mit völlig neuen Bauteilen umgehen, da er seine eigenen Bau- teile aus rechtlichen Gründen nicht mitnehmen darf, und die neue Firma wahrschein- lich ihre eigenen Bauteile verwendet. Übertragen auf den Maschinenbau würde das bedeuten, daß jede Maschinenbaufirma ihren eigenen Typ Schrauben verwenden wür- de: Schrauben mit dreieckigen Köpfen, Schrauben mit Linksgewinde, Schrauben mit abenteuerlichen Maßen, Schrauben nur für Spezialschraubendreher. Der Aufwand für Konstruktion und Herstellung der eigenen Schrauben wäre beträchtlich. Das kann sich keine Maschinenbaufirma leisten; statt dessen bestellt man Schrauben in Standardgrö- ßen im Katalog.
Softwarefirmen leisten sich den Luxus der Exklusivität. In vielen Firmen werden eigene Code- und Klassenbibliotheken sowie Frameworks entwickelt. Der Aufwand dafür ist erheblich. Die Entwicklungszeit pracktisch einsetzbarer Klassenbibliotheken und Frameworks beträgt zumeist mehrere Mannjahre. Trotzdem sind diese „Schrau- ben“ nur innerhalb des eigenen Entwicklungsteams einsetzbar, außerhalb der Firma möchte keiner diese fremden Bauteile haben; man verwendet lieber die eigenen. Nun kommt diese Verhaltensweise der Softwarefirmen und ihrer Entscheidungsträger nicht von ungefähr. Es gab bisher keinen echten Bauteilemarkt für Software. Es gab und gibt zwar Programmcode- und Klassenbibliotheken zu kaufen, doch sind dies nicht wirklich Softwarebauteile. Ein Bauteil - wie eine Schraube - ist etwas fertiges. Es exi- stiert, ist eindeutig spezifiziert, trägt eine Bezeichnung und hat oft ein klar umrissenes Einsatzgebiet. Man kann es bestellen, auspacken und einbauen. Kauft man sich je- doch eine Programmcode- oder Klassenbibliothek, so hat man kaum mehr als einen Konstruktionsplan für potentiell sehr viele Bauteile. Aber man muß diesen Konstruktionsplan zunächst verstehen, die richtigen Teile des Plans anwenden, dann das Bauteil selbst bauen(!), es auf Fehler prüfen und diese beseitigen, und erst dann kann man das so entstandene Bauteil verwenden.[7]
2.2 Anforderungen an Softwarekomponenten
Eine Softwarekomponente soll eine Aufgabe erfüllen oder ein Problem lösen, sie nimmt einem Satz von Eingangsdaten entgegen und produziert daraus einen Satz von Aus- gangsdaten. Dieser Teil wird als Implementierung bezeichnet. Der andere Teil ist die Schnittstelle. Sie stellt dem Programmierer die Funktionalität der Komponente in Form von Funktions- und Methodenaufrufen zur Verfügung (siehe Abbildung 2.1). An eine
Abbildung in dieser Leseprobe nicht enthalten
Abbildung 2.1: Softwarekomponente
universell einsetzbare Softwarekomponente ergeben sich folgende Anforderungen:
- Die Funktionalität einer Softwarekomponente darf für den Anwender der Komponente nur über eine Schnittstelle zugänglich sein. Die Implementierung wird gekapselt und darf nicht zugänglich sein. Das Verhalten der Softwarekomponente wird ausschließlich über deren Schnittstelle spezifiziert.
- Bei der Verwendung von Softwarekomponenten ist es von Vorteil, sie als Black Box zu betrachten. Kennt der Anwender der Komponente deren Implementie- rung nicht, so ist er auch nicht versucht, implementierungsspezifische Details auszunutzen.
- Eine Softwarekomponente soll unabhängig vom sie verwendenden Programm austauschbar sein. Eine Neukompilierung des Programms darf nicht notwendig werden.
- Die Bindung des Programms an die Softwarekomponente soll erst zur Laufzeit erfolgen. Nur so läßt sich eine Komponente nachträglich, ohne Neukompilie- rung austauschen. Es ist vorteilhaft wenn der Bindungsvorgang bei Programm- start erfolgt und alle Referenzen überprüft, damit es nicht zu unerwarteten Programmabstürzen aufgrund nicht aufgelöster Referenzen kommt.
- Komponenten sollen sprachunabhängig sein, sie sollen sich sowohl in verschiedenen Programmiersprachen implementieren, als auch von verschiedenen Programmiersprachen ausnutzen lassen.
- Softwarekomponenten und deren Schnittstellen sollen eindeutig identifizierbar sein.
- Verschiedene Versionen von Programmen und Softwarekomponenten müssen problemlos miteinander zusammenarbeiten können.
Da sich diese Anforderungen von den meisten Programmiersprachen nur zum Teil oder sehr schwer erfüllen lassen, bietet es sich an, ein Komponentenmodel einzuführen, das von der Implementierungssprache unabhängig ist. Genau das ist COM.[7]
2.3 COM als Basis
Um programmiersprachenunabhängige und universell einsetzbare Softwarekomponenten zu erstellen, wurde das Komponentenobjektmodell (COM) von Microsoft eingeführt. COM ist praktisch die „Werkbank“ zur Softwarekomponentenherstellung, auf der genormte „Bauteile“ entstehen können.
COM bildet das Fundament für weitere Technologien, wie Automatisierung, Ver- einheitlichter Datenaustausch, OLE1 und ActiveX-Steuerelemente (siehe Tabelle 2.1). Die auf COM aufbauenden Verfahren sind auch nicht völlig unabhängig von einander, so wird beispielsweise die Automatisierung innerhalb von ActiveX-Steuerelementen verwendet.
Abbildung in dieser Leseprobe nicht enthalten
Tabelle 2.1: Auf COM basierende Technologien
Das Komponentenobjektmodell besitzt insbesondere folgende Eigenschaften:
- COM ist programmiersprachenunabhänig. COM-Anpassungen existieren für viele gängige Programmiersprachen wie C, C++, Java und Visual Basic.
- COM verzichtet auf die Vererbung von Verhalten. Das heißt, daß Vererbung zwar innerhalb einer Komponente durch die Implementierungssprache verwendet werden kann, außerhalb der Komponente kann diese ihre Implementierung jedoch nicht vererben. Die COM-Designer haben die Vererbung als ein Mittel zum Aufbrechen der Kapselung von Komponenten erkannt. Daher ist die Vererbung von Implementierungen in COM nicht erlaubt.
- Im Gegensatz zur Sprache C++ sind Schnittstellen in COM von der Implemen- tierung völlig getrennt. In COM besitzen Schnittstellen eigene Bezeichner. Ei- ne Komponente kann mehrere Schnittstellen haben. Ein Zugriff auf die Interna einer Komponente kann ausschließlich über deren Schnittstelle erfolgen. COM- Schnittstellen verfügen ausschließlich über Funktionen; Variablen sind nicht Be- standteil einer Schnittstelle.
- Schnittstellen können - oder besser gesagt müssen - in COM vererbt werden. Durch die Vererbung von Schnittstellen wird die Spezifikation von Verhalten vererbt, nicht die Implementierung. Eine Schnittstelle ist schließlich nichts anderes als die Spezifikation von Verhalten.
- Komponenten (COM-Klassen) und Schnittstellen sind bei Benutzung von COM weltweit eindeutig identifizierbar. Zur Identifikation werden 128Bit lange IntegerZahlen, die Globally Unique Identifier, kurz GUID, verwendet.
- COM besitzt eine eingebaute Referenzzählung. Nicht mehr referenzierte Komponenten löschen sich selbständig.
- COM implementiert ein Client-Server-Modell. COM-Komponenten werden als COM-Server bezeichnet. Die Programme, die sich der COM-Komponenten bedienen, heißen COM-Clients.
Da auf COM basierende Technologien über ihre Schnittstellen definiert werden, kön- nen Implementierungsfragen zunächst völlig vernachlässigt werden. Systeme werden logisch definiert, die Implementierung wird nicht betrachtet. Durch die Eigenschaften von COM ist es möglich, (Teil-)Systeme zu einem späteren Zeitpunkt zu reimple- mentieren, ohne die Integrität des Gesamtsystems zu gefährden. Systeme können in beliebigen Programmiersprachen implementiert werden, solange eine COM-Bindung für diese Sprachen existiert. Programmiersprachen können beliebig gemischt werden, theoretisch kann jede COM-Klasse in einer anderen Sprache implementiert werden.
Auf COM-Komponenten kann in jedem Fall nur über Schnittstellen zugegriffen werden. Eine Schnittstelle implementiert keine Funktionalität. Sie ist nur der Zugang zur Implementierung. Jede Schnittstelle muß von einer anderen Schnittstelle abgeleitet werden, von der sie Funktionen(Methoden) erbt. Die Basisschnittstelle für alle anderen Schnittstellen heißt IUnknown, von ihr müssen alle weiteren Schnittstellen direkt oder indirekt abgeleitet werden (siehe Abbildung 2.2). COM-Schnittstellen sind per De- finition unveränderlich. Eine Schnittstelle darf daher nicht erweitert werden. Sollten Änderungen an einer Schnittstelle notwendig werden, so ist eine neue Schnittstelle zu definieren. Dadurch werden Versionsprobleme vermieden. Verwendet ein Programm eine Schnittstelle, so kann es sich darauf verlassen, daß diese immer ihrer ursprüngli- chen Definition entspricht.
Abbildung in dieser Leseprobe nicht enthalten
Abbildung 2.2: Hierarchie einiger COM-Schnittstellen
Die Eigenschaften von COM wirken sich auf die darauf aufbauenden Technologien aus. Weil COM programmiersprachenunabhänig ist, sind auch Technologien wie Au- tomatisierung, OLE und ActiveX-Steuerelemente programmiersprachenunabhänig.[7]
2.4 ActiveX-Steuerelemente
Hinter ActiveX-Steuerelementen steht die Idee des visuellen Programmierens, Softwarekomponenten mit der Maus zu einem funktionierendem Gesamtsystem „zusammenzuklicken“. ActiveX-Steuerelemente sind Softwarekomponenten auf einem relativ hohem Abstraktionsniveau, die als Bausteine bevorzugt in visuell orientierten Programmierumgebungen verwendet werden.[7]
Die COM-Technologie definiert, wie ActiveX-Objekte konstruiert sind und wie ihre Schnittstellen auszusehen haben. Die auf COM aufsetzende Schicht legt fest, wel- che Schnittstellen die verschiedenartigen Objekte unterstützen sollten und wie unter- schiedliche Objekttypen miteinander in Wechselwirkung treten. Über Schnittstellen wie IUnknown, die in jedem COM-Objekt erforderlich sind, fragt man die Komponen- te ab, um herauszufinden, welche anderen Schnittstellen die Komponente bietet. Jede Schnittstelle unterstützt einen speziellen Satz von Funktionen - eine Schnittstelle be- handelt etwa die visuelle Erscheinung des Steuerelements, eine andere steuert, wie die Erscheinung des Steuerelements mit der umgebenden Anwendung in Wechselwirkung tritt, eine weitere löst Ereignisse in der umgebenden Anwendung aus, usw.
Zu den Schlüsseltechnologien der ActiveX-Steuerelemente gehört die Automati- sierung. Damit kann eine Anwendung, die in eine andere Anwendung eingebettet ist, sich selbst aktivieren, ihren Teil der Benutzeroberfläche oder des Dokuments steu- ern, Änderungen am Dokument vornehmen und sich dann wieder schließen, wenn der Benutzer zu einem anderen Teil der Anwendung geht, der nicht von der einge- betteten Anwendung gesteuert wird. Ein Schlüssel zur Arbeitsweise der Automati- sierung ist eine spezielle Schnittstelle namens IDispatch.2 Die IDispatch-Schnittstelle besteht aus einem Zeiger auf eine Tabelle verfügbarer Methoden, die sich im ActiveX- Steuerelement oder der eingebetteten Anwendung ausführen lassen. Diesen Methoden sind ID-Nummern - sogenannte DISPIDs - zugeordnet, die ebenfalls in eine Tabelle geladen werden. In dieser Tabelle kann man dann nach der ID für eine bestimmte Me- thode nachschlagen. Nachdem man die DISPID für eine bestimmte Methode kennt, kann man diese über die Methode Invoke der IDispatch-Schnittstelle aufrufen. Dabei übergibt man die DISPID, um die auszuführende Methode zu kennzeichnen. Abbil- dung 2.3 zeigt, wie die IDispatch-Schnittstelle die Methode Invoke verwendet, um Methoden im ActiveX-Objekt auszuführen. Der größte Teil der Interaktion zwischen
Abbildung in dieser Leseprobe nicht enthalten
Abbildung 2.3: Die ActiveX-Schnittstelle Invoke
dem ActiveX-Container und einem ActiveX-Steuerelement findet über die IDispatchSchnittstellen statt. Eine dieser IDispatch-Schnittstellen gehört zum Steuerelement und wird durch den Container verwendet, um Aufrufe der verschiedenen Methoden auszuführen, die das Steuerelement dem Container verfügbar macht.
Der Container stellt dem Steuerelement zwei IDispatch-Schnittstellen bereit. Das Steuerelement verwendet die erste dieser IDispatch-Schnittstellen, um Ereignisse in der Container-Anwendung auszulösen. Die zweite Schnittstelle dient dazu, die Eigen- schaften des Steuerelements festzulegen, wie es Abbildung 2.4 darstellt. Die meisten Eigenschaften eines ActiveX-Steuerelements werden eigentlich vom Container bereit- gestellt, aber durch das Steuerelement verwaltet. Wenn man eine Eigenschaft für das Steuerelement setzt, ruft der Container eine Methode im Steuerelement auf, um es an- zuweisen, die Eigenschaften aus dem Container zu lesen. Größtenteils sind diese Ab- läufe für den Programmierer transparent, da Visual C++ eine Reihe von C++-Klassen um die Schnittstellen des ActiveX-Steuerelements aufbaut. Diese C++-Klassen legen Methoden frei. Genau über diese Methoden treten Sie in Wechselwirkung, und nicht durch direkte Aufrufe der IDispatch-Schnittstelle des Steuerelements.[2]
Als visuelle Komponenten müssen sich ActiveX-Steuerelemente natürlich durch eine grafische Darstellung representieren können. Diese Darstellung kann üblicher- weise in zwei Zuständen erfolgen: Im Entwurfsmodus, in dem der Programmierer das Steuerelement in sein Programm einfügt, und im Ausführungsmodus, in dem das Pro- gramm ausgeführt wird.
Um auf die Funktionalität des Steuerelements zugreifen zu können, stellt dies Ei- genschaften und Methoden zur Verfügung. Diese Eigenschaften und Methoden werden
Abbildung in dieser Leseprobe nicht enthalten
Abbildung 2.4: Wechselwirkungen zwischen ActiveX-Container und Steuerelement
von Steuerelementen durch Automatisierung implementiert. Bei den Eigenschaften wird allerdings zwischen verschiedenen Formen von Eigenschaften differenziert. So gliedern sich die von ActiveX-Steuerelementen unterstützten Eigenschaften in Stan- dardumgebungseigenschaften, erweiterte Eigenschaften und Steuerelementeigenschaf- ten. Standardeigenschaften sind so allgemein, daß sie in vielen ActiveX- Steuerele- menten verwendet werden können (aber nicht müssen!). Sie unterscheiden sich von anderen Eigenschaften eines ActiveX-Steuerelements vor allen Dingen durch lmple- mentierungsdetails. Die erweiterten Eigenschaften werden in Wirklichkeit gar nicht vom ActiveX-Steuerelement selbst implementiert, sondern von dem Container, in den es eingebettet ist. Zu den erweiterten Eigenschaften gehören beispielsweise Größe und Position des Steuerelements. Die Steuerelementeigenschaften sind schließlich die vom Steuerelement selbst frei definierbaren Eigenschaften. Alle Eigenschaften eines ActiveX- Steuerelements sind persistent. Der Container des Steuerelements stellt die- sem ein Speichermedium zur Verfügung, auf das es die Werte seiner Eigenschaften speichern kann. Auf diese Weise lassen sich Eigenschaftswerte durch die Entwick- lungsumgebung vorbelegen und müssen nicht zur Laufzeit des Steuerelements explizit gesetzt werden.
Anders als bei der Automatisierung ist es bei ActiveX-Steuerelementen notwendig, daß das Steuerelement den Container benachrichtigen kann, in den es eingebettet ist. Bei normalen Steuerelementen werden solche Benachrichtigungen durch Windows- Nachrichten realisiert. Bei ActiveX-Steuerelementen verwendet man statt dessen einen Methodenaufruf in umgekehrter Richtung. Das ActiveX-Steuerelement ruft eine Me- thode des Containers auf, um ihn über das Eintreffen eines Ereignisses zu informie- ren. Diese Aufrufe in umgekehrter Richtung werden als Ereignisse bezeichnet. In der Tat werden Ereignisse durch Aufrufe von Methoden einer IDispatch-Schnittstelle des Containers implementiert.[7]
Damit ein ActiveX-Steuerelement von der COM-Laufzeitbibliothek gefunden wer- den kann muß es in der Registrierungsdatenbank eingetragen sein. Die Registrierung kann mit dem Hilfsprogramm RegSvr32.exe durchgeführt werden. Das Programm befindet sich im Systemverzeichnis der Windows-Installation. RegSvr32.exe lädt die ihm übergebene DLL und ruft die Funktion DllRegisterServer auf, um das Steue- relement zu registrieren. Um den Registrierungseintrag wieder zu entfernen muß das Programm mit dem Parameter /u aufgerufen werden. Abbildung 2.5 zeigt die Einträge in der Registrierungsdatenbank für das Steuerelement MASTER_Seg7 unter dessen CLSID und Abbildung 2.6 die Einträge unter dem Klassennamen.
Abbildung in dieser Leseprobe nicht enthalten
Abbildung 2.5: CLSID in der Registrierungsdatenbank
Abbildung in dieser Leseprobe nicht enthalten
Abbildung 2.6: Klassennamen in der Registrierungsdatenbank
Kapitel 3 Erstellung eines ActiveX-Steuerelementes
An dieser Stelle soll eine Anleitung gegeben werden, wie ein ActiveX-Steuerelement mit dem Programm Microsoft Visual C++ erstellt, erweitert und getestet werden kann. Bezug wird hier vorrangig auf die Online-Hilfe des Visual Studios[5] von Microsoft und auf die Bücher „Visual C++ 6 - Windows-Programmierung mit den MFC“[7], sowie „Visual C++ in 21 Tagen“[2] genommen.
3.1 Erstellen eines ActiveX-Steuerelementes mit dem Assi- stenten
1. Menü Datei/Neu... Registerkarte Projekte
MFC ActiveX-Steuerelement-Assistent wählen. Hier müssen der Projektname und der Pfad für das Arbeitsverzeichnis angegeben werden (siehe Abbildung 3.1).
Abbildung in dieser Leseprobe nicht enthalten
Abbildung 3.1: Neues Projekt
2. Das nächste Dialogfeld erlaubt Einstellungen über die Anzahl der Steuerele- mente im Projekt, ob diese eine Laufzeitlizenz haben und ob Hilfedateien er- zeugt werden sollen. Es ist zweckmäßig in die Quellcodedateien Kommentare einfügen zu lassen (siehe Abbildung 3.2).
Abbildung in dieser Leseprobe nicht enthalten
Abbildung 3.2: Assistent Schritt 1 von 2
3. Im folgenden Dialogfenster können Einstellungen zu den Eigenschaften vorge- nommen werden (siehe Abbildung 3.3).
Abbildung in dieser Leseprobe nicht enthalten
Abbildung 3.3: Assistent Schritt 2 von 2
4. Zum Schluß wird angezeigt, welche Dateien der ActiveX-Steuerelement-Assistent nun erstellt. Es kann noch einmal auf die vorherigen Dialoge zurückgesprungen werden, um etwaige Änderungen vorzunehmen (siehe Abbildung 3.4).
Abbildung in dieser Leseprobe nicht enthalten
Abbildung 3.4: Informationen zum neuen Projekt
Nach dem Erzeugen der Dateien hat man bereits ein funktionierendes Steuerelement, welches kompiliert1 und mit Hilfe des Testcontainers für ActiveX-Steuerelemente2 getestet werden kann.
Durch das Erstellen wird das ActiveX-Steuerelement automatisch registriert.
3.2 Testcontainer für ActiveX-Steuerelemente
Um ein ActiveX-Steuerelement zu testen, kann es nach dem Erstellen über das Menü Extras in einem Testcontainer eingefügt werden. So muß nicht extra ein Programm geschrieben werden, was diese Funktion erfüllt. Der Testcontainer ermöglicht es dem Entwickler des Steuerelements, den Funktionsumfang des Steuerelements durch Än- dern der Eigenschaften, Aufrufen der Methoden und Auslösen der Ereignisse zu testen.
Nach dem Start des Containers, wird das Steuerelement als neues Steuerelement eingefügt (siehe Abbildung 3.5). Jetzt können die Eigenschaften über den Eigenschafts- dialog des Elements festgelegt werden. Über ein weiteres Dialogfeld können die Me- thoden und/oder Funktionen des ActiveX-Steuerelementes aufgerufen und getestet werden.
Das Testen des Steuerelementes empfiehlt sich während der Erstellung von Zeit zu Zeit, da so eventuelle Fehler leichter erkannt und korrigiert werden können.
3.3 Eigenen Programmcode einfügen
Um dem ActiveX-Steuerelement die nötigen Eigenschaften und Funktionen zu implementieren, muß nun der entsprechende Programmcode eingefügt werden. Der KlassenAssistent hilft dabei, die entsprechende Struktur anzulegen.
Abbildung in dieser Leseprobe nicht enthalten
Abbildung 3.5: Testcontainer
3.3.1 Vordefinierte Eigenschaften
Vordefinierte Eigenschaften unterscheiden sich von benutzerdefinierten Eigenschaften darin, daß sie bereits von der Klasse COleControl implementiert sind und allgemeine Eigenschaften unterstützen. Allgemeine Eigenschaften umfassen unter anderem die Beschriftung sowie die Vorder- und Hintergrundfarben des Steuerelements.
1. Im Klassen-Assistenten wählt man die Registerkarte Automatisierung und stellt da die gewünschte Klasse ein. Man betätigt den Button Eigenschaft hinzufügen.
2. Jetzt kann man aus dem Listenfeld Externer Name die entsprechende vorde- finierte Eigenschaft auswählen. Der Klassen-Assistent ergänzt das Dialogfeld automatisch. Als Implementierung wird vordefiniert ausgewählt (siehe Abbil- dung 3.6).
3. Bei den vordefinierten Farben BackColor und ForeColor ist es zweckmäßig, ei- ne neue Eigenschaftsseite für Farben3 einzufügen. Diese ist schon vordefiniert, muß aber noch per Hand in die ID-Tabelle eingefügt werden. Hinweis: der Zäh- ler muß entsprechend erhöht werden (siehe Abbildung 3.7).
3.3.2 Benutzerdefinierte Eigenschaften
Eine benutzerdefinierte Eigenschaft wird zum Offenlegen eines bestimmten Zustands oder eines Erscheinungsbildes eines ActiveX-Steuerelements für einen Programmierer
Abbildung in dieser Leseprobe nicht enthalten
Abbildung 3.6: vordefinierte Eigenschaft hinzufügen
BEGIN_PROPPAGEIDS(CMASTER_Seg7Ctrl, 2)
PROPPAGEID(CMASTER_Seg7PropPage::guid) PROPPAGEID(CLSID_CColorPropPage) END_PROPPAGEIDS(CMASTER_Seg7Ctrl)
Abbildung 3.7: ID-Tabelle für Eigenschaftsseiten
verwendet, der das Steuerelement einsetzt.
1. Im Klassen-Assistenten wählt man die Registerkarte Automatisierung und stellt da die gewünschte Klasse ein. Man betätigt den Button Eigenschaft hinzufügen.
2. Jetzt können der Externe Name der benutzerdefinierten Eigenschaft, Typ und Implementierung festgelegt werden. Der vorgeschlagene Variablenname kann auf Wunsch geändert werden. Bei Get/Set-Methoden können Übergabeparame- ter angegeben werden (siehe Abbildung 3.8).
3. In der Funktion DoPropExchange müssen für jede dauerhafte benutzerdefinierte Eigenschaft PX_ Funktionen aufgerufen werden.
Beispiel:
PX_Short (pPX, _T("AnzahlDigits"), m_anzahlDigits,4);
4. Um die Eigenschaft benutzerfreundlich zugänglich zu machen, können auf den Eigenschaftsseiten entsprechende Steuerelemente4 eingefügt, und mit Member- Variablen verbunden werden.
Abbildung in dieser Leseprobe nicht enthalten
Abbildung 3.8: benutzerdefinierte Eigenschaft hinzufügen
3.3.3 Member-Variablen
Allgemeine C++-Member-Variablen müssen in der Klassenansicht hinzugefügt werden. Member-Variablen für Datenaustausch und Datenüberprüfung müssen mit dem Klassen-Assistenten erstellt werden.
1. Member-Variable mit der Klassenansicht hinzufügen
- Klasse auswählen, zu der die Variable hinzugefügt werden soll. Im Kontextmenü den Punkt Member-Variable hinzufügen auswählen.
- Jetzt können Variablenname, Variablentyp und Zugriffstatus eingegeben werden.
2. Member-Variable mit dem Klassen-Assistenten hinzufügen
- Im Klassen-Assistent auf der Registerkarte Member-Variablen die Klasse auswählen, zu der die Variable hinzugefügt werden soll.
- Variable hinzufügen betätigen und im Dialog Name der Member-Variable eingeben und aus den Drop-Down-Feldern Kategorie und Variablentyp auswählen.
Diese Prozeduren fügen die Variablendefinition zur Header-Datei für die Klasse hinzu.
3.3.4 Member-Funktionen
Mit der Klassenansicht oder dem Klassen-Assistenten kann man eine Member-Funktion zu einer Klasse hinzufügen. Es wird eine Funktionsdeklaration zur Header-Datei und ein Funktionsrumpf zur Implementierungsdatei der Klasse hinzugefügt.
1. Klasse auswählen, zu der die Funktion hinzugefügt werden soll. Im Kontextme- nü den Punkt Member-Funktion hinzufügen auswählen.
2. Jetzt werden Funktionstyp5, Funktionsdeklaration6 und der Zugriffstatus ange- geben.
3.3.5 Ereignisse
Ereignisse, die das Steuerelement in der Container-Anwendung auslöst, können mit der Klassenansicht7 oder mit dem Klassen-Assistenten8 hinzugefügt werden (siehe Abbildung 3.9).
1. Bei vordefinierten Ereignissen wird ein Namen aus der Liste Externer Name gewählt, oder der Name für ein neues Ereignis eingegeben, das definiert wer- den soll. Hierbei handelt es sich um den Namen, den Automatisierungs-Clients verwenden, um ein Ereignis vom Steuerelement anzufordern. Im Feld Interner Name wird ein Namensvorschlag für eine Member-Funktion angezeigt. Er kann auf Wunsch verändert werden.
2. Es kann für vordefinierte Ereignisse im Bereich Implementierung angegeben werden, ob die vordefinierte Implementierung verwendet oder die Implemen- tierung angepaßt werden soll. Bei neuen Ereignissen, ist dieser Bereich nicht verfügbar.
3. Für ein zu definierendes Ereignis wird die Parameterliste verwendet, um alle Parameter anzugeben, die dem Ereignis zugewiesen werden sollen.
Abbildung in dieser Leseprobe nicht enthalten
Abbildung 3.9: Ereignis hinzufügen
[...]
1 Object Linking and Embedding
2 auch als Dispinterface bezeichnet
1 F7 oder Erstellen-Button bzw. Menü „Erstellen “
2 Menü „Extras“
3 CColorPropPage
4 Button, Eingabefeld, usw.
5 Rückgabedatentyp
6 Funktionsname und Liste der Parameter
7 rechte Maustaste auf die Ereignis-Schnittstelle
8 Registerkarte ActiveX-Ereignisse
-
-
-
-
Téléchargez vos propres textes! Gagnez de l'argent et un iPhone X. -
-
Téléchargez vos propres textes! Gagnez de l'argent et un iPhone X. -
-
Téléchargez vos propres textes! Gagnez de l'argent et un iPhone X. -
-
Téléchargez vos propres textes! Gagnez de l'argent et un iPhone X. -
-
Téléchargez vos propres textes! Gagnez de l'argent et un iPhone X. -
-
Téléchargez vos propres textes! Gagnez de l'argent et un iPhone X. -
-
Téléchargez vos propres textes! Gagnez de l'argent et un iPhone X. -
-
Téléchargez vos propres textes! Gagnez de l'argent et un iPhone X. -
-
Téléchargez vos propres textes! Gagnez de l'argent et un iPhone X. -
-
Téléchargez vos propres textes! Gagnez de l'argent et un iPhone X. -
-
Téléchargez vos propres textes! Gagnez de l'argent et un iPhone X. -
-
Téléchargez vos propres textes! Gagnez de l'argent et un iPhone X. -
-
Téléchargez vos propres textes! Gagnez de l'argent et un iPhone X. -
-
Téléchargez vos propres textes! Gagnez de l'argent et un iPhone X. -
-
Téléchargez vos propres textes! Gagnez de l'argent et un iPhone X.