Grundlagen der windows - programmierung
Grundlagen der Windows - Programmierung
von Andreas Luef
1. Programmablauf
1.1 Zustandsgesteuerter Ablauf
Herkömmliche Programme arbeiten meist zustandsgesteuert, d.h. die Funktionen werden sequentiell abgearbeitet, daß Programm wechselt aufgrund einer Benutzereingabe in den nachfolgenden Zustand.
Vorteile:
einfache Programmierung
für ungeschulte leichter lesbar
Nachteile:
Programmierer gibt Ablauf fix vor
für Anwender oft unverständlich und willkürlich
starr und unfrexibel
schlecht für nonpreemtives Multitasking geeignet (siehe 2.
2)
1.2 Ereignisgesteuerter Ablauf
Ein fortschrittlicherer Programmierstil als der zustandsgesteuerte ist der ereignisgesteuerte. Seit dem Siegeszug von Microsoft Windows (R) werden die meisten Programme ereignisgesteuert programmiert (nicht nur Windows - Software, diese ist nämlich nur ereignisgesteuert realisierbar).
Die Programmreaktion bzw. -funktionen werden vom Benutzer gesteuert, indem er ein Ereignis auslöst. Vorteile:
Benutzer "dirigiert" den Ablauf
flexibel
gut für nonpreemtives Multitasking geeignet (siehe 2.
2)
belibige Reihenfolge der Verarbeitungsschritte
Nachteile:
aufwendige Programmierung
neigt bei unsauberer Programmierung zum "Chaos"
2. Multitasking
Als Multitasking wird jener Mechanismus bezeichnet, der es dem Betriebssystem ermöglicht, mehreren Programmen gleichzeitig Ressourcen zur Verfügung zu stellen. Dies kann beispielsweise durch ein Zeitscheibenverfahren realisiert werden, bei dem das Betriebssystem abwechselnd Zeit für die zu bearbeitenden Prozessen zur Verfügung stellt, oder durch echte Parallelität.
2.1 Preemtives Multitasking
Beim preemtiven Multitasking übernimmt das Betriebssystem die Kontrolle über die Programme. Es friert die laufenden Prozesse eín, um auf andere Prozesse umzuschalten.
Der laufende Prozess wird nicht beendet, es werden lediglich seine Aktivitäten unterbrochen.
Das Programm selbst muß sich nicht darum kümmern, wann und wo diese Unterbrechungen vorgenommen werden.
Windows NT (R) verwendet preemtives Multitasking
2.2 Nonpreemtives Multitasking
Beim nonpreemptiven Multitasking (auch meldungsgetriebenes Multitasking genannt), daß von Windows 3.x (R) sowie Windows 95 (R) verwendet wird, muß sich der Prozeß selbst darum kümmern, daß andere Prozesse zum Zuge kommen. Deshalb waren unter Windows 3.
x nur jene Programme multitaskingfähig, die eigens dafür programmierte Routinen verwendeten. Ein Programm, daß im MS-DOS (R) - Fenster abläuft, wird unter Windows 3.x nicht unterbrochen, stürzt es ab, steht das gesamte System. Anders unter Windows NT (R), hier hat das Betriebssystem jederzeit die Möglichkeit, den Prozess zu unterbrechen, abgestürzte Programme bringen nicht mehr das gesamte System zum Absturz (außer einige Grafikanwendungen aus Kanada, stimmts, Elias? :-)).
Die Anwendung muß die Kontrolle dem Betriebssystem "zurückgeben", damit dieses auf andere Prozesse umschalten kann. Dies geschieht durch den Aufruf einer passenden Betriebssystem - Funktion.
Bei Windows - Programmen wird diese periodische Rückgabe der Steuerung an das Betriebsystem durch eine sogenannte Meldungs-Schleife realisiert.
Programme mit zustandsgesteuertem Ablauf (siehe 1.1) sínd für nonpreemtives Multitasking nur schlecht geeignet, da in bestimmten Zuständen (der genaue zeitpunkt muß oft willkürlich gewählt werden) die Kontrolle an das Betriebssystem zurückggegeben werden muß.
2.3 Programm - Instanzen
Alle Windows - Programme sind mehrfach ausführbar. Wird ein schon aktives Programm ein weiteres Mal gestartet, wird, sofern man dies nicht explizit verhindert, eine weitere Instanz der Applikation geöffnet.
Das Proramm läuft dann in zwei unabhängigen Fenstern, eine Instanz weiß von der Existenz der anderen Instanz nichts.
Jede Instanz verfügt über ihren eigenen Daten- (Speicher-) bereich, die Ressourcen werden jedoch nur beim Aufruf der ersten Instanz in den Hautspeicher gelden. Greifen daß Programm auf externe Dateien zu, kann es zu Prolemen kommen.
3. Nachrichten
3.1 Nachrichten (Meldungen, Messages)
Windows arbeitet meldungsbasiert, d.
h. alle relevanten Ereignisse (z.B.: Maus-Klick, Tastendruck, Ablauf eines Zeit - Intervalls...
) erzeugen Meldungen, die danach in sogenannten Nachrichten - Schleifen verarbeitet werden.
Nachrichten - Charakteristik:
werden in Form einer vorzeichenlosen 16-Bit Ganzzahl gespeichert
werden durch vordefinierte Konstanten (in WINDOWS.H, ca. 250) dargestellt
WM_LBUTTONDOWN Linke Maustaste gedrückt
WM_CLOSE Anwendung wird geschlossen
WM_KEYDOWN Taste gedrückt
WM_RESIZE Fenstergröße wird geändert
können mittels "WinSight" protokolliert werden
Jede Meldung liefert zusätzliche Informationen (z.B.: WM_KEYDOWN liefert zusätzlich: welche Taste gedrückt? Welche Zusatztasten (Alt, Strg, .
..) gedrückt?). Diese Informationen werden in zwei Parametern geliefert, die Bedeutung dieser Parameter ist meldungsabhängig.
WPARAM ..
. Parameter vom Typ WORD
LPARAM ... Parameter vom Typ LONG
Windows verwendet 2 verschiedene Übergabe - Mechanismen:
PUSH - Modell:
Übergabe erfolgt bei GetMessage, die Applikation ist aktiv. Die Meldung wird in einer MSG - Struktur übergeben.
PULL - Modell:
Aufruf einer Fensterfunktion durch Windows, die Applikation ist passiv. Die Meldung wird in Form einzelner Parameter übergeben.
3.2 Nachrichten-Konzept von Windows
Die Folgende Grafik zeigt den Meldungsfluß zwischen Windows und den Einzelnen Applikationen.
3.3 WinMain
Die Funktion WinMain entspricht der Funktion main() in einen normalen C-Programm, sie wird von Windows beim Programmstart aufgerufen.
Fix vorgegebener Funktions-Kopf:
int PASCAL WinMain(HINSTANCE hInst, HINSTANCE hPrevInst, LPSTR lpCmd, int nShow);
(1) (2) (3) (4) (5) (6)
(1)
(2)
(3)
(4)
(5)
(6)
liefert im Fehlerfall einen Wert ungleich 0
Windows-"Aufruf-Konvention", spart Code (da nur eine fixe Anzahl von Parametern erlaubt werden, der Stack wird abgebaut)
Bezug auf die aktuelle Programm-Instanz (siehe 2.3 Instanzen)
Bezug der vorhergehenden Programm - Instanz
Kommandozeilenparameter (entspricht argv in Standard-C)
Pramater für die Funktion ShowWindow, gibt an, wie das Fenster dargestellt werden soll (Vollbild, Fenster, Symbol)
Die Funktion WinMain erfüllt eine Reihe von wichtigen Routine-Aufgaben:
Registrieren der Hauptfenster-Klasse
Wird das Programm zum ersten Mal aufgerufen, wird eine Fensterklasse erzeugt, dieser Vorgang ist bei weiteen Programminstanzen nicht mehr notwendig. (siehe 2.3 Instanzen)
Im zuge der Registration werden einige Fenster - Eigenschaften festgelegt. Jedes Windows - Fenster muß einer registrierten Klasse angehören, deshalb gibt es einige vorregistrierte Klassen für Standard-Fenster wie etwa MessageBox, Button, ListBox, ..
.
Erzeugen des Hauptfensters
Ist eine entsprechende Klasse registriert, wird das Hauptfenster erzeugt. Dieser Vorgang ist bei jeder Programm - Instanz notwendig, er legt die restlichen Fenstereigenschaften fest (z.B.: Fensterstil)
Anzeigen des Hauptfensters
Durch Aufruf der Funktion ShowWindow (die den Parameter nShow übernimmt) und einem anschließendem UpdateWindow wird das Fenster angezeigt.
Initialisieren der Meldungsschleife
Die Funktion GetMessage liefert anliegende Nachrichten aus der Meldungsschleife.
3.4 Die Fensterfunktion
Die Fensterfunktion wird von Windows aufgerufen (PUSH - Modell), sie ist für die Meldungsauswertung zuständig.
Fix vorgegebener Funktions-Kopf:
LONG FAR PASCAL _export WndProc(HWND hWnd, UINT msg, WPARAM wP, LPARAM lP);
HWND hWnd
UINT msg
WPARAM wP
LPARAM lP
Fenster-Bezug
Meldungscode (z.B.: WM_PAINT, WM_CLOSE, ..
.)
Zusatz-Parameter vom Typ WORD (16 Bit)
Zusatz-Parameter vom Typ LONG (32 Bit)
Die Fensterfunktion sollte nicht alle Meldungen selbst behandeln, sondern nur einige, wichtige. Andere Meldungsbearbeitungsfunktionen (ein wahres Unwort) können deshalb ausgelagert werden, oder, wenn keine spezielle Behandlung erwünscht ist, an die Default-Fensterfunktion DefWindowProc weitergeleitet werden.
Beispiel für ausgelagerte Meldungsbearbeitung:
...
void WndProcWMCOMMAND(HWND hWnd, WPARAM wParam)
{
// Abarbeitung der Meldungen für Menü, Toolbar, ...
...
}
void WndProcWMPAINT(HWND hWnd, WPARAM wParam)
{
// Bildschirmausgabe
...
}
LONG WndProcWMCLOSE (HWND hWnd, UINT msg, WPARAM wP, LPARAM lP)
{
// Rückfrage, evt. Einstellungen oder Arbeitsbereich speichern
..
.
}
LONG FAR PASCAL _export WndProc(HWND hWnd, UINT msg, WPARAM wP, LPARAM lP)
{
LONG ret = 0;
...
switch (msg)
{
case WM_COMMAND: WndProcWMCOMMAND(hWnd,wP); break;
case WM_PAINT: WndProcWMPAINT(hWnd,wP); break;
case WM_CLOSE: ret = WndProcWMCLOSE(hWnd, msg, wP, lP); break;
case WM_DESTROY: PostQuitMessage (0); break;
default: ret = DefWindowProc(hWnd msg, wP, lP);
}
return ret;
}
3.5 Abhandlung bei "Anwendung beenden"
Anhand des Beispiels "Anwendung beenden" soll gezeigt werden, wie das Programm auf die Benutzeraufforderung reagiert, sich zu beenden.
(2)
(4)
(1)
(3)
(5)
...
void WndProcWMCOMMAND(HWND hWnd, WPARAM wParam)
{
...
switch (wParam)
{
case MENU_ENDE: PostMessage (hWnd,WM_CLOSE,0,0); break;
...
}
...
}
LONG WndProcWMCLOSE (HWND hWnd, UINT msg, WPARAM wP, LPARAM lP)
{
if(MessageBox("Wirklich beenden?","Beenden",MB_YESNO) == IDYES)
return DefWindowProc (hWnd, msg, w, lP);
else return 0;
}
LONG FAR PASCAL _export WndProc(HWND hWnd, UINT msg, WPARAM wP, LPARAM lP)
{
LONG ret = 0;
...
switch (msg)
{
case WM_COMMAND: WndProcWMCOMMAND(hWnd,wP); break;
case WM_CLOSE: ret = WndProcWMCLOSE(hWnd, msg, wP, lP); break;
case WM_DESTROY: PostQuitMessage (0); break;
default: ret = DefWindowProc(hWnd msg, wP, lP);
}
return ret;
}
Erläuterung:
Der Aufruf des Menüpunktes "Datei/Beenden" löst ein WM_COMMAND aus, dieses wird zur Bearbeitung an die Funktion WndProcWMCOMMAND übergeben.
In der Funktion WndProcWMCOMMAND wird der in wPararm übergebene ID-Wert ausgewertet, bei MENU_ENDE wird mittels PostMessage (siehe 3.6) die Nachricht WM_CLOSE an das Programmfenster geschickt.
Das Programmfenster reagiert auf WM_CLOSE mit dem Aufruf der Prozedur WndProcWMCLOSE.
Die Funktion WndProcWMCLOSE leitet die Meldung nach Rückfrage an den User an die Default-Window-Funktin DefWindowProc weiter, diese löst die Nachricht WM_DESTROY aus.
WM_DESTROY wird von der Fensterfunktion mit dem Aufruf von PostQuitMessage beantwortet, die Anwendung wird geschlossen.
3.6 Nachrichten versenden
Jede Windows - Applikation kann Nachrichten an beliebige Fenster verschicken. Man unterscheidet nach dem Verhalten nachdem die Nachricht verschickt wurde, zwei Übermittlungsmethoden:
Synchrone Übertragung:
mittels SendMessage (hWnd, msg, wParam, lParam);
Die Applikation, die die Nachricht verschickt hat wartet, bis das Zielfenster die Nachricht bearbeitet hat.
Der Rücksprung aus der Funktion SendMessage erfolgt erst nach der Abarbeitung.
Asynchrone Übertragung:
mittels PostMessage (hWnd, msg, wParam, lParam);
Der Rücksprung aus der Funktion PostMessage erfolgt sofort, die Applikation läuft weiter. Die Nachricht wird in die Nachrichten - Warteschlange der Zielapplikation gestellt.
4. Ausgabe (GDI, DC)
4.1 GDI - Graphics Device Interface
Das GDI stelt eine Bibliothek von Routinen dar und wird sowohl von Windows selbst als auch von allen Applikationen zur geräteunabhäängigen Grafik- und Textausgabe verwendet.
Es bildet die logische Schnittstelle zwischen den Programmen und den Hardware - Treibern der Geräte. Es werden 4 logische Einheiten unterstützt:
Bildschirme
Hardcopy - Geräte
Bitmaps
Mata - Dateien
Jedes Fenster entspricht einer eigenen Zeichenoberfläche mit eigenenem Koordinatensystem, automatisches Clipping verhinder versehentliches Überschreiben anderer Fenster
4.2 Einheitenkontext (Device Context)
Der Einheitenkontext oder Device Context (DC) stellt die Verbindung zu einer bestimmten Einheit (Zeichenoberflöche) her. Er sorgt für die Zugriffserlaubnis, bei Hardcopy-Geräten (Drucker, Plotter,...
) durch "Spooling", bei Bildschirmen durch "Clipping".
Der DC liefert eine Art Werkzeugkasten, in dem logische Werkzeuge enthalten sind. Solche Wekzeuge sind beispielsweise
Pinsel (Brush, Füllwerkzeug))
Zeichenstift (Pen)
Schriften (Fonts)
etc.
Der DC wird über einen hdc angesprochen, einem Handle, und wird vom Window-Manager "geliehen".
prinzipieller Ablauf
nach WM_PAINT
sonst
DC anfordern
BeginPaint
GetDC
Ausgaben durchführen
TextOut
TextOut
DC zurückgeeben
EndPaint
ReleaseDC
Ändern der Werkzeuge im DC:
Beispiel: anderer Stift (Pen)
Bezug auf logischen Stift besorgen
entweder vom "Basisstift" ausgehend mittels GetStockObject
neuen Stift anwählen mittels CreatePen
gewähltern Stift in den DC aufnehmen mittels SelectObject
4.3 "bleibende Ausgaben"
Da aufgrund normaler Benutzeraktivitäten das Programmfenster im Anzeigebereich jederzeit überschrieben werden kann (sei es durch andere Programmfenster, den Bildschirmschoner, .
..), muß das Programm jederzeit in der Lage sein, sein Fenster neu darzustellen.
Wird ein Fenster ganz oder zumindest teilweise zerstört, sendet Windows die Meldung WM_PAINT an das entsprechende Programmfenster. Durch das Abfangen der Meldung in der Meldungsbehandlungsfunktion WndProc kann auf WM_PAINT reagiert werden, indem das Fenster neu gezeichnet wird. zu diesem Zweck müssen jedoch alle Informationen bekannt sein, die zum Neuzeichnen des Fensters nötig sind.
Beispiel: Anzeigen der aktuellen Mausposition
Mausklick verursacht WM_LBUTTONDOWN
in der Funktion, die die Meldung bearbeitet, wird die aktuelle Mauspositon am Bildschirm angezeigt
sofortige Ausgabe funktioniert zwar, jedoch geht die Ausgabe verloren, wenn das Fenster minimiert wird, da zum Anzeigen ein linker Mausklick nötig ist
Richtige Methode für "bleibende" Anzeige:
als Reaktion auf WM_LBUTTONDOWN wird die aktuelle Position des Mauszeigers in einer Variable gespeichert
Anzeige erfolgt erst bei WM_PAINT
erzwingen einer neuerlichen Ausgabe bei Mausklick mittels InvalidateRect
InvalidateRect
Diese Funktion "zerstört" die aktuelle Ausgabe, indem es Windows anweist, das Fenster neu zu zeichen.
Beispiel für Programm mit bleibener Ausgabe Erklärung:
Das Programm gibt einie Bitmap im Fenster aus, es reagiert auf das Ereignis WM_PAINT
Ein anderes Fenster (hier NT-Explorer) überschreibt die Ausgabe
Die zweite Anwendung wird geschlossen, das Fenster, in der die Bitmap angezeigt wird, bleibt zerstört. Windows sendet WM_PAINT
Das Programm reagiert auf die Meldung und gibt die Bitmap neuerlich aus
5. Resourcen
5.1 Resourcen
Resourcen sind read-only Dateien, die hauptsächlich für die Gestaltung der Benutzeroberfläche verwendet werden. Diese Daten werden unabhängig vom Programm erstellt und verwaltet und später zum Objektcode des Programms gelinkt.
Eine eventuelle Änderung der resourcen (z.B.: hinzufügen eines Menüpunktes, ...) kann daher ohne änderung des eigendlichen Quellcodes geschehen, es werden lediglich die Resourcen - Files geändert.
Arten von Resourcen:
Menüleisten
Dialogfenster
Cursors (Mauszeiger)
Icons
Schriftarten
Accelerators (Hotkeys, Tastaturkürzel; z.B.: [Alt]+[F4] zum Beenden der Applikation
6. Dialoge
6.1 Standard-Dialoge
Standard - Dialoge sind seit Windows 3.1 verfügbar und erleichtern Routineaufgaben wie zum Beispiel das Öffnen von Dateien.
Weiters tragen sie zur Verbesserung der Bedienbarkeit von Windows - Programmen bei, da wichtige, oft genutzte Dialoge ein einheitliches Erscheinungsbild haben und somit intuitiv bedienbar sind.
Standard - Dialoge:
Datei öffnen
Datei Speichern
Farbe auswählen
Schrift wählen
Text suchen
Drucken
Natürlich kann mit Hilfe eines Dialog - Editors auch ein benutzerdefinierter Dialog erstellt werden. Dieser kann mit einer Vielfalt von Kontrollelementen bestückt werden, die wichtigsten davon sind:
Textfelder (zur Texteingabe)
Buttons (zum Auslösen von Ereignissen)
Listboxen (Auswahl aus einer Liste)
Comboboxen (aufklappbare List-Boxen)
6.2 Modaler Dialog
Ein modaler Dialog muß vor dem Weiterarbeiten mit der Applikation geschlossen werden. Das Elternfenster wird vollkommen daktiviert, die Steuerung wird an die Funktion DialogBox übergeben, die eine eigene Meldungsschleife enthält. Die Rückkehr zum Elternfenster erfolgt mit dem Aufruf der Funktion EndDialog.
Applikationsmodaler Dialog
Die Applikation, die den Dialog aufgerufen hat, wird deaktiviert, das Wechseln zu anderen Applikationen ist ohne weiters möglich.
Systemmodaler Dialog
Das gesamte System (Windows) ist lahmgelegt, lediglich die Dialogbox bleibt bedienbar. (Verwendug bei Systemfehlern, z.B.: Allgemeine Schutzverletzung)
6.3 Nichtmodaler Dialog
Beim nichtmodalen Dialog kann der User zwischen Dialog und em Rest der Applikation wechseln.
Ein nicht-modaler Dialog wird in C mittels der Funktion CreateDialog erstellt, die Kontrolle bleibt jedoch beim Hauptfenster. Da es keine eigene Meldungsschleife gibt, muß die Meldungsschleife in WinMain modifiziert werden.
Anmerkungen: |
| impressum | datenschutz
© Copyright Artikelpedia.com