Systemschnittstellen - online

Transcrição

Systemschnittstellen - online
Systemschnittstellen
Stand: 16.10.03
Skript
Systemschnittstellen
Thomas Kowarsch
Stand: 16.10.03
© Thomas Kowarsch
Seite 1/101
Systemschnittstellen
Stand: 16.10.03
Inhaltsverzeichnis
1.Allgemeines........................................................................................5
1.1.Übungen...................................................................................... 5
1.2.Literatur....................................................................................... 6
1.3.Inhalt........................................................................................... 7
1.4.Systeme....................................................................................... 7
1.4.1.Plattform................................................................................ 7
1.4.2.Softwareumgebung.................................................................. 7
1.4.3.Begriff System........................................................................ 7
1.4.4.Statisches System................................................................... 8
1.4.5.Stationäre Systeme................................................................. 8
1.4.6.Dynamische Systeme............................................................... 8
1.4.7.Geschlossene Systeme............................................................. 8
1.4.8.Offene Systeme....................................................................... 8
2.Betriebssysteme.................................................................................9
2.1.Allgemeines.................................................................................. 9
2.1.1.Abstraktion............................................................................. 9
2.1.2.Gründe für den Erfolg des PCs................................................... 9
2.2.UNIX.......................................................................................... 10
2.3.Windows 2000/NT/XP................................................................... 10
2.3.1.Windows Versionen................................................................ 10
2.3.2.NT Charakteristika................................................................. 11
2.3.3.Dateisysteme........................................................................ 11
2.4.Chronologisches........................................................................... 12
3.WinDOS............................................................................................13
3.1.GUI............................................................................................ 13
3.1.1.Anwendungsprogrammierung unter MS-DOS.............................. 13
3.1.2.Windows-Programmierung...................................................... 13
3.1.3.GUI - Grafic user interface...................................................... 14
3.1.4.Ziel der GUI.......................................................................... 14
3.1.5.Tendenz............................................................................... 15
3.1.6.Konsequenzen....................................................................... 15
3.2.Herkömmliche Programmierung..................................................... 15
3.3.Callback..................................................................................... 16
3.3.1.Einrichtung einer Plattform-Routine zur Aufnahme eines Zeigers auf
eine C-Funktion............................................................................. 16
3.4.Events........................................................................................ 17
3.4.1.Definition.............................................................................. 17
3.5.WinDos....................................................................................... 18
3.5.1.Feedback.............................................................................. 19
4.OpenGL und GLUT............................................................................ 20
4.1.Fensterumgebung........................................................................ 20
© Thomas Kowarsch
Seite 2/101
Systemschnittstellen
Stand: 16.10.03
4.2.GLUT.......................................................................................... 20
4.3.Design – Philosophie..................................................................... 21
4.4.Funktionalitäten........................................................................... 22
4.5.Programmierung.......................................................................... 23
4.5.1.Visual Studio......................................................................... 23
4.5.2.Initialisierung........................................................................ 23
4.5.3.Start der Ereignisverarbeitung................................................. 23
4.5.4.Fenster Verwaltung................................................................ 24
4.6.Zusatztools für GLUT.................................................................... 24
4.6.1.GLUI.................................................................................... 24
4.6.2.PLIB.................................................................................... 25
4.6.3.MUI..................................................................................... 25
4.7.GLUT Befehle.............................................................................. 25
5.Win32...............................................................................................26
5.1.Datentypen................................................................................. 26
5.2.Ungarische Notation..................................................................... 33
5.3.Librarys...................................................................................... 36
5.4.Resourcen................................................................................... 36
5.5.Übersetzung................................................................................ 37
6.Betriebssystem - Kern......................................................................37
6.1.Hauptfunktion.............................................................................. 48
6.2.Registrierung............................................................................... 49
6.2.1.WNDCLASSEX-Struktur........................................................... 49
6.2.2.RegisterClassEx..................................................................... 50
6.3.Initialisierung.............................................................................. 51
6.3.1.CreateWindowEx.................................................................... 51
6.3.2.ShowWindow........................................................................ 52
6.3.3.UpdateWindow...................................................................... 54
6.4.Hauptnachrichtenschleife............................................................... 54
6.4.1.GetMessage.......................................................................... 54
6.4.2.TranslateMessage.................................................................. 55
6.4.3.DispatchMessage................................................................... 55
6.5.CALLBACK - Funktion.................................................................... 56
6.5.1.WM_PAINT - Nachricht........................................................... 56
6.5.2.Bildschirmausgabe................................................................. 57
6.5.2.a)Device Kontext.......................................................................................... 57
6.5.2.b)BeginPaint(), EndPaint()............................................................................ 62
6.5.3.Schliessen von Fenstern/Applikation......................................... 65
6.5.4.Tastatur - Nachrichten............................................................ 66
6.5.4.a)Wie kann eine gedrücke SHIFT - Taste abgefragt werden?..................... 71
6.5.4.b)Wie kann eine Berechnung abgebrochen werden?.................................. 71
6.5.4.c)Wie kann eine gedrückte CTRL - Taste ( VK_CONTROL ) per Programm
simuliert werden?................................................................................................... 72
6.5.4.d)Wie kann die CAPS - LOCK - Taste ( VK_CAPITAL ) invertiert werden?. 72
© Thomas Kowarsch
Seite 3/101
Systemschnittstellen
Stand: 16.10.03
6.5.4.e)Wie kann ein "floating - pop - up - menu" nach der Anzeige sichtbar
bleiben?................................................................................................................. 72
6.5.5.Maus - Nachrichten................................................................ 73
6.5.6.DefWindowProc..................................................................... 77
6.6.Dialoge....................................................................................... 78
6.6.1.Modale Dialoge...................................................................... 78
6.6.1.a)Beispiel: DialogBox als Hauptprogramm................................................... 81
6.6.1.b)About-Dialog.............................................................................................. 84
6.6.1.c)Aufruf des About-Dialogs:.......................................................................... 84
6.6.2.Modless Dialoge..................................................................... 85
6.6.2.a)CreateDialog() - Aufruf.............................................................................. 86
6.6.3.Controls............................................................................... 86
7.Dynamic-Link Library's.................................................................... 88
7.0.1.Wie löst der Linker die DLL_Einsprünge auf?.............................. 89
7.0.2.Wie wird diese DLL benutzt?.................................................... 93
8.Daemon............................................................................................94
8.1.Schreiben von Daemon ................................................................ 95
8.2.Beispiel...................................................................................... 97
8.3.Fehlermeldungen......................................................................... 97
8.4.Prozessgruppen und Sessions........................................................ 98
8.5.WebServer.................................................................................. 99
© Thomas Kowarsch
Seite 4/101
Systemschnittstellen
Stand: 16.10.03
1.Allgemeines
1.1.Übungen
Die Gesamtpunktezahl wird mit maximal 15% auf die Klausur
angerechnet. Es gelten hierfür alle Übungen ausser Zeiger und WinDOS.
Alle Übungen sind selbst oder in Gruppen zu erarbeiten.
Jede Datei (*.cpp;*.h) muss oben im Dokument den/die Namen des/der
Autoren mit Matrikelnummer enthalten.
Es gibt max 3 Punkte für jede vollständig richtig abgegebe Übung;
2 Punkte, falls kleinere Fehler vorhanden sind;
1 Punkt, falls die Aufgabe nur teilweise/ansatzweise erfüllt wurde.
Für besondere Features wird ein Bonus in Form eines + vergeben.
Abgabe:
Die Abgabe wird mündlich in der Übungsstunde vorgenommen.
Die Übungen müssen an dem Stichtag (wird vorher in der Vorlesung und
auf der Webseite bekannt gegeben) in der von Ihnen eingetragenen
Übungsstunde abgegeben werden.
Für jede Folgestunde, in der die Übungen nach den Stichtag abgegeben
werden, wird die Punktzahl incrementiert. (z.B. wird die Übung eine
Woche später abgegeben, können nur noch max. 2 Punkte erreicht
werden)
© Thomas Kowarsch
Seite 5/101
Systemschnittstellen
Stand: 16.10.03
1.2.Literatur
•
Charles Petzhold: „Windows Programmierung“,
Microsoft Press, 2000, 1300+ S.
(59,90 €, inkl. CD mit Original, in der Bibliothek)
•
„Die Programmiersprache C. Ein Nachschlagewerk“, RRZN 1995
•
B.W.Kernighan, D.M.Ritchie: „Programmieren in C“ (2.Ausgabe, ANSIC), Carl Hanser Verlag 1990
•
M.A.Ellis, B.Stroustrup: „The Annotated C++ Reference Manual“ (ANSIBase Document), Addison-Wesley Publishing Company 1991
•
Andrew S. Tanenbaum: „Betriebssysteme - Entwurf und Realisierung“
Carl Hanser Verlag 1990
Weitere Skripte:
–
Prof. Dr. Bachmann: http://homepages.fh-giessen.de/~hg54/
–
Prof. Dr. Christidis: http://homepages.fh-giessen.de/~hg11237/
*Hier muss der eigene Name und Matrikelnummer stehen
© Thomas Kowarsch
Seite 6/101
Systemschnittstellen
Stand: 16.10.03
1.3.Inhalt
Ausgewählte Plattformen und Softwareumgebungen, sowie deren
Strunktur, Funktionsweisen und Softwareimplementierungen unter ihnen.
Schwerpunkt: C, Windowsprogrammierung
1.4.Systeme
1.4.1.Plattform
Unter einer Plattform versteht man die tiefste Hardwarenächste
genutzte Schicht. In der Regel handelt es sich hierbei um das
Betriebsystem.
1.4.2.Softwareumgebung
Eine Softwareumgebung ist eine Sammlung von Programmen oder
Programmteilen, die zur bestimmten Nutzung die Kommunikation mit
der Plattform übernehmen. (vgl. Sw-Paket, -Bibliothek,
-Entwicklungsumgebung, 4DOS, OpenGL, Windows95)
1.4.3.Begriff System
Ein System ist eine Menge von Komponenten, (Gegenständen,
Individuen, Größen, Prozessen, Ideen), die untereinander in einer
kausalen Wechselwirkung stehen und von ihrer Umwelt entweder als
abgeschlossen oder als in einer wohldefinierten Beziehung stehend
betrachtet werden können sowie
die Gesamtheit der unter ihnen herrschenden Beziehungen.
Die Existenz von Systemen ist meist mit der Erfüllung eines Zweckes
verbunden (vgl. technische, politische, soziale, Regal-, Gleichungsoder Planetensysteme). Im Sinne dieser Definition kann jedes System
in beliebig viele Teil- oder Subsysteme zerlegt werden, sofern dies
sinnvoll erscheint.
Der Begriff “System” ist ein Idealtypus (erzeugt durch gedanklich
einseitige Steigerung bestimmter Elemente der Wirklichkeit):
Komponenten sind selten abgeschlossen, nicht immer unterscheidbar,
Beziehungen selten eindeutig; z.B.: Verkehrssysteme, philosophische,
mathematische (Gleichungs-) Systeme Software-Systeme lassen sich
in sehr guter Näherung durch Idealtypus beschreiben (trotz
Digitalisierungsfehler, Fremdeinflüsse durch Betriebssystem u.ä.)
© Thomas Kowarsch
Seite 7/101
Systemschnittstellen
Stand: 16.10.03
1.4.4.Statisches System
Ein statisches System verändert sich nicht mit der Zeit.
Beispiel: Kartenhaus
1.4.5.Stationäre Systeme
Stationäre Systeme haben ein gleichbleibendes Zeitverhalten.
Beispiel: Stromgenerator im Dauerbetrieb
1.4.6.Dynamische Systeme
In dynamischen Systemen können sich im Laufe der Zeit die
Komponenten und Beziehungen ändern.
Beispiel: Straßenverkehr
1.4.7.Geschlossene Systeme
Geschlossene Systeme haben keinen Austausch mit der SystemUmgebung (u. gehen langfristig in den Zustand max. Entropie über).
Beispiel: U-Boot, Raumschiff, mechanische Uhr
1.4.8.Offene Systeme
Offene Systeme ist sind durch den Austausch von Materie, Energie,
Information mit der System-Umgebung gekennzeichnet.
Beispiel: EU
© Thomas Kowarsch
Seite 8/101
Systemschnittstellen
Stand: 16.10.03
2.Betriebssysteme
2.1.Allgemeines
Programme, deren Zusammenwirken eine ‚wohldefinierte‘ Beziehung
zwischen Rechner-Hw und Nutzer/in (bzw.: Applikation) herstellen,
bilden das Betriebssystem.
Übernahme der (schwierigen) Programmierung einzelner HwKomponenten und deren Zusammenspiels. Für den Anwender verhält
sich das Betriebssystem wie eine Virtuelle Maschine.
Wichtig: Information hiding (Einf. v. Abstraktionsstufen)
2.1.1.Abstraktion
Bei mehrfacher gleichzeitiger Nutzung (Programme, Menschen):
Regelung des Zugriffs auf Hw-Komponenten, Daten, Rechenzeit:
Ressourcen-Verwaltung.
Bestrebungen zur Hw-Abstraktion (theoretisch) ab 1941
Vorstellung des ersten -verdrahteten- programmierbaren Rechners Z3
(K.Zuse)
Heute: ca. ein Dutzend Betriebssysteme
z.B. OS/2 (IBM), VMS (DEC), System 7.5 (Apple), BeOS (Be Inc.), MSDOS und Windows (Microsoft), UNIX (...)
2.1.2.Gründe für den Erfolg des PCs
•
Mächtiger Anbieter (IBM)
•
Gewähr für Fortbestand trotz Einsatzes v. Fremdprodukten
•
PC-Anbindung an Großrechner möglich Modulares Bau-Konzept:
•
Nach Bedarf aufrüstbar
•
Günstige Nachbauten Dritter
•
Orientierung am Massenmarkt:
•
Preis erschwinglich (Institutionen / Heimbedarf)
•
Kurze Einarbeitung ( “ / “ )
© Thomas Kowarsch
Seite 9/101
Systemschnittstellen
Stand: 16.10.03
2.2.UNIX
•
Multi-User Multi-Tasking
•
Multi-Threading
•
Virtueller Speicher (Swapping, Paging)
•
Skalierbarkeit
•
Multi-Prozessor-Fähigkeit
•
Scheduling über Prioritäten u. Zeitscheiben (Time slicing)
•
Kern-Schale-Architektur u. C/S-Untertützung: Hintergrund-prozesse
„Dämonen“(Spooler-Dämon lpd etc.)
2.3.Windows 2000/NT/XP
•
Multi-User
•
Multi-Tasking
•
Multi-Threading
•
Virtueller Speicher (Paging)
•
Skalierbarkeit
•
Multi-Prozessor-Fähigkeit
•
Scheduling über Prioritäten u. Zeitscheiben (Time sharing)
•
Grafische Benutzungsoberfläche
2.3.1.Windows Versionen
•
Windows 9x / ME / XP Home: Heimmarkt (Small Office / Home
Office)
Fokus: Minimaler Ressourcen-Bedarf.
•
WindowsNT / 2000 / XP Prof. Workstation: Client-Betriebssystem
Fokus: Sicherheit, Skalierbarkeit, Erweiterbarkeit, Stabilität; gut
zentral zu verwalten.
•
WindowsNT / 2000 Server: Server-Betriebssystem
Fokus: Domäne-Verwaltung (inkl. Service für Macintosh, Gateway
zu Netware 3.x, DHCP u.a.) - in Konkurrenz zu Novell, Banyan oder
UNIX.
© Thomas Kowarsch
Seite 10/101
Systemschnittstellen
Stand: 16.10.03
2.3.2.NT Charakteristika
•
Kompatibilität: Durch Submodule Applikationen von Windows 3.x,
Windows 95, MS-DOS, OS/2 und POSIX betreibbar
•
Portierbarkeit: nur zeitkritische Teile des Hardware Abstraction
Layer (HAL) in Assembler, sonst in ANSI-C geschrieben
•
Modularität: Benötigte DLL's nach Bedarf geladen/entfernt
•
Erweiterbarkeit: Modularer Aufbau ermöglicht Modul-Zusätze
•
Skalierbarkeit: Windows NT unterstützt das symmetrische
Multiprocessing (baugleiche Prozessoren).
•
Sicherheit: Erfüllung der Sicherheitsanforderungen des USVerteidungsministeriums (C2). *
•
Verteilte Systeme: Vorbereitet für vert. Prozesse
•
Zuverlässigkeit und Stabilität: Unterscheidung zw. User- und
Kernel-Prozessen (Sicherheit vor Fehlern in Applikation)
2.3.3.Dateisysteme
•
FAT (File Allocation Table): DOS-Dateisystem und NTDiskettenformat. Max. Dateigröße: 4 GB
•
HPFS (High Performance File System): OS/2-Dateisystem. Max.
Dateigröße: 4 bis 8 GB (nicht mehr bei Windows NT 4.0).
•
NTFS (New Technology File System): 64-Bit-Dateisystem von NT
mit Fokus auf Sicherheit. Max. Dateigröße: 17 Milliarden GB
© Thomas Kowarsch
Seite 11/101
Systemschnittstellen
Stand: 16.10.03
2.4.Chronologisches
1941
Zuse Z3
In den 60ern
Verstärkte Anstrengungen in den 60ern - insb. zur Einf.
von Dialogbetrieb (vs. Stapelbetrieb mit Operator)
Mitte der 60er
Ken Thompson, Dennis Ritchie (Bell Labs, AT&T) u.
MIT-Forscher entwickelten MULTICS, ein MehrbenutzerBetriebssystem für General Electric (Mainframe GE645)
Trotz Nicht-Einsatzes von MULTICS (techn. Mängel)
Weiter-Entwicklung durch Thompson
(„Space Travel“, 2 Benutzer)
Verballhornung durch Brian Kernighan „UNICS“
1969
Betriebssystem UNICS, ab 1970: Unix (Assembler).
Gleichzeitig: Thompson u. Ritchie entwickeln Sprache A
(BCPL-* basiert), verbesserte Version B,
Weiterentwicklung zu C.
1973
Unix erstes BS größtenteils in einer Hochsprache
(kaum 1000 Zeilen Maschinencode) ? Portierbarkeit!
Keine Vermarktung von Unix
wg. US-Kartell-Bestimmungen
1975
Abgabe zum Selbstkostenpreis an Univers.:
Univ. of California
Berkeley Software Distribution (BSD) Erweiterungen
1980-1990
Xenix (Microsoft, ab Mitte 80er: Santa Cruz Operation)
1981
PC-Vorstellung durch IBM mit MS-DOS
1983
Apple-Computer Lisa mit grafischer Oberfläche
1984
Apple-Computer Macintosh mit graf. Oberfläche
1984
IEEE / POSIX
(Portable Operating System Interface for uniX) ?
Standardisierungsvorgabe der US-Regierung.
1985
MS präsentiert Windows 1.01
1987
OS/2 v. IBM / MS, zeichenorientiert
1988
OS/2 v. IBM / MS mit grafischer Oberfläche
1988
Normung zu ANSI-C (Komitee X3J11).
1990
Trennung IBM – MS
1991
Linux 0.02 (Linus Torvalds, FIN)
1993
Windows NT
1995
Windows 95
1998
Windows 98
2000
Windows 2000
2001
Windows ME
2002
Windows XP
© Thomas Kowarsch
Seite 12/101
Systemschnittstellen
Stand: 16.10.03
3.WinDOS
3.1.GUI
3.1.1.Anwendungsprogrammierung unter MS-DOS
“Standard-I/O” und standardisierte Rechenzeit-Zuweisung;
abweichende Handhabung durch Programmierer/in
3.1.2.Windows-Programmierung
Kommunikation mit Peripherie ins System integriert:
Geräte werden wie “unter Windows” angesprochen.
© Thomas Kowarsch
Seite 13/101
Systemschnittstellen
Stand: 16.10.03
3.1.3.GUI - Grafic user interface
Zur Verdeutlichung: Word for DOS wurde auf 20 Disketten ausgeliefert
- davon 2 für Programm (Rest für diverseTreiber)
Früherer Anspruch an Rechner (bis in die 80er):
Erzeugung v. Ergebnissen u. Darstellung auf Drucker
Heutiger Anspruch:
Ständiger intuitiver Dialog Ergebnisse in div. Formen/Medien
Wichtig für die Realisierung:
Forschung am Xerox PARC (Palo Alto Research Center) Mitte 70er (?
Konzept für graf. Benutzungsschnittstelle: GUI)
3.1.4.Ziel der GUI
Verlagerung des Schreibtisches in den PC
„Desktop“: - Rechner auf dem Tisch, oder aber:
- Tisch-Oberfläche!
Zugrundeliegende Vorstellung:
zeilenorientierte Arbeitsweise: . . Papier-Stapel (Batch)
Fensterumgebung: . . . . . . . . . . . Lose Papierblätter
ungeordnete, quasi-parallele Bearbeitung inhaltlich verwandter
Arbeits-Abläufe („P“C)
Anforderungen
•
Intuitive Handhabung --> Minimierung d. Voraussetzungen
(z.B.: Brief-/Mail-Schreiben nach Klick statt Befehl-Eingabe)
•
Quasi-parallele Bearbeitung --> Präemptives Multitasking
(z.B.: Erstellung einer Präsentation während Internet-Suche)
•
Arbeits-Abläufe einer Person --> Prozeß-Kommunikation
(z.B.: Löschen v.Datei in allen betroffenen Fenstern anzeigen)
Plattform / Betriebssystem
•
Einheitliches „Look & Feel“ --> Kapselung d. Ein-/Ausgabe
(z.B.: Programm-übergreifende Realisierung v. „Drag&Drop“)
Applikationen / Bibliotheken
Weitere Steigerung d. Hw-Abstraktion durch zusätzl. SW
© Thomas Kowarsch
Seite 14/101
Systemschnittstellen
Stand: 16.10.03
3.1.5.Tendenz
Dialog-Komponenten immer komplexer / differenzierter
(z.B.: gezielte Warn-Meldungen mit Fallunterscheidungen)
Dialog (quasi-)unabhängig vom Programm
(z.B.: Menüleisten mit: „Datei - Bearbeiten - Ansicht -...“)
--> Loslösung der eigentlichen Applikation von Ein-/Ausgabe
--> Abgabe d. Ablaufkontrolle an GUI-Umgebung/-Plattform
3.1.6.Konsequenzen
Konsequenzen für die Applikations-Entwicklung:
für die Ergonomie: sehr groß
für das DV-Ergebnis: keine
für die Sw-Konzeption: gering
für die Codierung: deutlich (v.a. f. kleine Sw-Projekte)
Zusätzlicher Codierungsaufwand durch Berücksichtigung der
Plattform-Aufrufe
(z.B.: Ausgabe im Fenster) - aber auch der plattform-eigenen
Erfordernisse (Plattform-‘Eigenleben‘)
(z.B.: Änderung der Fenstergröße, Löschung des Fensters)
3.2.Herkömmliche Programmierung
Bei der herkömmlichen Methode wartet z.B. das Nachfolgende
Programm auf eine Eingabe des Benutzers, indem er wartet bis der
Tastaturpuffer Daten erhalten hat. Danach wird meist eine Berechnung
durchgeführt und das Ergebnis auf dem Bildschirm ausgegeben.
#include <stdio.h>
#include <conio.h>
int main ()
{
char ch;
int num = 0;
while ((ch = getch()) != 27)
{
num++;
printf ("%d\n", ch);
}
return num;
}
© Thomas Kowarsch
Seite 15/101
Systemschnittstellen
Stand: 16.10.03
3.3.Callback
Zentraler Begriff bei Errichtung o. Nutzung v. Sw-Plattformen: -->
Callback: Funktion des Anwendungsprogramms, die in vorgegebenen
Situationen von der Sw-Umgebung aufgerufen wird (z.B. zum
Auffrischen des Fensterinhalts)
Hintergrund: Multitasking --> Teilen von Ressourcen mit anderen
(I/O, Rechenzeit etc.)
I/O-Koordination nur durch Plattform möglich
(Info über laufende Programme u. Ressourcen-Bedarf)
Maßnahmen nach Wiederzuweisung von Ressourcen nur durch
Plattform einzuleiten
Aber:
--> Code nur als Bestandteil der Applikation sinnvoll:
(Info über Wiederherstellungs-Maßnahmen)
Uhr: . . . . . . . . . . Weiterlaufen
Bild: . . . . . . . . . . Neuladen
Wie kann die (neue) Applikation der (älteren) Plattform mitteilen,
welche Funktion aufzurufen ist?
3.3.1.Einrichtung einer Plattform-Routine zur Aufnahme eines
Zeigers auf eine C-Funktion
#include <stdio.h>
#include <conio.h>
/* Callback-Registrierung: */
int init (int (*callback)()) {
return (*callback) ();
}
/* Callback: */
int myfunction () {
printf ("In myfunction! \n");
getchar();
return 0;
}
int main () {
init (myfunction);
return 0 ;
}
© Thomas Kowarsch
Seite 16/101
Systemschnittstellen
Stand: 16.10.03
3.4.Events
Verstärkter Einsatz von Callbacks in modernen Plattformen u.
Umgebungen führt zum weiteren Paradigmenwechsel: Klassisch:
Programm fordert vom Betriebss. Ressourcen u. Aktionen an
(prozedurorientierte Arbeitsweise - z.B.: Single Task)
Nunmehr meist:
BS gibt Programm Bescheid, wann es und mit welcher Funktion „an der
Reihe ist”
(ereignisgesteuerte Arbeitsweise )
3.4.1.Definition
Als Ereignis (engl. event) bezeichnen wir jedes Vorkommnis
(occurence), das eine nicht-sequentielle Bearbeitung eines Programms
bewirkt. * Ein Vorkommnis kann eine Zustandsänderung (Meßwert)
oder die Erfüllung einer Bedingung (x == y) sein.
Ein dazugehöriges Ereignis kann die Abarbeitung einer if-Abfrage im
Programm sein.
Synchrone Ereignisse treten zu vorhersagbaren Zeitpunkten,
asynchrone zu nicht-vorhersagbaren ein.
Synchrone Ereignisse sind z.B. if-Abfragen im prozedur-orientierten
Programm: sie treten vorhersagbar ein (ab Programmbeginn).
Asynchrone Ereignisse sind z.B. Tasten- u. Maus-Aktionen (Zeit oft
nicht-vorhersagbar: „OK“ vs. „Anhalten“).
© Thomas Kowarsch
Seite 17/101
Systemschnittstellen
Stand: 16.10.03
3.5.WinDos
Bei der herkömmlichen Programmierung hat unser Programm auf die
Eingabe des Benutzers gewartet und diese Schnittstelle erst dann wieder
freigegeben, bis das Programm dies erlaubte.
Weiterhin wurde die Ausgabe direkt und ohne Umwege auf dem Bildschirm
erzeugt.
Um u.a. Portierbarkeit auf andere Plattformen und deren Unabhängigkeit,
sowie Multitasking zu realisieren, muss die Entscheidungsgewalt über
Ausgabe und Eingabe der Plattform (WinDos) überlassen werden. Dieses
löst Ereignisse (Events) in unserer Applikation aus.
Ereignisse finden in Form eines Funktionsaufrufes (Callback) statt. Das
WinDos ruft, wenn ein Ereignis stattfindet die entsprechende CallbackFunktion mit geeigneten Parametern in unserer Applikation auf.
Die Applikation muss dann auf das Ereignis reagieren und so schnell wie
möglich die Callback Funktion wieder beenden, um die Kontrolle an
WinDos wieder zurückzugeben.
D.h.: Das WinDos wartet nun auf eine Eingabe des Benutzers.
Schritt 1: Beim Starten von WinDos wird bei uns die Applikation gestartet
(Dies kann auch später zB durch Druck auf z.B. F4 usw geschehen).
Bei der Initialisierung/Start der Applikation muss diese dem WinDos
mitteilen, wie seine Callback Funktionen für das Neuzeichnen und dem
Tastendruck heissen. Dazu liefter das WinDos zwei Funktionen
initkeypressed und initrepaint.
Schritt 2: Drückt dieser eine Taste, entscheidet WinDos darüber an welche
Applikation (in unserem Beispiel gibt es nur eine) die Nachricht
weitergeleitet wird. WinDos ruft dann die Funktion Callback Funktion für
das Event Tastendruck in der Applikation auf. Diese wurde bei der
Initialisierung der Applikation (Dem Starten) per initkeypressed dem
WinDos zuvor mitgeteilt.
Schritt 3: Das WinDos entscheidet nun darüber, wann der Bildschirm
aufgefrischt werden soll. Hat der Benutzer nun eine Taste gedrückt soll in
unserem Beispiel danach sofort eine Auffrischung des Bildschirms
geschehen. WinDos löscht den Bildschirm und teilt der Applikation mit,
dass es neu zeichnen soll, indem es die entsprechende Callback Funktion
aufruft. Die Callback Funktion der Applikation zeichnet neu, indem sie die
Ausgabefunktion von WinDos (wdprintf) verwendet.
© Thomas Kowarsch
Seite 18/101
Systemschnittstellen
Stand: 16.10.03
3.5.1.Feedback
Vorteile:
•
Durch Austausch der Plattform kann jede Applikation auf jede
Hardware übertragen werden.
•
Die Programmierung der Applikation bedarf nun keiner komplizierten
Funktionsaufrufe.
•
Durch Erweiterung der Plattform kann Multitasking implementiert
werden
•
Durch Erweiterung von Schnittstellenfunktionen für andere
Ausgabemedien (Drucker, usw) bedarf es keinerlei grossen Aufwand
in der Applikation.
© Thomas Kowarsch
Seite 19/101
Systemschnittstellen
Stand: 16.10.03
4.OpenGL und GLUT
4.1.Fensterumgebung
Die Unabhängigkeit der OpenGL von Fenstersystemen erfordert für
Grafik-SW-Projekte die Adoption entweder eines ‚nativen‘
Fenstersystems oder einer Programmierschnittstelle (Application
Programming Interface, API), die die Anbindung an Fenstersysteme
übernimmt.
Eine solche Programmierschnittstelle ist GLUT (OpenGL Utility Toolkit vgl. glutttony).*
Aktuelle Version: 3.7
Literatur:
M.J.Kilgard: „OpenGL Programming for the X Window System“
Addison-Wesley 1996
E.Angel: „Interactive Computer Graphics: A top-down approach with
OpenGL“ Addison-Wesley 1996
4.2.GLUT
HTML-Online-Dokumentation zu GLUT:
Links zu Quellen und Dokumentation:
http://www.opengl.org/developers/documentation/glut.html
darunter erreichbar:
Benutzungshandbuch:
http://www.opengl.org/developers/documentation/glut/spec3/spec3.ht
ml
Quellen u. Dokumentation für MS-Windows zu GLUT:
http://www.xmission.com/~nate/glut.html
© Thomas Kowarsch
Seite 20/101
Systemschnittstellen
Stand: 16.10.03
4.3.Design – Philosophie
Fenster-Einrichtung u. -Verwaltung mit wenigen Aufrufen (für EinFenster-Applikationen genügt Callback +Start) :
--> Schnelle Erlernbarkeit, Augenmerk auf Fenster-Inhalt
Aufrufe mit möglichst knappen Parameterlisten, Zeiger nur bei Eingabe
von Zeichenketten, keine Zeiger-Rückgabe durch GLUT:
-->Leichte Handhabung, Fehlerrobustheit
Keine Verwendung v. Daten des nativen Fenstersystems (FensterHandler, Schriftarten):
--> Unabhängigkeit vom Fenstersystem
Übernahme der Ereignisverarbeitung, Überlassung von OpenGLDisplaylisten der Applikation:
--> Einschränkung gleichzeitiger Verwendung weiterer Ereignisverarbeitung, keine Einschränkung des OpenGL-Einsatzes
Zustandshaftes (stateful) API:
--> Einfache Applikationen durch Voreinstellungen (current window/
menu), Vermeidung wiederholten Datentransfers
Tendenz: Mehrere, differenziert aufgerufene Callbacks
--> Vermeidung unnötigen Codes je nach Art der Applikation
© Thomas Kowarsch
Seite 21/101
Systemschnittstellen
Stand: 16.10.03
4.4.Funktionalitäten
Einrichtung und Handhabung mehrerer Grafik-Fenster
Ereignisverarbeitung durch Callbacks (event processing)
Unterstützung vielfältiger Eingabegeräte
Routinen zur Einhaltung von Zeitvorgaben (timer)
Ausnutzung nicht-rechenintensiver ("idle”) Zeitintervalle
Erzeugung von Pop-Up-Menü-Kaskaden
Unterprogramme zur Generierung geometrischer Körper
Mehrere Bitmap- und Vektor-Schriftarten (stroke fonts)
Diverse Funktionen zur Fenster- und Overlayverwaltung
bietet ein komplettes API für das native Fenstersystem
--> Sw-Entwicklung ohne Einarbeitung in Fenstersystem
überläßt Fenster-Einrichtung dem nativen Fenstersystem
--> Erhaltung des plattformeigenen Look & Feel
wird regelmäßig aktualisiert
--> Befolgung von Trends, Beseitigung von Bugs
ist kostenlos erhältlich inkl. Source-Code
--> Verwendbarkeit in Ausbildung
--> Anpassung an individuelle Sw-Entwicklung möglich
© Thomas Kowarsch
Seite 22/101
Systemschnittstellen
Stand: 16.10.03
4.5.Programmierung
4.5.1.Visual Studio
Um ein Glut Programm zu erstellen müssen Sie zuerst ein Projekt vom
Typ Win32 Konsolenapplikation anlegen. Erstellen Sie dann zu diesem
Projekt eine C++ Quellcode Datei.
4.5.2.Initialisierung
Initialisierung des Fenstersystems,
Überprüfung der main-Parameter,
Setzen der Voreinstellungen für Fenster-Position, Größe,
Darstellungsmodus (Single/ Double Buffer)
4 Routinen:
int main() {
void glutInit(int *argc, char **argv);
void glutInitWindowSize(int width, int height);
/* def.: (400,400) */
void glutInitWindowPosition(int x, int y);
/* def.: (-1,-1)*/
void glutInitDisplayMode(unsigned int mode);
/* def.: (GLUT_RGB | GLUT_SINGLE)*/
}
4.5.3.Start der Ereignisverarbeitung
Letzte Anweisung in main() vor Überlassung der Programmsteuerung
an GLUT und den dort registrierten Callbacks der Anwendung (kein
return!)
1 Routine:
void glutMainLoop(void);
© Thomas Kowarsch
Seite 23/101
Systemschnittstellen
Stand: 16.10.03
4.5.4.Fenster Verwaltung
Fenster-Generierung und -Steuerung 18 Routinen:
int glutCreateWindow(char *name);
int glutCreateSubWindow(int win,int x,int y,int wid,int hig);
void glutSetWindow(int win);
int glutGetWindow(void);
void glutDestroyWindow(int win);
void glutPostRedisplay(void);
void glutSwapBuffers(void);
void glutPositionWindow(int x, int y);
void glutReshapeWindow(int width, int height);
void glutFullScreen(void);/* may vary by window system */
void glutPopWindow(void);
void glutPushWindow(void); /* execution upon return to GLUT*/
void glutShowWindow(void);
void glutHideWindow(void);
void glutIconifyWindow(void); );
void glutSetWindowTitle(char *name);
void glutSetIconTitle(char *name);
void glutSetCursor(int cursor); /* 23 GLUT_CURSOR_xxx */
4.6.Zusatztools für GLUT
4.6.1.GLUI
GLUI 2.1: GLUT-based C++ User Interface
(Paul Rademacher, Univ. of North Carolina)
http://www.cs.unc.edu/~rademach/glui/
© Thomas Kowarsch
Seite 24/101
Systemschnittstellen
Stand: 16.10.03
4.6.2.PLIB
PLIB 1.4.2: A Portable Games Library / SDK (Steve J. Baker)
http://plib.sourceforge.net/
PUI: A Picoscopic User Interface (part of PLIB)
http://plib.sourceforge.net/pui/index.html
4.6.3.MUI
MUI: Micro User Interface (Tom Davis, Silicon Graphics Inc.)
http://www.opengl.org/developers/code/mjktips/mui/mui.html
..übernimmt von GLUT Ereignisse und Callbacks
..ist ältere GLUT-Benutzungsschnittstelle (seit GLUT 3.5, 1997)
..hat einen überschaubaren Umfang
..besitzt als einzige Dokumentation -neben dem veröffent-lichten
Quellcode- die persönlichen Notizen von Steve J. Baker (PLIB)
..Fensterdarstellung wie Pulldown, Menüs, Buttons, usw.
4.7.GLUT Befehle
Dokumentation zu GLUT unter glut-3.spec.pdf.
© Thomas Kowarsch
Seite 25/101
Systemschnittstellen
Stand: 16.10.03
5.Win32
5.1.Datentypen
Beim Übergang von Win16 nach Win32 haben sich die int - Typen von
2 Byte auf 4 Byte erweitert. Die anderen Grundtypen bleiben
ungeändert.
Datentyp
Win16 Modell
T,S,M,C,L,V&Z
Win32 Modell
X,P,F
char
signed 8 Bit
signed 8 Bit
signed char
signed 8 Bit
signed 8 Bit
unsigned char
unsigned 8 Bit
unsigned 8 Bit
signed short
signed 16 Bit
signed 16 Bit
unsigned short
unsigned 16 Bit
unsigned 16 Bit
int
signed 16 Bit
signed 32 Bit
unsigned int
unsigned 16 Bit
unsigned 32 Bit
long
signed 32 Bit
signed 32 Bit
unsigned long
unsigned 32 Bit
unsigned 32 Bit
float
32-Bit floating
32-Bit floating
double
64-Bit floating
64-Bit floating
Daten - Typen sind in Header - Files definiert und bestimmen den
Speicherbedarf eines Bitmusters in Byte und die Bedeutung dieses
Bitmusters.
Diese Typen werden u.a. für Funktions - Parameter, Funktions Rückgabe - Werte, und für Nachrichten benötigt.
Handles werden benutzt, um mit einer Deskriptor - Tabelle auf
geladenen Resourcen oder einen benötigten globalen Kontext
zuzugreifen. Ein Handle entspricht dem Index der Deskriptor - Tabelle.
Ein 8 - Byte Deskriptor - Eintrag enthält die Ziel - Byte - Adresse, den
Byte - Umfang, die Zugriffsrechte.
In der folgenden Tabelle sind Daten - Typen für Character, Integer,
Boolean, Pointer und Handles enthalten. Die meisten Pointer - Typen
beginnen mit dem Prefix P oder LP.
ATOM
Atom (a reference to a character string in an
atom table)
BOOL
Boolean variable (should be TRUE or FALSE)
BOOLEAN
Boolean variable (should be TRUE or FALSE)
BYTE
Byte (8 bits)
© Thomas Kowarsch
Seite 26/101
Systemschnittstellen
Stand: 16.10.03
CCHAR
Windows character
CHAR
Windows character
COLORREF
Red, green, blue (RGB) color value (32 bits)
CONST
Variable whose value is to remain constant
during execution
CRITICAL_SECTION
Critical-section object
CTRYID
Country identifier
DLGPROC
Pointer to an application-defined dialog box
callback procedure.
DWORD
Doubleword (32 bits)
EDITWORDBREAKPROC
Pointer to an application-defined callback
function that the operating system calls when a
multiline edit control needs to break a line of
text. See EditWordBreakProc for information on
functions of this type.
ENHMFENUMPROC
Pointer to an application-defined callback
function that enumerates enhanced-metafile
records
ENUMRESLANGPROC
Pointer to an application-defined callback
function that enumerates resource languages
ENUMRESNAMEPROC
Pointer to an application-defined callback
function that enumerates resource names
ENUMRESTYPEPROC
Pointer to an application-defined callback
function that enumerates resource types
FARPROC Pointer
to a callback function
FLOAT
Floating-point variable
FONTENUMPROC
Pointer to an application-defined callback
function that enumerates fonts
GOBJENUMPROC
Pointer to an application-defined callback
function that enumerates graphics device
interface (GDI) objects
GRAYSTRINGPROC
Pointer to an application-defined callback
function that draws gray text
HACCEL
Handle of an accelerator table
HANDLE
Handle of an object
HBITMAP
Handle of a bitmap
HBRUSH
Handle of a brush
HCONV
Handle of a dynamic data exchange (DDE)
conversation
© Thomas Kowarsch
Seite 27/101
Systemschnittstellen
Stand: 16.10.03
HCONVLIST
Handle of a DDE conversation list
HCURSOR
Handle of a cursor
HDC
Handle of a device context (DC)
HDDEDATA
Handle of DDE data
HDWP
Handle of a deferred window position structure
HENHMETAFILE
Handle of an enhanced metafile
HFILE
Handle of a file
HFONT
Handle of a font
HGDIOBJ
Handle of a GDI object
HGLOBAL
Handle of a global memory block
HHOOK
Handle of a hook
HICON
Handle of an icon
HINSTANCE
Handle of an instance
HKEY
Handle of a registry key
HLOCAL
Handle of a local memory block
HMENU
Handle of a menu
HMETAFILE
Handle of a metafile
HOOKPROC
Pointer to an application-defined hook function
HPALETTE
Handle of a palette
HPEN
Handle of a pen
HRGN
Handle of a region
HRSRC
Handle of a resource
HSZ
Handle of a DDE string
HWINSTA
Handle of a workstation
HWND
Handle of a window
INT
Signed integer
LANGID
Language identifier
LCID
Locale identifier
LCTYPE
Locale type
LINEDDAPROC
Pointer to a callback function that processes
line coordinates
LONG
32-bit signed value
© Thomas Kowarsch
Seite 28/101
Systemschnittstellen
Stand: 16.10.03
LP
Pointer to a null-terminated Unicode™ string
LPARAM
32-bit message parameter
LPBOOL
Pointer to a Boolean variable
LPBYTE
Pointer to a byte
LPCCH
Pointer to a constant Windows character
LPCCHOOKPROC
Pointer to an application-defined hook function
LPCFHOOKPROC
Pointer to an application-defined hook function
LPCH
Pointer to a Windows character
LPCOLORREF
Pointer to a COLORREF value
LPCRITICAL_SECTION
Pointer to a critical-section object
LPCSTR
Pointer to a constant null-terminated Windows
character string
LPCTSTR
Pointer to a constant null-terminated Unicode
or Windows character string
LPCWCH
Pointer to a constant null-terminated Unicode
character
LPCWSTR
Pointer to a constant null-terminated Unicode
character string
LPDWORD
Pointer to an unsigned doubleword (32 bits)
LPFRHOOKPROC
Pointer to an application-defined hook function
LPHANDLE
Pointer to a handle
LPHANDLER_FUNCTION
Pointer to a handler function
LPINT
Pointer to a signed integer
LPLONG
Pointer to a signed long (32 bits)
LPOFNHOOKPROC
Pointer to an application-defined hook function
LPPRINTHOOKPROC
Pointer to an application-defined hook function
LPSETUPHOOKPROC
Pointer to an application-defined hook function
LPSTR
Pointer to a null-terminated Windows character
string
LPTCH
Pointer to a Unicode character or a Windows
character
LPTSTR
Pointer to a null-terminated Windows or
Unicode character string
LRESULT
Signed result of message processing
LPVOID
Pointer to any type
© Thomas Kowarsch
Seite 29/101
Systemschnittstellen
Stand: 16.10.03
LPWCH
Pointer to a Unicode character
LPWORD
Pointer to an unsigned word (16 bits)
LPWSTR
Pointer to a null-terminated Unicode character
string
LUID
Locally unique identifier
MFENUMPROC
Pointer to an application-defined callback
function that enumerates metafile records
NPSTR
Pointer to a null-terminated Windows character
string
NWPSTR
Pointer to a null-terminated Unicode string
PBOOL
Pointer to a Boolean variable
PBOOLEAN
Pointer to a Boolean variable
PBYTE
Pointer to a byte
PCCH
Pointer to a constant Windows character
PCH
Pointer to a Windows character
PCHAR
Pointer to a Windows character
PCRITICAL_SECTION
Pointer to a critical-section object
PCSTR
Pointer to a constant null-terminated Windows
character string
PCWCH
Pointer to a constant Unicode character
PCWSTR
Pointer to a constant null-terminated Unicode
character string
PDWORD
Pointer to an unsigned doubleword (32 bits)
PFLOAT
Pointer to a floating-point variable
PFNCALLBACK
Pointer to a callback function
PHANDLE
Pointer to a handle
PHANDLER_
ROUTINE
Pointer to a handler routine
PHKEY
Pointer to a registry key
PINT
Pointer to a signed integer
PLONG
Pointer to a signed long (32 bits)
PLUID
Pointer to a locally unique identifier (LUID)
PROPENUMPROC
Pointer to an application-defined callback
function that enumerates window properties.
See PropEnumProc for information on functions
of this type.
© Thomas Kowarsch
Seite 30/101
Systemschnittstellen
Stand: 16.10.03
PROPENUMPROCEX
Pointer to an application-defined callback
function that enumerates window properties.
See PropEnumProcEx for information on
functions of this type.
PSHORT
Pointer to a signed short (16 bits)
PSID
Pointer to a security identifier (SID)
PSTR
Pointer to a null-terminated Windows character
string
PSZ
Pointer to a null-terminated Windows character
string
PTCH
Pointer to a Windows or Unicode character
PTCHAR
Pointer to a Windows or Unicode character
PTSTR
Pointer to a null-terminated Windows or
Unicode character string
PUCHAR
Pointer to an unsigned Windows character
PUINT
Pointer to an unsigned integer
PULONG
Pointer to an unsigned long (32 bits)
PUSHORT
Pointer to an unsigned short (16 bits)
PVOID
Pointer to any type
PWCH
Pointer to a Unicode character
PWCHAR
Pointer to a Unicode character
PWORD
Pointer to an unsigned word (16 bits)
PWSTR
Pointer to a null-terminated Unicode character
string
REGSAM
Security access mask for registry key
SC_HANDLE
Handle of a service
SENDASYNCPROC
Pointer to an application-defined callback
function that the operating system calls when
the SendMessageCallback function is called.
The system passes the message to the callback
function after passing the message to the
destination window procedure. See
SendAsyncProc for information on functions of
this type.
SERVICE_STATUS_
HANDLE
Handle of a service status value
SHORT
Short integer
SPHANDLE
Pointer to a handle
© Thomas Kowarsch
Seite 31/101
Systemschnittstellen
Stand: 16.10.03
TCHAR
Unicode character or Windows character
TIMERPROC
Pointer to an application-defined timer callback
function
UCHAR
Unsigned Windows character
UINT
Unsigned integer
ULONG
Unsigned long integer (32 bits)
USHORT
Unsigned short integer (16 bits)
VOID
Any type
WCHAR
Unicode character
WNDENUMPROC
Pointer to an application-defined callback
function that enumerates windows
WNDPROC
Pointer to an application-defined window
procedure
WORD
Unsigned word (16 bits)
WPARAM
32-bit message parameter
YIELDPROC
Pointer to a yield callback function
© Thomas Kowarsch
Seite 32/101
Systemschnittstellen
Stand: 16.10.03
5.2.Ungarische Notation
In Ungarn wird ( anstelle von "Hans Müller" ) der Familien - Name
zuerst genannt ( "Müllers Hans" ). Bei Win16 existierten viele
verschiedene Speicher - Modelle. Damit bei größeren Programmen an
der Window - Variablen der zughörige Typ erkennbar ist, wurden dem
Variablen - Namen Prä - Character voran gestellt. Z.B. steht "lp" für
"long Pointer", "lpsz" für "long Pointer auf \0 begrenzten String", "dw"
für "Doppel Wort", "h" für "Handle", "n" für "Anzahl", "f" für "Flag",
usw.
Ein Beispiel ist der Aufruf von CreateWindowEx().
HWND CreateWindowEx(
DWORD dwExStyle,
// extended window style
LPCTSTR lpClassName,
// pointer to registered class name
LPCTSTR lpWindowName, // pointer to window name
DWORD dwStyle,
// window style
int x,
// horizontal position of window
int y,
// vertical position of window
int nWidth,
// window width
int nHeight,
// window height
HWND hWndParent,
// handle to parent or owner window
HMENU hMenu,
identifier
// handle to menu, or child-window
HINSTANCE hInstance,
// handle to application instance
LPVOID lpParam
// pointer to window-creation data
);
© Thomas Kowarsch
Seite 33/101
Systemschnittstellen
Stand: 16.10.03
Prefix Naming Conventions
Prefix
Type
Description
Example
ch
char
8-bit character
chGrade
ch
TCHAR
16-bit character
if _UNICODE is defined
chName
b
BOOL
Boolean value
bEnabled
n
int
Integer (size dependent on operating
system)
nLength
n
UINT
Unsigned value (size dependent on
operating system)
nLength
w
WORD
16-bit unsigned value
wPos
l
LONG
32-bit signed integer
lOffset
dw
DWORD
32-bit unsigned integer
dwRange
p
*
Pointer
pDoc
lp
FAR*
Far pointer
lpDoc
lpsz
LPSTR
32-bit pointer to character string
lpszName
lpsz
LPCSTR
32-bit pointer to constant character
string
lpszName
lpsz
LPCTSTR
32-bit pointer to constant character
string
if _UNICODE is defined
lpszName
h
handle
Handle to Windows object
hWnd
lpfn
callback
Far pointer to CALLBACK function
© Thomas Kowarsch
lpfnAbort
Seite 34/101
Systemschnittstellen
Stand: 16.10.03
Windows verwendet für Nachrichten-, Style-, ControlKonstanten die folgenden Gruppen:
BM_
Button Control Messages
BN_
User Button Notification
Codes
BS_
Button Control Styles
CBS_
Combo Box styles
CCS_
LVS_
TVS_
TCS_
ACS_
COMMON CONTROL STYLES
CS_
Class styles
CF_
Predefined Clipboard Formats
DS_
Dialog Styles
ES_
Edit Control Styles
HELP_
Commands to pass to
WinHelp()
HT
WM_NCHITTEST,
MOUSEHOOKSTRUCT Mouse Pos
ID
Dialog Box Command
IDs
IDI_
Standard Icon IDs
LANG_
language IDs.
LBS_
Listbox Styles
MA_
WM_MOUSEACTIVATE
Return Codes
MF_
Menu flags for
Add/Check/EnableMenuItem()
MFS_
Menu flags for
Add/Check/EnableMenuIt
em()
MK_
Key State Masks for Mouse
Messages
OBM_
OEM Resource Ordinal
Numbers
PWR_
wParam for WM_POWER
SBS_
Scroll Bar Styles
SC_
System Menu Command Values
SIZE_
WM_SIZE message
wParam values
SORT_
Sorting IDs.
SS_
Static Control Constants
SW_
ShowWindow() Commands
TBS_
Tab style
VK_
Virtual Keys, Standard Set
WA_
WM_ACTIVATE state
values
WM_
Window Messages
WM_DDE_
DDE - Mesages
WS_
Window Styles
WS_EX_
Extended Window Styles
WVR_
WM_NCCALCSIZE return values
© Thomas Kowarsch
Seite 35/101
Systemschnittstellen
Stand: 16.10.03
5.3.Librarys
Windows.h enthält die Funktions - Prototypen. Dadurch kann der
Compiler die Schreibweise ( Syntax ) in dem eigenen Programm
überprüfen.
Damit der Linker die zugeordneten DLL - Einsprünge einbinden kann,
sind außerdem z.B. die folgenden Bibliotheken
•
kernel32.lib
•
user32.lib
•
gdi32.lib
•
coredll.lib
•
msvcrt.lib
in das Projekt aufzunehmen. Soll zusätzlich die "messaging
functionality" in das eigene Programm aufgenommen werden, so ist
#include Msgstore.h erforderlich. Soll zusätzlich die "e-mail
functionality" in das eigene Programm aufgenommen werden, so ist
#include Addrstor.h erforderlich. Natürlich sind auch die zugehörigen
*.lib - Files in die Entwicklungs - Umgebung aufzunehmen. Oft werden
die folgenden ( voreingstellten ) *.lib - Files verwerdet:
kernel32.lib
user32.lib
winspool.lib
comdlg32.lib
shell32.lib
uuid.lib
ole32.lib
odbc32.lib
gdi32.lib
advapi32.lib
oleaut32.lib
odbccp32.lib
5.4.Resourcen
Windows - Applikationen benötigen viele statische Daten
( Fenstergröße, Farbe, Controls, ... ). In den meisten Fällen werden die
Geometrie - Resourcen mit Hilfe visueller, interaktiver Tools ( z.B.
Resourcen Workshop ) erstellt.
Diese Resourcen können im *.RC - ASCII - File ( oder in einem binären
*.RCT - Template - File ) gespeichert werden.
Ein RC - Compiler übersetzt diesen *.RC - ASCII - File in einen binären
*.RES - File, der durch den Linker dem *.EXE - File hinzugefügt wird.
Weil eine standardisierte Binärform benutzt wird, ist es mit dem
Resourcen Workshop auch möglich, aus einem *.EXE - Programm den
*.RC - ASCII - File zu erhalten.
© Thomas Kowarsch
Seite 36/101
Systemschnittstellen
Stand: 16.10.03
5.5.Übersetzung
6.Betriebssystem - Kern
Der eigentliche Betriebssystem - Kern besteht aus den drei Dateien
•
KRNL386.EXE ( 85 kB, 377 kB ),
•
USER.EXE ( 47 kB, 321 kB ),
•
GDI.EXE ( 21 kB, 162 kB )
Bei diesen Dateien handelt es sich um sogenannte DLL’s ( Dynamic
Link Libarys ). Dies sind binäre Funktionsbibliotheken. Zum
Betriebssystem gehören noch weitere Komponenten, wie z.B.
•
COMMDLG: Common Dialog Boxen,
•
DDEML: Dynamic Datat Exchange Management Library,
•
DIB.DRV: Device independent bitmap driver,
•
OLECLI.DLL, OLESVR.DLL: Objekt linking and embedding,
•
SHELL.DLL: Drag-drop-feature, Registrations-Basis,
•
LZEXPAND.DLL: Daten decompression,
•
TOOLHELP.DLL: Tool help,
•
VER.DLL, VER.LIB: File Installation and versions checking, usw.
•
Installable drivers,
•
True Type fonts,
DLL’s sind binäre Instanzen von Objekte und enthalten Daten
( Properties ) und Methoden ( Funktionen ). Benötigt eine
Applikation eine DLL, so wird diese geladen und die benötigte Funktion
ausgeführt. Falls die Dateiendung nicht *.DLL ist ( z.B. *.EXE ), so
muß die Datei explizit geladen/freigegeben werden.
Ist die DLL bereits geladen, so wird in der DLL lediglich ein Zähler
hochgezählt. Ein DLL darf bei Bedarf aus dem Speicher entfernt
werden, wenn dieser Zäher 0 ist. Eine DLL wird nur einmal geladen,
auch wenn diese DLL von mehreren Anwendungen benutzt wird. Der
Zugriff auf eine Funktion und deren Ausführung kann über die ASCII Namen - Tabelle ( langsamer ) oder den Index der Funktions Adress - Tabelle ( schneller ) erfolgen. Der hinterlegte Wert in der
Funktions - Tabelle zeigt auf den Anfang der eigentlichen Funktion.
Diese Zugriffsart ist schneller, als der Zugriff über die ASCII - Namen Tabelle.
Die DOS - Interrupttabelle ist grob mit der DLL - Funktionstabelle
vergleichbar (die Zuordnung von Interruptzeiger zu
Interruptserviceroutinen)
© Thomas Kowarsch
Seite 37/101
Systemschnittstellen
Stand: 16.10.03
Bei interoperablen Systemen ( UNIX - WINDOWS ) wird der Zugriff
über die ASCII - Namen - Tabelle benutzt.
Bevor eine DLL - Funktion ausgeführt wird, werden die
Funktionsparameter auf den Stack des aurufenden Programmes
gelegt.
DLL’s arbeiten immer auf dem Benutzerstack.
Die Funktions - Adress - Tabelle bedingt, daß das aurufende Programm
( Applikation ) den gewünschten Index der DLL - Funktions - Adress Tabelle kennt. Die Namen - Index - Zuordnungen sind in LIB Dateien ( Libary ) enthalten. Beim Erstellen eines Programmes
werden diese Indizes der DLL - Funktions - Adress - Tabelle in den
Maschinencode eingefügt. Der Linker trägt den Index in das
Maschinenprogramm ein. Der DLL - Name wird nur einmal in das
Applikationsprogramm eingetragen.
KRNL386.EXE
Die Dateien KRNL386.EXE ist eine DLL ( Dynamic Link Libarys ).
KRNL386.EXE
•
kontrolliert und verwaltet den Speicher,
•
lädt Applikationen,
•
verteilt die Resourcen an Programme und Tasks.
In KRNL386.EXE sind binäre Funktionen enthalten. Die wesentlichen
Funktionen sind in der folgende Tabelle zusammengefaßt.
Object
Creator function
Destroyer function
Change
notification
Communications
FindFirstChangeNotification
FindCloseChangeNotific
ation
device
GetStdHandle
CloseHandle
Event
CreateEvent,
OpenEvent
CloseHandle
Event log
OpenEventLog,
RegisterEventSource,
OpenBackupEventLog
CloseEventLog
File
CreateFile
CloseHandle,
DeleteFile
File mapping
CreateFileMapping,
OpenFileMapping
CloseHandle
Find file
FindFirstFile
FindClose
Heap
HeapCreate
HeapDestroy
Mailslot
CreateMailslot
CloseHandle
© Thomas Kowarsch
Seite 38/101
Systemschnittstellen
Stand: 16.10.03
Module
LoadLibrary,
GetModuleHandle
FreeLibrary
Mutex
CreateMutex,
OpenMutex
CloseHandle
Pipe
CreateNamedPipe,
CreatePipe
CloseHandle,
DisconnectNamedPipe
Process
CreateProcess,
OpenProcess,
GetCurrentProcess
CloseHandle,
TerminateProcess
Semaphore
CreateSemaphore,
OpenSemaphore
CloseHandle
Thread
CreateThread,
CreateRemoteThread,
GetCurrentThread
CloseHandle,
TerminateThread
Timer
CreateWaitableTimer,
OpenWaitableTimer
CloseHandle
Update resource
BeginUpdateResource
EndUpdateResource
USER.EXE
Der File USER.EXE ist eine DLL, die die auf dem Bildschirm die Fenster
erzeugt und manipuliert ( create, move, size, remove), die Icons und
andere Komponenten des Benutzer-Interface behandelt, die Eingaben
( dispatch ) von Keyboard, Mause und anderen Eingabe-Geräten an die
zugehörige Applikation verteilt. Mit den Funktionen von USER.EXE
können interaktive Fenster ( desktop - shell ) erstellt werden.
Die User Interface Services
•
erzeugen und manipulieren Bildschirm - Fenster ( Screen
Windows ),
•
behandeln Icons und andere Komponenten des
Benutzerinterfaces,
•
verteilen die Eingabe von Keyboard, Maus und anderen Geräten
an die zugehörigen Applikationen
USER.EXE enthält Funktionen für die folgenden Aufgaben:
•
Dialogelemente ( Controls )
Auslöseknöpfe ( Buttons ), Textboxen ( List Boxes
), aufklappbare Textboxen ( Combo Boxes ), Text - Editor ( Edit Controls
), RTF - Text - Bearbeitung ( Rich Edit Controls ), Rollbalken ( Scroll
Bars ), feste Texte ( Static Controls )
•
lesbare Daten ( Resources )
© Thomas Kowarsch
Seite 39/101
Systemschnittstellen
Stand: 16.10.03
Textcursor ( Carets ), Mauscursor ( Cursors ), kleines Symbolbild
( Icons ), Menus, benutzerdefinierte Daten ( Resources )
•
Programmierschnittstelle ( Shell and Common Controls )
Windows Shell API, standardisierter Dialogelemente ( Common
Controls ), Wizard97 Specifications
•
Benutzereingaben ( User Input )
Nachrichtenzugriff ( Accessibility ), Mauseingaben ( Mouse
Input ), Tasten - Code der Tastatur ( Keyboard Input ), standardisierter
Tastencode ( Virtual-Key Codes ), Alt-Tasten ( Keyboard Accelerators
), fertige Dialoge ( Common Dialog Box Library )
•
Fensternhirachie ( Windowing )
Fensterbehandlung ( Windows ) Datenzuordnung zu Fenstern (
Window Properties ), mehrere Fenster mit gleichen Eigenschhaften (
Queues
Window Classes ), Nachrichtenbearbeitung ( Message and Message
), ereignisgesteuerter Funktionsaufruf ( Callback, Window Procedures
), Behandlung von Dialogen ( Dialog Boxes ), alle Fenster innerhalb
des Eltern Fenster ( Multiple Document Interface )
Die folgenden Funktionen werden zum Erzeugen und Manipulieren
von Fenstern benutzt.
© Thomas Kowarsch
Seite 40/101
Systemschnittstellen
Stand: 16.10.03
AdjustWindowRect AdjustWindowRectEx AnimateWindow ArrangeIconicWindows
BeginDeferWindowPos BringWindowToTop CascadeWindows
ChildWindowFromPoint
ChildWindowFromPointEx CloseWindow CreateWindow CreateWindowEx
DeferWindowPos
DestroyWindow EnableWindow EndDeferWindowPos EnumChildProc
EnumChildWindows
EnumThreadWindows EnumThreadWndProc EnumWindows
EnumWindowsProc FindWindow
FindWindowEx GetClientRect GetDesktopWindow GetForegroundWindow
GetLastActivePopup
GetNextWindow GetParent GetTopWindow GetWindow
GetWindowPlacement
GetWindowRect GetWindowText GetWindowTextLength
GetWindowThreadProcessId
IsChild IsIconic IsWindow IsWindowUnicode IsWindowVisible IsZoomed
MoveWindow OpenIcon SetForegroundWindow SetParent SetWindowLong
SetWindowPlacement
SetWindowPos SetWindowText ShowOwnedPopups ShowWindow
ShowWindowAsync
TileWindows WindowFromPoint WinMain
GDI.EXE
GDI ist eine Abkürzung für (G)raphic (D)evice (I)nterface. Der File
GDI.EXE ist eine DLL, die das Graphics Device Interface ( GDI ) mit
den Funktionen zur Bild - Erzeugung und Bild - Anzeige ( nicht nur
Screen ) enthält. Hierher gehören z.B. auch Fonts und Device Kontext.
•
Bilderzeugung und Bildanzeige ( nicht nur auf dem Bildschirm,
auch auf z.B. Druckern ).
•
Fonts
•
Device - Kontext
Den Device Kontext benutzen die folgenden Funktionen.
CancelDC ChangeDisplaySettings CreateCompatibleDC CreateDC
CreateIC DeleteDC DeleteObject DeviceCapabilities DrawEscape
EnumDisplayDevices
GetDC
EnumDisplaySettings EnumObjects EnumObjectsProc GetCurrentObject
GetDCBrushColor GetDCEx GetDCOrgEx GetDCPenColor GetDeviceCaps
GetGraphicsMode GetObject GetObjectType GetStockObject ReleaseDC
ResetDC
RestoreDC SaveDC SelectObject SetDCBrushColor SetDCPenColor
© Thomas Kowarsch
Seite 41/101
Systemschnittstellen
Stand: 16.10.03
Mit Fonts und Texten werden die folgenden Funktionen benutzt:
AddFontResource CreateFont CreateFontIndirect CreateScalableFontResource
DrawText DrawTextEx
EnumFontFamiliesEx EnumFontFamExProc ExtTextOut
GetAspectRatioFilterEx
GetCharABCWidths GetCharABCWidthsFloat GetCharacterPlacement
GetCharWidth32
GetCharWidthFloat GetFontData GetFontLanguageInfo
GetFontUnicodeRanges
GetGlyphIndices GetGlyphOutline GetKerningPairs GetOutlineTextMetrics
GetRasterizerCaps GetTabbedTextExtent GetTextAlign
GetTextCharacterExtra
GetTextColor GetTextExtentExPoint GetTextExtentPoint32 GetTextFace
GetTextMetrics PolyTextOut RemoveFontResource SetMapperFlags
SetTextAlign
SetTextCharacterExtra SetTextColor SetTextJustification TabbedTextOut
TextOut Nicht mehr benutzt werden sollten:
EnumFontFamilies EnumFontFamProc EnumFonts EnumFontsProc
GetCharWidth
GetTextExtentPoint
Im Zusammenhang mit der Paint - Nachricht werden die folgenden
Funktionen benutzt:
BeginPaint DrawAnimatedRects DrawCaption DrawEdge DrawFocusRect
DrawFrameControl DrawState DrawStateProc DrawTextEx
EndPaint ExcludeUpdateRgn GdiFlush GdiGetBatchLimit GdiSetBatchLimit
GetBkColor GetBkMode GetBoundsRect GetROP2 GetUpdateRect
GetUpdateRgn
GetWindowDC GetWindowRgn GrayString InvalidateRect InvalidateRgn
LockWindowUpdate
OutputProc PaintDesktop RedrawWindow SetBkColor SetBkMode
SetBoundsRect
SetRectRgn SetROP2 SetWindowRgn UpdateWindow ValidateRect
ValidateRgn
WindowFromDC
GetDeviceCaps()
Als ein Beispiel wird GetDeviceCaps() gewählt. GetDeviceCaps() gibt
Informationen zum Device Kontext zurück.
int GetDeviceCaps( HDC hDC,
// device-context handle int nIndex // index of capability to query
);
© Thomas Kowarsch
Seite 42/101
Systemschnittstellen
Stand: 16.10.03
nIndex kann eine der folgenden Zahlen sein. Die eingerückten
Konstanten kennzeichnen die zugehörigen Rückgabeweerte.
DRIVERVERSION The device driver version.
TECHNOLOGY Device technology:
DT_PLOTTER Vector plotter,
DT_RASDISPLAY Raster display,
DT_RASPRINTER Raster printer,
DT_RASCAMERA Raster camera,
DT_CHARSTREAM Character stream,
DT_METAFILE Metafile und GetObjectType(),
DT_DISPFILE Display file
HORZSIZE Width, in millimeters, of the physical screen.
VERTSIZE Height, in millimeters, of the physical screen.
HORZRES Width, in pixels, of the screen.
VERTRES Height, in raster lines, of the screen.
LOGPIXELSX Number of pixels per logical inch along the screen width.
LOGPIXELSY Number of pixels per logical inch along the screen height.
BITSPIXEL Number of adjacent color bits for each pixel.
PLANES Number of color planes.
NUMBRUSHES Number of device-specific brushes.
NUMPENS Number of device-specific pens.
NUMFONTS Number of device-specific fonts.
NUMCOLORS Number of entries in the device's color table,
ASPECTX Relative width of a device pixel used for line drawing.
ASPECTY Relative height of a device pixel used for line drawing.
ASPECTXY Diagonal width of the device pixel used for line drawing.
PDEVICESIZE Reserved.
CLIPCAPS Flag that indicates the clipping capabilities of the device.
SIZEPALETTE Number of entries in the system palette.
NUMRESERVED Number of reserved entries in the system palette.
COLORRES Actual color resolution of the device, in bits per pixel.
PHYSICALWIDTH For printing devices: the width of the physical page,
in device units.
© Thomas Kowarsch
Seite 43/101
Systemschnittstellen
Stand: 16.10.03
PHYSICALHEIGHT For printing devices: the height of the physical
page, in device units.
PHYSICALOFFSETX For printing devices: the distance from the left
edge of the
physical page to the left edge of the printable area, in device units.
PHYSICALOFFSETY For printing devices: the distance from the top
edge of the
physical page to the top edge of the printable area, in device units.
VREFRESH Windows NT only: For display devices: the current vertical
refresh
rate of the device, in cycles per second (Hz).
DESKTOPHORZRES Windows NT only: Width, in pixels, of the virtual
desktop.
DESKTOPVERTRES Windows NT only: Height, in pixels, of the virtual
desktop.
BLTALIGNMENT Windows NT only: Preferred horizontal drawing
alignment, expressed
as a multiple of pixels.
RASTERCAPS Value that indicates the raster capabilities of the device:
RC_BANDING Requires banding support.
RC_BITBLT Capable of transferring bitmaps.
RC_BITMAP64 Capable of supporting bitmaps larger than 64K.
RC_DI_BITMAP Capable of supporting the SetDIBits and GetDIBits functions.
RC_DIBTODEV Capable of supporting the SetDIBitsToDevice function.
RC_FLOODFILL Capable of performing flood fills.
RC_GDI20_OUTPUT Capable of supporting features of Windows 2.0.
RC_PALETTE Specifies a palette-based device.
RC_SCALING Capable of scaling.
RC_STRETCHBLT Capable of performing the StretchBlt function.
RC_STRETCHDIB Capable of performing the StretchDIBits function.
CURVECAPS Value that indicates the curve capabilities of the device:
CC_NONE Device does not support curves.
CC_CHORD Device can draw chord arcs.
CC_CIRCLES Device can draw circles.
CC_ELLIPSES Device can draw ellipses.
CC_INTERIORS Device can draw interiors.
CC_PIE Device can draw pie wedges.
CC_ROUNDRECT Device can draw rounded rectangles.
© Thomas Kowarsch
Seite 44/101
Systemschnittstellen
Stand: 16.10.03
CC_STYLED Device can draw styled borders.
CC_WIDE Device can draw wide borders.
CC_WIDESTYLED Device can draw borders that are wide and styled.
LINECAPS Value that indicates the line capabilities of the device:
LC_NONE Device does not support lines.
LC_INTERIORS Device can draw interiors.
LC_MARKER Device can draw a marker.
LC_POLYLINE Device can draw a polyline.
LC_POLYMARKER Device can draw multiple markers.
LC_STYLED Device can draw styled lines.
LC_WIDE Device can draw wide lines.
LC_WIDESTYLED Device can draw lines that are wide and styled.
POLYGONALCAPS Value that indicates the polygon capabilities of the
device:
PC_NONE Device does not support polygons.
PC_INTERIORS Device can draw interiors.
PC_POLYGON Device can draw alternate-fill polygons.
PC_RECTANGLE Device can draw rectangles.
PC_SCANLINE Device can draw a single scanline.
PC_STYLED Device can draw styled borders.
PC_WIDE Device can draw wide borders.
PC_WIDESTYLED Device can draw borders that are wide and styled.
PC_WINDPOLYGON Device can draw winding-fill polygons.
TEXTCAPS Value that indicates the text capabilities of the device:
TC_OP_CHARACTER Device is capable of character output precision.
TC_OP_STROKE Device is capable of stroke output precision.
TC_CP_STROKE Device is capable of stroke clip precision.
TC_CR_90 Device is capable of 90-degree character rotation.
TC_CR_ANY Device is capable of any character rotation.
TC_SF_X_YINDEP Device can scale independently in the x- and y-directions.
TC_SA_DOUBLE Device is capable of doubled character for scaling.
TC_SA_INTEGER Device uses integer multiples only for character scaling.
TC_SA_CONTIN Device uses any multiples for exact character scaling.
TC_EA_DOUBLE Device can draw double-weight characters.
TC_IA_ABLE Device can italicize.
TC_UA_ABLE Device can underline.
TC_SO_ABLE Device can draw strikeouts.
TC_RA_ABLE Device can draw raster fonts.
TC_VA_ABLE Device can draw vector fonts.
TC_RESERVED Reserved; must be zero.
TC_SCROLLBLT Device cannot scroll using a bit-block transfer.
© Thomas Kowarsch
Seite 45/101
Systemschnittstellen
Stand: 16.10.03
GetSystemMetrics
Mit der Funktion GetSystemMetrics köennen ( geometrische )
Fenster - und Screen - Werte abgefragt werden.
Durch
RECT rc ; //Dialog mittig zentrieren GetWindowRect
( hWnd , & rc ) ; rc.left = ( GetSystemMetrics
( SM_CXSCREEN ) - rc.right + rc.left ) / 2 ; rc.top = ( GetSystemMetrics
( SM_CYSCREEN ) - rc.bottom + rc.top ) / 2 ; SetWindowPos (
hWnd, NULL, rc.left, rc.top, 0, 0, SWP_NOSIZE
| SWP_NOZORDER ) ;
kann ein Fenster zentriert werden.
Windows - Objekte
Windows kennt Objekte. Mit den Funktionen CreateWindow(),
DestroyWindow() soll die Nutzung dieser Objekte erklärt werden.
Eine Applikation führe z.B. CreateWindow() aus. CreateWindow()
erzeugt im Speicher ein Window - Objekt und lieferte ein gültiges
Handle.
Nach dem Create... kann das Objekt verwendet werden.
Durch DestroyWindow() wird das Objekt vernichtet. Der reservierten
Speicher wird frei gegeben. Das Fenster - Handle wird ungültig und
darf nicht mehr verwendet werden.
•
Ein Objekt hat nur ein Handle.
•
Ein Duplizieren eines Handles ist nicht sinnvoll.
•
Handles sind public für alle Prozesse.
© Thomas Kowarsch
Seite 46/101
Systemschnittstellen
•
Stand: 16.10.03
Ein Benutzer kann maximal 65536 Handles verwenden.
Die folgende Tabelle enthält die Benutzer - Objekte.
User Objects
Creator function
Destroyer function
Accelerator table
CreateAcceleratorTable
DestroyAcceleratorTable
Cursor CreateCursor
LoadCursor,
GetCursor,
SetCursor
DestroyCursor
DDE conversation
DdeConnect,
DdeConnectList,
DdeQueryNextServer,
DdeReconnect
DdeDisconnect,
DdeDisconnectList
Desktop
GetThreadDesktop
Applications cannot
delete this object.
Hook
SetWindowsHook,
SetWindowsHookEx
UnhookWindowsHook,
UnhookWindowsHookEx
Menu
CreateMenu,
CreatePopupMenu,
GetMenu,
GetSubMenu,
GetSystemMenu,
LoadMenu,
LoadMenuIndirect
DestroyMenu
Window
CreateWindow,
CreateWindowEx,
CreateDialogParam,
CreateDialogIndirectParam,
CreateMDIWindow,
FindWindow,
GetWindow,
GetClipboardOwner,
GetDesktopWindow,
GetDlgItem,
GetForegroundWindow,
GetLastActivePopup,
GetOpenClipboardWindow,
GetTopWindow,
WindowFromDC,
WindowFromPoint,
and others
DestroyWindow
Window position
BeginDeferWindowPos
EndDeferWindowPos
Window station
GetProcessWindowStation
Applications cannot
delete this object.
Lebensdauer von Objekten
Applikationen können Objekte erzeugen und verwenden. Ein Objekt
kann auch von mehreren Applikationen benutzt werden ( shared ). Das
Betriessystem erzeugt und nutzt ( Stock - ) Objekte, die vielfach von
Applikationen genutzt werden.
© Thomas Kowarsch
Seite 47/101
Systemschnittstellen
Stand: 16.10.03
Typ
belegt
durch
Sichtbarkeit
Lebensdauer
Overhead
Static
C-Compiler
Programm
Programm
0 (Allignment)
Automatic
C-Compiler
Funktion
Funktion
0 (Stackwort)
Heap
System
allokiert
Programm
Programm,
System bei
shared
32 Byte
Resourcen
RCCompiler
Programm,
System bei
shared
Owner
ca. 32 Byte
User
Objekte
GDIFunktionen
System
System
ca. 30-50 Byte
GDI
Objekte
UserFunktionen
System
Owner
ca. 30-50 Byte
Bei Win16 gibt es den lokalen Heap ( schnell, klein, gehört dem
Programm, 6 Byte Overhead ) und den globalen Heap ( groß, gehört
dem Programm/System, 24 Byte Overhead )
6.1.Hauptfunktion
int APIENTRY WinMain(HINSTANCE hInstance, HINSTANCE
hPrevInstance, LPSTR lpCmdLine, int nCmdShow ) {
// Registrierung der Windowsklasse
...
// Initialisierung der Anwendung durchführen:
...
// Accelerators und Hauptnachrichtenschleife
...
}
© Thomas Kowarsch
Seite 48/101
Systemschnittstellen
Stand: 16.10.03
6.2.Registrierung
6.2.1.WNDCLASSEX-Struktur
Hat eine Applikation mehrere Fenster, so gibt es Daten, die von allen
Fenstern benötigt werden. Diese Daten werden in der WNDCLASSEX Struktur gespeichert. The WNDCLASSEX structure is similar to the
WNDCLASS structure. There are two differences. WNDCLASSEX
includes the cbSize member, which specifies the size of the structure,
and the hIconSm member, which contains a handle to a small icon
associated with the window class.
typedef struct _WNDCLASSEX {
UINT
cbSize;
// sizeof( WNDCLASSEX ) ;
UINT
style;
//
CS_HREDRAW,CS_VREDRAW,CS_DBLCLKS,CS_CLASSDC,CS_OWNDC,
//
CS_PARENTDC,CS_BYTEALIGNWINDOW,CS_BYTEALIGNCLIENT,
//
CS_NOCLOSE,CS_GLOBALCLASS,CS_SAVEBITS
WNDPROC lpfnWndProc;
// CALLBACK-Funktion
int
cbClsExtra;
// < 40 Byte
int
cbWndExtra;
// < 40 Byte
HANDLE
hInstance;
// von WinMain()
HICON
hIcon;
IDI_APPLICATION );
// LoadIcon
HCURSOR hCursor;
IDC_ARROW );
// LoadCursor( NULL,
HBRUSH hbrBackground;
( WHITE_BRUSH );
// ( HBRUSH ) GetStockObject
LPCTSTR lpszMenuName;
( NULL,
// NULL
LPCTSTR lpszClassName;
"HelloWin" ;
// static char szAppName[] =
HICON
hIconSm;
IDI_APPLICATION );
// LoadIcon( NULL,
} WNDCLASSEX;
© Thomas Kowarsch
Seite 49/101
Systemschnittstellen
Stand: 16.10.03
Damit später mit ( CreateWindow oder CreateWindowEx ) spezielle
Fenster angelegt werden können, müssen vorher der Speicherbereich
für die gemeinsamen Daten angelegt und initialisiert werden.
WNDCLASSEX wndclass
wndclass.cbSize
wndclass.style
wndclass.lpfnWndProc
...
wndclass.lpszClassName
=
=
=
=
{ 0 };
sizeof( WNDCLASSEX ) ;
...
...
= ...
6.2.2.RegisterClassEx
if ( ! RegisterClass( & wndclass ) ) Fehler;
Die hinterlegten Daten können mit GetClassInfoEx() erhalten werden.
Damit bei einem Aufruf von RegisterClassEx() ( oder RegisterClass() )
nicht 13 Parameter übergeben werden müssen, werden die
Eingabewerte in eine WNDCLASSEX - Struktur geschrieben, die dann
an die Funktion
ATOM RegisterClassEx( CONST WNDCLASSEX *lpwcx );
übergeben wird. Wenn kein Speicher für die Daten angelegt werden
konnte und diese Funktion erfolglos war, wird 0 zurück gegeben. In
diesem Fall kann der Fehler mit GetLastError() näher untersucht
werden.
Achtung! Ist RegisterClassEx() in einer NT - DLL, so wird beim
unloaden der Speicher nicht automatisch freigegeben. Es ist
unRegisterClassEx() erforderlich.
Das System kennt bereits die Klassen BUTTON, COMBOBOX, EDIT,
LISTBOX, MDICLIENT, SCROLLBAR, STATIC.
© Thomas Kowarsch
Seite 50/101
Systemschnittstellen
Stand: 16.10.03
6.3.Initialisierung
6.3.1.CreateWindowEx
Bis auf dwExStyle ist CreateWindowEx() identisch mit CreateWindow().
CreateWindowEx() kann ein Overlapped -, Pop - Up -, oder Child Window erstellen.
CreateWindowEx() sendet die WM_NCCREATE-, WM_NCCALCSIZE-,
WM_CREATE-Nachrichten zu dem angelegten Fenster. Der
Rückgabewert ist das Handle des neuen Fensters.
Das Fenster ist nicht sichtbar, obwohl das Handle != NULL den
allokierten Speicher referenziert und Fenster-Daten eingetragen
wurden.
HWND CreateWindowEx(
DWORD dwExStyle,
LPCTSTR lpClassName,
LPCTSTR lpWindowName,
DWORD dwStyle,
int x,
int y,
int nWidth,
int nHeight,
HWND hWndParent,
HMENU hMenu,
identifier
HINSTANCE hInstance,
LPVOID lpParam
);
//
//
//
//
//
//
//
//
//
//
extended window style
pointer to registered class name
pointer to window name
window style
horizontal position of window
vertical position of window
window width
window height
handle to parent or owner window
handle to menu, or child-window
// handle to application instance
// pointer to window-creation data
dwExStyle spezifiziert erweiterte Styles:
WS_EX_ACCEPTFILES, WS_EX_APPWINDOW, WS_EX_CLIENTEDGE,
WS_EX_CONTEXTHELP, WS_EX_CONTEXTHELP,
WS_EX_CONTROLPARENT, WS_EX_DLGMODALFRAME (double
border), WS_CAPTION, WS_EX_LEFT, WS_EX_LEFTSCROLLBAR,
WS_EX_LTRREADING, WS_EX_MDICHILD,
WS_EX_NOPARENTNOTIFY, WS_EX_OVERLAPPEDWINDOW,
WS_EX_PALETTEWINDOW, WS_EX_RIGHT,
WS_EX_RIGHTSCROLLBAR, WS_EX_RTLREADING,
WS_EX_STATICEDGE, WS_EX_TOOLWINDOW, WS_EX_TOPMOST,
WS_EX_TRANSPARENT, WS_EX_WINDOWEDGE
lpClassName zeigt auf einen "null-terminated string" der den Window Class - Namen spezifiziert oder ist ein integer atom ( GlobalAddAtom ).
lpClassName zeigt auf einen "null-terminated string" der den Window Namen spezifiziert ( Titelzeile, Text eines Controls ).
© Thomas Kowarsch
Seite 51/101
Systemschnittstellen
Stand: 16.10.03
dwStyle spezifiziert den Style des Fensters und Funktionalität:
WS_BORDER, WS_CAPTION, WS_CHILD, WS_CHILDWINDOW,
WS_CLIPCHILDREN, WS_CLIPSIBLINGS, WS_DISABLED,
WS_DLGFRAME, WS_GROUP, WS_HSCROLL, WS_ICONIC,
WS_MAXIMIZE, WS_MAXIMIZEBOX, WS_MINIMIZE,
WS_MINIMIZEBOX, WS_OVERLAPPED, WS_OVERLAPPEDWINDOW,
WS_POPUP, WS_POPUPWINDOW, WS_SIZEBOX, WS_SYSMENU,
WS_TABSTOP, WS_THICKFRAME, WS_TILED,
WS_TILEDWINDOW, WS_VISIBLE, WS_VSCROLL
Alle Fenster haben bereits die WS_CLIPSIBLINGS und
WS_CLIPCHILDREN Styles.
lpParam kann in der CREATESTRUCT - Struktur unter WM_CREATE an
die CALLBACK - Funktion weitergereicht werden.
In CreateWindowEx() können für die horizontale/vertikale Fenster Position anstelle von festen int x-, y-, nWidth-, nHeight- Werten auch
Bildschirm - bezogene Werte ( z.B. GetSystemMetrics(SM_CXSCREEN)
*1/8, GetSystemMetrics(SM_CYSCREEN)*1/5, GetSystemMetrics
(SM_CXSCREEN)*6/8, GetSystemMetrics(SM_CYSCREEN)*6/5 )
verwendet werden.
6.3.2.ShowWindow
Mit ShowWindow wird definiert wie das Fenster angezeigt wird.
BOOL ShowWindow(
HWND hWnd, // handle to window
int nCmdShow // show state of window
);
Parameter:
hWnd - Handle to the window.
nCmdShow - definiert wie das Fenster angezeigt wird. Folgende Werte
sind erlaubt:
SW_FORCEMINIMIZE Windows NT 5.0 oder später: Minimiert das
Fenster, wenn der Thread des Fensters, sich aufgehängt hat. Dieses
Flag Sollte nur benutzt werden, um das Fenster von einem anderen
Thread zu minimieren.
SW_HIDE Versteckt das Fenster und aktiviert ein anderes.
SW_MAXIMIZE Maximiert das Fenster
SW_MINIMIZE Minimiert das Fenster und aktiviert ein anderes.
SW_RESTORE Aktiviert und zeigt das Fenster. Wenn das Fenster zuvor
© Thomas Kowarsch
Seite 52/101
Systemschnittstellen
Stand: 16.10.03
minimiert oder maximiert gewesen ist, wird das Fenster in die Original
Größe und Position zurückgesetzt. Dieses Flag sollte nur dann
verwendet werden, dann das Fenster zuvor minimiert gewesen war.
SW_SHOW Aktiviert das Fenster und setzt es auf die momentane
Größe und Position.
SW_SHOWDEFAULT Sets the show state based on the SW_ flag
specified in theSTARTUPINFO structure passed to theCreateProcess
function by the program that started the application.
SW_SHOWMAXIMIZED Aktiviert und maximiert das Fenster .
SW_SHOWMINIMIZED Aktiviert und minimiert das Fenster .
SW_SHOWMINNOACTIVE Minimiert das Fenster, das letzte aktive
Fenster bleibt aktiv.
SW_SHOWNA Setzt das Fenster auf die momentane Größe und
Position, das letzte aktive Fenster bleibt aktiv.
SW_SHOWNOACTIVATE gleiche wie SW_SHOWNOACTIVATE
SW_SHOWNORMAL gleiche wie SW_RESTORE. Dieses Flag sollte nur
dann verwendet werden, dann das Fenster zum ersten Mal angezeigt
wird.
Rückgabewerte:
<> 0 : Wenn das Fenster sichtbar war
0 : Wenn das Fenster nicht sichtbar war
Unter Windows CE werden nur folgende Flags unterstützt:
SW_MAXIMIZE
SW_MINIMIZE
SW_RESTORE
SW_SHOWDEFAULT
SW_SHOWMAXIMIZED
SW_SHOWMINIMIZED
SW_SHOWMINNOACTIVE
Benötigte Headerfile: winuser.h.
Benötigte Library: user32.lib.
© Thomas Kowarsch
Seite 53/101
Systemschnittstellen
Stand: 16.10.03
6.3.3.UpdateWindow
Die UpdateWindow Funktion aktuallisiert den Clientbereich des
Fensters durch das Senden der WM_PAINT Nachricht. Die Nachricht
wird direkt gesendet und nicht zuvor in den Puffer geschrieben. Wenn
die Region leer ist, so wird keine Nachricht gesendet.
BOOL UpdateWindow(
HWND hWnd // handle of window
);
Parameter:
hWnd - Handle to the window
Rückgabewert
0 : Bei Erfolg
<> 0 : Fehler
Benötigte Headerfile: winuser.h.
Benötigte Library: user32.lib.
6.4.Hauptnachrichtenschleife
Die Nachrichtenschleife enthält
while ( GetMessage( & msg, NULL, 0, 0 ) ) {
TranslateMessage( & msg ) ;
DispatchMessage( & msg ) ;
}
6.4.1.GetMessage
GetMessage() holt aus dem Applikations - Buffer ( thread's message
queue ) die nächste Nachricht und stellt diese in der MSG - Struktur
zur Verfügung. GetMessage() erhält keine Nachrichten von einer
anderen Applikation.
Entnimmt GetMessage() dem Buffer die WM_QUIT - Nachricht, so ist
der Rückgabewert 0, sonst != 0. Ein ungültiges Window-Handle liefert
den Rückgabewert -1. Mit GetLastError() kann der Fehler analysiert
werden.
BOOL GetMessage(
LPMSG lpMsg,
// address of structure with message
HWND hWnd,
// handle of window
UINT wMsgFilterMin, // first message
UINT wMsgFilterMax // last message
);
© Thomas Kowarsch
Seite 54/101
Systemschnittstellen
Stand: 16.10.03
Wenn mit PostThreadMessage() per Programm eine Nachricht
versendet wird, so ist hWnd == NULL, sonst identifiziert hWnd das
Fenster.
wMsgFilterMin, wMsgFilterMax werden zum Eingrenzen der
Nachrichten verwendet ( z.B. WM_KEYFIRST, WM_KEYLAST,
WM_MOUSEFIRST, WM_MOUSELAST ).
6.4.2.TranslateMessage
Die Funktion
BOOL TranslateMessage( CONST MSG *lpMsg );
wandelt eine Virtual - Key - Nachricht in eine Zeichen - Nachricht um
( WM_KEYDOWN, WM_KEYUP, WM_SYSKEYDOWN, WM_SYSKEYUP ).
WM_KEYDOWN und WM_KEYUP Kombinationen ergeben WM_CHAR
oder WM_DEADCHAR - Nachrichten. WM_SYSKEYDOWN und
WM_SYSKEYUP Kombinationen ergeben WM_SYSCHAR oder
WM_SYSDEADCHAR - Nachrichten. Die Zeichen - Nachricht wird in die
Applikations - Nachrichten - Buffer gestellt. Mit GetMessage() oder
PeekMessage() wird diese Nachricht geholt.
6.4.3.DispatchMessage
Aus dem Handle der Nachricht kann das Fenster ersehen werden.
DispatchMessage() bestimmt das Fenster und leitet eine gültige
Nachricht an die CALLBACK - Funktion des Fensters.
LONG DispatchMessage( CONST MSG *lpmsg );
Wenn lpmsg auf eine WM_TIMER - Nachricht zeigt wird anstelle der
Window - CALLBACK - Funktion die Funktion lParam() != NULL
aufgerufen.
© Thomas Kowarsch
Seite 55/101
Systemschnittstellen
Stand: 16.10.03
6.5.CALLBACK - Funktion
Das System verwaltet die Tastatur, die Maus und den Bildschirm.
Wenn z.B. eine Taste gedrückt wird, so tritt ein Ereignis ein. Dieses
Ereignis ruft die CALLBACK - Funktion
LRESULT CALLBACK WndProc( HWND hWnd , UINT iMsg, WPARAM
wParam, LPARAM lParam ) des Fensters auf.
Aus dem Handle der Tasten - Nachricht kann das Fenster ersehen
werden. DispatchMessage() bestimmt das Fenster und ruft die
CALLBACK - Funktion des Fenster auf, d.h. die Tasten - Nachricht wird
an das Fenster geschickt.
Vor dem Aufruf der Fensters - CALLBACK - Funktion werden ( durch
das Windows - System ) die Parameter der Nachricht auf den Stack
gelegt, d.h. die Nachricht wird über den Aufrufer - Stack an die
CALLBACK - Funktion übergeben.
Nachrichten rufen dieFenster CALLBACK - Funktion auf.
Innerhalb der CALLBACK - Funktion können die Nachrichten bearbeitet
werden.
6.5.1.WM_PAINT - Nachricht
Ist z.B. ein Teilbereich des Bildschirm - Fensters verdeckt und wird die
Überdeckung beseitigt, so entsteht ein "weißes Rechteck". Das
Windows - System legt die WM_PAINT - Nachricht in den Applikations Message - Buffer. In der Hauptnachrichten - Schleife wird durch
DispatchMessage() die CALLBACK - Funktion aufgerufen. Wenn
Windows oder eine andere Applikation ein Neuzeichnen wünscht, so
wird eine WM_PAINT - Nachricht gesendet.
In der CALLBACK - Funktion kann
iMsg = WM_PAINT
hdc = (HDC) wParam;
benutzt werden.
Wenn z.B. das Fenster vergrößert wird, so wird automatisch die
WM_PAINT - Nachricht durch das Windows - System gesendet.
Die WM_PAINT - Nachricht ist eine nachrangige Nachricht.
Sind neben WM_PAINT weitere Nachrichten im Applikations Nachrichten - Buffer, so werden diese zuerst abgearbeitet.
© Thomas Kowarsch
Seite 56/101
Systemschnittstellen
Stand: 16.10.03
Die WM_PAINT - Nachricht wird auch durch die Funktionen
UpdateWindow(), RedrawWindow() ausgelöst. Eine WM_PAINT Nachricht steht in Zusammenhang mit den WM_ERAEBKGND -,
WM_NCPAINT - Nachrichten und den Funktionen DispatchMessage(),
DefWindowProc(), BeginPaint(), EndPaint(), GetUpdateRect(),
UpdateWindow(), RedrawWindow()
Wann wird WM_PAINT ausgelöst?
Eine Applikation zeichnet und aktualisiert ein Fenster
nachdem die Fenster - Daten allokiert und initialisiert wurden
( WM_CREATE ),
nachdem sich die Fenstergröße ändert ( WM_SIZE ),
nachdem Fenster - Anteile in den Vordergrund erscheinen,
nachdem das Fenster zum Icon wird ( WM_MINIMIZED ),
nachdem das Fenster zur Vollbild - Größe wird ( WM_MAXIMIZED ),
nachdem das Fenster gescrollt wurde ( WM_ ),
nachdem dar Fenster - Inhalt geändert wurde.
6.5.2.Bildschirmausgabe
6.5.2.a)Device Kontext
benutzen die folgenden Funktionen.
CancelDC ChangeDisplaySettings CreateCompatibleDC CreateDC
CreateIC DeleteDC DeleteObject DeviceCapabilities DrawEscape
EnumDisplayDevices EnumDisplaySettings EnumObjects
EnumObjectsProc GetCurrentObject GetDC GetDCBrushColor GetDCEx
GetDCOrgEx GetDCPenColor GetDeviceCaps GetGraphicsMode
GetObject GetObjectType GetStockObject ReleaseDC ResetDC
RestoreDC SaveDC SelectObject SetDCBrushColor SetDCPenColor
Mit Fonts und Texten werden die folgenden Funktionen benutzt:
AddFontResource CreateFont CreateFontIndirect
CreateScalableFontResource DrawText DrawTextEx
EnumFontFamiliesEx EnumFontFamExProc ExtTextOut
GetAspectRatioFilterEx GetCharABCWidths GetCharABCWidthsFloat
GetCharacterPlacement GetCharWidth32 GetCharWidthFloat
GetFontData GetFontLanguageInfo GetFontUnicodeRanges
GetGlyphIndices GetGlyphOutline GetKerningPairs
GetOutlineTextMetrics GetRasterizerCaps GetTabbedTextExtent
GetTextAlign GetTextCharacterExtra GetTextColor
GetTextExtentExPoint GetTextExtentPoint32 GetTextFace
© Thomas Kowarsch
Seite 57/101
Systemschnittstellen
Stand: 16.10.03
GetTextMetrics PolyTextOut RemoveFontResource SetMapperFlags
SetTextAlign SetTextCharacterExtra SetTextColor SetTextJustification
TabbedTextOut TextOut
Nicht mehr benutzt werden sollten:
EnumFontFamilies EnumFontFamProc EnumFonts EnumFontsProc
GetCharWidth GetTextExtentPoint
Im Zusammenhang mit der Paint - Nachricht werden die folgenden
Funktionen benutzt:
BeginPaint DrawAnimatedRects DrawCaption DrawEdge
DrawFocusRect DrawFrameControl DrawState DrawStateProc
DrawTextEx EndPaint ExcludeUpdateRgn GdiFlush GdiGetBatchLimit
GdiSetBatchLimit GetBkColor GetBkMode GetBoundsRect GetROP2
GetUpdateRect GetUpdateRgn GetWindowDC GetWindowRgn
GrayString InvalidateRect InvalidateRgn LockWindowUpdate
OutputProc PaintDesktop RedrawWindow SetBkColor SetBkMode
SetBoundsRect SetRectRgn SetROP2 SetWindowRgn UpdateWindow
ValidateRect ValidateRgn WindowFromDC
GetDeviceCaps()
Als ein Beispiel wird GetDeviceCaps() gewählt. GetDeviceCaps() gibt
Informationen zum Device Kontext zurück.
int GetDeviceCaps( HDC hDC,
// device-context handle int nIndex // index of capability to
query
);
nIndex kann eine der folgenden Zahlen sein. Die eingerückten
Konstanten kennzeichnen die zugehörigen Rückgabeweerte.
DRIVERVERSION The device driver version.
TECHNOLOGY Device technology:
DT_PLOTTER Vector plotter,
DT_RASDISPLAY Raster display,
DT_RASPRINTER Raster printer,
DT_RASCAMERA Raster camera,
DT_CHARSTREAM Character stream,
DT_METAFILE Metafile und GetObjectType(),
DT_DISPFILE Display file
© Thomas Kowarsch
Seite 58/101
Systemschnittstellen
Stand: 16.10.03
HORZSIZE Width, in millimeters, of the physical screen.
VERTSIZE Height, in millimeters, of the physical screen.
HORZRES Width, in pixels, of the screen.
VERTRES Height, in raster lines, of the screen.
LOGPIXELSX Number of pixels per logical inch along the screen width.
LOGPIXELSY Number of pixels per logical inch along the screen height.
BITSPIXEL Number of adjacent color bits for each pixel.
PLANES Number of color planes.
NUMBRUSHES Number of device-specific brushes.
NUMPENS Number of device-specific pens.
NUMFONTS Number of device-specific fonts.
NUMCOLORS Number of entries in the device's color table,
ASPECTX Relative width of a device pixel used for line drawing.
ASPECTY Relative height of a device pixel used for line drawing.
ASPECTXY Diagonal width of the device pixel used for line drawing.
PDEVICESIZE Reserved.
CLIPCAPS Flag that indicates the clipping capabilities of the device.
SIZEPALETTE Number of entries in the system palette.
NUMRESERVED Number of reserved entries in the system palette.
COLORRES Actual color resolution of the device, in bits per pixel.
PHYSICALWIDTH For printing devices: the width of the physical page,
in device units.
PHYSICALHEIGHT For printing devices: the height of the physical
page, in device units.
PHYSICALOFFSETX For printing devices: the distance from the left
edge of the physical page to the left edge of the printable area, in
device units.
PHYSICALOFFSETY For printing devices: the distance from the top
edge of the physical page to the top edge of the printable area, in
device units.
VREFRESH Windows NT only: For display devices: the current vertical
refresh rate of the device, in cycles per second (Hz).
DESKTOPHORZRES Windows NT only: Width, in pixels, of the virtual
desktop.
DESKTOPVERTRES Windows NT only: Height, in pixels, of the virtual
desktop.
BLTALIGNMENT Windows NT only: Preferred horizontal drawing
alignment, expressed as a multiple of pixels.
RASTERCAPS Value that indicates the raster capabilities of the device:
RC_BANDING Requires banding support.
RC_BITBLT Capable of transferring bitmaps.
RC_BITMAP64 Capable of supporting bitmaps larger than 64K.
RC_DI_BITMAP Capable of supporting the SetDIBits and GetDIBits
functions.
RC_DIBTODEV Capable of supporting the SetDIBitsToDevice function.
RC_FLOODFILL Capable of performing flood fills.
RC_GDI20_OUTPUT Capable of supporting features of Windows 2.0.
© Thomas Kowarsch
Seite 59/101
Systemschnittstellen
Stand: 16.10.03
RC_PALETTE Specifies a palette-based device.
RC_SCALING Capable of scaling.
RC_STRETCHBLT Capable of performing the StretchBlt function.
RC_STRETCHDIB Capable of performing the StretchDIBits function.
CURVECAPS Value that indicates the curve capabilities of the device:
CC_NONE Device does not support curves.
CC_CHORD Device can draw chord arcs.
CC_CIRCLES Device can draw circles.
CC_ELLIPSES Device can draw ellipses.
CC_INTERIORS Device can draw interiors.
CC_PIE Device can draw pie wedges.
CC_ROUNDRECT Device can draw rounded rectangles.
CC_STYLED Device can draw styled borders.
CC_WIDE Device can draw wide borders.
CC_WIDESTYLED Device can draw borders that are wide and styled.
LINECAPS Value that indicates the line capabilities of the device:
LC_NONE Device does not support lines.
LC_INTERIORS Device can draw interiors.
LC_MARKER Device can draw a marker.
LC_POLYLINE Device can draw a polyline.
LC_POLYMARKER Device can draw multiple markers.
LC_STYLED Device can draw styled lines.
LC_WIDE Device can draw wide lines.
LC_WIDESTYLED Device can draw lines that are wide and styled.
POLYGONALCAPS Value that indicates the polygon capabilities of the
device:
PC_NONE Device does not support polygons.
PC_INTERIORS Device can draw interiors.
PC_POLYGON Device can draw alternate-fill polygons.
PC_RECTANGLE Device can draw rectangles.
PC_SCANLINE Device can draw a single scanline.
PC_STYLED Device can draw styled borders.
PC_WIDE Device can draw wide borders.
PC_WIDESTYLED Device can draw borders that are wide and styled.
PC_WINDPOLYGON Device can draw winding-fill polygons.
TEXTCAPS Value that indicates the text capabilities of the device:
TC_OP_CHARACTER Device is capable of character output precision.
TC_OP_STROKE Device is capable of stroke output precision.
TC_CP_STROKE Device is capable of stroke clip precision.
© Thomas Kowarsch
Seite 60/101
Systemschnittstellen
Stand: 16.10.03
TC_CR_90 Device is capable of 90-degree character rotation.
TC_CR_ANY Device is capable of any character rotation.
TC_SF_X_YINDEP Device can scale independently in the x- and ydirections.
TC_SA_DOUBLE Device is capable of doubled character for scaling.
TC_SA_INTEGER Device uses integer multiples only for character
scaling.
TC_SA_CONTIN Device uses any multiples for exact character scaling.
TC_EA_DOUBLE Device can draw double-weight characters.
TC_IA_ABLE Device can italicize.
TC_UA_ABLE Device can underline.
TC_SO_ABLE Device can draw strikeouts.
TC_RA_ABLE Device can draw raster fonts.
TC_VA_ABLE Device can draw vector fonts.
TC_RESERVED Reserved; must be zero.
TC_SCROLLBLT Device cannot scroll using a bit-block transfer.
GetSystemMetrics
Mit der Funktion GetSystemMetrics köennen ( geometrische ) Fenster und Screen - Werte abgefragt werden.
Durch
RECT rc ; //Dialog mittig zentrieren
GetWindowRect ( hWnd , & rc ) ;
rc.left = ( GetSystemMetrics( SM_CXSCREEN ) - rc.right +
rc.left ) / 2 ;
rc.top = ( GetSystemMetrics ( SM_CYSCREEN ) - rc.bottom +
rc.top ) / 2 ;
SetWindowPos ( hWnd, NULL, rc.left, rc.top, 0, 0,
SWP_NOSIZE | SWP_NOZORDER ) ;
kann ein Fenster zentriert werden.
© Thomas Kowarsch
Seite 61/101
Systemschnittstellen
Stand: 16.10.03
6.5.2.b)BeginPaint(), EndPaint()
In der obigen CALLBACK - Funktion
LRESULT CALLBACK WndProc( HWND hWnd , UINT iMsg, WPARAM
wParam, LPARAM lParam )
wird die WM_PAINT - Nachricht durch
case WM_PAINT :
hDC = BeginPaint( hWnd, & ps ) ;
GetClientRect( hWnd, & rect ) ;
DrawText
( hDC, "Hallo, Win32!",1,&rect,DT_SINGLELINE|DT_CENTER|DT_VCENTER);
EndPaint
( hWnd, & ps ) ;
break ; //return 0;
behandelt. Der Hintergrund wird gelöscht und der Text wird erneut
durch DrawText() zentriert ausgegeben.
Die BeginPaint() - Funktion wird benutzt, um gemäß hDC = BeginPaint
( hWnd, & ps ) ;
den Text - Cursor ( Caret ) zu verbergen,
das Updating - Clipping - Rechteck in PAINTSTRUCT.rcPaint zu setzen,
den Device - Kontext zu ermitteln und
falls erforderlich WM_NCPAINT und WM_ERASEBKGND ( Title Bar,
System Menu, Scroll Bars ) auszulösen.
Der Device - Kontext enthält globale Daten, die von vielen GDI Funktionen zum Zeichnen gebraucht werden.
Praktisch alle GDI - Funktionen benötigen den Device - Kontext.
Durch EndPaint ( hWnd, & ps )
wird das Update - Rechteck auf NULL gesetzt ( keine WM_PAINT Rekursion ),
wird der Device - Kontext wieder frei gegeben,
wird das Caret wieder angezeigt.
BeginPaint() und EndPaint() benutzen PAINTSTRUCT.
typedef struct tagPAINTSTRUCT { // ps
HDC hdc;
BOOL fErase;
// TRUE: erase background with
hbrBackground of WNDCLASSEX
RECT rcPaint;
// painting rectangle
BOOL fRestore;
// Reserved; used internally
BOOL fIncUpdate;
// Reserved; used internally
BYTE rgbReserved[32]; // Reserved; used internally
© Thomas Kowarsch
Seite 62/101
Systemschnittstellen
Stand: 16.10.03
} PAINTSTRUCT;
Das Update - Rechteck wird in einer RECT - Struktur gespeichert.
RECT hat die folgenden Komponenten:
typedef struct _RECT { // rc
LONG left;
LONG top;
LONG right;
LONG bottom;
} RECT;
Durch
hDC = GetDC( hWnd ) ;
...
ReleaseDC( hWnd, hDC ) ;
wird ein hDC erhalten, das zum gesamten Client - Bereich gehört.
Auch die DefWindowProc() löscht das Update - Recheck ( validates ).
Falls erforderlich, versendet die DefWindowProc() die WM_NCPAINT,
WM_ERASEBKGND - Nachrichten. Dies entspricht dem Code
case WM_PAINT :
BeginPaint( hWnd, & ps ) ;
...
EndPaint ( hWnd, & ps ) ;
return 0;
in der DefWindowProc() - Funktion.
InvalidateRect(), ValidateRect(), GetUpdateRect()
Mit der GetUpdateRect() kann untersucht werden, ob eine Update
Rechteck vorhanden ist. Falls GetUpdateRect den wert 0 zurück gibt,
so ist kein BeginPaint() ... EndPaint() erforderlich. Wenn die Update Rechteck nicht leer ist, so sendet Windows eine WM_PAINT - Nachricht
zu dem Fenster. Durch die InvalidateRect() kann ein Rechteck zu dem
Update - Fenster - Rechteck hinzugefügt werden.
Durch InvalidateRect( hWnd, NULL, TRUE ) wird der gesamte Fenster Client - Bereich zur Update - Rechteck hinzugefügt, d.h. mit
WM_PAINT - Nachricht soll der Fenster - Hintergrund gelöscht und das
gesamte Fenster neu gezeichnet werden. Durch BeginPaint(),
ValidateRect()/ValidateRgn() wird das Update - Rechteck/Region
gelöscht.
© Thomas Kowarsch
Seite 63/101
Systemschnittstellen
Stand: 16.10.03
BOOL InvalidateRect(
HWND hWnd,
// handle of window with changed update Rect
CONST RECT *lpRect, // address of rectangle coordinates
BOOL bErase
// TRUE: BeginPaint() erased background
);
Mit der GetUpdateRect() kann untersucht werden, ob eine Update
Rechteck vorhanden ist. Falls GetUpdateRect den wert 0 zurück gibt,
so ist kein BeginPaint() ... EndPaint() erforderlich.
Falls ein Update Rechteck vorhanden ist, so sendet die UpdateWindow(
hWndMain ) eine synchrone WM_PAINT - Nachricht. Ebenso die
RedrawWindow( hWndMain ) Funktion, die eine erweiterte Kontrolle
( not Client, BackGround ) erlaubt.
© Thomas Kowarsch
Seite 64/101
Systemschnittstellen
Stand: 16.10.03
6.5.3.Schliessen von Fenstern/Applikation
WM_CLOSE - Nachricht
Wird durch einen
x - Mausklick die iMsg = WM_CLOSE - Nachricht ausgelöst, so wird die
CALLBACK - Funktion LRESULT CALLBACK WndProc( HWND hWnd ,
UINT iMsg, WPARAM wParam, LPARAM lParam ) mit iMsg =
WM_CLOSE aufgerufen.
Um mit Hilfe eines Anzeige - Fensters ( MessageBox ) eine Rückfrage
zu ermöglichen wird unter WM_CLOSE
case WM_CLOSE:
if ( GetParent( hWnd ) != NULL ) break;
char buf[256];
GetWindowText( hWnd, buf, 256 ) ; // Text der
Titelzeile wird nach buf kopiert
if ( MessageBox ( hWnd, "Do you want to Exit?", buf,
MB_ICONQUESTION | MB_YESNO) == IDYES ) {
DestroyWindow( hWnd ); //sendet WM_DESTROY
} return 0;
case WM_DESTROY: // Hauptfenster schliessen, zerstoert
automatisch die Child-Windows.
PostQuitMessage( 0 );
return 0;
ausgeführt. Falls der MessageBox - Rückgabewert TRUE ist, so wurde
der "YES" - Button gedrück. Dann wird durch DestroyWindow( hWnd )
die WM_DESTROY - Nachricht gesendet, d.h. die
LRESULT CALLBACK WndProc( HWND hWnd , UINT iMsg, WPARAM
wParam, LPARAM lParam )
Funktion wird mit iMsg = WM_DESTROY aufgerufen. Infolge von
PostQuitMessage( 0 ) wird das Fenster geschlossen.
Klick: Zeigt iMsg = WM_...- Nachrichten an
© Thomas Kowarsch
Seite 65/101
Systemschnittstellen
Stand: 16.10.03
6.5.4.Tastatur - Nachrichten
Wenn Prozessen mit unterschiedlicher Ausführungs - Geschwindigkeit
synchronisiert werden müssen, so werden Warteschlangen ( Buffer )
benötigt. Der schreibende Prozeß hinterlegt die unregelmäßig
eintreffenden Ereignisse in einem Buffer. Der lesende Prozeß holt sich
die Nachrichten und verarbeitet diese mit der eigenen
Geschwindigkeit.
Bei dem Windows - System - Tastatur - Buffer handelt es sich um
einen Ring - Buffer. Bei DOS enthält der Tastatur - Buffer 32 Worte
( 64 Byte ).
•
Tastaturereignis ==> int 9h ==> Zeichen in Puffer ==> int 16h
==> Buffer auslesen
#include <stdio.h>
extern key_read( int*, int* );
void main( ) {
int *ascii_ptr, *scan_ptr, num, num1; num = 0; num1 = 0;
ascii_ptr = &num; scan_ptr = &num1; // initialize pointers to zero
key_read( ascii_ptr, scan_ptr ); // call assembly routine
// print the high byte - ASCII code, and the low byte - extended code
// of the character placed in the keyboard buffer
printf( "ASCII Code hex %x or decimal %d\n", *ascii_ptr,"
" *ascii_ptr);
printf( "EXTENDED Code hex %x "
"or decimal %d\n", *scan_ptr, *scan_ptr);
}
******************************************************
.model small,c
.data
.code
PUBLIC key_read
key_read PROC
PUSH bp
;save the base pointer
MOV bp, sp
; Invoke Int 21h Function Ch to clear the keyboard buffer before ;
; accepting a keystroke.
MOV ah, 0CH
MOV al, 0
INT 21h
; Invoke Int 16h Function 0h to place the character code in the AX ; register.
MOV ah, 0H
INT 16H
MOV
MOV
bx, [bp+4] ;ASCII returned
[bx], al
MOV
MOV
bx, [bp+6] ;Extended code returned
[bx], ah
POP bp
RET
key_read ENDP
END
© Thomas Kowarsch
Seite 66/101
Systemschnittstellen
Stand: 16.10.03
Tasten - Scan - Code
Bei Windows kann der System - Tastatur - Buffer 60 Zeichen
aufnehmen.
Im System - Nachrichten - Buffer kommt der Tasten - Scan - Code.
Die Tasten - Nachricht wird aufbereitet ( einheitliches MSG - Format )
und in den Applikations - Nachrichten - Buffer gestellt.
Bei Windows hat ein Fenster den Focus. Dieses Fenster ist i.a. an der
blauen Titel - Zeile erkennbar. Die Tasten - Nachrichten werden in der
Haupt - Nachrichten - Schleife aus dem Applikations - Buffer geholt
( GetMessage ) und die CALLBACK - Funktion des Fensters wird mit
der Tasten - Nachricht ( iMsg, wParam, lParam ) aufgerufen, d.h.
•
die Tasten - Nachrichten werden an das Fenster geschickt.
Vor dem Aufruf der Fensters - CALLBACK - Funktion werden durch
das Windows - System die Parameter der Nachricht auf den Stack
gelegt, d.h. die Nachricht wird über den Aufrufer - Stack an die
CALLBACK - Funktion übergeben. An hWnd ist das Fenster ( genauer:
der Speicher für die Fensterdaten ) erreichbar. In iMsg ist die Tasten Nachricht eindeutig identifizierbar. Mit wParam, lParam können die
Tasten unterschieden werden.
LRESULT CALLBACK WndProc( HWND hWnd, UINT iMsg, WPARAM wParam, LPARAM lParam ) {
switch ( iMsg ) {
...
case WM_CHAR : {
switch ( LOWORD(wParam) ) {
case ‘\b’ : Rücktaste; break;
case ‘\t’ : Tabulatortaste; break;
case ‘\n’ : LF-Taste; break;
default : //normales Zeichen bearbeiten
}
}
...
}
return DefWindowProc( hWnd, iMsg, wParam, lParam ) ;
}
In dem obigen Beispiel werden nur einige WM_CHAR - Nachrichten
behandelt.
Tabelle der WM - Tastatur - Nachrichten
Es gibt die folgenden Keyboard - Nachrichten:
TastenNachricht
wParam, lParam enthalten ...
WM_ACTIVATE
fActive = LOWORD(wParam); // activation flag
fMinimized = (BOOL) HIWORD(wParam); // minimized flag
hwndPrevious = (HWND) lParam; // window handle
© Thomas Kowarsch
Seite 67/101
Systemschnittstellen
Stand: 16.10.03
WM_SETFOCUS
// handle of window losing focus
hwndLoseFocus = (HWND) wParam;
WM_KILLFOCUS
// handle of window receiving focus
hwndGetFocus = (HWND) wParam;
WM_KEYDOWN
WM_KEYUP
nVirtKey = (int) wParam; // virtual-key code
lKeyData = lParam; // key data
WM_CHAR
WM_SYSCHAR
chCharCode = (TCHAR) wParam; // character code
lKeyData = lParam; // key data
WM_HOTKEY
idHotKey = (int) wParam; // identifier of hot key
fuModifiers = (UINT) LOWORD(lParam); // key-modifier
flags
uVirtKey = (UINT) HIWORD(lParam); // virtual-key code
WM_GETHOTKEY
wParam = 0; // not used; must be zero
lParam = 0; // not used; must be zero
WM_SETHOTKEY
// virtual-key code and modifiers of hot key
wParam = (WPARAM) MAKEWORD(vkey, modifiers)
lParam = 0; // not used; must be zero
WM_DEADCHAR
chCharCode = (TCHAR) wParam; // character code
lKeyData = lParam; // key data
WM_SYSDEADCHAR
chCharCode = (TCHAR) wParam; // character code
lKeyData = lParam; // key data
WM_SYSKEYDOWN
WM_SYSKEYUP
nVirtKey = (int) wParam; // virtual-key code
lKeyData = lParam; // key data
Virtual - Tasten - Code
•
Je Taste werden mehr als eine Nachricht generiert.
Wird z.B. der Klein - Buchstabe a auf der Tastatur gedrückt, so wird
die CALLBACK - Funktion mehrfach aufgerufen, d.h. es werden die
folgenden 3 Nachrichten generiert:
•
WM_KEYDOWN ( virtuelle Taste ),
•
WM_CHAR ( wParam enthält ASCII von a ),
•
WM_KEYUP ( virtuelle Taste )
Wird z.B. der Groß - Buchstabe A auf der Tastatur gedrückt, so wird
die CALLBACK - Funktion mehrfach aufgerufen, d.h. es werden die
folgenden 5 Nachrichten generiert:
•
WM_KEYDOWN ( virtuelle Taste VK_SHIFT ),
•
WM_KEYDOWN ( virtuelle Taste a ),
•
WM_CHAR ( wParam enthält ASCII von A ),
•
WM_KEYUP ( virtuelle Taste a ),
•
WM_KEYUP ( virtuelle Taste VK_SHIFT )
Die (V)irtuellen (K)ey - Nachrichten ( VK_... ) können in der
© Thomas Kowarsch
Seite 68/101
Systemschnittstellen
Stand: 16.10.03
CALLBACK WndProc - Funktion etwa wie folgt benutzt werden.
LRESULT CALLBACK WndProc( HWND hWnd, UINT iMsg, WPARAM wParam, LPARAM lParam ) {
switch ( iMsg ) {
...
case WM_KEYDOWN : {
switch ( LOWORD(wParam) ) {
...
case VK_LEFT:
//die Caret-nach-links-Taste ( Pfeilchen-Taste )
//wurde gedrückt, jetzt soll ...
break ;
case VK_F1:
//die F1 - Taste wurde gedrückt, jetzt soll ...
break ;
}
}
...
}
return DefWindowProc( hWnd, iMsg, wParam, lParam ) ;
}
Die RETURN - Tasten können unterschieden werden durch das 24. Bit
von lParam.
switch ( iMsg ) {
case WM_KEYDOWN : {
switch ( LOWORD(wParam) ) {
...
case VK_RETURN:
if ( lParam & 0x01000000L ) { // Enter-Taste ( numeric keypad )
} else {
// Enter-Taste ( standard keypad )
}
break ;
...
}
}
}
Tabelle der Virtual - Tasten - Codes
Bei einer WM_KEYDOWN - Nachricht wird in LOWORD(wParam) der
( standardisierte ) Virtual - Key - Code übergeben.
Die folgende Tabelle enthält die #define`s.
VK_LBUTTON
0x01
VK_RBUTTON
0x02
VK_CANCEL
0x03
VK_MBUTTON
0x04
VK_BACK
0x08
VK_TAB
0x09
VK_CLEAR
0x0C
VK_RETURN
0x0D
VK_SHIFT
0x10
VK_CONTROL
0x11
VK_MENU
0x12
VK_PAUSE
0x13
VK_CAPITAL
0x14
VK_ESCAPE
0x1B
VK_SPACE
0x20
VK_PRIOR
0x21
VK_NEXT
0x22
VK_END
0x23
© Thomas Kowarsch
Seite 69/101
Systemschnittstellen
Stand: 16.10.03
VK_HOME
0x24
VK_LEFT
0x25
VK_UP
0x26
VK_RIGHT
0x27
VK_DOWN
0x28
VK_SELECT
0x29
VK_PRINT
0x2A
VK_EXECUTE
0x2B
VK_SNAPSHOT
0x2C
VK_INSERT
0x2D
VK_DELETE
0x2E
VK_HELP
0x2F
VK_0...VK_9
0x30...
0x39
VK_A...VK_Z
0x41...
0x5A
VK_LWIN
0x5B
VK_RWIN
0x5C
VK_APPS
0x5D
VK_NUMPAD0
0x60
VK_NUMPAD1
0x61
VK_NUMPAD2
0x62
VK_NUMPAD3
0x63
VK_NUMPAD4
0x64
VK_NUMPAD5
0x65
VK_NUMPAD6
0x66
VK_NUMPAD7
0x67
VK_NUMPAD8
0x68
VK_NUMPAD9
0x69
VK_MULTIPLY
0x6A
VK_ADD
0x6B
VK_SEPARATOR
0x6C
VK_SUBTRACT
0x6D
VK_DECIMAL
0x6E
VK_DIVIDE
0x6F
VK_F1
0x70
VK_F2
0x71
VK_F3
0x72
VK_F4
0x73
VK_F5
0x74
VK_F6
0x75
VK_F7
0x76
VK_F8
0x77
VK_F9
0x78
VK_F10
0x79
VK_F11
0x7A
VK_F12
0x7B
VK_F13
0x7C
VK_F14
0x7D
VK_F15
0x7E
VK_F16
0x7F
VK_F17
0x80
VK_F18
0x81
VK_F19
0x82
VK_F20
0x83
VK_F21
0x84
VK_F22
0x85
VK_F23
0x86
VK_F24
0x87
VK_NUMLOCK
0x90
VK_SCROLL
0x91
VK_LSHIFT
0xA0
VK_RSHIFT
0xA1
VK_LCONTROL
0xA2
VK_RCONTROL
0xA3
VK_LMENU
0xA4
VK_RMENU
0xA5
VK_PROCESSKEY
0xE5
WINVER
<=0x04
00
VK_ATTN
0xF6
VK_CRSEL
0xF7
VK_EXSEL
0xF8
VK_EREOF
0xF9
VK_PLAY
0xFA
VK_ZOOM
0xFB
VK_NONAME
0xFC
VK_PA1
0xFD
VK_OEM_CLEAR
0xFE
Z.B. wird durch die Alt - Taste die wParam = VK_MENU Nachricht generiert.
VK_L... bzw. VK_R... gehören zu der linken bzw. rechten Alt - , Ctrl und Shift - Tasten und werden nur als Parameter bei den
GetAsyncKeyState(), GetKeyState() - Funktionen benutzt.
Tasten - Zustand - Flags
© Thomas Kowarsch
Seite 70/101
Systemschnittstellen
Stand: 16.10.03
Der aktuelle Zustand aller Tasten wird in einem Buffer protokolliert.
Auch die Applikation kann diese Einträge lesen/schreiben, wobei
zwischen synchron/asynchron unterschieden wird. Wird eine neue
Tasten - Nachricht in den Applikations - Nachrichten - Warteschlange (
Applikations - Buffer ) eingetragen, so ändert sich der asynchron
Keyboard - Zustand. Der synchron Keyboard - Zustand entspricht dem
momentanen Zustand der Tastatur.
6.5.4.a)Wie kann eine gedrücke SHIFT - Taste abgefragt werden?
if ( GetKeyState ( VK_SHIFT ) & 0x80000000L ) { // SHIFT - Taste gedrückt
}
GetKeyState() ( imGegensatz zu GetAsyncKeyState ) liefert den
Zustand ohne Verzögerung zurück.
Durch GetKeyState ( VK_LBUTTON ) wird z.B. der aktuelle Zustand
der linken Maustaste abgefragt.
6.5.4.b)Wie kann eine Berechnung abgebrochen werden?
Dauert z.B. eine Berechnung zu lange und soll diese Berechnung durch
•
die Escape - Taste oder
•
die linke Maus - Taste
abgebrochen werden, so kann dies mit der ( asynchronen )
GetAsyncKeyState() - Funktion
if ( ( GetAsyncKeyState ( VK_LBUTTON ) < 0 ) // linke Maus - Taste down
|| ( GetAsyncKeyState ( VK_ESCAPE ) < 0 ) // Escape Taste
){
... z.B. ... exit ( -1 ); oder ... SendMessage ( hWnd, WM_CLOSE, 0, 0 )
}
erfolgen.
Um den Zustand von mehreren Tasten zu untersuchen, wie z.B. die
•
Shift - Taste ( VK_SHIFT, VK_LSHIFT, VK_RSHIFT ),
•
Ctrl - Taste ( VK_CONTROL, VK_LCONTROL, VK_RCONTROL ),
•
Alt - Taste ( VK_MENU, VK_LMENU, VK_RMENU )
können alle 256 Virtual Keys in einen Buffer buf kopiert werden. Die
Funktionen GetKeyboardState(), SetKeyboardState(),
GetAsyncKeyState(), GetKeyState(), MapVirtualKey() werden
benutzt. Es kann dann z.B. zwischen linken und rechten SHIFT Tasten unterschieden werden.
Die GetKeyboardState( buf ) - Funktion kopiert alle 256 Virtual Keys
in einen Buffer buf. Eine Taste ist gerade gedrückt, wenn das 7. Bit
gesetzt ist ( sonst 0 ). Der Gedrückt/Losgelassen - Zustand hat
© Thomas Kowarsch
Seite 71/101
Systemschnittstellen
Stand: 16.10.03
gewechselt, wenn das 0. Bit gleich 1 ist ( tggled ). Normalerweise ist
eine Taste nicht gedrückt, dann ist das 0. Bit gleich 1.
6.5.4.c)Wie kann eine gedrückte CTRL - Taste ( VK_CONTROL ) per Programm
simuliert werden?
BYTE buf[256];
GetKeyboardState( buf ); // hole VK_ - Keys
buf[VK_CONTROL] |= 0x80; // setze "gedrückt" bei VK_CONTROL - Taste
SetKeyboardState( buf ); // schreibe VK_ - Keys zurück
6.5.4.d)Wie kann die CAPS - LOCK - Taste ( VK_CAPITAL ) invertiert werden?
BYTE buf[256];
GetKeyboardState( buf );
if ( buf[VK_CAPITAL] & 1 ) buf[VK_CAPITAL] &= 0xFE;
else
buf[VK_CAPITAL] |= 0x01;
SetKeyboardState( buf );
VK_L... bzw. VK_R... gehören zu der linken bzw. rechten Alt - , Ctrl und Shift - Tasten und werden nur als Parameter bei den
GetAsyncKeyState(), GetKeyState() - Funktionen benutzt.
6.5.4.e)Wie kann ein "floating - pop - up - menu" nach der Anzeige sichtbar bleiben?
case WM_RBUTTONDOWN:
BYTE buf[256];
GetKeyboardState( buf ); // hole VK_ - Keys
buf[VK_RBUTTON] = 0x00; // setze "losgelassen" bei VK_RBUTTON - Maus - Taste
SetKeyboardState( buf ); // schreibe VK_ - Keys zurück
... create - pop - up - Menu ...
... call TrackPopUp
...
break;
lParam - Tastenflags
TranslateMessage() benutzt die Funktion ToAsciiEx() um den virtuellen
Key - Code ( z.B. für die WM_KEYDOWN - Nachricht ) zu erzeugen.
Eine Nachricht enthält in LOWORD( lParam ) die Anzahl von
automatischen Tasten - Wiederholungen. Durch diesen Anschlag Wiederholungs - Zähler werden Überflutungen von Nachrichten
vermieden.
In HIWORD( lParam ) sind interessante Tasten - Flags, die im
folgenden erklärt werden. Eine Nachricht enthält in HIWORD( lParam )
interessante Tasten - Flags, die im folgenden erklärt werden.
Bit
HIWORD( lParam ) - Bits
15
1 if the key is up;
0 if the key is down.
© Thomas Kowarsch
Seite 72/101
Systemschnittstellen
14
1 if the key was previously up;
0 if the key was previously down.
13
1 if the ALT key is down.
12
1 if Windows displays a menu.
11
1 if Windows displays a dialog box.
10
Not used.
9
Not used.
8
1 if the key is extended;
0 if it is not.
7
generally 0.
6..0
hardware-scan code
(used mainly in the translation of
ALT+number-pad character code input).
Stand: 16.10.03
6.5.5.Maus - Nachrichten
Die Maus - Nachrichten werden in der Haupt - Nachrichten - Schleife
aus dem Applikations - Buffer geholt ( GetMessage ) und die
CALLBACK - Funktion des Fensters wird mit der Maus - Nachricht (
iMsg, wParam, lParam ) aufgerufen, d.h.
•
die Maus - Nachrichten werden an das Fenster geschickt.
Vor dem Aufruf der Fensters - CALLBACK - Funktion werden durch
das Windows - System die Parameter der Nachricht auf den Stack
gelegt, d.h. die Nachricht wird über den Aufrufer - Stack an die
CALLBACK - Funktion übergeben. An hWnd ist das Fenster ( genauer:
der Speicher für die Fensterdaten ) erreichbar. In iMsg ist die Maus Nachricht eindeutig identifizierbar. Typische iMsg sind:
WM_LBUTTONDOWN, WM_RBOTTOMDOWN, WM_MOUSEMOVE,
WM_NCLBUTTONDBLCLICK.
Die Behandlung von Maus - Ereignisses geschieht vielfach in der
CALLBACK - Funktion. In lParam wird die aktuelle Maus - Position an
die CALLBACK - Funktion übergeben.
© Thomas Kowarsch
Seite 73/101
Systemschnittstellen
Stand: 16.10.03
LRESULT CALLBACK WndProc( HWND hWnd, UINT iMsg, WPARAM wParam, LPARAM lParam ) {
switch ( iMsg ) {
...
case WM_LBUTTONDOWN :
x = LOWORD(lparam); // 16 BIT
y = HIWORD(lparam) // pt = MAKEPOINT(lparam); // 32 BIT, pt vom Typ Point
break;
...
}
return DefWindowProc( hWnd, iMsg, wParam, lParam ) ;
}
Für einen Doppel - Klick muß nach WM_LBUTTONDOWN ein Zähler
gestartet werden. Deshalb ist für einen Doppelklick ein Eintrag
WNDCLASSEX wndclass={ 0 };
wndclass.cbSize=sizeof(WNDCLASSEX);
...
wndclass.style = ... | CS_DBLCLKS; // Zeitgeber ½ sec.
RegisterClass( & wndclass );
erforderlich.
WM - Maus - Nachrichten
Ein Fenster besteht aus dem Fenster - Inneren ( Client - Bereich )
und dem Nicht Client - Bereich ( NC ). Auch der Fenster - Rand gehört
zu NC.
Maus-Nachricht
wParam,
lParam
enthalten ...
weitere
Spezifizierun
g ...
WM_CAPTUR
ECHANGED
hwndNewCap
ture =
(HWND)
lParam; //
handle of
window to
gain mouse
capture
© Thomas Kowarsch
Seite 74/101
Systemschnittstellen
WM_MOUSE
MOVE
WM_LBUTTO
NDOWN
WM_LBUTTO
NUP
WM_RBUTTO
NDOWN
WM_RBUTTO
NUP
WM_MBUTTO
NDOWN
WM_MBUTTO
NUP
WM_LBUTTO
NDBLCLK
WM_MBUTTO
NDBLCLK
WM_RBUTTO
NDBLCLK
WM_MOUSEA
CTIVATE
Stand: 16.10.03
fwKeys =
wParam; //
key flags
xPos =
LOWORD
(lParam); //
horizontal
position of
cursor
yPos =
HIWORD
(lParam); //
vertical
position of
cursor
hwndTopLev
el = (HWND)
wParam; //
handle of
top-level
parent
nHittest =
(INT)
LOWORD
(lParam); //
hit-test value
uMsg =
(UINT)
HIWORD
(lParam); //
mouse
message
© Thomas Kowarsch
fwKeys:
MK_CONTROL Set if the CTRL key is down.
MK_LBUTTON Set if the left mouse button is down.
MK_MBUTTON Set if the middle mouse button is
down.
MK_RBUTTON Set if the right mouse button is
down.
MK_SHIFT Set if the SHIFT key is down.
nHittest is the return value of DefWindowProc:
MA_ACTIVATE Activates the window, and does not
discard the mouse message.
MA_ACTIVATEANDEAT Activates the window, and
discards the mouse message.
MA_NOACTIVATE Does not activate the window,
and does not discard the mouse message.
MA_NOACTIVATEANDEAT Does not activate the
window, but discards the mouse message
Seite 75/101
Systemschnittstellen
WM_MOUSE
WHEEL
© Thomas Kowarsch
Stand: 16.10.03
fwKeys =
LOWORD
(wParam); //
key flags
zDelta =
(short)
HIWORD
(wParam); //
wheel
rotation
xPos =
(short)
LOWORD
(lParam); //
horizontal
position of
pointer
yPos =
(short)
HIWORD
(lParam); //
vertical
position of
pointer
fwKeys:
MK_CONTROL Set if the CTRL key is down.
MK_LBUTTON Set if the left mouse button is down.
MK_MBUTTON Set if the middle mouse button is
down.
MK_RBUTTON Set if the right mouse button is
down.
MK_SHIFT Set if the SHIFT key is down.
Seite 76/101
Systemschnittstellen
WM_NCHITT
EST
© Thomas Kowarsch
Stand: 16.10.03
xPos =
LOWORD
(lParam); //
horizontal
screen
position of
cursor
yPos =
HIWORD
(lParam); //
vertical
screen
position of
cursor
Value Location of hot spot is the return value of
DefWindowProc:
HTBORDER In the border of a window that does not
have a sizing border
HTBOTTOM In the lower horizontal border of a
window
HTBOTTOMLEFT In the lower-left corner of a
window border
HTBOTTOMRIGHT In the lower-right corner of a
window border
HTCAPTION In a title bar
HTCLIENT In a client area
HTCLOSE In a close button HTERROR On the
screen background or on a dividing line between
windows
(same as HTNOWHERE, except that the
DefWindowProc
function produces a system beep to indicate an
error)
HTGROWBOX In a size box (same as HTSIZE)
HTHELP In a Help button
HTHSCROLL In a horizontal scroll bar
HTLEFT In the left border of a window
HTMENU In a menu
HTMAXBUTTON In Maximize button
HTMINBUTTON In Minimize button
HTNOWHERE On the screen background or on a
dividing line between windows
HTREDUCE In a Minimize button
HTRIGHT In the right border of a window
HTSIZE In a size box (same as HTGROWBOX)
HTSYSMENU In a System menu or in a Close
button in a child window
HTTOP In the upper horizontal border of a window
HTTOPLEFT In the upper-left corner of a window
border
HTTOPRIGHT In the upper right corner of a window
border
HTTRANSPARENT In a window currently covered by
another window
HTVSCROLL In the vertical scroll bar
HTZOOM In a Maximize button
Seite 77/101
Systemschnittstellen
WM_NCLBUT
TONDBLCLK
WM_NCLBUT
TONDBLCLK
WM_NCLBUT
TONDOWN
WM_NCLBUT
TONUP
WM_NCMBU
TTONDBLCLK
WM_NCMBU
TTONDOWN
WM_NCMBU
TTONUP
WM_NCMOU
SEMOVE
WM_NCRBUT
TONDBLCLK
WM_NCRBUT
TONDOWN
WM_NCRBUT
TONUP
Stand: 16.10.03
nHittest =
(INT)
wParam; //
hit-test value
pts =
MAKEPOINTS
(lParam); //
position of
cursor
nHittest see WM_NCHITTEST
Das Maus - Rad ( WM_MOUSEWHEEL ) kann z.B. zur Steuerung von
Scroll - Bars eingesetzt werden
6.5.6.DefWindowProc
Einige Nachrichten werden in der eigenen CALL-Klassen-CALBACKFunktionen behandelt. Alle anderen Nachrichten werden an die
"default - Windows - CALLBACK - Funktion" DefWindowProc()
übergeben.
DefWindowProc() ist wie eine Applikations - CALLBACK - Funktion
aufgebaut. DefWindowProc() behandelt die folgenden Nachrichten:
WM_NCCREATE, WM_NCCALCSIZE, WM_NCHITTEST,
WM_NCPAINT, WM_NCACTIVATE, WM_CANCELMODE,
WM_SETTEXT, WM_GETTEXT, WM_GETTEXTLENGTH,
WM_PAINT, WM_PAINTICON, WM_ERASEBKGND,
WM_ICONERASEBKGND, WM_SYNCPAINT,WM_SYSCOMMAND,
WM_ACTIVATE, WM_SETREDRAW, WM_WINDOWPOSCHANGING,
WM_WINDOWPOSCHANGED,WM_CTLCOLOR, WM_SETCURSOR,
WM_MOUSEACTIVATE, WM_SHOWWINDOW,
WM_NCLBUTTONDOWN, WM_NCLBUTTONUP,
WM_NCLBUTTONDBLCLK, WM_NCMOUSEMOVE,
WM_KEYDOWN, WM_SYSKEYDOWN, WM_KEYUP,
WM_SYSKEYUP, WM_SYSCHAR, WM_CLOSE,
WM_QUERYOPEN, WM_QUERYENDSESSION, WM_ISACTIVEICON,
WM_CHARTOITEM, WM_VKEYTOITEM, WM_DRAWITEM,
WM_GETHOTKEY, WM_SETHOTKEY, WM_QUERYDRAGICON,
WM_QUERYDROPOBJECT, WM_DROPOBJECT,
© Thomas Kowarsch
Seite 78/101
Systemschnittstellen
Stand: 16.10.03
© Thomas Kowarsch
Seite 79/101
Systemschnittstellen
Stand: 16.10.03
6.6.Dialoge
Es gibt zahlreiche Funktionen, die zum Erzeugen und Manipulieren von
modalen/modeless Dialogen und deren Unterfenster ( Controls )
dienen:
CreateDialog CreateDialogIndirect CreateDialogIndirectParam
CreateDialogParam DefDlgProc DialogBox DialogBoxIndirect
DialogBoxIndirectParam DialogBoxParam DialogProc EndDialog
GetDialogBaseUnits GetDlgCtrlID GetDlgItem GetDlgItemInt
GetDlgItemText GetNextDlgGroupItem GetNextDlgTabItem
IsDialogMessage MapDialogRect MessageBox MessageBoxEx
SendDlgItemMessage SetDlgItemInt SetDlgItemText
MessageBoxIndirect
6.6.1.Modale Dialoge
Ein modaler Dialog enthält eine eigene Nachrichten-Schleife. Erscheint
ein ( Applikations-)modale Dialog - Box auf dem Bildschirm so wird in
dieser Nachrichten-Schleife "gewartet", bis der Benutzer reagieren und
den Dialog beendet.
Messagebox
Eine MessageBox() entspricht einem modalen Dialog. Z.B. wird die
Applikation blockiert, bis der Benutzer den "OK" - Button gedrückt hat.
Eine MessageBox() erzeugt die Anzeige - Box für Ausgabe-Text ohne
externe Resourcen. Eine eingebaute ( intern verfügbare ) CALLBACK Funktion behandelt die Nachrichten. Es gibt eine Anzahl von
verwendbaren Icons und Push-Buttons.
int MessageBoxEx(
HWND hWnd,
// handle of owner window
LPCTSTR lpText, // address of text in message box
LPCTSTR lpCaption, // address of title of message box
UINT uType,
// style of message box
WORD wLanguageId // language identifier
);
MessageBoxEx() hat gegenüber MessageBox() einen zusätlichen
WORD wLanguageId - Parameter. Falls hWnd = NULL verwendet wird,
so gehört die Message - Box zu keinem speziellen Fenster. lpCaption
zeigt auf den auszugebenden Text. Für lpszTitle = NULL ist, wird in der
Titel - Zeile "Error" angezeigt. Im Fehlerfall gibt die MessageBoxEx()
den Wert 0 zurück. Im Erfolgsfall gibt die MessageBoxEx() eine
© Thomas Kowarsch
Seite 80/101
Systemschnittstellen
Stand: 16.10.03
positiven Wert zurück. Der Rückgabe - Wert entspricht dem
gedrückten Button.
IDABORT Abort button was selected.
IDCANCEL Cancel button or ESC key was selected.
IDIGNORE Ignore button was selected.
IDNO
No button was selected.
IDOK
OK button was selected.
IDRETRY Retry button was selected.
IDYES
Yes button was selected.
Für uType kann verwendet werden:
MB_ABORTRETRYIGNORE three push buttons: Abort, Retry, and
Ignore.
MB_OK
one push button: OK. This is the default.
MB_OKCANCEL
two push buttons: OK and Cancel.
MB_RETRYCANCEL
two push buttons: Retry and Cancel.
MB_YESNO
two push buttons: Yes and No.
MB_YESNOCANCEL
three push buttons: Yes, No, and Cancel.
-------------------------------------------------------------MB_ICONEXCLAMATION, MB_ICONWARNING
icon ( exclamationpoint )
MB_ICONINFORMATION, MB_ICONASTERISK icon ( i in a circle )
MB_ICONQUESTION
icon ( question-mark )
MB_ICONSTOP, MB_ICONERROR, MB_ICONHAND icon ( stop -sign )
-------------------------------------------------------------MB_DEFBUTTON1
MB_DEFBUTTON2
MB_DEFBUTTON3
MB_DEFBUTTON4
The
The
The
The
first button is the default button.
second button is the default button.
third button is the default button.
fourth button is the default button.
-------------------------------------------------------------more:
MB_APPLMODAL, MB_SYSTEMMODAL, MB_TASKMODAL,
MB_DEFAULT_DESKTOP_ONLY, MB_HELP, MB_RIGHT,
MB_RTLREADING, MB_SETFOREGROUND, MB_TOPMOST,
MB_SERVICE_NOTIFICATION, MB_SERVICE_NOTIFICATION_NT3X
© Thomas Kowarsch
Seite 81/101
Systemschnittstellen
Stand: 16.10.03
Beispiele:
MessageBox( 0,"Client-Bereich",0, MB_OK );
MessageBox(hwnd,"MB_ICONINFORMATION","Titel",
MB_OK|MB_ICONINFORMATION);
Der einfache Aufruf einer MessageBox()-Funktion begrenzt die
optische Ausgestaltung, die Anzeigeposition und - Form, die
enthaltenen Buttons ( Controls ), usw, auf das notwendigste. Eine
erweiternde Gestaltung ist nicht möglich. Eine MessageBox() gehört zu
den modalen Dialogen ( Benutzer muß reagieren ). Eine ( allgemeine )
Dialog - Box kann mit der DialogBox()-Funktion aufgerufen werden.
Die DialogBox()-Funktion braucht eine Dialog-CALLBACK-Funktion und
ein Ressourcen-Script ( flexible optische Gestaltung ). Die DialogBox()
kann Controls enthalten, die Informationen angezeigen und
Benutzereingaben erlauben ( Texteingaben, Auswahlaktionen, usw. ).
Diese Unter - Fenster ( Child - Windows == Controls ) einer DialogBox
() werden Controls genannt. Die "DialogBox() - Funktion" ist ein
Macro, das gemäß
#define DialogBoxA(
lpDialogFunc) \
hInstance, lpTemplate, hWndParent,
DialogBoxParamA( hInstance, lpTemplate, hWndParent, lpDialogFunc,
0L)
definiert ist. Die Funktion
WINUSERAPI int WINAPI DialogBoxParamA(
HINSTANCE hInstance, // handle to application instance
LPCTSTR lpTemplate, // identifies dialog box template
HWND
hWndParent, // handle to owner window
DLGPROC lpDialogFunc // pointer to dialog box procedure
LPARAM dwInitParam //wird bei WM_INITDIALOG in lParam an
CALLBACK weitergereicht
);
© Thomas Kowarsch
Seite 82/101
Systemschnittstellen
Stand: 16.10.03
hInstance kann durch GetModuleHandle( NULL) oder unter
WM_CREATE durch
static HINSTANCE hInstance = ( LPCREATESTRUCT ) lParam->
hInstance
ermittelt werden.
6.6.1.a)Beispiel: DialogBox als Hauptprogramm
Existiert eine IDD_DIALOG-Dialog-Ressource und die dlg-CALLBACKFunktion dlgProc), so kann das Hauptprogramm etwa wie folgt
aussehen:
//Hauptprogramm
int APIENTRY WinMain( HINSTANCE hInstance,HINSTANCE
hiPrev,PSTR pCmdMain,int iShowMain)
{
return DialogBox(hInstance, MAKEINTRESOURCE(IDD_DIALOG),
NULL, (DLGPROC)dlgProc);
}
Die DialogBox() - Funktion verwendet intern die CreateWindowEx() Funktion.
Es wird i.a. eine interne vorhandene ( Dialog - ) Klassen Registrierung benutzt ( DefDlgProg, default dialog class ).
Für die DialogBox() wird eine eigener, zusätzlicher Nachrichten Buffer und eine eigene Nachrichten - Loop - Behandlung eingerichtet.
Bevor die Dialog - Box sichtbar wird, sendet DialogBox() die
WM_INITDIALOG - Nachricht an die lpDialogFunc - Funktion. In der
CALLBACK - Funktion wird WM_INITDIALOG im Normalfall mit return
FALSE beendet.
Falls die Dialog - Box den DS_SETFONT - Style hat, so wird die
WM_SETFONT - Nachricht an die lpDialogFunc - Funktion gesendet.
Wenn der WS_VISIBLE - Style spezifiziert wurde, so erscheint die
Dialog - Box.
Durch EndDialog ( hWnd, wParam ) wird der Dialog beendet, der
allokierte Speicher wird freigegeben. DialogBox() gibt wParam zurück.
Eine private Dialog - Klasse muß WNDCLASS - Struktur besetzten
( cbWndExtra = DLGWINDOWEXTRA ) und RegisterClass() aufrufen.
Das Dialog - Template muß dann das CLASS - Statement enthalten.
© Thomas Kowarsch
Seite 83/101
Systemschnittstellen
Stand: 16.10.03
Gegenüber einer MessageBox() ist der Programmier - Aufwand bei
Verwendung von DialogBox() größer.
int DialogBox(
HINSTANCE hInstance, // handle to application instance
LPCTSTR lpTemplate, // identifies dialog box template
HWND
hWndParent, // handle to owner window
DLGPROC lpDialogFunc // pointer to dialog box procedure
);
DialogBox() erzeugt mit
lpTemplate = MAKEINTRESOURCE( idRes )
aus der *.RC - Template Resource idRes die DialogBox, indem
automatisch die Resourcen - Daten in den Speicher geladen werden
und die DialogBox angezeigt wird. Durch eine System - Klassen CALLBACK - Funktion werden bestimmte Ereignisse ( Tab, ... ) ( vor - )
behandelt. Ein typischer Aufruf hat die Form:
int rval = DialogBox ( hInstance, MAKEINTRESOURCE( idRes ), hWnd,
( DLGPROC )dlgProc ) ;
Zur Behandlung der Ereignisse muß eine DIALOG - CALLBACK Funktion geschrieben werden. Diese Funktion wird mit DLGPROC
lpDialogFunc an DialogBox() übergeben. Der modale Dialog wird erst
beendet, wenn in der eigenen CALLBACK - Funktion EndDialog()
ausgeführt wird. Der Dialog wird meisten unter WM_CLOSE durch
EndDialog ( hWnd, rval ) beendet. Der Rückgabe - Wert von int
DialogBox() ist hier rval. Bei einem Fehler wird -1 zurück gegeben.
© Thomas Kowarsch
Seite 84/101
Systemschnittstellen
Stand: 16.10.03
Steht im *.RC - FIle unter IDD_DIALOG_ABOUT die Resourcen Beschreibung der Dialog - Box, so wird z.B. in der Fenster - CALLBACK
- Funktion WndProc() ( unter dem Menu - Punkt ID_MAIN_MENU_1 )
diese modale Dialog - Box erscheinen, wenn
LRESULT CALLBACK WndProc( HWND hWnd, UINT iMsg,WPARAM
wParam,LPARAM lParam)
{
switch ( iMsg ) {
case WM_CREATE : ... break ;//return 0;
case WM_PAINT : ... break ; //return 0;
case WM_DESTROY : PostQuitMessage( 0 ) ; break ;
//return 0;
case WM_COMMAND:
int wmId
= LOWORD( wParam );
int wmEvent = HIWORD( wParam );
switch ( wmId ) {
case ID_MAIN_MENU_1: //Aufruf der Dialog – Box
Dialog_Box( hWnd, IDD_DIALOG_ABOUT,myDlgBox ) ;
break ;
}
}
return DefWindowProc( hWnd, iMsg, wParam, lParam ) ;
}
eingetragen wird. Die Dialog - CALLBACK - Funktion myDlgBox ( muß
BOLL zurück geben ) ist zu schreiben. In myDlgBox ( muß BOLL
zurück geben ) sind die Buttons, Texteingaben, Radiobuttons, usw. zu
behandeln.
BOOL myDlgBox( HWND hWnd , UINT iMsg, WPARAM wParam, LPARAM
lParam ) {
switch ( iMsg ) {
case WM_INITDIALOG :
break;
case WM_COMMAND:
switch ( LOWORD( wParam ) ) {
case IDOK :
case IDCANCEL :
SendMessage( hWnd , WM_CLOSE, LOWORD( wParam ), 0 );
return TRUE;
}
case WM_CLOSE : EndDialog ( hWnd, wParam );
//beendet den modalen Dialog
break; //return TRUE;
}
return FALSE;
}
© Thomas Kowarsch
Seite 85/101
Systemschnittstellen
Stand: 16.10.03
Beim Initialisieren des Dialoges ( vor dem Sichtbarwerden ) wird die
WM_INITDIALOG - Nachricht gesendet ( sonst WM_CREATE ). Diese
Nachricht kommt, bevor das Fenster erscheint. Unter WM_INITDIALOG
können Anpassungen von Controls vorgenommen werden. Soll z.B. der
Dialog ( bezüglich des Fensters hWnd ) mittig zentriert erscheinen, so
kann unter WM_INITDIALOG die Position ermittelt und gesetzt werden.
6.6.1.b)About-Dialog
Die Resourcen werden mit Hilfe eines Identifizierers angesprochen. Für
das gesamte About - Template wird Die Konstante IDOK ist verfügbar
und wird für den OK-Button verwendet. Das Icon ist bereits unter
IDI_MAIN_ICON vorhanden und kann in das About - Template
eingefügt werden. Das MENUITEM "&About", ID_MENUITEM_ABOUT
wird für den Aufruf des About - Dialoges verwendet. Die Konstante
IDC_STATIC entspricht der Zahl -1.
6.6.1.c)Aufruf des About-Dialogs:
Der *.CPP - File enthält die Dialog - CALLBACK - Funktion
dlgAboutProc und die Fenster - CALLBACK - Funktion WndProc, in der
der Dialog durch
Dialog_Box( hWnd, IDD_DIALOG_ABOUT, dlgAboutProc ) ;
aufgerufen wird.
BOOL CALLBACK dlgAboutProc( HWND hWnd, UINT iMsg,WPARAM
wParam,LPARAM lParam)
{
switch ( iMsg ) {
case WM_INITDIALOG: ...
break;
case WM_COMMAND:
switch ( LOWORD(wParam) ) {
case IDOK:
case IDCANCEL:
SendMessage( hWnd, WM_CLOSE, LOWORD(wParam), 0);
return TRUE;
} break;
case WM_CLOSE: EndDialog ( hWnd, wParam );
DestroyWindow( hWnd );
break;
}
return FALSE;
}
© Thomas Kowarsch
Seite 86/101
Systemschnittstellen
Stand: 16.10.03
LRESULT CALLBACK WndProc( HWND hWnd, UINT iMsg,WPARAM
wParam,LPARAM lParam)
{
switch ( iMsg ) {
case WM_CREATE: ... break ;//return 0;
case WM_PAINT: ... break ; //return 0;
...
case WM_COMMAND:
switch ( LOWORD( wParam ) ) {
case ID_MENUITEM_ABOUT: //Aufruf der About – Box
Dialog_Box( hWnd, IDD_DIALOG_ABOUT,
dlgAboutProc ) ;
break ;
}
case WM_DESTROY: PostQuitMessage(0); break; //return 0;
...
}
return DefWindowProc( hWnd,iMsg,wParam,lParam ) ;
}
6.6.2.Modless Dialoge
Mit der Funktion IsDialogMessage() können Nachrichten der
Nachrichten-Schleife an das hDlgModeless-Fenster verteilt werden. Die
Modless - Dialog - Nachrichten müssen durch Erweiterung der Haupt Nachrichten - Schleife "verschickt" werden. Es können mehrere
Modeless - Dialoge gleichzeitig geöffnet sein. Für die Erweiterung der
Haupt - Nachrichten - Schleife kann eine globale Variable HWND
hDlgModeless verwendet werden. Ist das globale Handle hDlgModeless
!= NULL, so ist kein Modless - Fenster "offen". Wird ein Modless Fenster aktiviert ( WM_ACTIVATE ), so wird das globale Handle
hDlgModeless mit dem Handle des aktiven Fensters überschrieben.
Weil nur ein Fenster aktiv ist und den Focus hat, können beliebig viele
Modless - Fenster "gleichzeitig offen" sein.
für Modeless: Haupnachrichten-Schleife
while ( GetMessage( & msg, NULL, 0, 0 ) ) {
if ( NULL == hDlgModeless || ! IsDialogMessage
( hDlgModeless, & msg ) ) {
TranslateMessage( & msg );
DispatchMessage ( & msg );
}
}
© Thomas Kowarsch
Seite 87/101
Systemschnittstellen
Stand: 16.10.03
6.6.2.a)CreateDialog() - Aufruf
LRESULT CALLBACK WndProc( HWND hWnd, UINT iMsg,WPARAM
wParam,LPARAM lParam)
{
switch ( iMsg ) {
...
case WM_COMMAND:
switch ( LOWORD( wParam ) ) {
case ID_MENUITEM_MODELESS: //Aufruf der About – Box
Create_Dialog( hWnd, IDD_DIALOG_MODELESS,
dlgModelessProc ) ;
break ;
}
}
...
return DefWindowProc( hWnd, iMsg, wParam, lParam ) ;
}
Die Funktion Create_Dialog( hWnd, IDD_DIALOG_MODELESS,
dlgModelessProc ) benötigt die Resource IDD_DIALOG_MODELESS und
die CALLBACK - Funktion dlgModelessProc().
6.6.3.Controls
Ein Dialog enthält untergeordnete Fenster ( Controls ).
Zu einem Control gehört i.a. eine eingebauten Klasse.
Die Klasse enthält eine eingebaute CALLBACK - Funktion, die die
Ereignisse behandelt.
Zu einer ein/mehr - zeiligen Texteingabe gehört die Klasse "Edit". Zu
einem Button gehört die Klasse "Button". Mit der Kenntnis dieser
Control - Ereignisse können die Controls genutzt werden.
Als Beispiel werden die Combo - Box - Ereignisse angefügt. Die Combo
- Box ( Edit - Zeile mit List - Box ) kann die folgenden Nachrichten
senden/empfangen/behandeln:
Combo Box Messages
CB_ADDSTRING
CB_DELETESTRING
CB_DIR
CB_FINDSTRING
CB_FINDSTRINGEXACT
CB_GETCOUNT
CB_GETCURSEL
CB_GETDROPPEDCONTROLRECT
CB_GETDROPPEDSTATE CB_GETDROPPEDWIDTH
CB_GETEDITSEL
CB_GETEXTENDEDUI CB_GETHORIZONTALEXTENT CB_GETITEMDATA
© Thomas Kowarsch
Seite 88/101
Systemschnittstellen
Stand: 16.10.03
CB_GETITEMHEIGHT CB_GETLBTEXT
CB_GETLBTEXTLEN
CB_GETLOCALE CB_GETTOPINDEX
CB_INITSTORAGE
CB_INSERTSTRING CB_LIMITTEXT
CB_RESETCONTENT
CB_SELECTSTRING CB_SETCURSEL
CB_SETDROPPEDWIDTH
CB_SETEDITSEL CB_SETEXTENDEDUI
CB_SETHORIZONTALEXTENT CB_SETITEMDATA
CB_SETITEMHEIGHT
CB_SETLOCALE
CB_SETTOPINDEX
CB_SHOWDROPDOWN
CBN_CLOSEUP
CBN_DBLCLK
CBN_DROPDOWN
CBN_EDITCHANGE
CBN_EDITUPDATE
CBN_ERRSPACE
CBN_KILLFOCUS
CBN_SELCHANGE
CBN_SELENDCANCEL
CBN_SELENDOK
CBN_SETFOCUS
WM_COMPAREITEM
WM_DRAWITEM
WM_MEASUREITEM
Um einem Control eine Nachricht zu schicken wird anstelle von
HWND hCtl = GetDlgItem ( HWND hDlg, int idRes );
LONG SendMessage ( HWND hCtl, UINT iMsg, WPARAM wParam,
LPARAM lParam);
oft
LONG SendDlgItemMessage ( HWND hDlg, int idRes, UINT iMsg,
WPARAM wParam, LPARAM lParam);
benutzt.
© Thomas Kowarsch
Seite 89/101
Systemschnittstellen
Stand: 16.10.03
7.Dynamic-Link Library's
Das Windows - Betriebssystem besteht aus Dynamic-Link Libraries (
DLL's ). DLL's sind z.B. kernel32.dll, user32.dll, gdi32.dll, ). Mit
pview.exe können die geladenen DLLs angezeigt werden. Der
Compiler übersetzt jeden *.asm-, *.c-, *.cpp-FIle in einen *.obj-File.
Eine Static-Link-Library ( herkömmliche *.lib-Bibliothek ) entspricht
einer solchen der Code-, Daten-Sammlung ( z.B. libc.libObjektbibliothek, normale C-Laufzeitbibliothek ). Beim
Erstellungsvorgang ( "statisches Binden" ) wird in jede Applikation der
LIB-Code und die LIB-Daten kopiert. Dadurch entsteht ein einheitlicher
Adressraum. Weil viele Applikationen den gleichen Bibliotheks-Code
enthalten verschwendet dieses statische Verfahren Speicherplatz.
Applikation1
DLL
Applikation2
Code der App
@dllFunc
Code der App
call dllFunc()
...
call strlen()
Code der Dll
dllFunc-Code
call strlen()
call dllFunc()
...
call strlen()
Static-Libary
-Code strlen()
Static-Libary
-Code strlen()
Static-Libary
-Code strlen()
Resourcen
Resourcen
Resourcen
Daten
Daten
Daten
Stack
Stack
Applikation1
DLL
Applikation2
Code der App
@dllFunc
Code der App
call dllFunc()
...
call strlen()
Code der Dll
dllFunc-Code
call strlen()
call dllFunc()
...
call strlen()
Static-Libary
-Code strlen()
Static-Libary
-Code strlen()
Static-Libary
-Code strlen()
Resourcen
Resourcen
Resourcen
Daten
Daten
Daten
Stack
Stack
Applikation1 und Applikation2 nutzen die DLL
© Thomas Kowarsch
Seite 90/101
Systemschnittstellen
Stand: 16.10.03
7.0.1.Wie löst der Linker die DLL_Einsprünge auf?
CQuelltext
func1();
ASMQuelltext
call func1
ASM-Quelltext
ohne __declspec
(dllimport)
call 0x4000000;
0x4000000 ist die
Adresse von func1
ASM-Quelltext
mit __declspec(dllimport)
0x40000000: jmp DWORD PTR
__imp_func1
__imp_func1 ist die Adresse
der .exe-Importadreßtabelle
Eine Dynamic-Link Library ( DLL ) entspricht ( grob ) einem
ausführbaren File ( ausführbarer Code, allgemeine Daten, Resourcen )
der zur Laufzeit in den Arbeitsspeicher geladen und von mehreren
Applikationen genutzt wird. Eine DLL kann eine beliebige File-Endung (
z.B. *.fon ) haben. Dann muss die DLL explizit mit LoadLibrary() in
den Arbeitsspeicher geladen werden ( Explicit dynamic linking ).
System-DLLs sind z.B. user.exe, gdi.exe, krnl286.exe, krnl386.exe,
mouse.drv, keyboard.drv.
//Beispiel für explizites Laden der DLL:
typedef int ( * LPFUNC1) ( int );
typedef double ( * LPFUNC2) ( int, double );
LPFUNC1 lpFunc1a, lpFunc1b; LPFUNC2 lpFunc2;
HINSTANCE hLib = GetModuleHandle("myDll.dll");
if ( hLib == NULL ) hLib = LoadLibrary("myDll.dll"); // Load the DLL now
if ( hLib == NULL ) error ...
lpFunc1a = (LPFUNC1) GetProcAddress( hLib, "myFunc" );
if ( lpFunc1a != NULL) int i1a = ((lpFunc1a)(4711));
else error ...
lpFunc1b = (LPFUNC1) GetProcAddress( hLib, MAKEINTRESOURCE(1) );
if (lpFunc1b != NULL) int i1b = ((lpFunc1b)(4711));
else error ...
lpFunc2 = (LPFUNC2) GetProcAddress( hLib, MAKEINTRESOURCE(2) );
if (lpFunc2 != NULL) double x = ((lpFunc2)( 1.23, 47.11 ));
else error ...
FreeLibrary(hLib); // Unload DLL from memory
Mit der DLL-Schnellansicht kann die Ordinal Number der exportierten
Funktion ( 4 Byte-Index aus der DLL-Einsprung-Tabelle ) erhalten
werden. @2 wird als MAKEINTRESOURCE(2) verwendet. Falls
gewünscht kann beim Erstellen der DLL die Ordinal Number der
Funktion im *.def-File explizit festgelegt werden. Sind die FunktionsParameter bekannt, so wird ( im obigen Beispiel ) keine dynamische
*.lib benötigt.
Hat die DLL die File-Endung *.dll, so kann diese DLL bei ProgrammAusführung automatisch in den Arbeitsspeicher geladen werden
( Implicit dynamic linking ). Beim Programmstart wird die DLL
© Thomas Kowarsch
Seite 91/101
Systemschnittstellen
•
im aktuellen Verzeichnis,
•
im Systemverzeichnis
•
im Windows eigenem Verzeichnis und
•
im Pfad der Umgebungsvariable
Stand: 16.10.03
gesucht und ( falls gefunden ) geladen. Wird die benötigte DLL nicht
gefunden, so wird eine Fehlermeldung ausgegeben.
Eine Multithreaded DLL Version benötigt die C run-time library ( libcmt
[D].lib ) oder die C run-time library( msvcrt[D].lib ). [D] steht für die
Debug Version.
Linker-Schalter:
/MT
/MD
/ML
Multithread-aware library (default for DLLs)
MSVCRT40.DLL, dynamic-link library that is multithread aware
Single-thread-aware library (default for applications)
Verwendet wird z.B.
void
_endthread( void );
unsigned long _beginthread( void( __cdecl *start_address )( void * ),
unsigned stack_size, void *arglist );
//Multithreaded DLL-Beispiel:
HINSTANCE hLib = LoadLibrary("myDll.dll"); // Load the DLL now
if ( hLib == NULL ) error ...
...
_beginthread( firstThread, 0, NULL); // Start a thread
Sleep(10000L);
cout << "Exit Main Process" << endl;
FreeLibrary(hLibrary);
void firstThread(void* dummy) {
HINSTANCE hLibrary = LoadLibrary("myDll.dll");
...
FreeLibrary(hLibrary);
}
Erstellen einer DLL
Beim Erstellungsvorgang der DLL wird ein Header-File ( z.B. myDll.h )
und der DLL-Quellcode ( z.B. myDll.c ) benutzt. Daraus wird
myDll.dll und die ( Adressen- ) Import-Bibliothek myDll.lib
erzeugt. Der Erstellungsvorgang der Applikation ( z.B. myApp.c )
benutzt der Compiler für die Prüfung der Funktionsprototypen ( z.B.
myDll.h ). Der Linker holt aus myDll.lib die "dynamischen DLLEinsprungpunkte" und erstellt ( z.B. myExe.exe ). Wird myExe.exe
ausgeführt, so wird die myDll.dll aktuellen Verzeichnis,
Systemverzeichnis und ggf. im Pfad gesucht und geladen. Zur Laufzeit
benutzt myExe.exe die dynamisch gebundenen Funktionen
ausmyDll.dll. Im Header-File wird verwendet:
•
Win32: __declspec(dllimport), __declspec(dllexport)
•
Win16: __export
© Thomas Kowarsch
Seite 92/101
Systemschnittstellen
Stand: 16.10.03
Tritt beim Linken ein Fehler auf, wie etwa
*.obj:error LNK2001: unresolved external symbol
"?myFunc@@YAXPAD@Z (void __cdecl myFunc(char *))"
so ist es vielfach günstig, die DLL-Erstellung mit "reinem C"
durchzuführen. Dann wird die folgende Klammerung verwendet:
#ifdef __cplusplus //in windows.h enthalten
#define EXTERN_C extern "C"
#else
#define EXTERN_C extern
#endif
oder z.B.
#if defined(__cplusplus)
#define C_BEGIN extern "C" { ////////////////////////////////
#define C_END
} ////////////////////////////////
#else
#define C_BEGIN /////////////////////////////////////////////
#define C_END
/////////////////////////////////////////////
#endif //////////////////////////////////////////////////////////
In window.h ist WINAPI, PASCAL, CALLBACK als __stdcall definiert. Die
alten Win16-Bezeichner wie z.B. PASCAL, __far __pascal sollten in
Win32 durch WINAPI ersetzt werden. Win32-API-Funktionen benutzen
die "__stdcall calling convention". Dadurch erfolg automatisch ein
__cdecl-Aufruf mit Stackbereinigung bei variablen Argumentlisten.
Für __cdecl und __stdcall werden die Funktions-Argumente von rechts
nach links auf den Applikations-Stack gelegt.
Die folgende DLL wird mit myDll.h erstellt. Die DLL soll die Funktion
__declspec( dllexport ) int myDllFunc( int i )
exportieren.
Die Variable
extern __declspec( dllexport ) int myDllInt
wird in myDll.cpp definiert. Jede Applikation bekommt dann eine
eigene int myDllInt.
© Thomas Kowarsch
Seite 93/101
Systemschnittstellen
Stand: 16.10.03
#ifndef MYDLL_H
#define MYDLL_H
#include <windows.h>
#ifdef _DLL
#define DLL_EXPORT __declspec( dllexport )
#else
#define DLL_EXPORT __declspec( dllimport )
#endif
myDll.
h
extern DLL_EXPORT int myDllInt;
DLL_EXPORT int myDllFunc( int i );
class DLL_EXPORT myDllClass { //exportiere Klasse
public:
myDllClass(void); //Konstruktor
};
///////////////////
#endif //MYDLL_H
///////////////////
© Thomas Kowarsch
Seite 94/101
Systemschnittstellen
Stand: 16.10.03
Quelltext für die DLL:
//#define _DLL
#include "myDll.h"
myDll.
c
BOOL APIENTRY DllMain( HANDLE hModule,
DWORD ul_reason_for_call, LPVOID lpReserved )
{
switch (ul_reason_for_call) {
case DLL_PROCESS_ATTACH:
// DLL wird in den Adressraum des Prozesses eingeblendet.
// Bei einem Fehler return FALSE
case DLL_THREAD_ATTACH:
// Ein Thread wird erstellt.
// Hier können notwendige Initialisierungen durchgeführt werden
// Serialisieren:
// DisableThreadLibraryCalls( hModule );
// hThread = CreateThread( NULL, 0, SomeFunc, NULL, 0, &dwThreadId );
// WaitForSingleObject( hThread, INFINITE );
// CloseHandle ( hThread );
case DLL_THREAD_DETACH:
// Ein Thread wird ordnungsgemäss verlassen.
// Hier können notwendige Aufräumarbeiten durchgeführt werden
case DLL_PROCESS_DETACH:
// Die DLL wird aus dem Prozess-Adressraum ausgeblendet
// Hier können notwendige Aufräumarbeiten durchgeführt werden
// Auctung!
// TerminateProzess() führt NICHT immer DLL_PROCESS_DETACH aus!
// if ( pHeap != NULL ) HeapFree( GetProcessHeap(), 0, pHeap );
break;
}
return TRUE;
}
DLL_EXPORT int myDllInt=1; //exportierte Variable
DLL_EXPORT int myDllFunc(int i) { //exportierte Funktion.
char buf[256]; int j = i+myDllInt;
wsprintf( buf, "i+myDllInt=%d", j );
MessageBox(0,buf,0,MB_OK);
return j;
}
myDllClass::myDllClass() { //Konstruktor
return;
}
7.0.2.Wie wird diese DLL benutzt?
//myDll.lib in das Applikations-Projekt aufnehmen!
myApp.c
© Thomas Kowarsch
#include "myDll.h"
...
myDllInt++;
int i = myDllFunc( 3 + myDllInt );
...
Seite 95/101
Systemschnittstellen
Stand: 16.10.03
8.Daemon
Als Daemonen werden unter Linux die verschiedenen dienstbaren
Geister bezeichnet. Sie sind in etwa vergleichbar mit den
speicherresidenten Programmen unter DOS (TSR: terminate and stay
resident). Sie warten unauffällig im Hintergrund, ob es etwas für sie zu
tun gibt. Wenn ja, wird das erledigt, dann gehen sie wieder in
Wartestellung. Ein typisches Beispiel ist der lpd, der line printer
daemon. Er wartet, ob ein Druckauftrag gegeben wurde, wenn ja, wird
er von ihm abgearbeitet. Der lpd kann Druckjobs entgegennehmen,
auch wenn der Drucker nicht betriebsbereit oder sogar nicht einmal
angeschlossen ist, die Dateien werden eben solange
zwischengespeichert.
Daemonen können z.B. gleich beim Systemstart aus den Startdateien
heraus gestartet werden, z.B. aus /etc/rc.d/rc.local heraus. Daemonen
im Leerlauf verbrauchen zwar nur wenig Systemleistung, bei einem
gut ausgebauten Server sind aber recht viele Daemonen am Werk, die
dann eben doch eine nennenswerte Grundlast erzeugen.
Daher existiert noch eine weitere Startmöglichkeit über den
Metadaemon inetd. Aufgrund von Konfigurationsdateien, deren
Besprechung gleich folgt, achtet er permanent darauf, ob vom System
die Dienste eines Dämonen benötigt werden. Wenn ja, startet er den
entsprechenden Dämon, der sich nach Abarbeitung des Auftrages dann
wieder beendet. Im Idealfall ist dann nur dieser Metadaemon
permanent am Laufen, alle anderen laufen nur, wenn sie auch gerade
benötigt werden. Der Metadaemon inetd wird bei uns aus der Datei /
etc/rc.d/rc.inet2 heraus gestartet. Wann er welchen Daemon starten
soll, erfährt inetd aus der Konfigurationsdatei /etc/inetd.conf heraus.
Beispielsweise wird der POP-Server (Post Office Protocol, wird bei EMail genauer behandelt) bei Bedarf mit folgender Zeile gestartet:
pop3 stream tcp nowait root /usr/sbin/tcpd /usr/sbin/in.pop3d
Dabei steht ganz am Ende das eigentliche auszuführende Programm,
das aber über den TCP-Wrapper tcpd, der nur berechtige Zugriffe
zuläßt, aufgerufen wird. Der Name pop3 wird in der Datei /etc/services
einer Portnummer zugeordnet, in diesem Fall:
pop3110/tcp
pop3110/udp
© Thomas Kowarsch
Seite 96/101
Systemschnittstellen
Stand: 16.10.03
inetd lauscht nun u.a. am Port 110, ob dort eine Anfrage vorliegt.
Wenn ja, wird der über den Namen pop3 zugeordnete Dämon in.pop3d
gestartet. Dabei kann noch unterschieden werden zwischen TCPAnfragen (Transmission Control Protocol) und UDP-Anfragen
8.1.Schreiben von Daemon
Beim Schreiben von Daemons sind folgende Regeln zu beachten:
1. Aufruf von fork und anschließendes Beenden des Elternprozesses
Als erstes muß fork aufgerufen werde, und dann muss der
Elternprozess sich mit exit beenden. So erreicht man beim Aufruf
des Daemons in einer Shell, dass diese Shelle annimmt, das
Kommando habe such beendet, und sie so den Benutzer mit der
Ausgabe des Promptzeichens weitere Kommandos eingeben läßt.
2. Da der Kindprozess die Prozessgruppen-ID vom Elternprozess erbt,
seinerseits abr eine neue Prozeß-ID erhält, ist sichergestellt, daß der
Kindprozeß nicht ein Prozeßgruppenführer ist, was die
Voraussetzung für den nächsten Schritt (Aufruf von setsid) ist.
Aufrufen von setsid
Mit einem setsid-Aufruf wird eine neue Session kreiert, was folgende
Konsequenzen hat:
- Der Prozeß wird Sessionführer der neuen Session
- Der Prozeß wird Prozessgruppenführer der neuen Prozeßgruppe
- Der Prozeß hat kein Kontrollterminal
3. Wechseln ins Root-Directory oder in ein spezielles Directory
Da das von Elternprozeß geerbte Directory eventuell ein montiertes
Filesystem sein könnte, empfielt es sich, ins Root-Directory zu
wechseln. Der Grund dafür liegt in der Tatsache, daß beim
Hochfahren eines Systems ein Filesystem, auf dem noch ein Prozeß
(in diesem Fall der Daemon) läuft, nicht demontiert werden kann.
Manche Daemonprozesse wechseln in ein spezielles Directory, in
dem sie ihre Aktionen durchführen, wie z.B. der lpd-Daemon, der
meist in Spool-Directory wechselt.
© Thomas Kowarsch
Seite 97/101
Systemschnittstellen
Stand: 16.10.03
4. Setzen der Dateikreierungsmarke auf 0
Der Kindprozeß (Daemon) erbt die Dateikreierungsmarke vin seinem
Elternprozeß. Damit der Daemin für seine kreierten Dateien auch
genau die Zugriffsrechte erhält, die er fordert, ohne daß diese durch
die geerbte Dateikreierungsmarke umgeändert werden, sollt er die
Dateikreierungsmarke löschen (auf 0 setzen)
5. Schließen von nicht mehr benötigten Filedeskriptoren
Der Daemon sollte die vom Elternprozeß geerbten offenen, aber
nicht benötigten Filedeskriptoren schließen. Es hängt natürlich von
den jeweiligen Daemons ab, welche Filedeskriptoren zu schließen
sind. Wenn ein Daemon alle geerbten Filedeskriptoren schließen
möchte, kann er mit sysconfig(_SC_OPEN_MAX) die Nummer des
höchsten Filedeskriptor ermitteln und dann entsprechend alle
Filedescriptoren schließen.
© Thomas Kowarsch
Seite 98/101
Systemschnittstellen
Stand: 16.10.03
8.2.Beispiel
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
int daemonisieren() {
pid_t pid;
if ( (pid = fork()) < 0)
return -1;
else if (pid != 0)
exit (0); /* Elternprozess beendet sich */
/* Ab hier wird nur vom Kindprozess ausgeführt */
setsid();
/* Kind wird Sessionführer */
chdir("/");
/* Ins Root Directory wechseln */
umask(0);
/* Dateikreierungsmaske loeschen */
}
return 0;
int main() {
if (daemonisieren() != 0) {
printf("FEHLER: Daemonisierung nicht moeglich.\n");
return -1;
}
printf("... ich bin jetzt ein Daemon...\n");
sleep(20);
}
printf("... Ich verabschide mich nun als Daemon ...\n");
return 1;
8.3.Fehlermeldungen
Da Daemons kein Kontrollterminal haben, können sie Ihre Meldungen
nicht einfach auf die Standarfehlerausgabe ausgeben. Auch ist es
sicher nicht erwünscht, daß alle Daemons ihre Fehlermeldungen an der
Systemkonsole ausgeben, was sehr störend für den
Systemadministrator wäre.
Ebenso ist es nicht klug, daß jeder Daemin seine Fehlermeldung in
eine eigene Log-Datei schreibt. Die Überprüfung der einzelnen Dateien
durch den Systemadministrator würde dann sehr aufwendig.
© Thomas Kowarsch
Seite 99/101
Systemschnittstellen
Stand: 16.10.03
Was man braucht, ist eine zentrale Einrichtung, die für Meldungen von
Daemons verantwortlich ist.
Hierzu werden wir syslog verwenden.
syslog ist ebenfalls ein Daemon, der die Nachrichten (beschrieben in /
etc/syslog.conf) in die entsprechenden Dateien einträgt. Beschreibung
hierzu siehe man syslog, bzw. man 3 syslog
8.4.Prozessgruppen und Sessions
Jeder Prozesse unter Unix gehört zu einer Prozessgruppe. Jede
Prozessgruppe besteht aus einem oder mehreren Prozessen. Jede
Prozessgruppe kann einen Prozessgruppenführer haben, den man
daran erkennt, dass seine Prozess-ID gleich wie seine ProzessgruppenID ist.
Eine Prozessgruppe hört auf zu existieren,wenn sie keine Mitglieder
mehr hat. Ein Prozess kann die Prozessgruppe wechseln (Details dazu
in bei Herold, [1]).
Eine weitere Gruppierung sind sogenannte Sessions. Zu einer Session
können eine oder mehrere Prozessgruppen gehören. Eine Session
kann genau ein Kontrollterminal besitzen.
Der Prozess, der die Verbindung zum Kontrollterminal eingerichtet hat,
wird Kontrollprozess genannt (und ist Sessionführer).
In einer Session gibt es maximal eine Vordergrund-Prozessgruppe, alle
anderen Prozessgruppen sind Hintergrund-Prozessgruppen. Die
Vordergrund-Prozessgruppe existiert genau dann, wenn die Session
ein Kontrollterminal hat. Nur die Prozesse der VordergrundProzessgruppe können mit dem Kontrollterminal kommunizieren,
deshalb können auch nur diese Prozess mit CTRL-C (Signal SIGINT)
abgebrochen werden.
© Thomas Kowarsch
Seite 100/101
Systemschnittstellen
Stand: 16.10.03
8.5.WebServer
Ein Webserver sollte immer als Deamon (Hintergrund) laufen. Auf
Anfrage vom Webbrowser sendet der WebServer die entsprechend
angeforderten Dateien.
Der Webbrowser stellt eine Anfrage an dem entsprechenden Port
(Standartport ist 80, HTTPS: 443) . Es wird dann eine
Socketverbindung aufgebaut.
(1) Der Browser nimmt eine Verbindung an den Server zu Port 80 auf.
(2) Der Server erstellt einen neuen Channel (Neuer Port) und übergibt
den Handle an diesen.
(3) Es können Daten von Client zum Server und umgekehrt gesendet
werden, bis einer von beiden die Verbindung abbricht.
© Thomas Kowarsch
Seite 101/101

Documentos relacionados