This document is posted to help you gain knowledge. Please leave a comment to let me know what you think about it! Share it to your friends and learn new things together.
↑ Einleitung | SP2-Einleitung | Ziel der Veranstaltung | Kognitive Ziele | Praktische Ziele | Was ist
ein Programm? | Programmiermodell | Was ist ein System? | ./img/fachwerk.jpg | Objektbezogene Systembezeichnungen | ./img/telefon.jpg | Was sind Schnittstellen? | Software-Ergonomie | Kybernetik | ./img/kybernetik.jpg | Beispiel: menschlicher Körper | Was ist eine normal? | Was ist eine Norm? | Beispiele für Normen | Nationale Normungsinstitutionen | Internationale Normungsinstitutionen | ECMA Standards | Historisches | Einheiten | Prae-Potenzen
↑ Betriebssystem | Betriebssystem | ./img/intel_architektur.gif | ./img/memory_management.gif | ./img/descriptor1.gif | ./img/descriptor2.gif | MS-DOS | Starten von DOS | Software-Interrupt | UNIX | UNIX und C | UNIX-Standardisierungen | Windows | Architektur des NT-Betriebssystem | Struktur des NT 4.x-Betriebssystems | ./img/nt4.gif
↑ Windows Data Types | Datentypen aus Hardwaresicht | Binärzahlen.htm | Beispiel: Gleitpunktzahlen | Beispiel: Unicode | Beispiel: Unicode | Wie wird generischer UNICODE verwendet? | C++Grundtypen | Standard C- Bibliotheks-Header-Files || C-Header-Files ( Funktionsnamen ) | Standard C++ Bibliotheks-Header-Files | Schlüsselwörter | C-/C++-MACROS || windowsx.h | Windows Data Types | Windows-Standard Typen | RTL-Typen | Ungarische Notation | Windows-Header-Files
| Modless Dialoge | für Modeless: Haupnachrichten-Schleife | für Modeless: in der
CALLBACK | für Modeless: Aufruf | für Modeless: im Fenster hinterlegen | CreateDialog() - Aufruf | für Modeless: | *.RC enthält | *.CPP enthält | Interne Dialog - CALLBACK - Funktion | Standard - Dialoge | Controls | Static Text Control | Button Control | Edit Control | Beispiel zu Edit | List Box Control | Combo Box Control | Beispiel: Stringtable | Scroll Bar Control | Arrow - Keys und Notification Nachrichten
Rechner1 mit *.rc || ./img/rechner.gif | Hex-Rechner1 ohne *.rc | hex_rechner2 | Eingebaute Klassen (Methode 1) | Eingebaute Klassen (Methode 2) | Sub-Classing | Dialog-Erzeugung | Hauptnachrichten-Schleife für Modeless | Textausgabe in Control | Taschenrechner mit Texteingabe
↑ DLL's | DLLs | Lebensdauer von Objekten | Static-Linking | Dynamic-Linking | Unterschiede zwischen Static-Dynamic-Linking | shared data segment | Verwenden einer Funktion aus einer DLL
↑ MFC | MFC | Grober Zusammenhang mit ATL | Entwicklungskriterien | MFC und
Nachrichten | MFC-Klassen-Typen | MFC-Schreibweise | Hinweise zur Programmierung | Beispiel für CWND_Member-Funktion | CArray-Beispiel | Handles und MFC | MFC-Klassenhirachie (CE) | MFC-Klassenhirachie || ./img/mfc_hierachy_categories.gif || ./img/mfc_1.gif || ./img/mfc_2.gif | Hinweise zum Übersezungsvorgang
↑ CSharp-Einführung | C Sharp (Einführung) | Was ist .NET? | CS-Entwickler-Tools | CS-keywords | CS-
keywords | Typen in C# | Boxing and Unboxing | dll-Funktionen in C# | CS-Console-Applikation | Beispiel für cs-Console-Applikation
SP2-Praktikum-Gruppeneinteilung
Mi 1. 8.00- 9.30 C405: Gruppe A1, .. Mi 2. 9.50-11.20 C405: Gruppe B1, B2Mi 3. 11.30-13.00 C405: Gruppe C1, ..--------------------------------------------Do 4. 14.00-15.30Do 5. 15.45-17.15 F305: VorlesungDo 6. 17.30-19.00 C405: Gruppe D1
Wie wird das SP2-Praktikum durchgeführt?
1. Aufgaben per Internet 2. Bearbeitungszeit 1 Woche 3. Punktbewertung + Kontrollfragen 4. keine Überschreitung der Bearbeitungszeit
Kontroll-Fragen | Teil 1 | Teil 2 | Teil 3 | Teil 4 | h: MS-Visual Studio .NET | h:Console (main-) Programm | h: Macros, Datentypen, Zeigern | Datentypen aus Hardwaresicht
Für das Praktikum bitte unbedingt anmelden: [hier Klicken]
1. SP2-Praktikum (SS 2005)
Dieses Praktikum führt in die Windows-Projekt-Erstellung ein und wiederholt (mit groben Sprüngen) Programmierkenntnisse
und Voraussetzungen. Es ist günstig, die vorgegebene Bearbeitungsreihenfolge einzuhalten. Alle Tests, Kontrollfragen und
Lösungen sollen in EINEM einfachen Protokoll.txt-File (von Hand) mit-protokolliert werden.
❍ Wieviele Byte belegen im Win32-Programmiermodell die
Datentypen long, unsigned long, float, double, signed short,
unsigned short, char, signed char, bool?
Erklären sie dies bitte im Zusammenhang mit der | Hardware-
Archtektur von Dadatypen
❍ Welche Änderungen ergeben sich mit #define UNICODE für
String und Char?
4. Das Windows-System ist im Überblick zu quantifizieren ( *.exe, *.dll-Files, *.dll-Funktionen )
❍ In welchem absoluten Pfad befinden sich *.dll-Files des
Betriebssystems?
❍ Wieviele *.exe-Files gehören etwa zu dem benutzten Windows-
System?
❍ Wieviele *.dll-Files gehören etwa zu dem benutzten Windows-
System?
❍ Wieviele Funktionen enthält eine *.dll im Mittel?
❍ Für die C,C++-Programmentwicklung werden *.h-Files
benötigt.
In welchem Verzeichnis befinden sich die *.h-Files?
❍ Wieviele *.h-Files gehören zu der verwendeten C++-
Entwicklungsumgebung?
↑Hinweise zu MS-Visual Studio .NET
● A. Ein neues Projekt anlegen:
.NET-Studio-Haupt-Menu: DATEI NEU PROJEKT Win32ConsoleAnwendung LEERES C++-PROJEKT erstellen. Beim Dialog des Anwendungsassistenten anstelle von "ÜBERBLICK" bitte "ANWENDUNGSEINSTELLUNGEN" auswählen. Dort wird KONSOLE-Anwendung und LEERES Projekt angeklickt. Auchtung! Nur hier beim 1. Praktikum wird ein Win32-Konsole-Projekt (main-Funktion) verwendet. Später meistens eine WINDOWS-ANWENDUNG oder eine DLL-Erstellung. Projektname: myauf01 Pfad wählen: ...
● B. Einen CPP-Quelltext-File ins Projekt einfügen:
.NET-Studio-Haupt-Menu: DATEI NEUES ELEMENT HINZUFÜGEN DATEIEN C++-Quellcodedatei [x] dem Projekt hinzufügen
↑ Console-Applikation
Zum Ausführen von Tests (bitte Ergebnisse protokollieren) ist mit MS-Visual Studio .NET eine Console-Applikation zu erstellen:
stdout_to("CON"); // Dieser Macro-Aufrufe schaltet die // folgenden printf-Ausgaben auf die Konsole. stdout_to(__FILE__);// Dieser Macro-Aufrufe gibt die // folgenden printf-Ausgaben // im aktuellen cpp-Quelltext-File aus.
In windows.h, windef.h sind zahlreiche Macros definiert. Testen Sie die folgenden Macros:
| Betriebssystem | ./img/intel_architektur.gif | ./img/memory_management.gif | ./img/descriptor1.gif | ./img/descriptor2.gif | MS-DOS | Starten von DOS | Software-Interrupt | UNIX | UNIX und C | UNIX-
Standardisierungen | Windows | Architektur des NT-Betriebssystem | Struktur des NT 4.x-Betriebssystems | ./img/nt4.gif | Datentypen aus Hardwaresicht | Binärzahlen.htm | Beispiel: Gleitpunktzahlen | Beispiel: Unicode | Beispiel: Unicode | Wie wird generischer UNICODE verwendet? | C++Grundtypen | Standard C- Bibliotheks-Header-Files || C-Header-Files ( Funktionsnamen ) | Standard C++ Bibliotheks-Header-Files | Schlüsselwörter | C-/C++-MACROS || windowsx.h | Windows Data
↑ BetriebssystemAchtung! Hier werden lediglich einige Betriebssystem-Aspekte wiederholt ( vorrangig wird auf die Veranstaltung Betriebssysteme hingewiesen )!
Ein Computer-Hardwaresystem besteht aus Mikroprozessoren, Chips, Uhren, Schaltungen, Eingabegeräten, Tastatur, Maus, Laufwerk; Ausgabegeräten, Bildschirm,
Plattenlaufwerken; Peripheriegeräten, Drucker, Modem, Netzwerkkomponenten und weiteren Komponenten.
Moderne Prozessoren können eine aufwendige Architektur haben:
Moderne Prozessoren können verschiedene Speicher-Adressiersarten haben ( Memory-Management: Segnmentierung, Paging ):
Moderne Prozessoren können Descriptoren haben: ( Zugriffstypen, Zugriffrechte, Privilege Level, Call Gates, Interrupt and Exception-Handling, usw. )
Ein Betriebssystem ( Operating System, Systemsoftware, Basisprogramme ) besteht aus Software mit Basisroutinen für die Hardware - Ansteuerung und die Hardware -
Resourcen - Verwaltung. Ein Betriebssystem erfüllt 2 Aufgaben:
1. Virtuelle Maschine,
2. Resourcen-Verwalter
Die Betriebssystem - Architektur ( Instruktionssatz der zentralen Verarbeitungseinheit, der Speicher- organisation, Ein/Ausgabe auf Platten und Disketten, Bildschirm )
erfordert die (schwierige) Programmierung der Kontrollerbausteine. Diese Maschinen - Programme, wie Unterbrechungen ( interrupt ), Zeitgeber ( timer ) und die
Speicherverwaltung ( memory management ) sind in den BIOS enthalten. Für den Anwender ist die Benutzung dieser Programmteile einfacher, als die direkte
Programmierung der zugrundeliegende Hardware. Für den Anwender verhaelt sich das Betriebssystem wie eine Virtuelle Maschine.
Wenn auf einem Computer mehrere Benutzer gleichzeitig arbeiten wollen, entsteht die Notwendigkeit, Speicher, Ein-/Ausgabegeraete und andere ( teure ) Komponenten
zu verwalten und zu sichern. Aus dieser Sicht hat das Betriebssystem die Aufgabe, festzustellen, wer welche Resourcen verwendet, Resourcen auf Anforderung zu
gewaehren, Unterbrechungens - Informationen zu sammeln und zwischen den gegenseitig sich überschneidenden Anforderungen mehrerer Benutzer oder Programme zu
vermitteln.
Die Software - Schichten:
1. Physikalische Geräte
2. Mikroprogrammierung
3. Maschinensprache
4. Betriebssystem
5. Kommando - Interpreter, Editoren, Compiler
6. Anwendungsprogramme
Die Punkte 1, 2, 3 werden auch zu einer Hardware - Schicht zusammengefaßt. Die Punkte 4, 5 bilden die Systemprogramme. Zu den Applikationen (
Etwa 1980 hat Jim Paterson (ausgehend vom CP/M-80) ein 6 KB umfassendes Betriebssystem QDOS (Quick and Durty Operating System) entwickelt. IBM wollte eine
neue 16-Bit-Maschine auf Intel-Basis auf den Markt bringen. Mircosoft übernahm Jim Paterson und entwickelte MS-DOS unter strenger Geheimhaltung die Version 1.0
(1981). 1983 war die Version 2.0 ( hierarchisches Dateisystem mit 9 Sektoren für 360 kB Laufwerke, installierbare Geraetetreiber, Bildschirmtreiber ANSI.SYS,
Backgroundprozessing ). 1984 entstand für den PC-AT die Version 3.0 ( Netzwerk, 20 MB Festplatte, 1.2 MB Diskettenlaufwerke, Verbesserungen der Ausführungszeiten
Unter DOS ausführbare DOS-Programme sind z.B. *.EXE und *.COM. *.COM-Programme können maximal 64 KB Code enthalten. Beim Laden von *.EXE Programmen
werden die absoluten Speicher- bezüge angepasst.
↑ Starten von DOS
Nach dem Einschalten wird geprüft ob im Laufwerk A: (falls leer dann B:, dann C:, usw.) eine Diskette ist. Der Boot-Sektor wird automatisch geladen, die Boot-Routine
wird ausgeführt und IBMBIO.COM und IBMDOS.COM geladen. Nun wird die Datei CONFIG.SYS gesucht und die in CONFIG.SYS enthaltenen Treiber werden geladen
(DEVICE-Befehl). Dadurch wird der Kern des Betriebssystems zusammengebaut (SYStem CONFIGurieren). Dann wird der Kommando- prozessor (COMMAND.COM)
geladen, der automatisch die in
Beim Starten von DOS wird zuerst die Datei CONFIG.SYS (Gerätetreiber) und dann die Datei AUTOEXEC.BAT abgearbeitet. Die in AUTOEXEC.BAT enthaltenen
*.COM- und *.EXE-Programme der Reihe nach ausführt. *.Bat steht für eine BATch-Job-Stapeldatei.
Achtung! Das folgenden Beispiele ( DOS 5.0 ) können nicht kritiklos übernommen werden!
@ECHO OFF set comspec=c:\dos\command.com path C:\DOS;c:\bc\bin; append=c:\dos in not "%prompt%"=="" goto ende prompt $p$g lh keyb gr lh c:\dos\mouse.com nc :ende
Wesentliche Teile des MS-Dos-Betriebssystem werden über eine Interrupt-Adress-Tabelle abgewickelt. Diese Tabelle beginnt bei der Speicher-Adresse 0 und enthält 256
Adressen. Jeder Adress-Eintrag verwendet 4 Byte. Wird ( durch ein Gerät ) dem Interrupt-Controller-Baustein ein Hardware - Interrupt angezeigt, so legt das Gerät
danach den Tabelle-Index auf den Datenbus. Der Tabelle wird dann die Ziel-Adresse entnommen. Ab der Zielstelle wird das unterbrechende Programm ( ähnlich einem
Unterprogramm ) ausgeführt.
Bei einem Software-Interrupt ( z.B. INT 21h ) enthält der INT-Maschinen-Befehl bereits den Tabellen-Index. Ab der Zielstelle wird das unterbrechende Programm (
Wesentliche Teile des MS-Dos-Betriebssystem werden über eine Interrupt-Adress-Tabelle abgewickelt. Dadurch ergeben sich die folgenden Vorteile: Wird das
Betriebssystem verbessert oder erweitert, so wird der Maschinencode an der Zielstelle geändert. Die Folge der Adressen an den Zielstellen verschieben sich. Wenn
Anwendungsprogramme die direkte Adresse der Zielstelle verwenden würden, so müßten bei jeder Betriebssystemänderung alle Anwendungsprogramme
angepaßt werden. Wenn ein Anwendungsprogramm Funktionen des Betriebssystems verwendet, so wird lediglich den Index der Interrupt - Tabelle benutzt ( z.B. INT
21h ). Dadurch funktionieren die alten Anwendungsprogramme auch unter einer neueren Version des Betriebssystems.
↑ UNIX
UNIX ist ein Mehrprogrammsystem. Die einzigen aktiven Einheiten in einem UNIX-System sind die ( sequeltiellen ) Prozesse. Jeder Prozess hat einen eigenen
Programmzähler. Viele Prozesse laufen im Hintergrund ( Dämon, z.B.Terminplanung mit cron ).
↑ UNIX und C
Nachdem Ken Thomson aus dem MIT - Projekt ( MULTiplexed Information and Computing Service, PL/I ) verlassen hatte, schrieb er auf der PDP-7 ein kleineres
Betriebssystem UNICS ( UNiplexed Information and Computing Service, kastriertes MULTICS, späterer Name UNIX ). Die Übertragung des gesamten Assembler -
Codes auf PDP-11/20, PDP-11/45, PDP-11/70 war schwierig. Deshalb wurde ein Programmiersprache B ( vereinfachtes BCPL, stark vereinfachtes PL/I ) entwickelt. B
hatte keine Strukturen. Dennis Ritchie erweiterte B zu C.
Um das Betriessystem auf einen neuen Computer zu übertragen wurde zunächste ( mit mittleren Aufwand ) der C - Compiler portiert. Die meisten Software - Anteile
konnten dann übernommen werden. Der Quellcode wurde kostenlos an Universitäten abgegeben.
C wurde die Sprache der Systemprogrammierung.
Ausgehend von der typenlosen Sprache BCPL wurde die Programmiersprache C von Ken Thomson und Dennis Ritchie bei den Bell Laboratories auf einer PDP-11
entwickelt. Das Betriebssystem UNIX ist weitgehend in C geschrieben. UNIX Ver. 6 ist zu 95% in C geschrieben. C ist eine einfache und universelle Programmiersprache,
die auch bei Mikrocontrollern als Assembler-Ersatz verwendbar ist. C ist heute i.a. die erste hoehere Programmiersprache, die auf einem neuen Computer,
Microcomputers, Minicomputers oder Mainframe laeuft. Wir wollen immer zwischen der Programmiersprache C und den Bibliotheken unterscheiden. Bibliotheken
enthalten eingebaute Funktionen und Dienstleistungen. Bei Projekten werden solche Bibliotheken mit Hilfe eines C-Compilers oft selbst erstellt (z.B. Window-, Grafik-,
Device-Bibliotheken). 1988 wurde ANSI-C X3J11 genormt.
C ist für Programmier-Anfaenger wegen der cryptischen-Schreibweise nicht so einfach wie z.B. BASIC. Mit C kann man flexibel bis auf Betriebssystem- und Maschinenebene programmieren. Anders als z.B. bei OBERON gilt:
Die Verantwortung beim Programmieren mit C ( C++ ) liegt stets beim Programmierer!
↑ UNIX-Standardisierungen
Die Universität Kalifornia in Berkeley nutzte den C - Quellcode und entwickelte eigene UNIX-Erweiterungen ( vi, csh, Compiler für Pascal und Lisp, usw. ). Sun baute auf
dem Berkeley-Unix auf. Es gab unterschiedliche Unix-Normungsgremien z.B. AT&T SVID ( System V Interface Definition ), BSD ( Berkeley Sooftware Distribution ),
IEEE POSIX 1003.1 ( Portaples Operating System ). OSF ( IBM und weitere, Open Software Foundation, starke Erweiterungen X11, MOTIF, DCE, DME ), UI ( AT&T
und weitere, Unix International ).
Für UNIX hat sich die sogenannte Mach Gruppe schon frühzeitig bemüht, einen Kernel weiter zu entwickeln, der die folgenden Eigenschaften vereint:
● Beibehaltung Schnittstelle
● abstraktes Modell der Speicherverwaltung ( großer und nicht dicht besetzter Adreßraum, memory mapped files, Speicherverwaltungsmodule
für den Benutzer,
● Interprozeßkommunikation ( Transparenz im Netz, Schutzmechanismen, Austauschbare Datenmengen )
● Beachtung von neuen Technologien ( Vernetzung, Mehrprozeßortechnik, enge und lose Kopplung, Prozeß in Tasks und Threads abbilden )
● Werkzeuge ( im Kern eingebaute Testhilfe, Debugger, transparente Zugriffe auf andere Rechner, remote File access, remote Procedure Call
für C, Pascal und Common Lisp )
↑ WindowsWindows ist überwiegend in ANSI - C geschrieben. Einige wenige zeitkritische Teile des Betriebssystem - Kerns für die Hardware Abstraktions Layer ( HAL ) sind in
Assembler - Code geschrieben. Das Betriebssystem ist modular. Bei Bedarf werden die benötigten Teile ( DLL's ) geladen/entfernt.
Es gibt verschiedene Windows-Betriebssysteme:
1985 MS präsentiert Windows 1.01; 1987 Windows 2; 1987 OS/2 von IBM / MS, zeichenorientiert 1988 OS/2 von IBM/MS mit grafischer Oberfläche 1990 Windows 3.0 ( 16 Bit ) erscheint und wird ein großer Erfolg ( Trennung IBM – MS ). Im Oktober startet die Inmarsat-Organisation eigene Satelliten für die maritime Kommunikation. In den USA nimmt der erste kommerzielle Internet-Provider den Dienst auf.
Unter Federführung der Bundespost entsteht der Treiber-Standard CAPI 1.1 für ISDN-Karten. James Gosling und Bill Joy beginnen mit der Entwicklung der Programmiersprache Java; 1992 Windows 3.1; 1993 Windows 3.11; 1993 Windows NT ( Windows New Technology, 32-Bit-Betriebssystem, für Workstations Windows NT 3.1, für Windows NT 3.1 Advanced Server und Netzwerke ); 1996 Windows NT 3.5, und Windows NT 4.0, Sicherheit, Erweiterbarkeit, Stabilität und Skalierbarkeit, zentrale Administration, NT-Server tritt in Konkurrenz zu Novell, Banyan oder UNIX1995 Windows 95, ( unterstützt 32-Bit-Anwendungen und die so genannte Plug-and-Play-Technologie, mitgeliefert wurde der Internet-Browser Internet Explorer, für Heimmarkt = Small Office/Home Office; 1998 Windows 98 ( Update für Windows 95, Active Desktop bindet den Webbrowser Internet Explorer, unterstützt werden: FAT32, DVD- und MMX-Technologie, AGP (siehe Graphikkarte) USB-Anschlüsse ( Universal Serial Bus ), AGP ( Accelerated Graphics Port, 1997 Intel, direkte Verbindung von der Grafikkarte zum Prozessor sowie zum Arbeitsspeicher, Taktfrequenz 66 MHz, AGP 1X = 266 MByte/s, AGP 2X = 533 MByte/s, AGP 4X = 1066 MByte/s, Pipelining, 8 zusätzliche Leitungen, DIME-Auslagerungsmodus für Texturen ); 2000 Windows 2000 wird in 4 Zusammenstellungen ausgeliefert: Windows 2000 Professional ( für PC und Notebook ), Windows 2000 Server ( einfache Netzanwendungen ), Windows 2000 Advanced Server ( Unternehmenskritische und komplexe Netzanwendungen ) Windows 2000 Datacenter Server ( für Rechenzentren, Lagerverwaltungssysteme und Finanzsysteme ); 2001 Windows ME; 2002 Windows XP
NT-Design Ziele NT-Server
● Kompatibilität: Durch seine Submodule ist Windows
NT in der Lage, Applikationen für die Betriebssyteme
Windows 3.x, Windows 95, MS-DOS, OS/2 und
POSIX zu betreiben.
● Portierbarkeit: Windows NT ist fast vollständig in C
geschrieben. Für eine neue Hardware Architektur muß
deswegen lediglich eine neue HAL (Hardware
Abstraction Layer) geschrieben werden und ein NT-
komformer Compiler verfügbar sein.
● Skalierbarkeit: Windows NT unterstützt das
symmetrische Multiprocessing.
● Sicherheit: Windows NT beinhaltet ein
durchgängiges Sicherheitskonzept, das darauf
ausgelegt ist, die Sicherheitsanforderungen des
Amerikanischen Verteidungsministeriums zu erfüllen
(C2).
● Verteilte Systeme: Windows NT hat schon im
Betriebssystemkern weitreichende Funktionalität, um
Prozesse auf anderen Rechnern ablaufen zu lassen.
● Zuverlässigkeit und Stabilität: Durch sein Konzept
unterscheidet Windows NT zwischen User und Kernel
Prozessen. Dadurch ist es normalerweise einer
Applikation nicht möglich einen Windows NT
Rechner zu blockieren oder abzuschießen. Dadurch
kann ein Server auch dann weiter arbeiten wenn in
einer Applikation ein Fehler aufgetreten ist.
● Die Server - Version unterstützt beliebig viele
gleichzeitige Datei- und Druckerverbindungen,
Datei- und Druckerserver auch für Macintosh,
● Die Benutzerinformationen stehen allen Servern zur
Verfügung (Domänen Konzept),
● NT-Server ermöglicht eine zentrale
Benutzeradministration, Verzeichnis-Replikation,
● TCP/IP Unterstützung ( DHCP, WINS, DNS, etc.),
● NetWare Unterstützung ( GSNW, Migration Tool,
FPNW kompatibel ),
● fehlertolerante Plattenkonzepte werden unterstützt (
Parity, RAID 5 ),
● Multiuser Remote Access Service
● Erweiterbar: Da Windows NT sehr modular
aufgebaut ist, ist es einfach möglich neue Module
einzuhängen oder zusätzliche hinzuzufügen.
↑ Architektur des NT-Betriebssystem
Wichtige Teile des Betriebssystems sind im ( privilegierten ) Executive Modus geschützt.
● Hardware Abstraction Layer (HAL): Die HAL - Komponenten sind in Assembler geschrieben. Diese HAL - Schicht muß bei der
Portierung von Intel-Basis auf MIPS, Alpha, Power-PC und PA/RISC neu geschrieben werden.
● Kern (Kernel): Dieser Mach-Kernel ist überwiegend in ANSI-C geschrieben. Der Kernel bearbeitet Unterbrechungen und AUsnahmen,
Laufzeitfestlegung von Threads, Synchronisation von Prozessoren und stellt Objekte und Schnittstellen bereit.
Darüber hinaus stellt Windows NT eine Reihe geschlossener Subsysteme zur Ausführung von Applikationen zur Verfügung. Sie alle kommunizieren mit dem darunterliegenden Betriebssystem und regeln ihre Bildschirmausgaben über die Windows32-Graphikschnittstelle.
● Win32: Ausführung von 32-Bit Windows-Programmen, beinhaltet das WOW-Modul (Windows-on-Windows) zur Ausführung von 16-Bit-
Programmen.
● OS/2: OS/2 2.x Subsystem.
● POSIX: Zeichenorientiertes POSIX-Subsystem.
● Sicherheit: Subsystem zur Überwachung der Sicherheit der anderen Subsysteme
NT-Objekte NT-Objekte NT-Objekte
Resourcen als Objekte:
● Dateien
● Gemeinsam
benutzter Speicher
● Physikalische
Geräte jeder Art
● Prozesse/Threads
Ein NT-Thread:
● teilt sich das Code-
und Daten-
Segment eines
Prozesses mit
anderen Threads,
● hat seine eigenen
CPU-Register,
Stack-Raum und
einen eigenen
Instruktions -
Zähler,
● erhält vom System
eine gewisse CPU -
Zeit, so daß alle
Threads des
Unterschiedliche Objekte sind:
● Executive Objects
● hat bereits Windows NT 3.5 mit
Service Pack 3 die C2-
Zertifizierung für NT-Rechner
ohne Netzwerkanbindung
erhalten.
● NT ist für B1-Security ausgelegt.
● Für jedes Objekt gibt es ein
Zugriffstoken
Prozesses
gleichzeitig
ausgeführt werden.
Dateisysteme:
Die von Windows NT unterstützten Dateisysteme können parallel nebeneinander laufen.
● NTFS: New Technology File System, das eigentliche 64-Bit-Dateisystem von Windows NT mit starkem Fokus auf Sicherheit. Maximale
Dateigröße: 17 Milliarden Gbytes
● HPFS: High Performance File System, OS/2-Dateisystem. Maximal Dateigröße: 4 bis 8 Gbytes ( wird ab NT 4.0 nicht mehr unterstützt ).
● FAT: File Allocation Table, DOS Dateisystem und Diskettenformat unter NT. Maximale Dateigröße: 4 Gbytes.
↑ Datentypen aus HardwaresichtAlle binär gespeicherten Informationen bestehen aus kleinen, typisierten Einheiten. Jedem Buchstaben ist z.B. ein Bitmuster zugeordnet. Text besteht z.B. aus Buchstaben
und diese aus Binärcode. Maschinencode besteht z.B. aus kleinen binären Einheiten ( prozessor-spezifischen OpCode-Befehlen ). Zu einer ganzen Zahl im Speicher gehört
z.B. der Umfang von Bits, eine bestimmte Art des Bit-Muster-Aufbaues ( Interpretation dieser Bits ) und die Position, bei der diese Bits im Speicher sind (
Speicheradresse, Zeiger ).
Zu jeder vorhandenen Information gehört ein Identifizierer( physikalische RAM-Adresse, Entität, Ort der Information ) und ein Binärcode ( Bitmuster, Bedeutung, Semantik ).
Daten-Typen legen die elementare Bedeutung eines Speicher-Bit-Musters fest. Mit Daten-Typen sind sinnvolle Operationen möglich. Zu einer Programmiersprache
gehören Grundtypen, die für Zeichen, Zahlen, Strukturen verwendet werden können. Strukturen und Objekte legen die elementare Bedeutung einer Kombination von
Grundtypen fest.
↑ Beispiel: Gleitpunktzahlen
Zahlen in wissenschaftlicher Notation bestehen aus Vorzeichen ( Sign Bit ) , Mantisse ( Significant ) und Exponent ( Biased Exponent ). Wir müssen daher bei en sehr
genau zwischen der Von der Größe einer Gleitpunktzahl ( Wert des Exponenten ) ist die Darstellungsgenauigkeit ( Anzahl der gespeicherten Ziffern ) zu unterscheiden.
Das Format von Gleitpunktzahlen ist in IEEE 754 ( Floating Point Standard ) festgelegt.
Es gibt die Daten-Formate:
● Word Integer ( Zweierkomplement, Bereich 104, Genauigkeit 16 Bit ),
● Short Integer ( Zweierkomplement, Bereich 109, Genauigkeit 32 Bit ),
● Long Integer ( Zweierkomplement, Bereich 1018, Genauigkeit 64 Bit ),
● Packed BCD ( Bereich 1018, Genauigkeit 18 Digits ),
● Single Precision ( 8 Bit für Exponenten, Bereich 10+38; 24 Bits für Mantisse, Genauigkeit 24 Bit ),
● Double Precision ( 11 Bit für Exponenten, Bereich 10+308; 53 Bits für Mantisse, Genauigkeit 53 Bit ),
● Extended Precision ( 16 Bit für Exponenten, Bereich 10+-4932; 64 Bits für Mantisse, Genauigkeit 64 Bit ).
Gleitpunktzahlen werden vielfältig benötigt ( naturwissenschaftlichen, technischen Anwendungen, Grafik, numerische Mathematik, usw. ). Wegen des Zeitbedarfes
werden Fließkommaoperationen von Gleitpunktzahlen (engl. Floating Point Numbers ) in digitalen Einheiten ( Coprozessor ) ausgeführt.
Eine lesbare Schrift besteht aus Schriftzeichen. Eine Repräsentation von Bildern als Zeichen wird Font genannt. Outline-Typeface ist eine Konturschrift ( Vektoren,
Zeichen nur aus Umrisslinien ). TrueType-Fonts wurden von Apple und Microsoft entwickelt ( Zeichen werden füllbare Hüllkurven-Konturen ).
Bitmapped-Fonts entsprechen binären Bildern. Ein Font besteht z.B. aus einer "Bildersammlung" aus 256 einzelnen Elementen, die mit 8 Bits eindeutig identifiziert
werden können ( Code, z.B. ASCII ). Der Windows-ANSI-Zeichensatz enthält 256 Zeichen. Die ersten 32 Zeichen sind Steuerbefehle. Der ANSI-Zeichensatz ist von
Zeichen 32 bis Zeichen 127 mit dem ASCII-Zeichensatz identisch.
Unicode benutzt 16 Bits und kann 216 = 65536 verschieden Zeichen adressieren. Zu einem Zeichensatz gehören:
● Sonderzeichen und Einzelteile von Zeichen ( z.B. Doppelpunkt, deutsche Umlauten, usw. )
● Zeichen für Zahlen ( mathematischer Formeln )
● Silbenzeichen oder Wortzeichen für fernöstlicher Schriftkulturen
● Schreibrichtung ( bei arabischen Zeichen etwa ist die Schreibrichtung von rechts nach links )
Bei der darstellung von Zeichen können diese auch dynamisch kombiniert werden ( z.B."ä" aus "a" und darüber gesetzten Doppelpunkt ).
Das Unicode-Konsortium ( gegründet 1991, Linguisten, Fachleute ) koordiniert die weltweiten Schrift-Zeichen-Standardisierungen. Zeichen-Codes sollten
systemunabhängig, programmunabhängig, sprachunabhängig sein und dennoch eine Vielfalt der Zeichen-Darstellung unterstützen.
● US-ASCII: Coded Character Set--7-Bit American Standard Code for Information Interchange, ANSI X3.4-1986.
● ISO-646: International Standard--Information Processing--ISO 7-bit coded character set for information interchange, ISO 646:1983.
● ISO-2022: International Standard--Information Processing--ISO 7-bit and 8-bit coded character sets--Code extension techniques, ISO
2022:1986.
● ISO-8859: Information Processing -- 8-bit Single-Byte Coded Graphic Character Sets -- Part 1: Latin Alphabet No. 1, ISO 8859-1:1987.
Part 2: Latin alphabet No. 2, ISO 8859-2, 1987. Part 3: Latin alphabet No. 3, ISO 8859-3, 1988. Part 4: Latin alphabet No. 4, ISO 8859-4,
1988. Part 5: Latin/Cyrillic alphabet, ISO 8859-5, 1988. Part 6: Latin/Arabic alphabet, ISO 8859-6, 1987. Part 7: Latin/Greek alphabet, ISO
8859-7, 1987. Part 8: Latin/Hebrew alphabet, ISO 8859-8, 1988. Part 9: Latin alphabet No. 5, ISO 8859-9, 1990.
● ISO/IEC 10646: Unicode
Die vergebenen Codes ( Zahl-Zeichenwert-Zuordnung ) haben verbindlichen Charakter. Das Unicode-System ( Version 2.0 ) ist eine internationale Norm ISO/IEC 10646.
Das Unicode-System ist in Zahlenbereiche aufgeteilt ( ASCII, Schriftkultur, Sonderzeichen, auch noch Platz für Zukünftiges ).
Windows-Zeichen-Typen
Generisch TCHAR LPTSTR
ANSI UNICODE ANSI UNICODE
Explizit CHAR WCHAR LPSTR LPWSTR
Aufgelöst char wchar_t char * wchar_t
Unicode
Damit die generischen Typen den Unicode-Size verwenden, muß #define UNICODE ( vor den #include ) definiert sein.
ANSI-Zeichen werden auf dem Tastatur-Ziffernblock unter Windows erzeugt durch:
[Alt]-Taste drücken und die ANSI-Nummer mit vorangestellter [0] eingeben.
Beispiel: ø = [Alt]+[0]+[2]+[4]+[8].
Generic-Text Data Type Mappings
TCHAR.H enthält Typen für die "automatische" Anpassung von MBCS (Multi-Byte-Characters) und SBCS (Single-Byte-Characters).
Generic-textdata type name
SBCS (_UNICODE, _MBCS not defined) _MBCS defined _UNICODE defined
_TCHAR char char wchar_t
_TINT int int wint_t
_TSCHAR signed char signed char wchar_t
_TUCHAR unsigned char unsigned char wchar_t
_TXCHAR char unsigned char wchar_t
_T or _TEXT No effect (removed by preprocessor) No effect (removed by preprocessor)
L (converts following character or string to its Unicode counterpart)
_tprintf() kann generische _TCHAR verwenden bei #define UNICODE wird wprintf() benutzt, ohne #define UNICODE wird printf() benutzt
Wie wird generischer UNICODE verwendet?
#ifndef UNICODE #define UNICODE#endif
#include <windows.h>
/* hFile möge bereits existieren ... */ TCHAR Buf[1024]; int cc = wsprintf(Buf, TEXT("\r\n hwnd=0x%08x"),hwnd); #ifdef UNICODE char buf[512]; /* ansi-Buffer */ WideCharToMultiByte(CP_ACP,0,Buf,-1,buf,sizeof(buf),NULL,NULL); cc = (cc+1)/2; fwrite(buf, sizeof(TCHAR), cc, hFile); #else
fwrite(Buf, sizeof(TCHAR), cc, hFile); #endif
↑ Schlüsselwörter
Ein Betriessystem wird oft mit speziellen Entwicklungswerkzeugen entwickelt und gepflegt. Neuerungen (z.B. Einführung von DLL's) ändern auch die Unterstützung
durch "Standard-CPP-Compiler". CPP-Schlüsselwörter (hier MS-Keywords) sind reservierte, vordefinierte Identifizierer, die eine besondere Bedeutung haben und deshalb
im eigenen C++-Quelltext nicht frei verwende werden können. Identifizierer mit führenden Underscores ("__...") sind MS-Erweiterungen.
continue default delete deprecated dllexport dllimport do double
dynamic_cast else enum explicit extern false float for
friend goto if inline int
long mutable naked namespace new noinline noreturn nothrow
novtable operator private property protected public register reinterpret_cast
return selectany short signed sizeof static static_cast struct
switch template this thread throw true try typedef
typeid typename union unsigned using declaration, using directive
uuid virtual void
volatile wchar_t,__wchar_t while
↑ C-/C++-MACROS
Windows verwendet zahlreiche MACROS, die in C/C++-Header-File enthalten sind. Beispiel: Windows-Header-File windowsx.h
↑ C++Grundtypen
C++ kennt main() für Program Startup and Termination und die Standard-Streams: cin ( for standard input ), cout ( for standard output ), cerr ( for unbuffered standard
error output ), clog ( for buffered standard error output ).
C++ kennt die Header-Files ( bzw. subset ) : algorithm, bitset, cassert, cctype, cerrno, cfloat, ciso646, climits, clocale, cmath, complex, csetjmp, csignal, cstdarg, cstddef,
short int entspricht signed short int vorzeichbehaftete Zahl, bei 32 Bit Maschinen meist 2 Byte; int entspricht signed int; all. darf int bei mehrfach Kombinationen weggelassen werden; bei 32 Bit Maschinen meist sizeof(int) = 4;
int i1 = 256+255; char ch = i1;/* ch=255 */ int i2 = ch; /* i2 = -1 oder 255 */ long int entspricht signed long int; bei 32 Bit Maschinen meist sizeof(long) = 4
Typen für Fließkommazahlen
float bei 32 Bit Maschinen meist sizeof(float) = 4 double bei 32 Bit Maschinen meist sizeof(double) = 8
long double bei 32 Bit Maschinen meist sizeof(double) = 8 Typen für vorzeichenlose Integer, logische Werte, Bitfelder, usw.
unsigned char entspricht bei 32 Bit Maschinen meist 1 Byte; unsigned short int vorzeichenlose ganze Zahlen, bei 32 Bit Maschinen meist 2 Byte; unsigned short int shorti = -1; liefert ...
unsigned int vorzeichenlose ganze Zahlen, bei 32 Bit Maschinen meist 4 Byte; unsigned int ui = -1; liefert ... unsigned long int vorzeichenlose ganze Zahlen, bei 32 Bit Maschinen meist 4 Byte; unsigned long l = -1; liefert ...
↑ Standard C- Bibliotheks-Header-Files
Hier sind einige C-Header-Files ( Funktionsnamen ). Zum Vergleich siehe EINEN Windows-Header-File: windowsx.h
↑ Standard C++ Bibliotheks-Header-Files
Die C, C++-Prototypen von Funktionen, Macros, Datenstrukturen, usw. werden in Header-Files zusammengefaßt. Die beim Erstellen des Betriebssystems ( *.DLL's )
benutzten Header - Files werden zur Verfügung gestellt. Liegen auch die zugeordneten *.LIB - Files vor, so können die DLL - Funktionen in eigenen Applikationen
eingebunden werden.
Standard C++ library headers algorithm.h for defining numerous templates that implement useful algorithms bitset.h for defining a template class that administers sets of bits
cassert.h for enforcing assertions when functions execute cctype.h for classifying characters
cerrno.h for testing error codes reported by library functions cfloat.h for testing floating-point type properties
ciso646.h for programming in ISO 646 variant character sets climits.h for testing integer type properties
clocale.h for adapting to different cultural conventions cmath.h for computing common mathematical functions
complex.h for defining a template class that supports complex arithmetic csetjmp.h for executing nonlocal goto statements
csignal.h for controlling various exceptional conditions cstdarg.h for accessing a varying number of arguments
cstddef.h for defining several useful types and macros cstdio.h for performing input and output
cstdlib.h for performing a variety of operations cstring.h for manipulating several kinds of strings
ctime.h for converting between various time and date formats cwchar.h for manipulating wide streams and several kinds of strings
cwctype.h for classifying wide characters deque.h for defining a template class that implements a deque container
exception.h for defining several functions that control exception handling fstream.h for defining several iostreams template classes that manipulateexternal files
functional.h for defining several templates that help construct predicatesfor the templates defined in algorithm.h and numeric.h
iomanip.h for declaring several iostreams manipulators that take an argument
ios.h for defining the template class that serves as the base for manyiostreams classes
iosfwd.h for declaring several iostreams template classes before they arenecessarily defined
iostream.h for declaring the iostreams objects that manipulate the standard streams iso646.h.h for programming in ISO 646 variant character sets
istream.h for defining the template class that performs extractions iterator.h for defining several templates that help define and manipulate iterators
limits.h for testing numeric type properties list.h for defining a template class that implements a list container
locale.h for defining several classes and templates that control locale-specificbehavior, as in the iostreams classes
map.h for defining template classes that implement associative containers
memory.h for defining several templates that allocate and free storage forvarious container classes
new.h for declaring several functions that allocate and free storage
numeric.h for defining several templates that implement useful numeric functions ostream.h for defining the template class that performs insertions
queue.h for defining a template class that implements a queue container set.h for defining template classes that implement associative containerswith unique elements
sstream.h for defining several iostreams template classes that manipulatestring containers
stack.h for defining a template class that implements a stack container
stdexcept.h for defining several classes useful for reporting exceptions streambuf.h for defining template classes that buffer iostreams operations
string.h for defining a template class that implements a string container strstream.h for defining several iostreams classes that manipulate in-memorycharacter sequences
typeinfo.h for defining class type_info, the result of the typeid operator utility.h for defining several templates of general utility
valarray.h for defining several classes and template classesthat support value-oriented arrays
vector.h for defining a template class that implements a vector container
↑ Windows-Standard Typen
Ein Betriessystem ( im Gegensatz zur C++-Definition ) arbeitet mit ( exakt ) festgelegten Typen, Strukturen und Speicherabbildern.
↑ Windows Data TypesEs gibt Zahlreiche Betriebssystemstrukturen (Interface-Funktionen, Parameterart und -folge auf Stack, Nachrichtenspezifikationen, Systemparamter, Alignment, Hardware-
und Treiber-Abhängigkeiten, usw.). 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.
Term Header Description
ATOM Windef.h: typedef WORD ATOM; Atom
BOOL Windef.h: typedef int BOOL; Boolean variable (should be TRUE or FALSE).
BOOLEAN Winnt.h:typedef BYTE BOOLEAN; Boolean variable (should be TRUE or FALSE).
DWORD_PTR Basetsd.h: typedef ULONG_PTR DWORD_PTR; Unsigned long type for pointer precision. Use when casting a pointer to a long type to perform pointer arithmetic. (Also commonly used for general 32-bit parameters that have been extended to 64 bits in 64-bit Windows. )
DWORD32 Basetsd.h:typedef unsigned int DWORD32; 32-bit unsigned integer.
HLOCAL Windef.h: typedef HANDLE HLOCAL; Handle to a local memory block.
HMENU Windef.h: typedef HANDLE HMENU; Handle to a
HMETAFILE Windef.h: typedef HANDLE HMETAFILE; Handle to
HMODULE Windef.h: typedef HINSTANCE HMODULE; Handle to a module. The value is the base address of the module.
HMONITOR Windef.h : if(WINVER >= 0x0500) typedef HANDLE HMONITOR; Handle to a display monitor.
HPALETTE Windef.h: typedef HANDLE HPALETTE; Handle to a
HPEN Handle to a Pen
HRESULT Winnt.h: typedef LONG HRESULT; Return code used by interfaces. It is zero upon success and nonzero to represent an error code or status information.
HRGN Windef.h: typedef HANDLE HRGN; Handle to a
HRSRC Windef.h: typedef HANDLE HRSRC; Handle to a resource.
HSZ Ddeml.h: typedef HANDLE HSZ; Handle to a DDE string.
HWINSTA Windef.h: typedef HANDLE WINSTA; Handle to a
HWND Windef.h: typedef HANDLE HWND; Handle to a
INT Windef.h:typedef int INT; 32-bit signed integer.
INT_PTR Basetsd.h:#if defined(_WIN64) typedef __int64 INT_PTR; #else typedef int INT_PTR;
Signed integral type for pointer precision. Use when casting a pointer to an integer to perform pointer arithmetic.
INT32 Basetsd.h: typedef signed int INT32; 32-bit signed integer.
INT64 Basetsd.h: typedef signed __int64 INT64; 64-bit signed integer.
LANGID Winnt.h: typedef WORD LANGID; Language identifier.
32-bit pointer. On a 32-bit system, this is a native pointer. On a 64-bit system, this is a truncated 64-bit pointer.
POINTER_64 Basetsd.h: #define POINTER_64 __ptr64 64-bit pointer. On a 64-bit system, this is a native pointer. On a 32-bit system, this is a sign-extended 32-bit pointer.
PSHORT Winnt.h: typedef SHORT *PSHORT; Pointer to a SHORT.
PSIZE_T Basetsd.h: typedef SIZE_T *PSIZE_T; Pointer to a SIZE_T.
PSSIZE_T Basetsd.h: typedef SSIZE_T *PSSIZE_T; Pointer to a SSIZE_T.
PSTR Winnt.h: typedef CHAR *PSTR; Pointer to a null-terminated string of 8-bit Windows (ANSI) characters.
PTBYTE Winnt.h: typedef TBYTE *PTBYTE; Pointer to a TBYTE.
PTCHAR Winnt.h: typedef TCHAR *PTCHAR; Pointer to a TCHAR.
PUCHAR Windef.h: typedef UCHAR *PUCHAR; Pointer to a UCHAR.
PUINT Windef.h: typedef UINT *PUINT; Pointer to a UINT.
PUINT_PTR Basetsd.h: typedef UINT_PTR *PUINT_PTR; Pointer to a UINT_PTR.
PUINT32 Basetsd.h: typedef UINT32 *PUINT32; Pointer to a UINT32.
PUINT64 Basetsd.h: typedef UINT64 *PUINT64; Pointer to a UINT64.
PULONG Windef.h: typedef ULONG *PULONG; Pointer to a ULONG.
PULONGLONG Windef.h: typedef ULONGLONG *PULONGLONG; Pointer to a ULONGLONG.
PULONG_PTR Basetsd.h: typedef ULONG_PTR *PULONG_PTR; Pointer to a ULONG_PTR.
PULONG32 Basetsd.h: typedef ULONG32 *PULONG32; Pointer to a ULONG32.
PULONG64 Basetsd.h: typedef ULONG64 *PULONG64; Pointer to a ULONG64.
PUSHORT Windef.h: typedef USHORT *PUSHORT; Pointer to a USHORT.
PVOID Winnt.h: typedef void *PVOID; Pointer to any type.
PWCHAR Winnt.h: typedef WCHAR *PWCHAR; Pointer to a WCHAR.
PWORD Windef.h: typedef WORD *PWORD; Pointer to a WORD.
PWSTR Winnt.h: typedef WCHAR *PWSTR; Pointer to a null-terminated string of 16-bit Unicode characters.
SC_HANDLE Winsvc.h: typedef HANDLE SC_HANDLE; Handle to a service control manager database.
SC_LOCK Winsvc.h: typedef LPVOID SC_LOCK; Lock to a service control manager database.
SERVICE_STATUS_HANDLE
Winsvc.h: typedef HANDLE SERVICE_STATUS_HANDLE; Handle to a service status value.
SHORT Winnt.h: typedef short SHORT; Short integer (16 bits).
SIZE_T Basetsd.h: typedef ULONG_PTR SIZE_T; The maximum number of bytes to which a pointer can point. Use for a count that must span the full range of a pointer.
SSIZE_T Basetsd.h: typedef LONG_PTR SSIZE_T; Signed SIZE_T.
↑ RTL-TypenWindows-Standard Typen der RTL ( Run-Time Library )
Typ Beschreibung deklariert in
clock_t structure Stores time values; used by clock. TIME.H
_complex structure Stores real and imaginary parts of complex numbers; used by _cabs. MATH.H
_dev_t short or unsigned integer Represents device handles. SYS\TYPES.H
div_t, ldiv_t structures Store values returned by div and ldiv, respectively. STDLIB.H
_exception structure Stores error information for _matherr. MATH.H
FILE structure Stores information about current state of stream; used in all stream I/O operations. STDIO.H
_finddata_t,_wfinddata_t
_wfinddatai64_tstructures
_finddata_t stores file-attribute information returned by _findfirst and _findnext. _wfinddata_t stores file-attribute information returned by _wfindfirst and _wfindnext. _wfinddatai64_t stores file-attribute information returned by _wfindfirsti64 and _wfindnexti64.
_FPIEEE_RECORD structure Contains information pertaining to IEEE floating-point exception; passed to user-defined trap handler by _fpieee_flt.
FPIEEE.H
fpos_t (long integer, __int64,or structure, dependingon the target platform)
Used by fgetpos and fsetpos to record information for uniquely specifying every position within a file.
STDIO.H
_HEAPINFO structure Contains information about next heap entry for _heapwalk. MALLOC.H
jmp_buf array Used by setjmp and longjmp to save and restore program environment. SETJMP.H
lconv structure Contains formatting rules for numeric values in different countries. LOCALE.H
_off_t long integer Represents file-offset value. SYS\TYPES.H
_onexit_t pointer Returned by _onexit. STDLIB.H
_PNH pointer to function Type of argument to _set_new_handler. NEW.H
ptrdiff_t integer Result of subtraction of two pointers. STDDEF.H
sig_atomic_t integer Type of object that can be modified as atomic entity, even in presence of asynchronous interrupts; used with signal.
SIGNAL.H
size_t unsigned integer Result of sizeof operator. STDDEF.H and other include files
_stat structure Contains file-status information returned by _stat and _fstat. SYS\STAT.H
time_tlong integer Represents time values in mktime and time. TIME.H
_timeb structure Used by _ftime to store current system time. SYS\TIMEB.H
tm structure Used by asctime, gmtime, localtime, mktime, and strftime to store and retrieve time information.
TIME.H
_utimbuf structure Stores file access and modification times used by _utime to change file-modification dates.
SYS\UTIME.H
va_list structure Used to hold information needed by va_arg and va_end macros. Called function declares variable of type va_list that can be passed as argument to another function.
STDARG.H
wchar_t internaltype of a wide character
Useful for writing portable programs for international markets. STDDEF.H, STDLIB.H
wctrans_t integer Represents locale-specific character mappings. WCTYPE.H
wctype_t integer Can represent all characters of any national character set. WCHAR.H
wint_t integer Type of data object that can hold any wide character or wide end-of-file value. WCHAR.H
Die Typen und Strukturen eines Betriessystems sind vielfältig und umfangreich. Windows-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.
↑ 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, // handle to menu, or child-window identifier HINSTANCE hInstance, // handle to application instance LPVOID lpParam // pointer to window-creation data);
| Prefix Naming Conventions
↑ Prefix Naming ConventionsPrefix 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 lpfnAbort
Hungarian Notation (nach MS):
Prefix Description
a Array
b BOOL (int)
c Char
cb Count of bytes
cr Color reference value
cx Count of x (short)
dwDWORD (unsigned long)
fFlags (usually multiple bit values)
fn Function
g_ Global
h Handle
i Integer
l Long
Prefix Description
lp Long pointer
m_Data member of a class
n Short int
p Pointer
s String
sz Zero terminated String
tm Text metric
u Unsigned int
ulUnsigned long (ULONG)
wWORD (unsigned short)
x,yx, y coordinates (short)
Prefix Combination Description
pszMyString A pointer to a string.
m_pszMyStringA pointer to a string that is a data member of a class.
Convention Description
CMyClass Prefix 'C' for C++ class names.
COMyObjectClassPrefix 'CO' for COM object class names.
CFMyClassFactoryPrefix 'CF' for COM class factory names.
IMyInterfacePrefix 'I' for COM interface class names.
CImpIMyInterfacePrefix 'CImpI' for COM interface implementation classes.
↑ Windows-Header-Files
Das Betriessystem wurde überwiegend mit C/C++ entwickelt. Die System-Funktionen sind als Maschinencode in DLL's enthalten. Für die Entwicklung der System-
Funktionen wurden Header-Quelltext-Files benutzt. Diese Header-Files werden auch für die Programm-Entwicklungen verwendet. Es gibt zahlreiche Windows-Header-
↑ EntwicklungsumgebungUm aus ASCII-Files ein lauffaehiges *.EXE-Programm zu erstellen werden Übersetzungsprogramme benötigt, die aus lesbarem Buchstaben-Code maschinen-Code
generieren. Ein direkter Entwurf der Bitmuster des Maschinencodes ist wegen des Umfanges und der Komplexität nicht möglich.
Einbettungen von Tools
Werzeuge Dateien-Endungen
● Editor ( einfache bzw. auswendige Textbearbeitung
und -gestaltung ),
● Quelltext-Generierung ( Assistenten ),
● Assembler ( übersetzt von Assembler nach
Maschinencode ),
● Compiler ( übersetzt in Assembler bzw.
Maschinencode ),
● Linker ( fügt compilierte Files zusammen ),
● Projektverwaltung ( überwacht den Build-Prozess ),
● *.asm für Assembler - Quelltexte, *.c für C-Quell-
Texte, *.cpp für C++-Quell-Texte,
● *.obj für binärer OpCode nach dem Compilieren,
● *.lib für Bibliotheks-Routinen und Dll-Zuordnungen,
● *.rc für Resourcen - Quelltexte,
● *.res für binärere Resourcen - Files,
● *.map für die DLL - Adressen,
● *.exe für den executierbarer File,
● *.rtf für ASCII-Rich-Text-File incl. Formatierung,
● *.hlp für binärer HeLP-Files
Moderne Werkzeuge bestehen aus Software - Komponenten zur Programmentwicklung. Die Zahl der benötigten Tools wächst. Anstatt diese Programme einzeln (oder mit
Kommandozeile, bzw. make-File) zu verwenden, werden integrierende Bedienungsumgebung interaktiv verwendet. Es bestehen vielschichtige Abhängigkeiten zu (
standardisierten ) Software-Systemen, die durch die gleiche Bedienungsumgebung unterstützt werden und Entwicklungen mit unterschiedlichen Biblioteken und
Programmiersprachen (Java, C, Assembler, C++, VB, usw.) ermöglichen. Je moderner und komplexer ein Entwicklungssystem ist, um so größer ist die Zahl der
Einstellungen und Variationen und die Einarbeitungszeit.
Windows verwendet für Nachrichten-, Style-, Control- Konstanten die folgenden Gruppen:
BM_ Button Control Messages BN_ User Button Notification Codes
MF_ Menu flags for Add/Check/EnableMenuItem() MFS_ Menu flags for Add/Check/EnableMenuItem()
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
↑ *.LIB - Files
Windows.h enthält die Funktions - Prototypen. Dadurch kann der Compiler die Schreibweise ( Syntax ) in dem eigenen Programm überprüfen. Damit der Linker dnden
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:
Von den Entwicklungs - Werkzeugen mußte der Linker immer mehr Aufgaben übernehmen. Die Linker - Zeiten übersteigen vielfach die Compiler - Zeiten. Eine Teilung
der Linker - Aufgaben in traditionelles Linken und der Resourcen - Erstellung ist angezeigt.
Der Linker fügt Binärcode aneinander und verbindet die wechselseitigen Zuordnungen ( Adressen ). Bei einem Linker - Fehler ist der Zusammenhang mit dem lesbaren
ASCII - Quelltext verloren. Der Linker gibt im Fehlerfall die Namen der nicht gefundenen bzw. doppelt vorhanden Symbole aus. Weil bei C und C++ - Code gemäß
gemischt werden können, ist zur Fehlererkennung vielfach auf die Schreibweise der ausgegebenen Namen zu beachten.
Linker-Fehler-Anzeige
Diagnose
myFkt$int$int Es wurde mit C++ compiliert, bzw. eine C++ Bibliothek wird verwendet.
MYFKT Es wurde mit PASCAL deklariert compiliert, bzw. Linkerschalter auf Großbuchstaben, bzw. Win16 - Bibliothek wird verwendet.
_myFkt Es wurde mit C, CDECL compiliert, bzw. es werden C - Bibliotheken verwendet.
↑ *.RC - Files
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.
↑ Übersetzungsvorgang
Für den Übersetzungsvorgang von Windows - Applikationen werden die Header-Files
mit den Funktions - Prototypen in den C, C++ - Quelltext eingebunden. Dadurch kann bereits der Compiler in unseren *.C, *.CPP - Files die richtige Schreibweise der
Window - Typen und -Funktionen überprüfen. Der Compiler übersetzt die *.CPP - Files in *.OBJ - Files. Wenn der Linker-Pfad zu *.LIB richtig gesetzt ist, kann der
Linker aus den Window-Bibliotheken *.LIB die Einsprüngen in die Window-dll´s entnehmen und in unser Programm einbauen. Unser Programm verwendet dann die
benötigten Window-DLL’s. Der Resourcen-Compiler erzeugt aus *.RC den binären *.RES-File:
Um einen ausführbaren, binär - File ( *.EXE ) zu erzeugen, müssen ASCII - Files in Maschinen-Code übersetzt werden:
Die Steuerung des Übersetzungs-Vorganges wird i.a. von der Projekt - Entwicklungs - Umgebeung oder von make.exe (nmake.exe ) übernommen. Der
Übersetzungsvorgang kann auch die automatische Hyphertext - Help - Erzeugung enthalten.
↑ Betriebssystem-KernAm Anfang bestand das Windows-Betriebssystem aus weniger als 10 DLL's. Bei XP gibt es bis zu 2000 DLL's. Der eigentliche Betriebssystem - Kern besteht aus den drei
Dateien (nativ-Funktionen in DLL). Diese DLL's werden bei Start des Betriessystems geladen (und heissen deshalb nicht .dll sondern .exe).
Bei diesen Dateien handelt es sich um sogenannte DLL’s ( Dynamic Link Libarys ). Dies sind binäre Funktionsbibliotheken. Zum Betriebssystem gehören noch weitere
● 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). 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-Funktionsaufrufe erfolgenüber den 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 Object Creator function Destroyer function
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 Dialogelemente ( Controls ):
lesbare Daten ( Resources ) sind:
Programmierschnittstelle ( Shell and Common Controls
Fensterbehandlung ( Windows ) Datenzuordnung zu Fenstern ( Window Properties ), mehrere Fenster mit gleichen Eigenschhaften ( Window Classes ), Nachrichtenbearbeitung ( Message and Message Queues ), 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.
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.
Als ein Beispiel für den Umfang einer Funktion soll hier GetDeviceCaps() angegeben werden. GetDeviceCaps() gibt Informationen zum Device Kontext zurück.
int GetDeviceCaps( HDC hDC, // device-context handle int nIndex // index of capability to query );
Für den Parameter nIndex kann eine der folgenden Zahlen gewählt werden. Die eingerückten Konstanten kennzeichnen die zugehörigen Rückgabewerte.
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 fileHORZSIZE 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. 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. 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.
↑ Beispiel: GetSystemMetrics()
Mit der Funktion GetSystemMetrics köennen ( geometrische ) Fenster - und Screen - Werte abgefragt werden. Durch
Weil bereits ein erstes Programm unübersichtlich ist, wird das Grundgerüst zunächst im Pseudocode betrachtet. Ein einfaches Programm hat die folgende Struktur: Ein
Window-Programm besteht aus der WinMain()-Funktion, die
1. ... mit Hilfe von RegisterClassEx() eine Klasse einrichtet
2. ... mit Hilfe von CreateWindow die Daten für ein Fenster (zur Klasse) anlegt
3. ... eine Haupt-Nachrichten-Schleife einrichtet, die die Nachrichten an die (zu ergänzende)
Wegen der vielen Parameter wird der C/C++ - Quelltext z.T. bereits unuebersichtlich. Auch verfuegbare Klassen - Bibliotheken verwenden den gleichen Aufbau ( und sind
oft ebenfalls unuebersichtlich! ).
↑ "Hallo Welt"
Das folgende Beispiel besteht aus der WinMain() und der WndProc() - CALLBACK - Funktion. Es wird ein Hauptfenster angelegt und Text zentriert hinein geschrieben. //
Die Start - Adresse einer Window - Applikation ist die WinMain() - Funktion( APIENTRY ). WinMain ist der Haupt - Eintritts - Punkt für eine Windows - Anwendung.
Diese Funktion entspricht der Funktion main() bei einem C-Programm. Der WinMain - Startup - Code ruft die WinMain-Funktion durch den Namen auf. Windows
verwendet diese Funktion als "initial entry point" APIENTRY). Beim Start wird der Startup-Code ausgeführt, der u.a. die Windows-Funktionen
● InitTask ( KRNL386 ),
● InitApp ( USER ) und
● WaitEvent( KERNEL)
aufruft. Danach ruft der Startup - Code unsere WinMain - Funktion auf. Diese Schritte bei Start eines Win - Programmes können grob skizziert werden:
↑ WinMain() initialisiert Register
InitTask füllt bei Win16 die folgenden Register mit Werten, die beim Laden der Applikation auf den Stack gelegt werden:
BX = Stack-Grösse, CX = Heap-Grösse, DI = Instanz-Handle, SI = vorherige Instanz, ES = PSP-Adresse
↑ WinMain() initialisiert den Stack
Außerdem initialisiert InitTask pStackTop, pStackMin, pStackBottom im Task - Header der aufrufenden Tastk. DLL´s sind keine Task´s, rufen aber in ihrem Startup-Code
auch InitTask auf.
↑ WinMain() richtet Application-Message-Queue ein
Durch InitApp ( USER ) wird eine User - Nachrichten - Warte - Schlange ( Application - Message - Queue ) eingerichtet. Die Nachrichten der Application - Message -
Queue haben ein einheitliches Format.
Die Nachrichten, die zu unserem Programm gehören, werden durch Windows der
● System - Message - Queue entnommen,
● auf ein einheitliches Format gebracht und
● in unsere Application - Message - Queue
gelegt.
↑ WinMain() initialisiert die C - Laufzeit - Bibliothek
Die C-Laufzeit-Bibliothek wird initialisiert. Die statischen Konstruktoren von C++ werden initialisiert. Der Startup-Code legt die WinMain - Parameter auf den Stack und
ruft WinMain auf.
↑ WinMain() entfernt Prä - Nachrichten
WaitEvent ( KRNL386 ) prüft ( PostEvent, Reschedule ), ob bereits ein Ereignis an die aktuelle Task ( 0 ) geschickt wurde. Wenn das Ereignis abgeschickt und noch nicht
eingetroffen ist, so wird gewartet und dann die bisher eingetroffenen Ereignisse gelöscht (siehe: Start-Up-Code).
↑ 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.
Damit später mit ( CreateWindow oder CreateWindowEx ) spezielle Fenster angelegt werden können, müssen vorher der Speicherbereich für die gemeinsamen Daten
Die hinterlegten Daten können mit GetClassInfoEx() erhalten werden.
↑ RegisterClassEx()
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 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.
↑ 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.
Dabei ist das Fenster noch nicht sichtbar, obwohl das Handle != NULL den allokierten Speicher referenziert und Fenster-Daten eingetragen wurden.
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, // handle to menu, or child-window identifier HINSTANCE hInstance, // handle to application instance LPVOID lpParam // pointer to window-creation data );
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 ). dwStyle spezifiziert den Style des Fensters und Funktionalität:
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.
↑ Was ist ein Handle?
Win32 nutzt die 32-Bit-CPU-Architektur. Bei Win32 entspricht das Datensegment-Register DS nicht mehr einer direkten Adresse auf das aktuelle Datensegment.
● DS entspricht einem Index für die Deskriptor - Tabelle.
● Es gibt lokale Deskriptortabellen LDT und eine globale Deskriptortabellen GDT.
Ein 8 - Byte - Element aus der Deskriptor - Tabelle enthält die endgültige Byte - Zieladresse und das Sicherheits - Byte.
Beim erstmaligen Benutzen wird mit dem DS - Index das 8 - Byte - Element aus der Deskriptor - Tabelle geholt und in die CPU übertragen. Jeder CPU - Befehl kann
damit ( ohne Verzögerung ) das Element innerhalb der CPU nutzen ( Sicherheitsbyte, Protected Mode, Privileg Level ).
Beinahe jede Window - Funktion benötigt globale Window - Daten, Fenstergröße, Device - Kontext, usw. Damit die Funktion richtig ausgeführt wird, muß vorher das
Handle beschafft werden. Nur dann kann die Windows - Funktion die benötigten globalen Daten erreichen und nutzen.
● Hinter dem Handle verbirgt sich der Index in eine Deskriptortabelle.
● Ein Win16/Win32 - Handle bnutzt 16/32 Bit.
● Ein Handle mit dem Wert 0 wird nicht verwendet und dient zur Fehler - Erkennung.
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 sendet die aufgerufene DefWindowProc()
WM_DESTROY und PostQuitMessage(); beendet die Haupt-Nachrichtenschleife.
BOOL GetMessage( LPMSG lpMsg, // address of structure with message HWND hWnd, // handle of window UINT wMsgFilterMin, // first message UINT wMsgFilterMax // last message);
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 ).
↑ 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.
↑ Hot-Keys
Existiert Accelerator-Tabelle hAccel ("Hot-Keys" für das Menü), so können in der Hauptnachrichten-Schleife, nach GetMessage(), die "Hot-Keys"-Ereignisse abgefangen
und mit Hilfe der Funktion
int TranslateAccelerator(HWND hWnd, HACCEL hAccel, LPMSG lpMsg);
die dem hWnd-Fenster zugeordnete CALLBACK-Funktion aufgerufen werden.
↑ 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.
↑ 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 kommt über den einen
System-Buffer in den Applikations-Nachrichten-Buffer, wird dort entnommen und ruft die CALLBACK - Funktion
LRESULT CALLBACK WndProc( HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam) des Fensters mit DispatchMessage() auf. Aus dem
Handle der Tasten-Nachricht kann das Fenster ersehen werden. DispatchMessage() bestimmt das Fenster und ruft die CALLBACK - Funktion des Fenster auf.
Kurz-Sprechweise: 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. Die Nachrichten werden innerhalb der
CALLBACK - Funktion bearbeitet oder an die DefWindowProc() weiter geleitet.
↑ Beispiel: 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
uMsg = 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. 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,
↑ BeginPaint(), EndPaint()
Eine WM_PAINT - Nachricht wird meist verarbeitet durch
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 Das Update- Rechteck wird in einer RECT- Struktur gespeichert
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} PAINTSTRUCT;
typedef struct _RECT { // rc LONG left; LONG top; LONG right; LONG bottom; } RECT;
Ein Handle auf den Device-Context hDC ( das zum gesamten Client - Bereich gehört ), wird erhalten durch
hDC = GetDC( hWnd ) ;
...
ReleaseDC( hWnd, hDC ) ;
Das Update - Recheck ( validates ) wird auch gelöscht durch den Aufruf von DefWindowProc(), die ( falls erforderlich ) WM_NCPAINT, WM_ERASEBKGND -
Mit der GetUpdateBeginPaint() ... 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.
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.
↑ Sichtbarkeit von Fenstern
Ein Fenster kann in den Vordergrund geholt werden. Beispiel:
mit uMsg = 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 |
Funktion wird mit uMsg = WM_DESTROY aufgerufen. Infolge von PostQuitMessage( 0 ) wird das Fenster geschlossen.
↑ DefWindowProc()
Einige Nachrichten werden in der eigenen CALL-Klassen-CALBACK-Funktionen 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
Kontroll-Fragen: Kontroll-Fragen | cpp-Rahmen-Programm(cpp-Quelltext) | Nachrichtenprotokollierung.cpp-Quelltext | gdi-class-Quelltext | 2. SP2-Praktikum (SS 2005) | Hallo Welt | Text in Titelzeile | Maus-Postion in Titelzeile | Hinweise zu wsprintf() | Hinweise zur MessageBox() | Hinweise zur Nachrichtenprotokollierung | Hinweise zu WM_CHAR | Hinweise zu WM_KEYDOWN
↑ 2. SP2-Praktikum (SS 2005)
Es soll ein erste "Hallo Welt"-Windows-Applikation geschrieben, getestet und erweitert werden. Hierzu sollen die Teil-
Aufgabe 1, 2, 3, ..., usw. bearbeitet werden. Zur Reduzierung der Tipp-Tätigkeit darf von dem angegebenen cpp-Rahmen-
Programm ausgegangen werden. Das cpp-Rahmen-Programm wird erweitern.
Zum besseren Verstehen des Nachrichten-Konzeptes sind einige Tests durchzuführen. Es ist z.B. aktuelle Maus-
Position in der Titelzeile auszugeben, eine MessageBox() ist angezeigen. Die Nachrichten sollen in einem .txt-File
geschrieben werden. Später einmal sind die Nachrichten mit dem Spy-Werkzeug ( Spy ) zu verfolgen ( Maus-
Nachrichten, Tasten-Nachrichten, Fenstervergrößerung, usw. ). und die verwendeten Windows-Datenstrukturen mit
dem Debugger schrittweise anzuschauen.
1. Mit WinMain() ist eine Windows-Applikation zu schreiben. Ein Programm "Hallo
Welt" ist mit WinMain() und WndProc() zu erstellen. Verwenden Sie bitte das .cpp-
Rahmen-Programm.
2. Der Text in der Titelzeile ist bei WM_RBUTTONDOWN zu ändern
3. Die Maus-Position ( bei Klick mit der rechten Maus-Taste ) ist SetWindowText() in die
in Titelzeile zu schreiben.
4. Nun soll bei Klick mit der rechten Maus-Taste zusätzlich zur Maus-Position auch noch
MK_SHIFT oder/und MK_CONTROL in die in Titelzeile geschrieben werden.
MK_SHIFT (bzw. MK_CONTROL) soll die gleichzeit-gedrückte Shift-Taste (bzw.
Strg-Taste) anzeigen.
5. Es soll eine MessageBox() angezeigt werden, wenn die [A] Taste gedückt wird.
Verwenden Sie das Tasten-Ereignis WM_CHAR. In der MessageBox() soll die
Fenstergrösse (Breite,Höhe) ausgegeben werden.
6. An dieser Stelle soll das Nachrichten-Konzept besser verstanden werden. Hierzu ist die
WM_-Nachrichten-FOLGE zu prokollieren. Welches sind die ersten Nachrichten?
Welches sind die letzten Nachrichten? Welche Nachrichten wird beim "runter-drücken"
der A-Taste gesendet? Hier ist mehr zur Nachrichtenprotokollierung.
7. Die Tastatur soll nun "verfeinert" verwendet werden. Verwenden Sie hierzu das Tasten-
Ereignis WM_KEYDOWN. Wenn die [A] Taste gedückt wird, soll eine MessageBox()
angezeigt werden. Es soll eine ander MessageBox() angezeigt werden, wenn auf dem
Ziffernblock die [5] (bei aus-geschalteter NUM-Taste) gedrückt wird. Es soll eine ander
MessageBox() angezeigt werden, wenn auf dem Ziffernblock die [5] (bei ein-
geschalteter NUM-Taste) gedrückt wird.
8. Das "Hallo Welt"-Beispiel ist zu debuggen.
9. Es ist eine gdi-Klasse zu schreiben, zu testen und um die Möglichkeit einer Font-
Benutzung zu erweitern. Für Source-Hinweis siehe gdi-class-Quelltext
10. Die Nachrichten sind mit einem geeigneten Werkzeug ( Spy ) zu verfolgen.
11. optional: Es ist eine einfache Grafik zu erstellen, die die Funktionen MoveToEx(),
LineTo(), Ellipse(), Rectangle(), RoundRect(), Polyline(), PolyPolyline() verwendet.
12. optional: Mit einer Windows-Applikation sind unterschiedliche Parameter der
MessageBox()-Funktion zu untersuchen.
↑ Hallo Welt
Es ist ein einfaches, kleines Beispiel mit WinMain() und einer WndProc() - CALLBACK - Funktion sorgfältig zu
durchdenken. Hier ist ein cpp-Rahmen-Programm
Mit dem Debugger ist das Programm schrittweise durchzugehen. Das "Hallo Welt"-Beispiel ist zu debuggen und zu
kommentieren. Die Window-Daten-Strukturen sind anzuschauen (z.B. als Kommentar am Programm-Anfang in den
Quelltext einzufügen).
↑ Text in Titelzeile
Ändern Sie das Programm so, dass das Windows-Programm die eigene hg-Nummer in der Titelzeile beim
WM_RBUTTONDOWN-Ereignis anzeigt. Verwenden Sie
SetWindowText (hwnd, szText);
Der Text in der Titelzeile ist bei WM_RBUTTONDOWN zu ändern.
↑ Maus-Postion in Titelzeile
Die Position ( xPos, yPos ) der Maus soll bei einem Klick in der Titelzeile erscheinen. Verwenden Sie in der
CALLBACK-Funktion Maus-Nachrichten, wie z.B.
case WM_LBUTTONUP: break; case WM_RBUTTONUP: break; case WM_MBUTTONUP: break; case WM_LBUTTONDOWN: break; case WM_RBUTTONDOWN: break; case WM_MBUTTONDOWN: break; case WM_LBUTTONDBLCLK: break; case WM_MBUTTONDBLCLK: break; case WM_RBUTTONDBLCLK: break; case WM_MOUSEMOVE: break;
use_gdi soll auch 2D-Transformationsfunktionen (ein wenig ähnlich zu OpenGL) ermöglichen.
#ifdef use_gdi int _t; // Tiefe von mat_push(), mat_pop() int _w,_h; // Breite, Höhe double m_xMin, m_xMax, m_yMin, m_yMax; // 2D-Welt BOOL m_isotrop; double _M[6*8];// für 2D-Transformationen #endif
GDI() Der Class-Konstruktor GDI() { ... } initialisiert auf Gerätebasis das Fensterhandle m_hwnd = NULL; die Farbe m_crColor = RGB(0,0,0); die mat_push()-Schachtelunstiefe _t = 0; und die Matrixelemente (Einheitsmatrix) _M[0]=1.0; _M[1]=0.0; _M[2]=0.0; _M[3]=0.0; _M[4]=1.0; _M[5]=0.0;
sx > 1.0 streckt in x-Richtung,sx < 1.0 staucht in x-Richtung,sy > 1.0 streckt in y-Richtung,sy < 1.0 staucht in y-Richtung
Rotation mat_rotat(w)
Der Winkel w wird in Grad angegeben
Grösse der 2D-Weltmat_ortho(xMin,xMax,yMin,yMax)
mat_ortho() berechnet und setzt die Abbildungsfaktoren, _M[0], _M[1], _M[2], _M[3], _M[4], _M[5]=0.0;die für jede Umrechnung von der 2D-xy-Welt auf die i,j-Pixel gebraucht werden. Betriebssysteme unterstützen (ganzzahlige) Gerätekoordinaten.
begin_paint() begin_paint() setzt mit Hilfe von BeginPaint() den DeviceKontext m_hdc
set_color() set_color() rechnet die r,g,b-Werte 0.0 <= double r <= 1.00.0 <= double g <= 1.00.0 <= double b <= 1.0auf die (ganzzahlige) Gerätefarbe um.
begin_pen() end_pen()
begin_pen() und end_pen() hinterlegen Windows-Objekt im Device-Kontext. Mit begin_pen(INT idxStyle, UINT nWidth) können "trickreiche" Zeichenstift-Muster gesetzt werden.
move_to(x,y) move_to(x,y) rechnet x,y in i,j um und verwendet dann die Windows-GDI-Funktion MoveToEx(). move_to() ist ein "hingehen ohne Zeichnen".
line_to(x,y) line_to(x,y) rechnet x,y in i,j um und verwendet dann die Windows-GDI-Funktion LineTo(). LineTo() ist ein "hingehen mit Zeichnen".
g.begin_pen(); for (double t=0.0; t < 6.29; t += 0.1) { double x = 0.62*cos(t); double y = 0.62*sin(t); g.move_to( x, y); g.line_to(0.0,0.0); } g.end_pen();
case WM_SIZE:{ int w = LOWORD(lParam); int h = HIWORD(lParam); g.mat_viewport(hwnd, w, h); g.mat_ortho(-1.0,1.0, -1.0,1.0); return 0; } case WM_PAINT:{ g.begin_paint(hwnd); // on_???; g.end_paint(); break; } default: return DefWindowProc(hwnd,uMSG,wParam,lParam);
///////////////////////////////// globale Daten, die zu Member-// Variablen werden sollen://///////////////////////////// MSG m_msg; // aktuelle Nachricht
LRESULT prae_wnd_proc (HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam ) { // hinterlege die aktuelle Nachricht in der WIN-Instanz: this->set_msg(hwnd,uMsg,wParam,lParam);
switch(uMsg) {
case WM_CLOSE: { if (GetParent(hwnd))break; if(0 != this->get_hwnd_index(hwnd))break; TCHAR buf[1024]; GetWindowText(hwnd,buf,sizeof(buf)); int id = MessageBox(hwnd,TEXT("Exit?"), buf, MB_ICONQUESTION | MB_YESNO); if(id == IDYES) if( 0 == this->get_hwnd_index(hwnd)) DestroyWindow(hwnd);//sendet WM_DESTROY return 0; }
case WM_DESTROY: { PostQuitMessage(0); break; }
case WM_COMMAND:{ if(HIWORD(wParam) > 1)break; WORD id = LOWORD(wParam); //id=MENU-Item-Identifizierer m_pms = this->get_menu_tab(hwnd); if(!m_pms) return 0; int k = 0; // suche id in Menu-Tabelle while( m_pms[++k].pText) { // Menu-Text if( m_pms[k].id != id ) continue; if(!m_pms[k].menuProc) break; // Funktion ausführen BOOL ok = m_pms[k].menuProc();
} //InvalidateRect(hwnd,NULL,TRUE);UpdateWindow(hwnd); break;} // ende WM_COMMAND
case WM_ACTIVATE: { if ( WA_INACTIVE == LOWORD(wParam) ) { // becoming inactive m_hwnd = 0; } else { // becoming active m_hwnd = (GetWindowLong(hwnd,GWL_STYLE) & WS_CHILD)? GetParent(hwnd):GetWindow(hwnd,GW_OWNER); } break; } // ende WM_ACTIVATE
// get_hwnd_index() gibt den Index des aktuellen Fensters zurückint get_hwnd_index(HWND hwnd) { if(!IsWindow(hwnd)) return 0; for(int i = 0; i < hwa_max; i++) { if(hwnd == hwa[i]) return i; } return 0; }
// set_text() schreibt Text in ein Fenster (Titelzeile)void set_text(HWND hwnd, TCHAR * sz) { SetWindowText(hwnd, sz);}
// set_menu():// aus der vorhandenen "user-menu-struktur" wird// ein Menu und die Accel-Tabelle zusammengebaut// und gesetztBOOL set_menu(HWND hwnd, MENU_STRUCT menu_struc[]){ //!!! menu_struc muss static sein !!! err_if(!hwnd,"MENU_CLASS braucht hwnd"); if(!hwnd)return FALSE;
// hinterlege neue praeWndProc in hwnd-Daten: m_old_wnd_proc = this->set_wndproc(hwnd, praeWndProc); // hinterlege Menu-Tabellen-Zeiger in hwnd-Daten: MENU_STRUCT *pOldMenu = this->set_menu_tab(hwnd,menu_struc); err_if(pOldMenu,"pOldMenu");
// ermittle die Anzahl lenMenu von Menu-Items: int lenMenu = -1; while(menu_struc[++lenMenu].pText);
// Menu und Accel-Tab aus einer menu_struc erstellen: HMENU hMenu1 = 0, hMenu = CreateMenu();
ACCEL ac[200] = {0}; int lenAccel = 0;
WORD id = 10000; // idStart
for (int k = 0; k < lenMenu; k++) { // falls Funktion menu_struc[k].menuProc vorhanden ... if((k>0)&&(menu_struc[k].menuProc)) { id++; // diesen id-Identifizierer dem Menu-Item zuordnen // gleichzeitig die Accelarator-Tabelle aufbauen: WORD key = menu_struc[k].key; //menu_struc[k].key if(key) // falls ein Accel-Key: { err_if(lenAccel>=200,"lenAccel>=200"); BYTE fVirt = menu_struc[k].fVirt; ac[lenAccel].fVirt = (BYTE)(fVirt & ~0x80);//menu_struc[k].fVirt ac[lenAccel].key = key; //menu_struc[k].key ac[lenAccel].cmd = id; //id ab 10001 ... lenAccel++; } // Menu fertig zusammen bauen: menu_struc[k].id = id; AppendMenu(hMenu1,MF_STRING,id,menu_struc[k].pText); } else { if(hMenu1)DestroyMenu(hMenu1); hMenu1 = CreateMenu(); AppendMenu(hMenu,MF_POPUP,(int)hMenu1,menu_struc[k].pText); }
// Beipiel um ein Fenster zu "machen"// ist wnd_class_proc=NULL, so wird die // interne CALLBACK-Funktion verwendetHWND create_main_window(int xPos,int yPos,int dx,int dy,WNDPROC wnd_class_proc){ // existiert "my_class" bereits? WNDCLASSEX tem = {0}; tem.cbSize = sizeof(WNDCLASSEX) ; BOOL ok1 = GetClassInfoEx(GetModuleHandle(0),TEXT("my_class"),&tem);
if(!ok1) // "my_class" nur einmal anlegen: { WNDCLASSEX wndClass = {0}; if(!wnd_class_proc) wnd_class_proc = DefWindowProc;
/////////////////////////////////////////////////// lege globale Instanz win an://///////////////////////////////////////////////WIN_CLASS g = WIN_CLASS();
/////////////////////////////////////////////////// CALLBACK-Funkt-Einsprung muss ausserhalb // der Klasse erzeugt werden .../////////////////////////////////////////////////LRESULT CALLBACK praeWndProc(HWND hwnd,UINT uMsg,WPARAM wParam,LPARAM lParam) { return g.prae_wnd_proc(hwnd,uMsg,wParam,lParam );
// hier kann aufgräumt werden return (int) 0;} // ende WinMain
4. SP2-Praktikum (SS 2005)
Diese Aufgabe besteht darin, mit einer modalen DialogBox das Hauptprogramm zu gestalten und weitere DialogBoxen zu erstellen und die zugehörigen
CALLBACK-Funktionen zu schreiben.
1. DialogBox() soll in WinMain() benutzt werden.
2. Diese DialogBox soll ein Menu erhalten.
3. Es ist eine Dialog-CALLBACK-Funktion zu schreiben, die die Klick-Nachricht eines OK-Button bearbeitet.
4. Es sind Button's einzufügen, die notepad.exe starten.
5. Per Button-Klick sind weitere *.exe-Programme zu starten.
6. Es ist eine Prototyp füer einen Hex-Taschenrechner zu programmieren.
Es sind Verbesserungen und Erweiterungen ( ComboBox, Edit ) vorzunehmen.
7. Optional: Taschenrechner Ohne Ressourcen-Script
Hinweise
WinMain mit DialogBox()-Funktion
Es ist in einem neuen ( leeren ) Projekt ein einfacher Dialog zu erstellen ( z.B. 2 Buttons, Eingabe-Zeile, Menu, Icon ). Ist die IDD_DIALOG-Dialog-Resource (
resource.rc ) verfügbar, so kann mit der dlgProc-CALLBACK-Funktion ein Dialog gemaess
int ret = DialogBox( GetModuleHandle(NULL), MAKEINTRESOURCE( IDD_DIALOG), hwnd, (DLGPROC)dlgProc);
erzeugt werden. Das Windows-Hauptprogramm soll den DialogBox()-Aufruf (ohne Nachrichten-Schleife) enthalten. Die DialogBox() erzeugt implizit die while-Schleife eines (modalen) Hauptprogrammes. Die Dialog-Resource ( resource.rc ) soll den Identifizierer IDD_DIALOG haben. Ein IDD_DIALOG-Dialog und die dlg-CALLBACK-Funktion dlgProc) sollen mit dem Ressourcen-Workshop erstellt werden.
TCHAR buf[256]; GetWindowText(hwnd,buf,sizeof(buf)/sizeof(TCHAR)) ; int ret = MessageBox(hwnd,buf,"Exit?",MB_ICONQUESTION|MB_YESNO); if ( IDNO == ret ) return TRUE; EndDialog( hwnd, ret ); //wParam=IDNO wird der ret-Value von DialogBox() break; }
/* spaeter: case WM_COMMAND: { if(HIWORD(wParam)) break; switch ( LOWORD(wParam) ) { //MenuItems, Buttons case IDB_...: break; case IDM_...: MessageBox( hwnd, "Hallo","ID...",MB_OK); break; case IDOK : //(OK)-Button zum beenden SendMessage( hwnd, WM_CLOSE, LOWORD(wParam), lParam ); return TRUE; } } break; //Ende von WM_COMMAND*/
} //Ende von switch(iMsg) return FALSE;}
Menu für DialogBox
Die Main-DialogBox soll ein Menu IDM_MENU erhalten. Das Ressourcen-Script soll mit dem Resourcen-Workshop erstellt werden. Der Resourcen-
Workshop kann unmittelbar das Menu einfügen. Alternativ kann z.B. das Menu IDM_MENU ( zur Laufzeit ) unter case WM_INITDIALOG mit SetMenu()
Die DialogBox von Main soll einen Button IDB_... erhalten. Die Button-Beschriftung soll starte IDD_DIALOG1 sein. Ein Button-Klick von IDB_... soll einen
weiteren Dialog IDD_DIALOG1 anzeigen.
Starten von *.exe-Programmen
Als Beispiel wird beschrieben, wie das Notepad.exe-Programm gestartet werden kann. Am einfachsten ist die alte WinExec().Funktion.
PROCESS_INFORMATION pi; ZeroMemory(&pi,sizeof(pi)); BOOL ok = CreateProcess (0,aufruf, 0,0,0,NORMAL_PRIORITY_CLASS,0,0,&si,&pi); if(!ok){ //Process konnte nicht gestartet werden err_if(!ok,"KEIN PROCESS"); } else { //befreie, falls nicht mehr benötigt
CloseHandle(pi.hThread); // WaitForSingleObject(pi.hProcess, INFINITE); // der Process terminierte DWORD dwExitCode; // wie wurde er beendet? GetExitCodeProcess(pi.hProcess, &dwExitCode); //befreie, falls nicht mehr benötigt: CloseHandle(pipi.hProcess); }
Wozu kann GetFullPathName(filename,sizeof(path),path,?); nützlich sein?
Taschenrechner mit Ressourcenscript
Es ist ein Prototyp für einen Hex-Taschenrechner zu gestalten ( mit Verbesserungen und Erweiterungen ). Um einem Control eine Nachricht zu schicken kann
LONG SendDlgItemMessage( HWND hDlg, int idRes, UINT iMsg, WPARAM wParam, LPARAM lParam);
Für das Edit- und ComboBox-Control sollen die Macros ( wie z.B. Edit_SetText() ) aus WindosX.h verwendet werden.
Bei der Erstellung des Ressourcen-Scripts kann zunächst ein "leeres grosses Dialog-Rechteck" angelegt werden und in diesen rc-Quelltext wird der untere rc-Quelltext hinein kopiert ( ID-Konstanten beachten ).
Achtung! Es ist sinnvoll, die folgenden Konstanten- Bezeichner zu verwenden: IDC_COMBO1 IDC_EDIT1 IDC_BUTTON0 IDC_BUTTON1 IDC_BUTTON2 IDC_BUTTON3 IDC_BUTTON4 IDC_BUTTON5 Windows kenn bereits:
CONTROL "",IDC_STATIC,"Static",SS_BLACKRECT,98,30,6,101CONTROL "",IDC_STATIC,"Static",SS_BLACKRECT,5,21,116,6CONTROL "",IDC_STATIC,"Static",SS_BLACKRECT,58,29,6,101CONTROL "",IDC_STATIC,"Static",SS_BLACKRECT,7,132,116,6EDITTEXT IDC_EDIT1,7,141,113,45,ES_MULTILINE |WS_TABSTOP|ES_WANTRETURN|WS_VSCROLL|WS_HSCROLLDEFPUSHBUTTON "Schliessen",IDOK,37,193,50,14,NOT WS_TABSTOPEND
IDC_STATIC IDOK
Hier ein Anfang für die CALLBACK dlgHexCalcProc() und hex_show_number() zum Anzeigen von iNum in IDC_COMBO1 und der Funktion hex_calc_it(),
die abhängig von dem geklickten Button ( siehe default: iAsc = LOWORD( wParam ); ... ) auf die alte Zahl iFirstNum die aktuelle iNum "drauf-rechnet" und
Als ein Anfang kann der Weil der _hBut = CreateWindowEx()-Aufruf wird für jeden Button verwendet werden soll, ist eine "Schreinbvereinfachung" sinnvoll,
dlg_class.h | Teil A | "Notepad-Dialog" editor.gif | Verwaltung der Fenster mit glob. Handle-Array HWND hwa[10] | Wie wird der Modale zum Modeless? | Wie sieht eine Dialog-CALLBACK-Funktion aus? | Was ist nun für Modeless zu tun? | Teil B: | Übliche Tastenkombinationen (Dialogfelder) | Müssen Identifizierer stets neu definiert werden? | Was ist eigentlich zu tun? | Wie kann nun ein Modeless-Dialog
erstellt werden? | Wie kann ohne Visualität ein Modeless-Dialog erstellt werden? | Wie kann ohne eigene User-CALLBACK-Funktion mit der default_dlg_callback_proc getestet werden? | Wie kann die vorhandene default_dlg_callback_proc() erweitert werden? | Kontroll-Fragen:
↑ 5. SP2-Praktikum (SS 2005)
Der Teil A ist Pflichtteil für Sehfähige und optional für Sehbehinderte. Der Teil B ist Pflichtteil für Sehbehinderte und optional für
Sehfähige.
↑ Teil ADer Teil A ist Pflichtteil für Sehfähige und optional für Sehbehinderte. Diese Aufgabe besteht darin, mit Modless-Dialogen zu arbeiten.
Dialoge sind zu erstellen und die zugehörigen Dialog-CALLBACK-Funktionen sind zu schreiben. Falls sinnvoll sind gewohnte
Tastenkombinationen zu unterstützen. Im Einzelnen:
Ausgehend von einer eigenen Window-Applikation, die ein Menu hat, soll ein Standard-File-Open-Dialog hinzu gefügt werden. Der
Standard-File-Open-Dialog soll per Menu-Klick aufgerufen werden. Ein Standard-File-Open-Dialog wird mit GetOpenFileName(&ofn))
Achtung! Der String pFilt enthält Stringpaare mit \000 als Trennzeichen. Im Speicher ist pFilt durch \000\000 beendet. Der Aufruf von
get_Open_File_Name() liefert den ausgewählten File-Namen.
Nun ist beieinem entspechenden Menu-Klick ein .txt-File-Name auszuwählen, die File-Text-Daten sind zu lesen und in den Heap zu laden (
new ...). Die File-Text-Daten sind dann an ein Edit-Control ("EDIT"-Fenster) zu schicken. Hier ist mehr oder minder geeigneter erweiterter
cpp-Quelltext ...
/* Test für file_open_copy_to_heap:
BYTE *pFix = file_open_copy_to_heap(hwnd); err_if(!pFix,"kein File"); char * p = (char *) pFix; // Achtung! p kann geändert werden, // aber pFix darf nicht geändertwerden. // pFix wird später für delete gebraucht MessageBox(0,p,0,MB_OK); if(pFix) delete pFix;*/
switch(uMsg) { case WM_CLOSE: { // EndDialog() für modale ... // hide() für modeless ... break;} // // falls benötigt z.B.: WM_INITDIALOG, WM_LBUTTONDOWN,... // // WM_COMMAND wie bekannt IDOK, IDCANCEL, ... case WM_COMMAND: { switch (LOWORD(wParam)) { case IDOK: { // kommt von WM_CLOSE MessageBox(hwnd,TEXT("IDOK"),TEXT("WM_COMMAND"),MB_OK); break;}
case psh1: { // kommt von PushButten psh1
break;} } // ende switch (LOWORD(wParam)) break;} // ende WM_COMMAND
} // ende switch(uMsg) return FALSE; ////////////////////////////////////////// // Später einmal anstelle von return FALSE: // Hier könnte eine allen Dialogen gemeinsame // dlg-CALLBACK-Funktion aufgerufen werden: // return default_dlg_callback_proc(hwnd,uMsg,wParam,lParam);}
↑ Was ist nun für Modeless zu tun?
Sind HWND m_hDlg ein globales Handle für alle Modeless-Dialoge,
HACCEL m_hAccel ein globales Handle auf die aktuelle Accelerator-Tabelle und
MSG m_msg eine globale Struktur,
so werden durch main_loop() die Nachrichten verteilt: Zunächst (falls erfolgreich) mit TranslateAccelerator() andernfalls (falls erfolgreich)
mit IsDialogMessage() an die modeless Dialoge und, wenn das nichts war, mit DispatchMessage().
// Haupt-Nachrichtenschleife:void main_loop() { // hinterlege Nachricht in m_msg
while (BOOL bRet = GetMessage(&m_msg,NULL,0,0)) { err_if(-1==bRet,"-1==GetMessage()"); //err_if(!m_msg.hwnd,"!m_msg.hwnd");
F6 Zwischen Bildschirmelementen in einem Fenster oder auf dem Desktop umschalten
F10 Menüleiste im aktiven Fenster aktivieren
↑ Müssen Identifizierer stets neu definiert werden?
In dlgs.h gibt es bereits zahlreiche Identifizierer, die benutzt werden können. Gehört zu jedem Dialog-Template eine eigene CALLBACK-
Funktion, so müssen die Identifizierer nur innerhalb eines Dialoges eindeutig sein. Die Identifizierer aus dlgs.h liegen zwischen 1024 und
1279.
#define ctlFirst 0x0400#define ctlLast 0x04ff
Es gibt Pushbutton-Identifizierer psh1,psh2,...,pshHelp=psh15,psh16.Es gibt Edit-Control-Identifizierer edt1,edt2,...,edt16Es gibt ComboBox-Identifizierer cmb1,cmb2, ...,cmb16Es gibt ListBox-Identifizierer lst1,lst2, ...,lst16
↑ Was ist eigentlich zu tun?
Beginnen Sie bitte ein neue Window-Projekt, das zunächst diesen Header-File dlg_class.h enthalten soll.
Fügen Sie dem Projekt einen leeren meine_aufgabe.cpp-File hinzu, in den zunächst #include "dlg_class.h" geschieben wird. dlg_class.h
enthält die bekannte Menü-Unterstützung und wurde um Dialoge erweitert.
Schauen Sie sich die folgende Funktion create_main_window() an, die ein Hauptfenster erzeugt und kopieren sie diesen in
g.dlg_end(dlgProg) wird (falls vorhanden) die eigene Dialog-CALLBACK-Funktion dlgProg übergeben, die am ende
default_dlg_callback_proc() aufrufen sollte. Gibt es (zunächst) keine eigene Dialog-CALLBACK-Funktion dlgProg, so wird
g.dlg_end(NULL) verwendet, d.h. es wird dann automatisch (nur) die default_dlg_callback_proc() verwendet. Dies ist zum vorherigen
Testen des Dialoges geeignet. Die folgende Funktion create_dlg3() kann hinter #include "dlg_class.h" kopiert werden.
void create_dlg3(HWND hParent, DLGPROC dlgProg) { // Durch kopieren z.B. des Dialoges 1 und erweitern // wird nun der Dialog 3 erstellt: #define GHWND_IDX 3 WORD nx = 4; // !!! gewünschte Unterteilung der gesamte dlg-Breite in nx-Teile WORD ny = 10; // gewünschte Unterteilung der gesamte dlg-Höhe in ny-Teile WORD high = 14; // Höhe eines Button als Maß WORD width = 40; // !!! Mindestbreite eines Button als Maß WORD width_dialog = nx * width; // 160 Pixel WORD high_dialog = ny * high; // 140 Pixel WORD x_dlg_pos = GHWND_IDX*high + 100; WORD y_dlg_pos = GHWND_IDX*width;
// Text einfügen in die ListBoxen: ListBox_AddString(hList1, TEXT("links text 0")); ListBox_AddString(hList1, TEXT("links text 1")); ListBox_AddString(hList1, TEXT("links text 2")); ListBox_AddString(hList1, TEXT("links text 3")); ListBox_AddString(hList1, TEXT("links text 4"));
ListBox_AddString(hList2, TEXT("rechts text 0")); ListBox_AddString(hList2, TEXT("rechts text 1")); ListBox_AddString(hList2, TEXT("rechts text 2")); ListBox_AddString(hList2, TEXT("rechts text 3")); ListBox_AddString(hList2, TEXT("rechts text 4"));
In WinMain() kommt rein create_dlg3(ghwnd(0),NULL); g.show(ghwnd(3)); Nun sollte die Tab-Taste für die Controlls funktionieren. Auch
die Alt+F3-Taste sollte zyklisch die (Haupt-)Fenster weiterschalten.
↑ Wie kann die vorhandene default_dlg_callback_proc() erweitert werden?
Um auf bestimmte Ereigniss zu reagieren, müssen diese ausprogrammiert werden (CALLBAC-Funktion dlg_proc3). Als Beispiel seien in
einem ghwnd(3)-Dialog-Template die ListBox mit dem Identifizierer lst1 (aus dlgs.h) und ein Pushbutton mit dem Identifizierer psh1 (aus
dlgs.h) vorhanden. Das Handle auf die Listbox wird erhalten durch
HWND hList1 = GetDlgItem(ghwnd(3),lst1)
windowsx.h enthält Carsting-Makros für SendMessage, die einfacher zu benutzen sind. Es gibt z.B.
ListBox_GetCount(hList1);
ListBox_GetTextLen(hList1,line_idx);
ListBox_GetText(hList1,line_idx, buf);
Wichtig! Die folgende User-CALLBACK dlg_proc_3 ruft am Ende die default_dlg_callback_proc() auf, die allen Dialogen Gemeinsames
behandelt. CALLBACK dlg_proc3() kann als Muster für andere Dialog-CALLBACK-Funktionen dienen:
BOOL CALLBACK dlg_proc3(HWND hwnd,UINT uMsg,WPARAM wParam,LPARAM lParam) { switch(uMsg) { // nicht erforderlich: case WM_CLOSE: { ... break;} // nicht erforderlich: case WM_DESTROY:{ ... break;} // // falls benötigt z.B.: WM_INITDIALOG, WM_LBUTTONDOWN,... // // WM_COMMAND ist nicht bei Menu-Funktionen, // erforderlich, aber für zusätzliche // (Identifizierer-)Aktionen, wie z.B. // IDOK, IDCANCEL, usw. case WM_COMMAND: { switch (LOWORD(wParam)) { case IDOK: { // kommt von WM_CLOSE MessageBox(hwnd,TEXT("IDOK"),TEXT("WM_COMMAND"),MB_OK); break;} case psh1: { // kommt von PushButten psh1 //MessageBox(hwnd,TEXT("PushButten 1"),TEXT("WM_COMMAND"),MB_OK); // ListBox-Handles von Dialog 3 HWND hList1 = GetDlgItem(ghwnd(3),lst1);err_if(!hList1,"!hList1"); int max_lines = ListBox_GetCount(hList1); int line_idx = 2; // [0],[1],[2],[3],..[max-1] int n_char = ListBox_GetTextLen(hList1,line_idx); TCHAR buf[512]; if((n_char < 512) && (line_idx < max_lines)) ListBox_GetText(hList1,line_idx, buf); MessageBox(hwnd,buf,TEXT("hList1 [2]"),MB_OK); break;}
} // ende switch (LOWORD(wParam)) break;} // ende WM_COMMAND
} // ende switch(uMsg) ////////////////////////////////////////// // Hier ist die allen Dialogen gemeinsame // dlg-CALLBACK-Funktion aufzurufen: return default_dlg_callback_proc(hwnd,uMsg,wParam,lParam);}
Hier 2 Beispiele (create_dlg1,create_dlg2), die kommentiert und ungetestet sind ...
void create_dlg1(HWND hParent, DLGPROC dlgProg) { #define GHWND_IDX 1 // Dialog 1 bitte WORD nx = 4; // !!! gewünschte Unterteilung der gesamte dlg-Breite in nx-Teile WORD ny = 10; // gewünschte Unterteilung der gesamte dlg-Höhe in ny-Teile WORD high = 14; // Höhe eines Button als Maß WORD width = 40; // !!! Mindestbreite eines Button als Maß WORD high_menu = high; // es soll ein Menu dazu WORD high_dialog = ny * high + high_menu; WORD width_dialog = nx * width; WORD x_dlg_pos = GHWND_IDX*high + 100; WORD y_dlg_pos = GHWND_IDX*width;
ghwnd(GHWND_IDX) = // jetzt wird es spannend ... g.dlg_end(dlg_proc_1); err_if(!ghwnd(GHWND_IDX),"DLG_END(???,???)") // nun ist ghwnd(1) das globale Fenster-Handle! // Verwende Fenster 1 (siehe define GHWND_IDX als 1) // mit dem Makro ghwnd(1) oder // gleichwertig mit dem globalen Handle g.hwa[1]
// manipuliere edit-control: HWND hEdit = GetDlgItem(ghwnd(GHWND_IDX), edt1); err_if(!hEdit,"hEdit"); Edit_LimitText(hEdit,2048); // begrenze die Zeichen-Anzahl Edit_SetText(hEdit, TEXT("Edit-Init-Text")); // hinterlege Text
// Dialog 2 erstellen: // wahrscheinlich fehlerhaft ....:void create_dlg2(HWND hParent, DLGPROC dlgProg) { // Durch kopieren Dialog 1 und erweitern // wird nun der Dialog 2 erstellt: #define GHWND_IDX 2 WORD nx = 4; // !!! gewünschte Unterteilung der gesamte dlg-Breite in nx-Teile WORD ny = 10; // gewünschte Unterteilung der gesamte dlg-Höhe in ny-Teile WORD high = 14; // Höhe eines Button als Maß WORD width = 40; // !!! Mindestbreite eines Button als Maß WORD high_dialog = ny * high; WORD width_dialog = nx * width; WORD x_dlg_pos = GHWND_IDX*high + 100; WORD y_dlg_pos = GHWND_IDX*width;
// 0,5,ny bedeutet von oben 0 herunter bis 5 von den ny-Teilen // 0,nx,nx bedeutet die gesamte Breite (ebenso auch 0,1,1 oder 0,2,2 ) g.dlg_editM( 0,4,ny, 0,nx,nx, TEXT("hallo edt1"), edt1);
// 4,5,ny bedeutet von oben 4 herunter bis 5 von den ny=10-Teilen // 0,nx,nx bedeutet die gesamte Breite (ebenso auch 0,1,1 oder 0,2,2 ) g.dlg_button(4,5,ny, 0,nx,nx, TEXT("Beende"), IDCANCEL);// IDCANCEL aus winuser.h
// 6,7,ny bedeutet von oben 6 herunter bis 7 von den ny=10-Teilen // 0,1,2 bedeutet von links 0 nach rechts bis 1 von den 2-horizontalen Teilen g.dlg_static(5,6,ny, 0,1,2, TEXT("0,1,2 static-Text:"));//static-Text in Dialog // 1,2,2 bedeutet von links 1 nach rechts bis 2 von den 2-horizontalen Teilen
g.dlg_button(5,6,ny, 1,2,2, TEXT("Beende"), IDCANCEL);// IDCANCEL aus winuser.h
g.dlg_static(6,7,ny, 0,1,2, TEXT("0,1,2 weiterer static-Text:"));//static-Text in Dialog g.dlg_button(6,7,ny, 1,2,2, TEXT("Beende"), IDCANCEL);// IDCANCEL aus winuser.h
// 7,7,ny ist eine Vereinfachung für einen Teil und bedeutet von oben 7 bis 8 // 0,2,4 ist eine Vereinfachung für einen Teil und bedeutet von 0 bis 2 g.dlg_edit(7,8,ny, 0,2,4, TEXT("Hallo edt14"), edt14);// edt14 aus winuser.h // 2,2,4 ist eine Vereinfachung für einen Teil und bedeutet von 2 bis 3 g.dlg_button(7,8,ny, 2,2,4, TEXT("Beende"), IDCANCEL);// IDCANCEL aus winuser.h // 3,3,4 ist eine Vereinfachung für einen Teil und bedeutet von 3 bis 4 g.dlg_button(7,8,ny, 3,3,4, TEXT("Beende"), IDCANCEL);// IDCANCEL aus winuser.h g.dlg_combo(8,9,ny, 0,2,2, cmb1);// cmb1 aus winuser.h
ghwnd(GHWND_IDX) = // jetzt wird es spannend ... g.dlg_end(dlg_proc_1); err_if(!ghwnd(GHWND_IDX),"create_dlg2(): dlg_end(?)");
#define LEN_DLG_STRUCT 2048 typedef struct _DLG_STRUCT {//für das DlgTemplate DLGPROC dlgProc; // Dialog CALLBACK-Funktion !!! HWND hParent; // Handle des Parent-fensters int idxBuf; // idx, wo weiter geschrieben wird WORD buf[LEN_DLG_STRUCT]; // Speicher für das DlgTemplate-Aufbau } DLG_STRUCT; DLG_STRUCT m_ds;
// Array für alle (Haupt-) Fenster und Dialoge // i-tes Fenster-hwnd entspricht dem Makro ghwnd(i) // ghwnd(i) steht für (i)-tes-(g)lobales-(hwnd) #define hwa_max ((int)50) HWND hwa[hwa_max]; // hwa steht für (h)andle-(w)indow-(a)rray
WIN_CLASS() // Konstruktor { m_hDlg = 0; // akt: für Modeless-Fensterdaten m_pms = 0; // akt: Zeiger auf die static-menü-Tabelle m_hAccel = 0; // akt: Beschleunigungstasten-Tabelle aus m_pms
// get_anz_child() gibt die Anzahl der Childs zurück,// die zu hwnd gehören: ... wurde noch nicht geprüft ...int get_anz_child(HWND hwnd) { HWND hChild = GetWindow(hwnd,GW_CHILD); if (!hChild) return 0; int anz = 1; for (;hChild;hChild = GetNextWindow(hChild,GW_HWNDNEXT)) { anz++; } return anz;}
// get_hwnd_index() gibt den Index des aktuellen // Fenster-Handle-Arrays hwa[i], hwa[i] entspricht ghwnd(i), // zurückint get_hwnd_index(HWND hwnd) { HWND hParent = GetParent(hwnd); if(hParent) if(is_class(hParent,TEXT("#32770"))) hwnd = hParent;
// get_hwnd_next() gibt den Index des nächsten// Fenster-Handle im Array hwa[i] zurückint get_hwnd_next(HWND hwnd) { int i = get_hwnd_index(hwnd), i_akt = i; while(++i < hwa_max) if(hwa[i]) return i; i = -1; while(++i < i_akt ) if(hwa[i]) return i; return 0;}
// für die SetWindowPos()-Funktion brauchbar:#define SWP_ZONLY (SWP_NOSIZE|SWP_NOMOVE |SWP_NOACTIVATE)#define SWP_SIZEONLY (SWP_NOMOVE|SWP_NOZORDER|SWP_NOACTIVATE)#define SWP_MOVEONLY (SWP_NOSIZE|SWP_NOZORDER|SWP_NOACTIVATE)#define SWP_HIDEONLY (SWP_NOMOVE|SWP_NOZORDER|SWP_NOACTIVATE|SWP_NOSIZE|SWP_HIDEWINDOW)#define SWP_SHOWONLY (SWP_NOMOVE|SWP_NOZORDER|SWP_NOACTIVATE|SWP_NOSIZE|SWP_SHOWWINDOW)
case WM_COMMAND:{ if(HIWORD(wParam)==CBN_SETFOCUS) return TRUE; //lParam hCombo if(HIWORD(wParam) > 1) break; if(is_class(hwnd,TEXT("#32770")) && (LOWORD(wParam) == IDCANCEL)) { // IDCANCEL kommt bei Dlg von WM_CLOSE if((HIWORD(wParam) == BN_CLICKED) || lParam) { hide(hwnd); return TRUE; } } WORD id = LOWORD(wParam);//id=MENU-Item-Identifizierer m_pms = get_menu_tab(hwnd); if(!m_pms) break; //if((HIWORD(wParam)==1) && !lParam) { //..von Accel-Tab // if(!m_hAccel) break; //} int k = 0; // suche id in Menu-Tabelle while( m_pms[++k].pText) { // Menu-Text if( m_pms[k].id != id ) continue; err_if((ctlFirst<=id)&&(id<=ctlLast),"(ctlFirst<=id)&&(id<=ctlLast)"); if(!m_pms[k].menuProc) break; // Funktion ausführen BOOL ok = m_pms[k].menuProc(); } //InvalidateRect(hwnd,NULL,TRUE);UpdateWindow(hwnd); break;} // ende WM_COMMAND
/* viel getestet, wird wohl alles nicht gebraucht ... case WM_SETFOCUS: { //m_pms = get_menu_tab(hwnd); //SetFocus(hwnd); break; }
case WM_KILLFOCUS: { //????m_pms = get_menu_tab(hwnd); break; }
case WM_ACTIVATE: { //if(HIWORD(wParam)) break; // ist Minimized if (WA_INACTIVE==LOWORD(wParam)) { // becoming inactive m_pms = 0; } else { // becoming active m_pms = get_menu_tab(hwnd); } break; } // ende WM_ACTIVATE*/
default: { break;} } // ende switch return FALSE;}
// set_menu():// aus der vorhandenen "user-menu-struktur" wird ein// Menu und die Accel-Tabelle zusammengebaut und gesetztBOOL set_menu(HWND hwnd, MENU_STRUCT menu_struc[]){ //!!! menu_struc muss static sein !!! err_if(!hwnd,"set_menu: MENU braucht hwnd"); if(!hwnd)return FALSE;
MENU_STRUCT *pOldMenu = set_menu_tab(hwnd,menu_struc); // ermittle die Anzahl lenMenu von Menu-Items: int lenMenu = -1; while(menu_struc[++lenMenu].pText);
// Menu und Accel-Tab aus einer menu_struc erstellen: HMENU hMenu1 = 0, hMenu = CreateMenu();
ACCEL ac[200] = {0}; int kk = 0, lenAccel = 0;
WORD id = 10000; // idStart
for (int k = 0; k < lenMenu; k++) { // falls Funktion menu_struc[k].menuProc vorhanden ... if((k>0)&&(menu_struc[k].menuProc)) { id++; // diesen id-Identifizierer dem Menu-Item zuordnen // gleichzeitig die Accelarator-Tabelle aufbauen: WORD key = menu_struc[k].key; //menu_struc[k].key if(key) // falls ein Accel-Key: { err_if(lenAccel>=200,"set_menu: lenAccel>=200"); WORD fVirt = menu_struc[k].fVirt; ac[lenAccel].fVirt = ((WORD)fVirt & ~0xff80);//menu_struc[k].fVirt ac[lenAccel].key = key; //menu_struc[k].key ac[lenAccel].cmd = id; //id ab 10001 ... lenAccel++; } // Menu fertig zusammen bauen: menu_struc[k].id = id; AppendMenu(hMenu1,MF_STRING,id,menu_struc[k].pText); } else { if(k>0) AppendMenu(hMenu,MF_POPUP,(UINT)hMenu1,menu_struc[kk].pText); if(hMenu1)DestroyMenu(hMenu1); kk = k; hMenu1 = CreateMenu(); } }
if(FontSize < 6) FontSize = 9;*p++ = FontSize; //z.B. 9*p++ = FW_DONTCARE; // Weight*p++ = MAKEWORD(FALSE,DEFAULT_CHARSET );// italic flag and charset. if(font)p+=nCopyAnsiToWideChar(p,font);// Face name else p+=nCopyAnsiToWideChar(p,TEXT("Courier New")); ULONG ul=(ULONG)p;ul+=3;ul>>=2;ul<<=2;p=(LPWORD)ul; //Align m_ds.idxBuf = p - m_ds.buf; err_if(LEN_DLG_STRUCT - m_ds.idxBuf < 256,"LEN_DLG_STRUCT zu klein");}
void dlg_edit(WORD x, WORD y, WORD cx, WORD cy, TCHAR * szInitStr, WORD idRes){PWORD p = &m_ds.buf[m_ds.idxBuf]; m_ds.buf[8]++;DWORD lStyle = WS_VISIBLE|WS_CHILD|WS_TABSTOP|SS_LEFT|ES_AUTOHSCROLL;DWORD lExStyle = WS_EX_CLIENTEDGE;*p++ = 0; // LOWORD (lHelpID)*p++ = 0; // HIWORD (lHelpID)*p++ = LOWORD(lExStyle);*p++ = HIWORD(lExStyle);*p++ = LOWORD(lStyle); *p++ = HIWORD(lStyle);*p++ = x; *p++ = y; *p++ = cx; *p++ = cy;*p++ = idRes; // LOWORD (Control ID)*p++ = 0; // HOWORD (Control ID)p += nCopyAnsiToWideChar(p,TEXT("EDIT"));if(szInitStr)p +=nCopyAnsiToWideChar(p,szInitStr);else p +=nCopyAnsiToWideChar(p,TEXT(""));*p++ = 0; // Advance pointer over nExtraStuff WORD. ULONG ul=(ULONG)p;ul+=3;ul>>=2;ul<<=2;p=(LPWORD)ul; //Align m_ds.idxBuf = p - m_ds.buf; err_if(LEN_DLG_STRUCT - m_ds.idxBuf < 256,"LEN_DLG_STRUCT zu klein");}
void dlg_editM(WORD x, WORD y, WORD cx, WORD cy, TCHAR * szInitStr, WORD idRes){PWORD p = &m_ds.buf[m_ds.idxBuf]; m_ds.buf[8]++;DWORD lStyle = WS_VISIBLE | WS_CHILD | WS_TABSTOP | SS_LEFT | ES_MULTILINE | ES_AUTOVSCROLL | WS_VSCROLL | ES_WANTRETURN;DWORD lExStyle = WS_EX_CLIENTEDGE;*p++ = 0; // LOWORD (lHelpID)*p++ = 0; // HIWORD (lHelpID)*p++ = LOWORD(lExStyle);*p++ = HIWORD(lExStyle);*p++ = LOWORD(lStyle); *p++ = HIWORD(lStyle);*p++ = x; *p++ = y; *p++ = cx; *p++ = cy;*p++ = idRes; // LOWORD (Control ID)*p++ = 0; // HOWORD (Control ID)p += nCopyAnsiToWideChar(p,TEXT("EDIT"));if(szInitStr)p += nCopyAnsiToWideChar(p,szInitStr);else p += nCopyAnsiToWideChar(p,TEXT(""));*p++ = 0; // Advance pointer over nExtraStuff WORD. ULONG ul=(ULONG)p;ul+=3;ul>>=2;ul<<=2;p=(LPWORD)ul; //Align m_ds.idxBuf = p - m_ds.buf; err_if(LEN_DLG_STRUCT - m_ds.idxBuf < 256,"LEN_DLG_STRUCT zu klein");}
void dlg_list(WORD x, WORD y, WORD cx, WORD cy, WORD idRes){PWORD p = &m_ds.buf[m_ds.idxBuf]; m_ds.buf[8]++;DWORD lStyle = WS_VISIBLE|WS_CHILD|WS_TABSTOP|WS_VSCROLL|WS_BORDER |LBS_HASSTRINGS|LBS_NOTIFY; //LBS_WANTKEYBOARDINPUT//LBS_MULTIPLESEL or the LBS_EXTENDEDSEL
if(szStr)p += nCopyAnsiToWideChar(p,szStr); else p += nCopyAnsiToWideChar(p,TEXT("?"));*p++ = 0; // Advance pointer over nExtraStuff WORD. ULONG ul=(ULONG)p;ul+=3;ul>>=2;ul<<=2;p=(LPWORD)ul; //Align m_ds.idxBuf = p - m_ds.buf; err_if(LEN_DLG_STRUCT - m_ds.idxBuf < 256,"LEN_DLG_STRUCT zu klein"); return TRUE;}/////////////////////////////////////////////////void dlg_combo(WORD x, WORD y, WORD cx, WORD cy, WORD idRes){PWORD p = &m_ds.buf[m_ds.idxBuf]; m_ds.buf[8]++;
// innere Position der Dialog-Breite bei nr:int get_x(WORD nr, WORD nr_max){ err_if(!nr_max,"Anzahl nx der horizontalen Teile?"); if (nr > nr_max) nr = nr_max; WORD d = 3, dlg_width = m_ds.buf[11]; WORD xPos = (dlg_width-d)*nr/nr_max + d; return xPos;}// innere Position der Dialog-Höhe bei nr:int get_y(WORD nr, WORD nr_max){ err_if(!nr_max,"Anzahl ny der vertikalen Teile?"); if (nr > nr_max) nr = nr_max; WORD d = 3, dlg_high = m_ds.buf[12]; WORD yPos = (dlg_high-d)*nr/nr_max + d; return yPos;}// innere Dialog-Breite von nr bis nr_end:int get_cx(WORD nr, WORD nr_end, WORD nr_max){ err_if(!nr_max,"Anzahl nx der horizontalen Teile?"); if (nr > nr_max) nr = nr_max; if (nr_end > nr_max) nr_end = nr_max; if (nr_end <= nr ) nr_end = nr + 1; WORD d = 3, dlg_width = m_ds.buf[11]; WORD cx = (dlg_width-d)*(nr_end-nr)/nr_max-d; return cx;}// innere Dialog-Höhe von nr bis nr_end:int get_cy(WORD nr, WORD nr_end, WORD nr_max){ err_if(!nr_max,"Anzahl ny der vertikalen Teile?"); if (nr > nr_max) nr = nr_max;
if (nr_end > nr_max) nr_end = nr_max; if (nr_end <= nr ) nr_end = nr + 1; WORD d = 3, dlg_high = m_ds.buf[12]; WORD cy = (dlg_high)*(nr_end-nr)/nr_max-d; return cy;}
// gehe zum nächsten Fenster g.hwnd[]BOOL show_next_dlg(){ HWND hwnd = g.get_ghwnd(); // hole das globale-aktuelle hwnd int idx_next = g.get_hwnd_next(hwnd); // hole nächstes globales hwnd g.show(ghwnd(idx_next)); // mache dieses Fenster sichtbar return TRUE;}
// lediglich zum TestenBOOL on_help(){ HWND hwnd = g.get_ghwnd(); TCHAR * pInfo = TEXT("Dies ist Programm von\n\n\t VORNAME NACHMANE\n\nWeiterte Infos sind ..."); TCHAR * pTitle = TEXT("Info zur 3.Übung"); MessageBox(hwnd, pInfo, pTitle, MB_OK); return TRUE;}////////////////////////////////////////////////////////////////#endif
auf_06.exe(grobe Vorstufe) einige cpp-"brocken"
6. SP2-Praktikum (SS 2005)
Teil A
Der Teil A ist Pflichtteil für Sehfähige und optional für Sehbehinderte. Diese Aufgabe besteht darin, mit MDI-Applikationen zu arbeiten. Es ist eine MDI-Applikation zu erstellen, die
es ermöglicht, Quelltexte (hilfreich) zusammem zu erstellen ("hablautomatische Quellcode-Generierung"). Z.B. sollen (zahlreiche!) HTML-Konstrukte (oder Konstrukte einer anderen
Sprache, XML-, ...,usw. ) an der Cursor-Stelle (z.B. mit Hilfe eines Kontext-Menus) einfügbar sein. Die zugehörigen Dialog-CALLBACK-Funktionen sind zu schreiben. Im Einzelnen:
Was ist MDI?
Ein "Single Document Interface" (SDI, z.B. Notepad) kann zu einer Zeit ein Dokument händeln. Ein "Multiple Document Interface" (MDI, z.B. Word, Dev.Studio, usw.) kann
gleichzeitig mehrere Dokumente bedienen. Auch gibt es MTI-Anwendungen ( Multiple Top-Level Interface).
MDI ist eine Windows-Applications, die zum "standard user interface" wurde. Bei MDI können auf der (Client Area)-Bildschirmfläche innerhalb des Haupt-Fensters (Frame Fenster,
Rahmen-Fenster) mehrere Child-Fenster sein. Alle Child-Fenster werden an der Client Area geklippt. Child-Fenster werden auf der Client Area minimiert. Child-Fenster können mit
Strg+F4 geschlossen werden. Zwischen den Child-Fenstern kann mit Strg+Tab navigiert werden. Für diese (Sytem-)Tasten-Nachrichten wird die Hauptnachrichtenschleife um
TranslateMDISysAccel() erweitert. Eine MDI-Applikation hat 3 Fensterarten:
Die Schritte um ein Frame-Fenster zu erzeugen sind:- WNDCLASSEX-Struktur füllen, Frame-Fenster-Klasse registrieren (RegisterClassEx)- Frame-Fenster erzeugen mit CreateWindowEx- Haupt-Message-Loop um TranslateMDISysAccel erweitern- Haupt-CALLBACK-Funktion gibt Nachrichten DefFrameProc weiter (nicht DefWindowProc).
Fenster können horizontal/vertikal die Client-Fläche des Frame-Window unterteilen.
Eine MDI-Apllikation besteht aus einem Haupt-Fensters (Rahmen-Fenster bildet die Client Area), einem unsichtbaren Client Fenster (Klassen-Name "MDICLIENT") MDI-Cild-
Fenstern, die sich auf der Client Area befinden und durch die "MDICLIENT"-Klasse mit eingebauter CALLBACK-Funktion, kontrolliert werden. Typisches Aussehen:
// Anlegen eines Child-Fensters // nach der neueren Methode b: HWND hChild = ::CreateMDIWindow(myChildClass,TEXT("Hello"),WS_OVERLAPPEDWINDOW|WS_CHILD|WS_VISIBLE,CW_USEDEFAULT,CW_USEDEFAULT,CW_USEDEFAULT,CW_USEDEFAULT,m_hClient,hInst,NULL); //::BringWindowToTop(hChild); --------------------------------------------------
hwnd das Handle innerhalb einer Child-CALLBACK-Funktion. Es gilt: static HWND m_hClient = ::GetParent(hwnd);static HWND m_hFrame = ::GetParent(m_hClient);
// soll später auf m_hMenu[0] geladen werden"&Datei":"Neues &Text-Fenster", IDM_EDIT_NEW_TEXT) "Programm &beenden", IDM_APP_EXIT) "Fenster &Daten", IDM_ENUM_WINDOW_DATEN)
// soll später auf m_hMenu[1] geladen werden"&Datei": "Neues &Text-Fenster", IDM_EDIT_NEW_TEXT "Fenster &schließen", IDM_EDIT_CLOSE_TEXT "Fenster &Daten", IDM_ENUM_WINDOW_DATEN "Programm &beenden", IDM_APP_EXIT
Es ist günstig, die gemeinsame Hauptarbeit von mdi_default_frame_proc() durchführen zu lassen. Die eigene myFrameProc() ruft am Ende die mdi_default_frame_proc() auf etwa
case IDM_WINDOW_SHOWMINIMIZE: { HWND hChild =(HWND) SendMessage(m_hClient, WM_MDIGETACTIVE,0,0); ShowWindow(hChild,SW_SHOWMINIMIZED); return 0; } case IDM_WINDOW_SHOWMAXIMIZE: { HWND hChild =(HWND) SendMessage(m_hClient, WM_MDIGETACTIVE,0,0); if(IsWindow(hChild)) SendMessage(m_hClient,(UINT)WM_MDIMAXIMIZE,(WPARAM)hChild,0); return 0; } case IDM_APP_EXIT: { // Programm beenden SendMessage(hwnd, WM_CLOSE,0,0); return 0;} // Nachrichten zum Anordnen der Dokumentenfenster case IDM_WINDOW_TILE_VERTIKAL: { // SendMessage(m_hClient, WM_MDITILE,0,0); // oder: WORD nWindows = TileWindows(m_hClient,MDITILE_VERTICAL,0,0,0); return 0;}
case IDM_WINDOW_TILE_HORIZONTAL: { WORD nWindows = TileWindows(m_hClient,MDITILE_HORIZONTAL,0,0,0); return 0;}
case IDM_WINDOW_CASCADE: { SendMessage(m_hClient,WM_MDICASCADE,0,0); return 0;} case IDM_WINDOW_ARRANGE:{ // SendMessage(m_hClient, WM_MDIICONARRANGE,0,0); // oder: UINT height = ArrangeIconicWindows(m_hClient); return 0;} case IDM_WINDOW_CLOSEALL:{ // Schließen aller Dokumentenfenster EnumChildWindows(m_hClient, EnumCloseProc, 0); return 0;}
default: { // Weitergabe ans aktive Dokumentenfenster HWND hChild =(HWND) SendMessage(m_hClient, WM_MDIGETACTIVE,0,0); if(IsWindow(hChild)) SendMessage(hChild, WM_COMMAND, wParam, lParam); break; } // ...und danach an DefFrameProc } break; } // ende WM_COMMAND case WM_QUERYENDSESSION: case WM_CLOSE:{ // alle Dokumentenfenster schließen SendMessage(hwnd, WM_COMMAND, IDM_WINDOW_CLOSEALL, 0); if(NULL != GetWindow(m_hClient, GW_CHILD)) return 0; break; } // i.e., call DefFrameProc case WM_DESTROY: PostQuitMessage(0); return 0; } // Weitergabe an DefFrameProc(ersetzt DefWindowProc) return DefFrameProc(hwnd, m_hClient, uMsg, wParam, lParam);}
Wie sieht die Child-CALLBACK-Funktion aus?
Es ist günstig, die gemeinsame Aarbeit von mdi_default_child_proc() durchführen zu lassen. Die eigene myFrameProc() ruft am Ende die mdi_default_child_proc() auf etwa gemäß:
case WM_COMMAND:{ /* switch(LOWORD(wParam)) { // case IDM_...: { ... break; } // case IDM_...: { ... break; } default:{ break; } } // switch(LOWORD(wParam)) */ break; } // ende von WM_COMMAND } // ende von switch(uMsg)
return mdi_default_child_proc(..);}
Die mdi_default_child_proc() behandelt u.a. bei WM_SIZE das Anpassen des "EDIT" an das umgebende Fenster, setzt bei WM_SETFOCUS den Cursor ins "EDIT". Bei Comiler-
fehlern kann unwichtiges zunächst auskommentiert werden:
SendMessage(m_hClient,WM_MDISETMENU, (WPARAM) m_hMenu[1],(LPARAM)GetSubMenu(m_hMenu[1],1)); } else { // Eingabefokus wechselt,d.h. m_hMenu[0] setzen SendMessage(m_hClient, WM_MDISETMENU, (WPARAM) m_hMenu[0],(LPARAM) GetSubMenu(m_hMenu[0],0)); } DrawMenuBar(m_hwnd[0]); break; } case WM_QUERYENDSESSION: case WM_CLOSE: { TCHAR child_titel[512]; // Cild-Fenster beenden? memset(child_titel, 0, sizeof(child_titel)); GetWindowText(hwnd,child_titel, 512); /* // Nummer i des Child-Fensters (nur ein Test!) LONG i = GetWindowLong(hwnd,GWL_ID)-(LONG)FIRST_CHILD_IDX; TCHAR child_num [128]; memset(child_num,0,sizeof(child_num)); wsprintf(child_num,TEXT("Child-Fenster = %li schließen"),i);
int ret = MessageBox(hwnd, child_num, child_titel, MB_ICONQUESTION|MB_OKCANCEL); if (IDOK != ret) return 0; // bleib! */ int ret = MessageBox(hwnd, TEXT("Child-Fenster schließen?"), child_titel, MB_ICONQUESTION|MB_OKCANCEL); if (IDOK != ret) return 0; // bleib!
// sonst zerstören mit DefMDIChildProc break; }
// Weitergabe an DefMDIChildProc(ersetzt DefWindowProc) return DefMDIChildProc(hwnd,uMsg,wParam,lParam);}
Gibt es hilfreiche Funktionen?
is_hwnd_class() prüft, ob ein hwnd zu einer bestimmten Klasse ehört.
// gehört hwnd zu einer bestimmten Fnster-Class? BOOL is_hwnd_class(HWND hwnd, TCHAR *className) { TCHAR buf[512]; int anz = GetClassName(hwnd, buf, 512); int diff= CompareString(LOCALE_USER_DEFAULT, NORM_IGNORECASE | NORM_IGNOREKANATYPE | NORM_IGNOREWIDTH,buf,-1,className,-1); //if(GetWindowLong(hwnd,GWL_STYLE)&DS_MODALFRAME) ... return (diff == CSTR_EQUAL); }
Mit Hilfe der EnumChildWindows(..,EnumCallBack,...)-Funktion wird der EnumCloseProc() - Funktionszeiger hinterlegt. Es werden alle ChildWindows durchlaufen und jedesmal
wird EnumCloseProc() aufgerufen. Antwortet EnumCloseProc() mit TRUE, so wird das Durchlaufen fortgesetzt.
BOOL CALLBACK EnumCloseProc(HWND hwnd, LPARAM lParam){ // falls Client-Fenster? - nicht abbauen: if(GetWindow(hwnd, GW_OWNER)) return TRUE; // Nachricht an das Client-Fenster: Dokument zurück auf Originalgröße SendMessage(GetParent(hwnd), WM_MDIRESTORE,(WPARAM) hwnd, 0); // Nachricht an das Dokumentenfenster: Schließen OK? if(!SendMessage(hwnd,WM_QUERYENDSESSION,0,0))return TRUE;
// OK. Nachricht an das Client-Fenster: Dokumentenfenster abbauen SendMessage(GetParent(hwnd),WM_MDIDESTROY,(WPARAM) hwnd, 0); return TRUE;}
Wie können ALLE fenster durchlaufen werden?
Folgend bedeutet NULL "system-zugehörig", d.h. alle. Mit Hilfe der EnumChildWindows(NULL,EnumCallBack,...)-Funktion wird der EnumCallBack() - Funktionszeiger hinterlegt.
Es werden alle ChildWindows durchlaufen und jedesmal wird EnumCallBack() aufgerufen. Antwortet EnumCallBack() mit TRUE, so wird das Durchlaufen fortgesetzt. Es ergibt sich
etwa die folgende Anzeige:
// dies ist verbesserungsfähig ...BOOL CALLBACK EnumCallBack(HWND nhWnd, LPARAM Param ) { static int Nummer;// zum Zählen der Fenster #define NCHAR 1024 TCHAR buf[ NCHAR]; buf[0]='\0'; TCHAR BUF[6*NCHAR], * p = BUF; HWND hParent = (HWND) Param; HWND hEdit = GetWindow(m_hwnd[2],GW_CHILD); //SendMessage(hEdit,WM_SETFONT,(WPARAM)GetStockObject(ANSI_FIXED_FONT),TRUE);
if(Nummer <= 0){ // Überschrift p += wsprintf(p,TEXT("\r\n win | hwnd | Titel")); p += wsprintf(p,TEXT("\r\n=====|==========|=========="));
}
GetWindowText( nhWnd, buf,NCHAR); if ( buf[0] != '\0' ) { int nMax = GetWindowTextLength(hEdit); if( ( p - BUF ) > nMax - 2*NCHAR) {//err("BUF[] zu klein"); SendMessage(hEdit,EM_LIMITTEXT,(WPARAM)6*NCHAR,0L); } p += wsprintf(p,TEXT("\r\n %03i | %08x | %s"), Nummer++, nhWnd, buf); SendMessage(hEdit,EM_REPLACESEL,0,(LPARAM)BUF); // anstelle von // while (HIWORD(SendMessage(hEdit,EM_SCROLL,SB_PAGEUP,0L))); // kann : SendMessage(hEdit, WM_VSCROLL, (WPARAM)SB_TOP,0L); SendMessage(hEdit, WM_HSCROLL, (WPARAM)SB_PAGELEFT,0L); } return TRUE; #undef NCHAR }
Wie geht es weiter?
Wenn die MDI-Applikation bis hierher stabil funktioniert, so ist nun diese zu erweitern. Die MDI-Applikation soll es ermöglichen, Quelltexte "hablautomatische zu Generieren". Z.B.
sollen (zahlreiche!) HTML-Konstrukte (oder Konstrukte einer anderen Sprache, XML-, ...,usw. ) an der Cursor-Stelle (z.B. mit Hilfe eines Kontext-Menus) einfügbar sein. Die
zugehörigen CALLBACK-Funktionen sind zu schreiben.
Teil B
Der Teil B ist Pflichtteil für Sehbehinderte optional für alle anderen. Diese Aufgabe besteht darin, mit MDI-Applikationen zu arbeiten. Es ist eine MDI-Applikation zu erstellen, die es
ermöglicht, Quelltexte (hilfreich) zusammem zu erstellen ("hablautomatische Quellcode-Generierung"). Z.B. sollen (zahlreiche!) HTML-Konstrukte (oder Konstrukte einer anderen
Sprache, XML-, ...,usw. ) an der Cursor-Stelle (z.B. mit Hilfe eines Kontext-Menus) einfügbar sein. Im Einzelnen: Es sollte ein Projekt angelegt werden, das einen Header-File
vorgegebenen "auf_06.h" und einen selbst zu schreibenden "auf_06.cpp" enthalten soll. Der Aufbau von "auf_06.cpp" ist etwa:
#define STRICT#include "auf_06.h"// hier kommen die eigenen #define IDM_...// hier kommt die Menü-erzeugende Funktion: create_all_menu() ...// hier kommt die eigene myChildProc()- CALLBACK-Funktion ...
// hier kommt WinMain() ...
Hinweise zur Menü-erzeugende Funktion: create_all_menu()
Mit den Macros (alles Grusbuchstaben, sind bereits in auf_06.h enthalten) MDI_MENU_BEGIN(idx), MDI_MENU_POPUP(text), MDI_MENU_ITEM(text,idRes),
MDI_MENU_END() können Menüs zusammen gebaut werden, etwa gemäß:
void create_all_menu(){ // Hinterlege Menu bei m_hMenu[0]: MDI_MENU_BEGIN(0) // kein; MDI_MENU_POPUP("&Datei")// kein; MDI_MENU_ITEM("Neues &Text-Fenster", IDM_EDIT_NEW_TEXT) // kein;
Es ist eine CALLBACK-myChildProc() zu schreiben, die Tags an der aktuellen Caret-Position einfügt. Ein markierter Bereich wird eingerahmt, etwa bei einem pre-Tag wird <pre> vor
den markierter Bereich geschrieben und </pre> nach dem den markierter Bereich. Sind die globalen Variablen m_pPrae und m_pPost gesetzt, so erledigt dies
SendMessage(hwnd,WM_COMMAND,IDM_ERSETZE_PRAE_POST,0); IDM_ERSETZE_PRAE_POST existiert schon in "auf_06.h".
Hinweise zur eigene myChildProc()- CALLBACK-Funktion
myChildProc() soll (bei unklarer Lage) am Ende die eingebaute mdi_default_child_proc()-Funktion aufrufen, die einige Ereignisse behandelt (siehe "auf_06.h").
Bitte beachten Sie, dass die Identifizierer, wie z.B. IDM_DO_PRE_TAG selbst definiert werden müssen (unmittelbar nach #include "auf-06.h"). Dies kann etwa erfolgen, gemäß:
// eigene Identifizierer zwischen 1000 und 1999 wählen:#define IDM_DO_P_TAG 1001#define IDM_DO_PRE_TAG 1002#define IDM_DO_CENTER_TAG 1003#define IDM_DO_IMG_TAG 1004
// in "auf_06.h" gibt es bereits (bitte anschauen):#define IDM_FILE_OPEN 4001#define IDM_FILE_SAVE 4002#define IDM_FILE_SAVE_AS 4003#define IDM_APP_EXIT 4004#define IDM_EDIT_NEW_TEXT 4005#define IDM_EDIT_CLOSE_TEXT 4006#define IDM_WINDOW_CASCADE 4007#define IDM_WINDOW_TILE_VERTIKAL 4008#define IDM_WINDOW_TILE_HORIZONTAL 4009 #define IDM_WINDOW_ARRANGE 4010#define IDM_WINDOW_SHOWMINIMIZE 4011#define IDM_WINDOW_SHOWDEFAULT 4012#define IDM_WINDOW_SHOWMAXIMIZE 4013#define IDM_WINDOW_CLOSEALL 4014#define IDM_ENUM_CHILD_WINDOW_DATEN 4015
Das folgende Hauptprogramm erstellt das Menü, die notwendigen Klassen, das Frame-Fenster (m_hwnd[0]), intern das Client-Fenster und 2 Child-Fenster (m_hwnd[1],m_hwnd[2]).
int WINAPI WinMain(HINSTANCE, HINSTANCE hInst, PSTR, int){ m_hInst = GetModuleHandle(0); create_all_menu(); // ist zu modifizieren create_mdi_classen(); // aus "auf_06.h" // FrameWindow-Rahmenfenster m_hwnd[0] anlegen int xPos = 0; int yPos = 0; int dx = GetSystemMetrics(SM_CXSCREEN); int dy = GetSystemMetrics(SM_CYSCREEN); // Rahmenfenster anlegen m_hwnd[0] = CreateWindow( myFrameClass, myAppName, WS_OVERLAPPEDWINDOW | WS_CLIPCHILDREN, xPos,yPos,dx,dy,NULL,m_hMenu[0],m_hInst,0); // m_hClient wurde unter WM_CREATE angelegt m_hClient = GetWindow(m_hwnd[0], GW_CHILD); err_if(!m_hClient,"m_hClient"); ShowWindow(m_hwnd[0], SW_SHOW); UpdateWindow(m_hwnd[0]); // m_hwnd[1] ist ein Child-Fenster m_hwnd[1] = create_mdi_edit_window(TEXT("[1]")); // m_hwnd[2] ist ein weiteres Child-Fenster m_hwnd[2] = create_mdi_edit_window(TEXT("[2]"));
// Hauptnachrichtenschleife aus "auf_06.h" main_loop();
// gehört hwnd zu einer bestimmten Fnster-Class?BOOL is_hwnd_class(HWND hwnd, TCHAR *className) { TCHAR buf[512]; int anz = GetClassName(hwnd, buf, 512); int diff= CompareString(LOCALE_USER_DEFAULT, NORM_IGNORECASE
// hole die selektierten Text-Positionen: DWORD hilo = SendMessage(hEdit,(UINT)EM_GETSEL, (WPARAM)&m_idxSel1,(LPARAM)&m_idxSel2); int nSel = m_idxSel2 - m_idxSel1; if(nSel <=0 ) return TRUE;
// Wieviele Buchstaben enthält hEdit? int nSrc = Edit_GetTextLength(hEdit); err_if(nSrc<=0,"nSrc<=0");
// falls m_pSrc bereits allokiert ist, // dann erst freigeben: if (m_pSrc) {free(m_pSrc); m_pSrc = 0;} m_pSrc = (CHAR*)malloc((nSrc+10)*sizeof(CHAR)); memset(m_pSrc,0,(nSrc+10)*sizeof(CHAR)); err_if(!m_pSrc,"m_pSrc = new ?");
// hole hEdit-Text nach m_pSrc-Heap: nSrc = Edit_GetText(hEdit,m_pSrc,nSrc); //memset(buf,0,MAX_BUF*sizeof(CHAR)); // hole selektierten text in buf for(int i=0; i < nSel;i++) { if((i+2) >= MAX_BUF) break; m_buf[i] = m_pSrc[m_idxSel1 + i]; } m_buf[i] = (CHAR)0;
CHAR ch; // Wieviele Buchstaben enthält hEdit? // 4 mehr allokieren: int nSrc = 4 + Edit_GetTextLength(hEdit); int nPrae = strlen(m_pPrae); int nPost = strlen(m_pPost);
// falls m_pSrc allokiert ist, erst freigeben if (m_pSrc) { free(m_pSrc); m_pSrc=0; } // allokiere für Src von hEdit: m_pSrc = (CHAR*)malloc((nSrc)*sizeof(CHAR)); err_if(!m_pSrc,"m_pSrc = new ?");
// falls m_pDst allokiert ist, erst freigeben: if (m_pDst) { free(m_pDst); m_pDst=0;} // allokiere für Dst (zusammen gesetzter text): int nDst = nSrc + nPrae + nPost; m_pDst = (CHAR*) malloc((nDst)*sizeof(CHAR)); err_if(!m_pDst,"m_pDst = new ?"); // alle Speicher auf 0 setzen: memset(m_pSrc,0,(nSrc)*sizeof(CHAR)); memset(m_pDst,0,(nDst)*sizeof(CHAR)); memset(m_buf,0,MAX_BUF*sizeof(CHAR)); // hole hEdit-Text nach m_pSrc int nSrc1 = Edit_GetText(hEdit,m_pSrc,nSrc); // Ist was Markiert? DWORD hilo = SendMessage(hEdit,(UINT)EM_GETSEL, (WPARAM)&m_idxSel1,(LPARAM)&m_idxSel2); int nSel = m_idxSel2 - m_idxSel1; // anfangs-string ins Ziel: ch = m_pSrc[m_idxSel1]; m_pSrc[m_idxSel1]=(CHAR)0; strcat(m_pDst,m_pSrc); m_pSrc[m_idxSel1]=ch; // m_pPrae ins Ziel: if(nPrae > 0) strcat(m_pDst,m_pPrae); ch=m_pSrc[m_idxSel2]; m_pSrc[m_idxSel2]=(CHAR)0; strcat(m_buf,&m_pSrc[m_idxSel1]);m_pSrc[m_idxSel2]=ch; // tue markierten-text ins Ziel: strcat(m_pDst,m_buf); // m_pPost ins Ziel: if(nPost > 0) strcat(m_pDst,m_pPost); // rest von m_pSrc ins Ziel: strcat(m_pDst,&m_pSrc[m_idxSel2]); // hinterlege im Editor: Edit_SetText(hEdit,m_pDst);
7. SP2-Praktikum (SS 2005)Diese Aufgabe besteht darin, das Erstellen von DLL's zu üben und eine "kleine brauchbaren" Windows-Anwendung (nach freiem Ermessen mit *.dll, *.lib, Dokumentation) zu entwickeln und zu testen.
Hinweise
In der Entwicklungsumgebung sind 2 Projekte anzulegen. Zunächt ein Projet für das Erstellen einer Dll, dann ein Projet für eine Console-Applikation.
● 1.Projekt: sp2_dll ( Windows-DLL, beginnend mit einem leeren Projekt )
● 2.Projekt: sp2_app ( Console-Applikation, beginnend mit einem leeren Projekt )
In das Projekt sp2_dll ( 1.Projekt ) sind zunächst die beiden Files sp2_dll.h, sp2_dll.cpp einzufügen. Die Übersetzung soll die Files sp2_dll.dll und sp2_dll.lib erstellen (Bitte nachschauen). Später soll die
Anwendung ( 2. Projekt: sp2_app als Console-Applikation) die erstellten DLL-Files ( sp2_dll.dll und sp2_dll.lib ) nutzen.
DLL's haben Import/Export-Tabellen, d.h. der Linker braucht Hilfe-Stellungen ( storage-class modifiers ). Beispiele sind:
DLL's können auch "SHARED"-Daten verwalten. Hierzu benötigt der Linker ebenfalls Hilfe-Stellungen. Der Aufbau ist etwa wie folgt:
#pragma data_seg("SHARED")
// Definition von einfachen Variablen,
// wie z.B. int, char[] arrays, zeiger
// Keine Klassen verwenden, die einen
// tiefen Copy Constructors brauchen
// Ende des "shared data segment"
// Zurück zum normalen Daten-Segment-Bereich
#pragma data_seg()
// Das folgende Linker-Pragma veranlasst den Linker
// die notwendigen initialisierungen für das
// "shared data segment" zu erzeugen
#pragma comment(linker, "/section:SHARED,RWS")
DLL-Erstellung
Beim Programmieren von neuen Applikationen wird nicht nur die *.dll benötigt, sondern auch die zugehörige *.lib. Hier kommt ein einführendes Beispiel, das als erste Grundlage zum Erstellen der DLL
und der LIB verwendet werden soll. Zunächst sind die sp2_dll.dll und die sp2_dll.lib zu erstellen. Im Header-File sp2_dll.h werden infolge von
#ifdef _DLLBUILD_
die storage-class modifiers ( automatisch ) umgeschalten, denn was für die DLL ein EXPORT ( #define _DLLBUILD_ ), ist für die Applikation ein IMPORT ( #undef _DLLBUILD_ ).
///////////////////////////////////// Funktions-Prototyp:///////////////////////////////////DLL_API int sp2_dllFunc( int i );DLL_API HINSTANCE GetDllInstance(void);
///////////////////////////////////// Referenz: ///////////////////////////////////extern DLL_API int sp2_dllInt;
///////////////////////////////////// C++-Klasse: // ohne tiefen Copy-Konstruktor!
//exportierte Variable DLL_API int sp2_dllInt = 1;
//exportierte Funktion. DLL_API int sp2_dllFunc(int i) { char buf[256]; int j = i + sp2_dllInt; sp2_dllInt += 10; wsprintf( buf, "i + sp2_dllInt = %d", j ); MessageBox(0,buf,0,MB_OK); return j; }#pragma data_seg() #pragma comment(linker, "/section:SHARED,RWS")
///////////////////////////////////// DllMain ist Pflicht///////////////////////////////////BOOL WINAPI DllMain( HINSTANCE hinstDLL,DWORD fdwReason,LPVOID lpvReserved){ switch (fdwReason) { case DLL_PROCESS_ATTACH: case DLL_THREAD_ATTACH: case DLL_THREAD_DETACH: case DLL_PROCESS_DETACH: break; } hInst = hinstDLL; return TRUE;}
Applikation-Erstellung
Das 1.Projekt: sp2_app enthält die Windows-Applikation. Weil der sp2_app.exe-File die Dll zunächst im eigenen Direktory sucht, so ist es günstig die Linker-Ausgabe in das Debug-Verzeichnis des DLL-
Projektes umzuleiten. Dort befinden sich bereits sp2_dll.dll und sp2_dll.lib. Dem Linker muss noch die benötigte LIB ( sp2_dll.lib ) mitgeteilt werden. Dies kann erfolgen mit:
DLL's können auch "SHARED"-Daten verwalten. Hierzu benötigt der Linker ebenfalls Hilfe-Stellungen. Der Aufbau ist etwa wie folgt:
#pragma data_seg("SHARED")
// Definition von einfachen Variablen,
// wie z.B. int, char[] arrays, zeiger
// Keine Klassen verwenden, die einen
// tiefen Copy Constructors brauchen
// Ende des "shared data segment"
// Zurück zum normalen Daten-Segment-Bereich
#pragma data_seg()
// Das folgende Linker-Pragma veranlasst den Linker
// die notwendigen initialisierungen für das
// "shared data segment" zu erzeugen
#pragma comment(linker, "/section:SHARED,RWS")
DLL-Erstellung
Beim Programmieren von neuen Applikationen wird nicht nur die *.dll benötigt, sondern auch die zugehörige *.lib. Hier kommt ein einführendes Beispiel, das als erste Grundlage zum Erstellen der DLL
und der LIB verwendet werden soll. Zunächst sind die sp2_dll.dll und die sp2_dll.lib zu erstellen. Im Header-File sp2_dll.h werden infolge von
#ifdef _DLLBUILD_
die storage-class modifiers ( automatisch ) umgeschalten, denn was für die DLL ein EXPORT ( #define _DLLBUILD_ ), ist für die Applikation ein IMPORT ( #undef _DLLBUILD_ ).
///////////////////////////////////// Funktions-Prototyp:///////////////////////////////////DLL_API int sp2_dllFunc( int i );DLL_API HINSTANCE GetDllInstance(void);
///////////////////////////////////// Referenz: ///////////////////////////////////extern DLL_API int sp2_dllInt;
DLL_API void func(); DLL_API int i = 10; DLL_API int j; DLL_API int n;
///////////////////////////////////// Konstruktor der Klasse/////////////////////////////////// sp2_dllClass::sp2_dllClass() { return; }
///////////////////////////////////// SHARED-Variablen in der DLL///////////////////////////////////#pragma data_seg("SHARED") //exportierte Variable DLL_API int sp2_dllInt = 1;
//exportierte Funktion. DLL_API int sp2_dllFunc(int i) { char buf[256]; int j = i + sp2_dllInt; sp2_dllInt += 10; wsprintf( buf, "i + sp2_dllInt = %d", j ); MessageBox(0,buf,0,MB_OK); return j; }#pragma data_seg() #pragma comment(linker, "/section:SHARED,RWS")
///////////////////////////////////// DllMain ist Pflicht///////////////////////////////////BOOL WINAPI DllMain( HINSTANCE hinstDLL,DWORD fdwReason,LPVOID lpvReserved){ switch (fdwReason) { case DLL_PROCESS_ATTACH: case DLL_THREAD_ATTACH: case DLL_THREAD_DETACH: case DLL_PROCESS_DETACH:
break; } hInst = hinstDLL; return TRUE;}
Applikation-Erstellung
Das 1.Projekt: sp2_app enthält die Windows-Applikation. Weil der sp2_app.exe-File die Dll zunächst im eigenen Direktory sucht, so ist es günstig die Linker-Ausgabe in das Debug-Verzeichnis des DLL-
Projektes umzuleiten. Dort befinden sich bereits sp2_dll.dll und sp2_dll.lib. Dem Linker muss noch die benötigte LIB ( sp2_dll.lib ) mitgeteilt werden. Dies kann erfolgen mit:
enthält für die Konstruktion und Fertigung mit Hilfe eines Rechners CAD ( Computer-
Aided-Design ) und CAM ( Computer-Aided-Manufacturing )
Nach DIN 19226 gilt:
Ein System ist eine abgegrenzte Anordnung von aufeinander einwirkenden Gebilden.
Solche Gebilde können sowohl Gegenstände als auch Denkmethoden und deren
Ergebnisse ( z.B. Organisationsformen, mathematische Methoden,
Programmiersprachen) sein. Diese Anordnung wird durch eine Hüllfläche von ihrer
Umgebung abgegrenzt oder abgegrenzt gedacht. Durch die Hüllfläche werden
Verbindungen des Systems mit seiner Umgebung geschnitten. Die mit diesen
Verbindungen übertragenen Eigenschaften und Zustände sind die Größen, deren
Beziehungen untereinander das dem System eigentümliche Verhalten beschreibt.
Durch zweckmäßiges Zusammenfügen und Unterteilen von solchen Systemen
können größere und kleinere Systeme entstehen.
Objektbezogene Systembezeichnungen:
Systeme können nach Prinzipien eingeteilt und unterschieden werden:
abstrakt: lat. abstrahere
formal äußere Form ( nicht Inhalt )
verbal mündlich
konkret: gegenständlich
konzipiert lat. concipere
real lat., zu res "Sache"
Etwas auführlicher:
abstrakt:
lat. abstrahere: wegziehen, wegschleppen, von den individuellen Merkmalen losgelöst, nicht konkret, sinnlich nicht wahrnehmbar, rein begrifflich, unanschaulich, von der Wirklichkeit abgetrennt; Gegensatz: konkret. Abstrakt wird auch als Bezeichnung für die Erfassung des Wesentlichen verwendet ( z.B. Person – Mensch – Säugetier – Lebewesen – Seiendes etc. ). Aristoteles nannte es aphairesis ( griechisch: Wegnahme ) das methodische Erfassen des Wesentlichen ( Abstraktionsmethode, induktiven Logik, Phänomenologie ).
formal Formal meint die äußere Form ( nicht den Inhalt ) und kann ohne Entsprechung in der
Wirklichkeit sein, der Form genügend, nur äußerlich, nicht in Wirklichkeit, Axiome werden in Zeichen des Operationssystems ausgedrückt
verbal mündlich, mit Worten, mit Hilfe der Sprache
konzipiert lat. concipere: zusammenfassen, begreifen, sich vorstellen; von einer bestimmten
Vorstellung, Idee ausgehend etwas planen, entwerfen, entwickeln; einen Plan oder ein schriftliches Konzept für etwas machen;
real lat., zu res "Sache", wirklich, tatsächlich, nicht nur in der Einbildung, in der Wirklichkeit vorhanden, der Realität entsprechend;Gegensatz: irreal.
künstlich:Wer sich künstlich aufregt, regt sich über etwas mehr als nötig auf
natürlich:Die lateinische Fügung ( in natura ) entspricht der Bedeutung "in Wirklichkeit; in seiner wirklichen, natürlichen Gestalt". Das Haus sieht in natura ganz anders aus als auf dem Foto.
Ein System S besteht aus einer Menge M von Komponenten und damit definierten Relation R, d.h. aus dem
Begriffspaar S = ( M, R ).
Wird
M = { i, s, o } : Eingabe-, System-, Ausgabe - Zustände R = { I, S, O } : Eingabe-, Übergangs-, Ausgabe - Funktionen
in
S = ( M, R ) : Menge von Komponenten, Relationen
eingesetzt, so ergibt sich mit der Zeit t die Darstellung eines Sytems S zu
S = ( { i, s, o, t }, { I, S, O } )
Gödel:
Jedes formale System ist unvollständig. Die wahre Welt umfasst mehr als das
Denken. Das Denken umfasst mehr als die Sprache.
Ein diskretes System wird in der Graphentheorie ( Topologie ) dargestellt durch eine Menge von Punkten ( Ecken oder
Knoten ), die durch Kanten ( Linien; gerichtete oder ungerichtete ) verbunden sind.
Ein statisches System ist unabhängig von der Zeit.
Bei einem dynamischen System können sich im Laufe der Zeit die Komponenten und Beziehungen ändern.
Ein offenes System ist sind durch den Austausch von Materie, Energie, Information mit der System - Umgebung
gekennzeichnet.
Bei einem geschlossenes System ist kein Austausch mit der System - Umgebung möglich. Ein geschlossenes System
geht langfristig in den Zustand maximaler Entropie über.
Bei einem Aufbausystem steht die statische Darstellung der Systemstruktur, d.h. die Verknüpfung der in einem
System enthaltenen Komponenten im Vordergrund ( Strukturbäume, Hirarchiestrukturen, Strukturmatrizen, ).
Charakteristisch sind die Bezeichnungen für die Verknüpfungen: Relation, Beziehung, Kopplung.
Bei einem Ablaufsystem steht die Darstellung der Systemfunktionen als Folgeverknüpfung ( Vorgänger, Nachfolger,
Sequenz ) im Vordergrund. Ein modulares System [ engl. modular systems ] nutzen eine funktionale Zerlegung ind
kleinere Teilaufgaben.
Praktische Anwendungen sind: Netzpläne, Programmablaufpläne, Flußdiagramme. Die Netzplantechnik ( Teilgebiet
des Operations-Research ) ist ein Verfahren zur Analyse, Planung und Kontrolle von Großprojekten und zur
Gewährleistung eines optimalen Einsatzes von Personal, Betriebs- und Finanzmitteln. Die Projekte werden zunächst
gedanklich in Einzeltätigkeiten ( Aktivitäten, Vorgänge ) zerlegt und diese dann gemäß ihren technologisch bedingten
Verknüpfungen mit Mitteln der Graphentheorie ( Graph ) dargestellt, im einfachsten Fall mit Pfeilen als Tätigkeiten
und Knoten als Ereignissen. Der sich daraus ergebende Netzplan bildet die Grundlage für die Zeitplanung. Dabei
werden die frühestmöglichen Zeitpunkte für den Abschluss der Einzeltätigkeiten und damit auch das frühestmögliche
Projektende errechnet ( kritischer Pfad ). Aus der Bestimmung der spätestzulässigen, das frühestmögliche Projektende
nicht gefährdenden Eintrittszeitpunkten der Einzeltätigkeiten ergeben sich gewisse zeitliche Spielräume ( Pufferzeiten
). Die bekanntesten Methoden der Netzplantechnik sind CPM ( englisch critical path method ) und MPM ( Metra
Potenzial-Methode ) für deterministische sowie PERT ( englisch program evaluation and review technique ) für
stochastische Vorgänge.
Damit grundlegende Wechselwirkungen zwischen diese Komponenten möglich sind, läuft auf diesem
Hardwaresystem ein Betriebssystem. Das Betriebssystem ist ein wesentlicher Bestandteil der Systemsoftware. Die
Systemsoftware besteht aus einzelnen Teilen und Gruppe von Basisprogrammen, die die Hardware unmittelbar
ansprechen und Dateien verwalten. Die Anwendungssysteme ( Applikationen, Programme ) nutzen diese
grundlegenden Basisprogramme.
Der Begriff Systemtechnik ( System Engineering, auch System Analysis ) entstammt etymologisch dem Griechischen
und bedeutet soviel wie "zusammen, stellen, Handwerk". Der Begriff Systemtechnik wird als Verallgemeinerung und
Erweiterung der ingenieurwissenschaftlichen Methodik betrachtet. Die Systemtechnik ist auf die Untersuchung und
Entwicklung von Systemen als sinnvoll gegliedertes Gebilde ausgerichtet. Strukturiert werden Objekte und Prozesse.
Wissenschaftliche Fragen werden in der Systemtheorie behandelt.
Beispiel: Nach DIN 1314 wird der Druck p meist in der Einheit bar angegeben und zählt vom Nullpunkt aus.
Druckdifferenzen werden durch die Formelzeichen, nicht aber durch die Einheit gekennzeichnet. Dies gilt besonders
für die Manometerablesung bzw. atmosphärischen Druckdifferenzen.
Nationale Normungsinstitutionen1917 wurde in Deutschland der Normalienausschuß für den Allgemeinen Maschinenbau gegründet
1926 in Deutscher Normenausschuß e.V. ( DNA ) umbenannt wurde.
1936 wurden die Normen staatlich verbindlich.
1975 erfolgte eine Umbenennung in DIN = Deutsches Institut für Normung e.V. und die Anerkennung als nationale Normungsinstitution der Bundesrepublik Deutschland
1990 übernahm das DIN die gesamtdeutsche Normung. DIN hat die Rechtsform eines eingetragenen, gemeinnützigen Vereins mit Sitz in Berlin. Mitglieder ( etwa 6000 ) können Firmen, Verbände, interessierte Körperschaften, Behörden und Organisationen aber keine Einzelpersonen sein. Die Normungsarbeit wird in 4600 Arbeitsausschüssen von etwa 28 500 Fachleuten ( ehrenamtliche Mitarbeiter von Herstellern, Handel, Handwerk, Verbraucher, Behörden, Wissenschaftseinrichtungen ) geleistet und von 1000 hauptamtlichen Mitarbeitern koordiniert. DIN finanziert sich zu etwa 60% aus dem eigenen Beuth-Verlag ( Normen, Normentwürfe und DIN-Taschenbücher ). Die eigene Normungsarbeit ist in DIN 820-4) festgelegt und ausgerichtet an Freiwilligkeit, Öffentlichkeit, Beteiligung aller interessierten Kreise, Konsens, Einheitlichkeit und Widerspruchsfreiheit, Ausrichtung am Stand der Technik, an den wirtschaftlichen Gegebenheiten und am allgemeinen Nutzen sowie Internationalität.
Internationale Normungsinstitutionen1906 Genf: International Electrotechnical Commission ( IEC )
1926 Genf: International Federation of the National Standardizing Associations ( ISA )
1947 International Organization for Standardization ( ISO, ersetzte die ISA ). Die ISO besteht aus etwa 120 nationalen Normungsinstitutionen. Die Internationale Fernmelde-Union ( IFU ) ist für Telekommunikation zuständig.
1961 Brüssel: das Europäische Komitee für Normung ( CEN, Comité Européen de Normalisation; nicht staatliche, gemeinnützige Vereinigung; Deutsches Mitglied ist das DIN )
1961 Brüssel: Europäische Komitee für elektrotechnische Normung ( CENELEC, Comité Européen de Normalisation Electrotechnique; nicht staatliche, gemeinnützige Vereinigung; Deutsche Mitglieder sind die DKE = Deutsche Elektrotechnische Kommission und der VDE = Verband Deutscher Elektrotechniker )
1982 Zusammenschluss von CEN und CENELEC zur Gemeinsamen Europäischen Normungsinstitution. CEN/CENELEC-Mitglieder übernehmen ( soweit möglich ) die europäischen Normen ( EN ) als nationale Normen. Im Bereich der Telekommunikation sorgt das Europäische Institut für Telekommunikationsnormen ( ETSI, Institut Européen des Normes de Télécommunication, etwa 12000 europäische Normen ) in enger Zusammenarbeit mit CEN/CENELEC für europaweite Normen.
DFÜ-Normen schafft die CCITT ( ComitConsultatif International Télégraphique et Téléphonique, Genf, nationalen Behörden, privaten Firmen sowie nationalen und internationalen wissenschaftlichen Organisationen ) ständiges Organ der internationalen Fernmeldeunion ( Abkürzung ITU ). Das CCITT ist 1993 in der ITU aufgegangen.
Beispiele für Normen
X.400
An international message-handling standard for connecting e-mail networks and for connecting users to e-mail networks. X.400 is published by the International Telegraph and Telephone Consultative Committee ( CCITT standards body, now called the International Telecommunications Union (ITU). The X.400 Application Programming Interface Association XAPIA defines programming interfaces to X.400. MAPI applications are fully interoperable with X.400 messaging applications.
X.435 Electronic Data Interchange (EDI): A standard for integrating data with various native formats into a, which has been defined by the International Telegraph and Telephone Consultative Committee standards body, now called the International Telecommunications Union (ITU), and is implemented in the X.435 message-handling standard. X.435 is an international message-handling standard that is published by the International Telegraph and Telephone Consultative Committee CCITT standards body, now called the International Telecommunications Union (ITU), and that implements the Electronic Data Interchange (EDI) standard for integrating data with various native formats into a message.
X.400 Schicker, Pietro, "Message Handling Systems, X.400", Message Handling Systems and Distributed Applications, E. Stefferud, O-j. Jacobsen, and P. Schicker, eds., North-Holland, 1989, pp. 3-41.
X.500 An international message-handling standard for directory services, published by the International Telegraph and Telephone Consultative Committee CCITT standards body, now called the Internal Telecommunications Union (ITU).
X.509 An international message-handling standard for message authentication and encryption. X.509 is published by the International Telegraph and Telephone Consultative Committee CCITT standards body, now called the Internal Telecommunications Union (ITU).
XAPIA The X.400 Application Programming Interface Association, the standards-setting body for programming interfaces to X.400 components. XAPIA also defines the Common Messaging Calls inteface component.
US-ASCII Coded Character Set--7-Bit American Standard Code for Information Interchange, ANSI X3.4-1986.
ISO-646 International Standard--Information Processing--ISO 7-bit coded character set for information interchange, ISO 646:1983.
ISO-2022 International Standard--Information Processing--ISO 7-bit and 8-bit coded character sets--Code extension techniques, ISO 2022:1986.
ISO-8859 Information Processing -- 8-bit Single-Byte Coded Graphic Character Sets -- Part 1: Latin Alphabet No. 1, ISO 8859-1:1987. Part 2: Latin alphabet No. 2, ISO 8859-2, 1987. Part 3: Latin alphabet No. 3, ISO 8859-3, 1988. Part 4: Latin alphabet No. 4, ISO 8859-4, 1988. Part 5: Latin/Cyrillic alphabet, ISO 8859-5, 1988. Part 6: Latin/Arabic alphabet, ISO 8859-6, 1987. Part 7: Latin/Greek alphabet, ISO 8859-7, 1987. Part 8: Latin/Hebrew alphabet, ISO 8859-8, 1988. Part 9: Latin alphabet No. 5, ISO 8859-9, 1990.
ISO 9241-10 Grundsätze der Dialoggestaltung
ISO/DIS 9241-11
Richtlinien zur Gebrauchstauglichkeit
ISO/DIS 9241-12
Informationsdarstellung
ISO/DIS 9241-13
Benutzerführung
ISO 9241-14 Dialogführung über Menüs
ISO/DIS 9241-15
Dialogführung über Kommandosprachen. (DIS = Abkürzung für Draft International Standard, finaler Entwurf der ISO).
ISO/DIS 9241-1+
Dialogführung über direkte Manipulation. (DIS = Abkürzung für Draft International Standard, finaler Entwurf der ISO).
ISO/DIS 9241-17
Dialogführung über Bildschirmformulare (DIS = Abkürzung für Draft International Standard, finaler Entwurf der ISO).
ISO 9241 1998 verabschiedete die ISO die Ergonomie-Normenreihe. "Ergonomische Anforderungen an Bürotätigkeiten mit Bildschirmgeräten"
ISO/IEC 10646 Unicode
ISO-Norm 13407
Beschreibt einen benutzerorientierten Entwicklungszyklus ( 1998 verabschiedet ). Unter dem Titel "Benutzer-orientierte Gestaltung interaktiver Systeme" formuliert die Norm für Hard- und Software Kriterien, die die Anpassung interaktive Systeme an den Benutzer ermöglichen sollen.
RFC 783 Sollins, K., "TFTP Protocol (revision 2)", RFC 783, MIT, June 1981.
RFC-821 Postel, J., "Simple Mail Transfer Protocol", STD 10, RFC 821, USC/Information Sciences Institute, August 1982.
RFC822 Standard of the Format of Internet Text Messages ,D.Crocker,1982: Legt den Aufbau des Kopfes einer E-Mail-Nachricht fest,z.b. die Codierung von Sender- und Empfaengeradresse.
RFC1521 MIME(Multipurpose Internet Mail Extensions)Part One: Definiert ein Schema fuer die Unterbringung verschiedenartigster Daten innerhalb des Hauptteils einer E-Mail-Nachricht. Beispilesweise von Grafiken oder ausfuehrbaren Dateien. Gilt nicht fuer E-Mail ,sondern natuerlich auch fuer das Web.
RFC1522 MIME(Multipurpose Internet Mail Extensions)Part Two: Der zweite Teil der MIME-Definition. Definiert den Kodierungsmechanismus fuer Zeichen,die ueber den 7-Bit-Us_ASCII-Zeichensatz hinausgehen,in den Kopffeldern von E-Mail-Nachrichten.
POSTSCRIPT Adobe Systems, Inc., PostScript Language Reference Manual, Addison-Wesley, 1985.
POSTSCRIPT2 Adobe Systems, Inc., PostScript Language Reference Manual, Addison-Wesley, Second Edition, 1990.
ATK Borenstein, Nathaniel S., Multimedia Applications Development with the Andrew Toolkit, Prentice-Hall, 1990.
ECMA-158 December 1997, Standardizing Information and Communication Systems, Portable Common Tool Environment (PCTE) - C Programming Language Binding
DIN 1304 Formelzeichen
DIN 66234 ( Teil 8)EG ( 90/270/ )
Software-Ergonomie ist ein wesentlicher Bereich der Arbeitsgestaltung. Die EG-Richtlinie 90/270/ EWG von 1990 ( DIN 66234, Teil 8 ) legt die Anforderungen fest, die ein ergonomisch gestalteter Dialog zwischen Mensch und Computer erfüllen soll. Arbeitgeber sollen benutzerfreundliche Software einsetzen, die der ausführenden Tätigkeit angepasst ist ( verständliche Format, angemessenes Bearbeitungtempo, Rückmeldungen über Ergebnisse der Abläufe ).
... Sinnbilder Schaltpläne von Leitungen, Schaltern, Maschinen und Aggregate DIN-Normen oder den Richtlinien entnommen.
ECMA Standards
ECMA - Standardizing Information and Communication Systems ( ECMA blue cover)
Stichwort Kommentar
ECMA-6 7-Bit Coded Character Set, 6th edition (December 1991)
ECMA-13File Structure and Labelling of Magnetic Tapes for Information Interchange, 4th edition (December 1985)
ECMA-35 Character Code Structure and Extension Techniques, 6th edition (December 1994)
ECMA-43 8-Bit Coded Character Set Structure and Rules, 3rd edition(December 1991)
ECMA-48 Control Functions for Coded Character Sets, 5th edition(June 1991)
ECMA-74Measurement of Airborne Noise Emitted by Information Technology and Telecommunications Equipment, 6th edition (December 1999)
ECMA-948-Bit Single-Byte Coded Graphic Character Sets - Latin Alphabets No. 1 to No. 4, 2nd edition (June 1986)
ECMA-99Data Interchange on 130 mm Flexible Disk Cartridges Using MFM Recording at 13 262 ftprad on Both Sides, 3,8 Tracks per mm (September 1985)
ECMA-100Data Interchange on 90 mm Flexible Disk Cartridges Using MFM Recording at 7 958 ftprad on 80 Tracks on Each Side - ISO Type 301, 2nd edition (December 1988)
ECMA-106Private Telecommunication Networks (PTN) - Signalling Protocol at the S Reference Point - Circuit Mode Basic Services (SSIG-BC), 3rd edition (December 1993)
ECMA-107 Volume and File Structure of Disk Cartridges for Information Interchange, 2nd edition (June 1995)
ECMA-108Measurement of High-Frequency Noise emitted by Information Technology and Telecommunications Equipment, 3rd edition (December 1996)
ECMA-109Declared Noise Emission Values of Information Technology and Telecommunications Equipment, 4th edition (December 1996)
ECMA-125Data Interchange on 90 mm Flexible Disk Cartridges Using MFM Recording at 15 916 ftprad on 80 Tracks on Each Side - ISO Type 302 (December 1987)
ECMA-1288-Bit Single-Byte Coded Graphic Character Sets - Latin Alphabet No. 5, 2nd edition (December 1999)
ECMA-130 Data Interchange on Read-only 120 mm Optical Data Disks (CD-ROM), 2nd edition (June 1996)
ECMA-144 8-Bit Single-Byte Coded Character Sets - Latin Alphabet No. 6, 3rd edition (December 2000)
ECMA-1458 mm Wide Magnetic Tape Cartridge for Information Interchange - Helical Scan Recording (December 1990)
ECMA-1463,81 mm Wide Magnetic Tape Cartridge for Information Interchange - Helical Scan Recording - DATA/DAT Format (December 1990)
ECMA-147Data Interchange on 90 mm Flexible Disk Cartridges using MFM Recording at 31 831 ftprad on 80 Tracks on Each Side - ISO Type 303 (December 1990)
ECMA-148Private Integrated Services Network (PISN) - Specification, Functional Model and Information Flows - Identification Supplementary Services (ISSD), 3rd edition (June 1997)
ECMA-1503,81 mm Wide Magnetic Tape Cartridge for Information Interchange - Helical Scan Recording - DDS-DC Format using 60 m and 90 m Length Tapes, 2nd edition (June 1992)
ECMA-151Data Compression for Information Interchange - Adaptive Coding with Embedded Dictionary - DCLZ Algorithm (June 1991)
ECMA-152Data Interchange on 12,7 mm 18-Track Magnetic Tape Cartridges - Extended Format, 2nd edition (December 1993)
ECMA-153Information Interchange on 130 mm Optical Disk Cartridges of the Write Once, Read Multiple (WORM) Type, using the Magneto-Optical Effect, 2nd edition (June 1994)
ECMA-154Data Interchange on 90 mm Optical Disk Cartridges, Read only and Rewritable, M.O., 2nd edition (June 1994)
ECMA-156Private Telecommunication Networks (PTN) - Signalling at the S Reference Point - Generic Keypad Protocol for the Support of Supplementary Services (SSIG-KP), 2nd edition (June 1993)
ECMA-157Private Telecommunication Networks (PTN) - Signalling Protocol at the S Reference Point - Identification Supplementary Services (SSIG-ID), 2nd edition (June 1993)
ECMA-158Portable Common Tool Environment (PCTE) - C Programming Language Binding, 4th edition (December 1997)
ECMA-159Data Compression for Information Interchange - Binary Arithmetic Coding Algorithm (December 1991)
ECMA-160Determination of Sound Power Levels of Computer and Business Equipment Using Sound Intensity Measurements; Scanning Method in Controlled Rooms, 2nd edition (December 1992)
ECMA-161Private Telecommunication Networks (PTN) - Signalling at the S Reference Point - Generic Feature Key Management Protocol for the Control of Supplementary Services (SSIG-FK), 2nd edition (June 1993)
ECMA-162Portable Common Tool Environment (PCTE) - Ada Programming Language Binding, 4th edition (December 1997)
ECMA-163Private Integrated Services Network (PISN) - Specification, Functional Model and Information Flows - Name Identification Supplementary Services (NISD), 3rd edition (September 1997)
ECMA-165Private Integrated Services Network (PISN) - Generic Functional Protocol for the Support of Supplementary Services - Inter-Exchange Signalling Procedures and Protocol (QSIG-GF), 4th edition(June 2001)
ECMA-167Volume and File Structure for Write-Once and Rewritable Media using Non-Sequential Recording for Information Interchange, 3rd edition(June 1997)
ECMA-168Volume and File Structure of Read-Only and Write-Once Compact Disk Media for Information Interchange, 2nd edition (December 1994)
ECMA-1698 mm Wide Magnetic Tape Cartridge Dual Azimuth Format for Information Interchange - Helical Scan Recording (June 1992)
ECMA-1703,81 mm Wide Magnetic Tape Cartridge for Information Interchange - Helical Scan Recording - DDS Format Using 60 m and 90 m Length Tapes (June 1992)
ECMA-1713,81 mm Wide Magnetic Tape Cartridge for Information Interchange - Helical Scan Recording - DATA/DAT-DC Format Using 60 m and 90 m Length Tapes (June 1992)
ECMA-173Private Integrated Services Network (PISN) - Specification, Functional Model and Information Flows - Call Diversion Supplementary Services (CFSD), 2nd edition (June 1997)
ECMA-177Private Integrated Services Network (PISN) - Specification, Functional Model and Information Flows - Call Transfer Supplementary Service (CTSD), 2nd edition (September 1997)
ECMA-178Private Integrated Services Network (PISN) - Inter-Exchange Signalling Protocol - Call Transfer Supplementary Service (QSIG-CT), 2nd edition (September 1997)
ECMA-179 Services for Computer Supported Telecommunications Applications (CSTA) Phase I (June 1992)
ECMA-180 Protocol for Computer Supported Telecommunications Applications (CSTA) Phase I (June 1992)
ECMA-182Data Interchange on 12,7 mm 48-Track Magnetic Tape Cartridges - DLT1 Format (December 1992)
ECMA-183Data Interchange on 130 mm Optical Disk Cartridges - Capacity: 1 Gigabyte per Cartridge (December 1992)
ECMA-184Data Interchange on 130 mm Optical Disk Cartridges - Capacity: 1,3 Gigabytes per Cartridge (December 1992)
ECMA-185Private Integrated Services Network (PISN) - Specification, Functional Model and Information Flows - Call Completion Supplementary Services (CCSD), 2nd edition (June 1997)
ECMA-193Private Integrated Services Network (PISN) - Specification, Functional Model and Information Flows - Do Not Disturb and Do Not Disturb Override Supplementary Services (DND(O)SD), 2nd edition (June 1997)
ECMA-194Private Integrated Services Network (PISN) - Inter-Exchange Signalling Protocol - Do Not Disturb and Do Not Disturb Override Supplementary Services (QSIG-DND(O)), 3rd edition (June 1997)
ECMA-195Data Interchange on 130 mm Optical Disk Cartridges - Capacity: 2 Gigabytes per Cartridge, 2nd edition (June 1995)
ECMA-196 Data Interchange on 12,7 mm 36-Track Magnetic Tape Cartridges (December 1993)
ECMA-197Data Interchange on 12,7 mm 112-Track Magnetic Tape Cartridges - DLT2 Format (December 1993)
ECMA-1983,81 mm Wide Magnetic Tape Cartridge for Information Interchange - Helical Scan Recording - DDS-2 Format using 120 m Length Tapes, 2nd edition (June 1995)
ECMA-201Data Interchange on 90 mm Optical Disk Cartridges - Capacity: 230 Megabytes per Cartridge, 2nd edition (December 1994)
ECMA-202Private Integrated Services Network (PISN) - Specification, Functional Model and Information Flows - Call Intrusion Supplementary Service (CISD), 2nd edition (June 1997)
ECMA-217Services for Computer Supported Telecommunications Applications (CSTA) Phase II (December 1994)
ECMA-218Protocol for Computer Supported Telecommunications Applications (CSTA) Phase II (December 1994)
ECMA-219Authentication and Priviledge Attribute Security Application with Related Key Distribution Functions - Part 1, 2 and 3, 2nd edition (March 1996)
ECMA-220Private Integrated Services Network (PISN) - Specification, Functional Model and Information Flows - Call Interception Additional Network Feature (ANF-CINTSD), 2nd edition (June 1997)
ECMA-234 Application Programming Interface for Windows (APIW) (December 1995)
ECMA-235 The ECMA GSS-API Mechanism (March 1996)
ECMA-2363,81 mm Wide Magnetic Tape Cartridge for Information Interchange - Helical Scan Recording - DDS-3 Format using 125 m Length Tapes (June 1996)
ECMA-238Data Interchange on 130 mm Optical Disk Cartridge of Type WORM (Write Once Read Many) using Irreversible Effects - Capacity: 2,6 Gbytes per Cartridge (June 1996)
ECMA-239Data Interchange on 90 mm Optical Disk Cartridges - HS-1 Format - Capacity: 650 Megabytes per Cartridge (June 1996)
ECMA-240Data Interchange on 120 mm Optical Disk Cartridges using Phase Change PD Format - Capacity: 650 Mbytes per Cartridge (June 1996)
ECMA-241Private Integrated Services Network (PISN) - Specification, Functional Model and Information Flows - Message Waiting Indication Supplementary Service (MWISD), 4th edition (February 2002)
ECMA-244Private Integrated Services Network (PISN) - Mapping Functions for the Employment of a Circuit Mode Basic Service and the Supplementary Service User-to-User Signalling as a pair of On-demand Inter-PINX Connections (Mapping-UUS), 2nd edition (September 2000)
ECMA-2468 mm Wide Magnetic Tape Cartridge for Information Interchange - Helical Scan Recording - AIT-1 Format, 2nd edition(June 1998)
ECMA-2478 mm Wide Magnetic Tape Cartridge for Information Interchange - Helical Scan Recording - HH-1 Format, 2nd edition(June 1998)
ECMA-24812,65 mm Wide Magnetic Tape Cassette for Information Interchange - Helical Scan Recording - DTF-1 Format, 2nd edition (June 1998)
ECMA-2498 mm Wide Magnetic Tape Cartridge for Information Interchange - Helical Scan Recording - DA-2 Format, 2nd edition (June 1998)
ECMA-250Private Integrated Services Network (PISN) - Specification, Functional Model and Information Flows - Common Information Additional Network Feature (ANF-CMNSD), 2nd edition (December 1998)
ECMA-251Private Integrated Services Network (PISN) - Inter-Exchange Signalling Protocol - Common Information Additional Network Feature (QSIG-CMN), 2nd edition (December 1998)
ECMA-258Data Interchange on 12,7 mm 128-Track Magnetic Tape Cartridges - DLT 3-XT Format (June 1997)
ECMA-259 Data Interchange on 12,7 mm 208-Track Magnetic Tape Cartridges - DLT 5 Format (June 1997)
ECMA-260Data Interchange on 356 mm Optical Disk Cartridges - WORM, using Phase Change Technology Capacity: 14,8 and 25 Gbytes per Cartridge (June 1997)
ECMA-277Private Integrated Services Network (PISN) - Circuit Emulation Specification - Emulation of Basic Access by ATM Networks (June 1998)
ECMA-278Data Interchange on 12,7 mm 128-Track Magnetic Tape Cartridge - Parallel Serpentine Format, 2nd edition (June 2000)
ECMA-27980 mm (1,23 Gbytes per side) and 120 mm (3,95 Gbytes per side) DVD-Recordable Disk (DVD-R) (December 1998)
ECMA-280Data Interchange on 130 mm Optical Disk Cartridges of Type WORM (Write Once Read Many) Using Irreversible Effects - Capacity: 5,2 Gbytes per Cartridge (December 1998)
ECMA-281Private Integrated Services Network (PISN) - Specification, Functional Model and Information Flows - Private User Mobility (PUM) - Registration Supplementary Service (PUMRSD), 2nd edition(June 2000)
ECMA-2918 mm Wide Magnetic Tape Cartridge for Information Interchange - Helical Scan Recording AIT-1 with MIC Format (December 1999)
ECMA-2928 mm Wide Magnetic Tape Cartridge for Information Interchange - Helical Scan Recording AIT-2 with MIC Format (December 1999)
ECMA-2938 mm Wide Magnetic Tape Cartridge for Information Interchange - Helical Scan Recording - MammothTape-2 Format (December 1999)
ECMA-294B-ISDN and B-PISN - Digital Subscriber Signalling System No. two (DSS2), Broadband Inter-Exchange Signalling (B-QSIG), and Signalling System No. 7 (SS7) - Call Control in a Separated Call and Bearer Control Environment - Part 1: Protocol Specification (December 1999)
ECMA-295
B-ISDN and B-PISN - Digital Subscriber Signalling System No. two (DSS2), Broadband Inter-Exchange Signalling (B-QSIG), and Signalling System No. 7 (SS7) - Call Control in a Separated Call and Bearer Control Environment - Part 2: Protocol Implementation Conformance Statement (PICS) Proforma Specification (December 1999)
ECMA-296B-ISDN and B-PISN - Digital Subscriber Signalling System No. two (DSS2), Broadband Inter-Exchange Signalling (B-QSIG), and Signalling System No. 7 (SS7) - Prenegotiation - Part 1: Protocol Specification (December 1999)
ECMA-297B-ISDN and B-PISN - Digital Subscriber Signalling System No. two (DSS2), Broadband Inter-Exchange Signalling (B-QSIG), and Signalling System No. 7 (SS7) - Prenegotiation - Part 2: Protocol Implementation Conformance Statement (PICS) Proforma Specification (December 1999)
ECMA-299Private Integrated Services Network (PISN) - Specification, Functional Model and Information Flows - Single Step Call Transfer Supplementary Service (SSCT-SD) (February 2000)
ECMA-300Private Integrated Services Network (PISN) - Inter-Exchange Signalling Protocol - Single Step Call Transfer Supplementary Service (QSIG-SSCT) (February 2000)
ECMA-301Private Integrated Services Network (PISN) - Specification, Functional Model and Information Flows - Wireless Terminal Location Registration Supplementary Service and Wireless Terminal Information Exchange Additional Network Feature (WTMLR-SD) (June 2000)
ECMA-302Private Integrated Services Network (PISN) - Inter-Exchange Signalling Protocol - Wireless Terminal Location Registration Supplementary Service and Wireless Terminal Information Exchange Additional Network Feature (QSIG-WTMLR) (June 2000)
ECMA-303Private Integrated Services Network (PISN) - Specification, Functional Model and Information Flows - Wireless Terminal Call Handling Additional Network Features (WTMCH-SD) (June 2000)
ECMA-307Corporate Telecommunication Networks - Signalling Interworking between QSIG and H.323 - Generic Functional Protocol for the Support of Supplementary Services (June 2000)
ECMA-308Corporate Telecommunication Networks - Signalling Interworking between QSIG and H.323 - Call Transfer Supplementary Services, 2nd edition (June 2001)
ECMA-309Corporate Telecommunication Networks - Signalling Interworking between QSIG and H.323 - Call Diversion Supplementary Services, 2nd edition (June 2001)
ECMA-310Private Integrated Services Network (PISN) - Specification, Functional Model and Information Flows - Simple Dialog Supplementary Service (SDSD) (June 2000)
ECMA-312Private Integrated Services Network (PISN) - Profile Standard for the Use of PSS1 (QSIG) in Air Traffic Services Networks, 2nd edition (June 2001)
ECMA-313Private Integrated Services Network (PISN) - Specification, Functional Model and Information Flows - Call Identification and Call Linkage Additional Network Feature (CIDLSD) (September 2000)
ECMA-31512,65 mm Wide Magnetic Tape Cassette for Information Interchange - Helical Scan Recording - DTF-2 (December 2000)
ECMA-3168 mm Wide Magnetic Tape Cartridge for Information Interchange - Helical Scan Recording - VXA-1 Format (December 2000)
ECMA-317Data Interchange on 300 mm Optical Disk Cartridges of Type WORM (Write Once Read Many) Using Irreversible Effects - Capacity: 30 Gbytes per Cartridge (December 2000)
ECMA-318Private Integrated Services Network (PISN) - Use of QSIG at the C Reference Point between a PINX and an Interconnecting Network (December 2000)
ECMA-319Data Interchange on 12,7 mm - 384- Track Magnetic Tape Cartridges - Ultrium-1 Format (June 2001)
ECMA-320Data Interchange on 12,7 mm - 448-Track Magnetic Tape Cartridges - SDLT1 Format (June 2001)
ECMA-321Streaming Lossless Data Compression Algorithm (SLDC) (June 2001)
ECMA-322Data Interchange on 130 mm Magneto-Optical Disk Cartridges - Capacity: 9,1 Gbytes per Cartridge (June 2001)
ECMA-323XML Protocol for Computer Supported Telecommunications Applications (CSTA) Phase III (June 2001)
ECMA-324Private Integrated Services Network (PISN) - Specification, Functional Model and Information Flows - Short Message Service (SMSSD) (June 2001)
ECMA-325Private Integrated Services Network (PISN) - Inter-Exchange Signalling Protocol - Short Message Service (QSIG-SMS) (June 2001)
ECMA-326Corporate Telecommunication Networks - Signalling Interworking between QSIG and H.323 - Call Completion Supplementary Services (June 2001)
ECMA-328Detection and measurement of chemical emissions from electronic equipment (August 2001)
ECMA-3298 mm Wide Magnetic Tape Cartridge for Information Interchange - Helical Scan Recording - AIT-3 Format (December 2001)
ECMA-330120 mm (4,7 Gbytes per side) and 80 mm (1,46 Gbytes per side) DVD Rewritable Disk (DVD-RAM) (December 2001)
ECMA-331Case for 120 mm and 80 mm DVD-RAM Disks (December 2001)
ECMA-332Corporate Telecommunication Networks - Signalling Interworking between QSIG and H.323 - Basic Services (December 2001)
ECMA-333Private Integrated Services Network (PISN) - Mapping Functions for the Tunnelling of QSIG through H.323 Networks (December 2001)
ECMA-334C# Language Specification (December 2001)
ECMA-335Common Language Infrastructure (CLI) (December 2001)
ECMA-336Private Integrated Services Network (PISN) - Mapping Functions for the Tunnelling of QSIG through IP Networks (Mapping/IP-QSIG) (June 2002)
Historischeseinige Jahreszahlen
1941 Zuse Z3, ab etwa 1960 Einführung von Dialogbetrieb ( Stapelbetrieb mit Operator )
1960 Ken Thompson, Dennis Ritchie (Bell Labs, AT&T) u. MIT-Forscher entwickelten MULTICS, ein Mehrbenutzer-Betriebssystem 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, Weiterentw. zu C. 1973, Unix erstes BS größtenteils in einer Hochsprache ( kaum 1000 Zeilen Maschinencode, portierbar ), Keine Vermarktung von Unix wg. US-Kartell-Bestimmungen 1975, BSD-UNIX: Abkürzung für Berkeley Software Distribution-UNIX. Bezeichnung für eine UNIX-Variante ( entwickelt an der Berkeley-Universität in Kalifornien, Abgabe an Universitäten zum Selbstkostenpreis ) 1980, Xenix ( Microsoft, ab Mitte 80er: Santa Cruz Operation, etwa bis 1990 )
1981 IBM bringt den ersten PC ( mit MS-DOS ) heraus: 8088-CPU, 4.77 MHz, 64 KByte Speicher, 5.25"-Diskettenlaufwerk. Microsoft entwickelt dazu eine erste Version des Betriebssystems MS-DOS. Hayes bringt ein Modem mit 1200 Bit/s heraus. Herwig Feichtinger, heute bei Shamrock, gründet mit "mc" eine der ersten Computer-Zeitschriften. Novell stellt ein Netzwerk vor, mit dem mehrere Computer auf eine gemeinsame Festplatte zugreifen können. Hewlett-Packet konstruiert den ersten 32-Bit-Mikroprozessor.
1981 MS-DOS ( Microsoft-Disc Operating System, angelehtn an CP/M 80 für 160 KByte Disketten entwickelt, Version 1.25 ( ab 1982 ) benutzt zweiseitige Disketten ( 320 KByte Kapazität );ab 1983 MS-DOS 2.11 mit FAT-Festplatten und User-Hardware-Anpassungen durch Treiber ( in der CONFIG.SYS );ab 1984 MS-DOS 3.2 mit HD-Disketten ( 5.25 Zoll, 720 KByte) und die Einbindung in Netzwerke. ab 1984 MS-DOS 3.3 konnten Platten mit mehr als 32 MByte verwaltet werden;ab 1988 gab es das fehlerbehaftete MS-DOS 4.X mit DOS-Shell, Festplatten bis 2 GByte, EMS-Speicher nach dem LIM-Standard;ab 1991 erschien MS-DOS 5.0 mit HMA und UMA ab 1993 MS-DOS 6.X mit Zusatzprogrammen, wie Online-Komprimierer Doublespace, einem Virenschutz- und einem Backup-Programm, Memmaker-Speicher-Optimierer, ab 6.22 als Drivespace; )
1983 Apple bringt mit "Lisa" erstmals einen per Maus bedienbaren Computer mit grafischer Oberfläche heraus. Wegen des hohen Preises von rund 75.000 Dollar wird er ein Flop. Microsoft kündigt Windows 1.0 an, es wird erst 1985 verfügbar. Sony kündigt die 3,5"-Diskette an. IBM und Microsoft entwickeln zusammen das Betriebssystem OS/2. Novell bringt die Netware-Software heraus. Microcom erfindet ein fehlerkorrigierendes Modem-Protokoll (MNP).
1984 POSIX ( Portable Operating System Interface for UNIX ). Schnittstellen-Standard der IEEE, der von allen UNIX-Derivaten benutzt wird, dementsprechend auch von Programmen, die unter UNIX laufen beziehungsweise Übergänge zu UNIX-Rechnern herstellen.
1988 Normung zu ANSI-C ( Komitee X3J11 ).
1991 Linux 0.02 ( Linus Torvalds entwickelt einen Kern, FIN )
1985 1985, MS präsentiert Windows 1.01; 1987, Windows 2; 1987, OS/2 von IBM / MS, zeichenorientiert 1988, OS/2 von IBM/MS mit grafischer Oberfläche 1990, Windows 3.0 ( 16 Bit ) erscheint und wird ein großer Erfolg ( Trennung IBM – MS ). Im Oktober startet die Inmarsat-Organisation eigene Satelliten für die maritime Kommunikation. In den USA nimmt der erste kommerzielle Internet-Provider den Dienst auf. Unter Federführung der Bundespost entsteht der Treiber-Standard CAPI 1.1 für ISDN-Karten. James Gosling und Bill Joy beginnen mit der Entwicklung der Programmiersprache Java; 1992, Windows 3.1; 1993, Windows 3.11; 1993 Windows NT ( Windows New Technology, 32-Bit-Betriebssystem, für Workstations Windows NT 3.1, für Windows NT 3.1 Advanced Server und Netzwerke );
1996: Windows NT 3.5, und Windows NT 4.0; 1995, Windows 95, ( unterstützt 32-Bit-Anwendungen und die so genannte Plug-and-Play-Technologie, mitgeliefert wurde der Internet-Browser Internet Explorer ); 1998, Windows 98 ( Update für Windows 95, Active Desktop bindet den Webbrowser Internet Explorer, unterstützt werden: FAT32, DVD- und MMX-Technologie, AGP (siehe Graphikkarte) USB-Anschlüsse ( Universal Serial Bus ), AGP ( Accelerated Graphics Port, 1997 Intel, direkte Verbindung von der Grafikkarte zum Prozessor sowie zum Arbeitsspeicher, Taktfrequenz 66 MHz, AGP 1X = 266 MByte/s, AGP 2X = 533 MByte/s, AGP 4X = 1066 MByte/s, Pipelining, 8 zusätzliche Leitungen, DIME-Auslagerungsmodus für Texturen ); 2000, Windows 2000 wird in 4 Zusammenstellungen ausgeliefert: Windows 2000 Professional ( für PC und Notebook ),Windows 2000 Server ( einfache Netzanwendungen ), Windows 2000 Advanced Server ( Unternehmenskritische und komplexe Netzanwendungen ) Windows 2000 Datacenter Server ( für Rechenzentren, Lagerverwaltungssysteme und Finanzsysteme ); 2001, Windows ME; 2002, Windows XP
Zur Darstellung einer Zahl w betrachten wir das Beispiel w = 432.1 = 4 102 + 3 101 + 2 100 + 1 10-1. Das Zehnersystem hat die Basis b = 10. Es gibt 10 Ziffer 0,1,2,3,4,5,6,7,8,9. Eine von diesen Ziffern wird mit ai bezeichnet. Für jede Ziffer gilt 0 <= ai < b. Mit den Ziffern ai wird eine Zahl w in des Basis b repräsentiert durch: w = anmax*bnmax + anmax-1*bnmax-1 + ... + anmin+1*bnmin+1 + anmin*bnmin mit natürlichen 0 <= ai < b Abkürzende Schreibweise für natürliche Zahlen w (mit nmin=0): w = (akak-1...a0)b Achtung! Fehlerhaften Eingaben werden nicht geprüft.
math.h=====================abs Return absolute value of integer parameteracos Calculate arccosineasin Calculate arcsineatan Calculate arctangentatan2 Calculate arctangent, 2 parametersatof Convert string to doubleceil Return the smallest integer that is greater or equal to xcos Calculate cosinecosh Calculate hyperbolic cosineexp Calculate exponentialfabs Return absolute value of floating-pointfloor Round down valuefmod Return remainder of floating point divisionfrexp Get mantissa and exponent of floating-point valuelabs Return absolute value of long integer parameterldexp Get floating-point value from mantissa and exponentlog Calculate natural logarithmlog10 Calculate logarithm base 10modf Spli floating-point value into fractional and integer partspow Calculate numeric powersin Calculate sinesinh Calculate hyperbolic sinesqrt Calculate square roottan Calculate tangenttanh Calculate hyperbolic tangent
stdio.h=====================clearerr Reset error indicators.fclose Close a stream.feof Check if End Of File has been reached.ferror Check for errors.fflush Flush a stream.fgetc Get next character from a stream.fgetpos Get position in a stream.fgets Get string from a stream.fopen Open a file.fprintf Print formatted data to a stream.fputc Write character to a stream.fputchar Write character to stdout.fputs Write string to a stream.fread Read block of data from a stream.freopen Reopen a file using a different file mode.fscanf Read formatted data from a stream.fseek Reposition stream's position indicator.fsetpos Reposition file pointer to a saved location.ftell Return the current position of the file pointer.fwrite Write block of data to a stream.getc Get the next character.getchar Get the next character from stdin.gets Get a string from stdin.getw Get the next int value from a stream.perror Print error message.printf Print formatted data to stdout.putc Write character to a stream.putchar Write character to stdout.puts Write a string to stdout.putw Write an integer to a stream.
remove Delete a file.rename Rename a file or directory.rewind Reposition file pointer to the beginning of a stream.scanf Read formatted data from stdin.setbuf Change stream buffering.setvbuf Change stream buffering.sprintf Format data to a string.sscanf Read formatted data from a string.tmpfile Open a temporary file.tmpnam Generate a unique temporary filename.ungetc Push a character back into stream.
Streams.Streams are an abstraction used in C and C++ for input and output operations through I/O devices based on characters, like files, keyboard, printer, screen and I/O ports.A stdio.h stream is represented by a pointer to a FILE structure that contains internal info about properties and indicators of a file. Normally data contained in these structures are not referred directly. When using stdio.h functions, pointer to FILE structures are only used to be passed as parameters to I/O functions.
Properties.A stream has some properties that defines which functions can be used with it or how the functions will treat the stream. Most of them are defined in the mode parameter when fopen function is called.
AccessSpecifies if the operations performed with the stream will have read and/or write access to the file.
Text / BinaryText files are those where lines are delimited by the special character
EOL (End Of Line), and some translations occur when this special character is read or written for that these file can be directly outputed to a console. The End of a text file is defined by the first occurrence of the EOF character.A binary file is a file where each byte is read or written as a character, no translations occur, and the End of a binary file matches with the physical End of the File.
BufferA buffer is a block of memory where data is accumulated before being physically reador written to the file. Buffered stream causes I/O operations with the stream to be faster because normally buffers are faster than physical devices like disks or ports. A stream can be unbuffered so the data is directly read or written to the device. The use of stream buffers can be specified using functions setbuf and setvbuf.
Indicators.A stream has some indicators that specify the current state of it. These are internally modified and affect the behavior of Input/Output functions:
Error IndicatorThis indicator is set when an error has occurred in an operation related with the stream.This indicator can be checked using ferror, and can be reset by a call to clearerr or byany repositioning functions (rewind, fseek and fsetpos).
End-Of-File IndicatorWhen this indicator is set, the last reading or writing operation permormed has reached the End of the file associated with the stream. This can be checked with the feof function, and can be reset by calling to clearerr or by any repositioning functions (rewind, fseek and fsetpos).
Position Indicator (File pointer)This indicator is an internal pointer that points to the next character within the
stream that has to be read or written by the next I/O operation. This value can be obtained by the ftell and fgetpos functions, and can be changed calling to rewind, fseek and fsetpos unctions
Standard StreamsWhen a program that includes stdio.h begin its execution, three predefined streams are opened:
stdinThis is the standard input stream. By default stdin corresponds to the keyboard, but this can be redirected by the operating system.
stdoutThis is the standard output stream. By default stdout is directed to the screen, but the operating system can redirect it to a file or any other output device.
stderrThe standard error stream. This is an output stream specifically intendend to receive error messages. By default is directed to the standard output (like stdout), but it can be redirected to a log file or any other output device.
stdlib.h===============* = not ANSI-C, but supported by most compilers.
abort Abort current process returning error codeabs Return absolute value of integer parameteratexit Specifies a function to be executed at exitatof Convert string to doubleatoi Convert string to integeratol Convert string to longbsearch Binary search
calloc Allocate array in memorydiv Divide two integer values* ecvt Convert floating point value to stringexit Terminate calling process* fcvt Convert floating point value to stringfree Deallocate dynamically allocated memory* gcvt Convert floating point value to stringgetenv Get string from environment* itoa Convert integer to stringlabs Return absolute calue of long integer parameterldiv Divide two long integer values* lfind Linear search* lsearch Linear search* ltoa Convert long integer value to stringmalloc Allocate memory block* max Return the greater of two parameters* min Return the smaller of two parameters* putenv Create or modify environment variableqsort Sort using quicksort algorithmrand Generate random numberrealloc Reallocate memory blocksrand Initialize random number generatorstrtod Convert string to double-precision floating-point valuestrtol Convert string to long integerstrtoul Convert string to unsigned long integer* swab Swap bytessystem Execute command* ultoa Convert unsigned long integer to string===============stdlib.h summary:C stdlib.h library functions can be divided in these groups depending on their utility:
process control and environment variables:abort, atexit, exit, getenv, putenv, system
sorting and searching:bsearch, lfind, lsearch, qsort, swab
mathematical operations:abs, div, labs, ldiv
string.h=====================memchr Search buffer for a charactermemcmp Compare two buffersmemcpy Copy bytes to buffer from buffermemmove Copy bytes to buffer from buffermemset Fill buffer with specified characterstrcat Append stringstrchr Find character in stringstrcmp Compare two stringsstrcoll Compare two strings using locale settingsstrcpy Copy stringstrcspn Search string for occurrence of charcter setstrerror Get pointer to error message string
strlen Return string lengthstrncat Append substring to stringstrncmp Compare some characters of two stringsstrncpy Copy characters from one string to anotherstrpbrk Scan string for specified charactersstrrchr Find last occurrence of character in stringstrspn Get length of substring composed of given charactersstrstr Find substringstrtok Sequentially truncate string if delimiter is foundstrxfrm Transform string using locale settings
time.h=====================asctime Convert tm structure to stringclock Return number of clock ticks since process startctime Convert time_t value to stringdifftime Return difference between two timesgmtime Convert time_t value to tm structure as UTC timelocaltime Convert time_t value to tm structure as local timemktime Convert tm structure to time_t valuetime Get current time
Types and constants:CLK_TCKConstant that defines the number of clock ticks per second. Used by clock function.
clock_t and time_tData types returned by clock and time functions respectivelly. They are generally defined as long int.
tmStructure returned or used by asctime, gmtime, localtime and mktime.
/*****************************************************************************\* ** windowsx.h - Macro APIs, window message crackers, and control APIs ** ** Version Win32 / Windows NT ** ** Copyright (c) 1992-1996, Microsoft Corp. All rights reserved.** *\*****************************************************************************/
#ifndef _INC_WINDOWSX#define _INC_WINDOWSX
#ifdef __cplusplusextern "C" { /* Assume C declarations for C++ */#endif /* __cplusplus */
/****** ScrollBar control message APIs ***************************************/
/* NOTE: flags parameter is a collection of ESB_* values, NOT a boolean! */#define ScrollBar_Enable(hwndCtl, flags) EnableScrollBar((hwndCtl), SB_CTL, (flags))
/* Note: the following are for interpreting MDIclient to MDI child messages. */#define GET_WM_MDIACTIVATE_FACTIVATE(hwnd, wp, lp) (lp == (LONG)hwnd)#define GET_WM_MDIACTIVATE_HWNDDEACT(wp, lp) (HWND)(wp)#define GET_WM_MDIACTIVATE_HWNDACTIVATE(wp, lp) (HWND)(lp)/* Note: the following is for sending to the MDI client window. */#define GET_WM_MDIACTIVATE_MPS(f, hwndD, hwndA)\ (WPARAM)(hwndA), 0
#ifdef __cplusplus} /* End of extern "C" { */#endif /* __cplusplus */
#endif /* !_INC_WINDOWSX */
============================================= ACHTUNG! Nicht lauffähig! Nur Pseudo Code!=============================================
LRESULT API IDefWindowProc(HWND hWnd, UINT iMsg, WPARAM wParam, LPARAM lParam ) { int i; HBRUSH hbr; HWND hWndT;
switch ( iMsg ) { case WM_NCCREATE: // If WS_HSCROLL or WS_VSCROLL, initialize storage for scroll positions. // NOTE: Scroll bar storage and text storage will be freed automatically //by Windows during CreateWindow() if (TestWF(hWnd, (WFHSCROLL | WFVSCROLL))) { // Initialize extra storage for if (InitPwSB(hWnd) == NULL) return((LONG)FALSE); } // Store window text if present. return((LRESULT)(LONG)DefSetText(hWnd, ((LPCREATESTRUCT)lParam)->lpszName));
case WM_NCCALCSIZE: // wParam = fCalcValidRects // lParam = LPRECT rgrc[3]: // lprc[0] = rcWindowNew = New window rectangle // if fCalcValidRects: // lprc[1] = rcWindowOld = Old window rectangle // lprc[2] = rcClientOld = Old client rectangle // On return: // rgrc[0] = rcClientNew = New client rect // if fCalcValidRects: // rgrc[1] = rcValidDst = Destination valid rectangle // rgrc[2] = rcValidSrc = Source valid rectangle
CalcClientRect(hWnd, (LPRECT)lParam); break;
case WM_NCHITTEST: // Determine what area the passed coordinate is in. return((LRESULT)(DWORD)FindNCHit(hWnd, (LONG)lParam));
case WM_NCPAINT: // Do non-client area drawing. DWP_DoNCPaint(hWnd, (HRGN)wParam); break;
case WM_NCACTIVATE: // Do non-client drawing in response to activation or deactivation. DWP_DoNCActivate(hWnd, (BOOL)wParam); return (LRESULT)(DWORD)TRUE;
case WM_CANCELMODE: // Terminate any modes the system might be in, //such as scrollbar tracking, menu mode, button capture, etc. DWP_DoCancelMode(hWnd); break;
case WM_SETTEXT: // Set the new text and redraw the caption or icon title window. DefSetText(hWnd, (LPCSTR)lParam); DWP_RedrawTitle(hWnd); break;
case WM_GETTEXT: // If the buffer size is > 0, copy as much of the window text as // will fit (making sure to zero terminate the result). if (wParam){ if (hWnd->hName) return (LRESULT)(LONG)TextCopy(hWnd->hName, (LPSTR)lParam, (int)wParam); // No string: make sure we return an empty string.
((LPSTR)lParam)[0] = 0; } return (0L);
case WM_GETTEXTLENGTH: // Just return the length of the window text (excluding 0 terminator) if (hWnd->hName) return((LRESULT)(LONG)lstrlen(TextPointer(hWnd->hName))); return(0L);
case WM_PAINT: case WM_PAINTICON: DWP_Paint( iMsg, hWnd); break;
case WM_ERASEBKGND: case WM_ICONERASEBKGND: return (LRESULT)(LONG)DWP_EraseBkgnd(hWnd, iMsg, (HDC)wParam);
case WM_SYNCPAINT: // This message is sent when SetWindowPos() is trying to get the screen // looking nice after window rearrangement, and one of the windows involved // is of another task. This message avoids lots of inter-app message traffic // by switching to the other task and continuing the recursion there. // wParam = flags // LOWORD(lParam) = hrgnClip // HIWORD(lParam) = hWndSkip (not used; always NULL) // hWndSkip is now always NULL. // NOTE: THIS MESSAGE IS FOR INTERNAL USE ONLY! ITS BEHAVIOR // IS DIFFERENT IN 3.1 THAN IN 3.0!! DoSyncPaint(hWnd, NULL, ((WORD)wParam | DSP_WM_SYNCPAINT)); break;
case WM_SYSCOMMAND: SysCommand(hWnd, (int)wParam, lParam); break;
case WM_ACTIVATE: // By default, windows set the focus to themselves when activated. if ((BOOL)wParam) SetFocus(hWnd); break;
case WM_SETREDRAW: // Set or clear the WS_VISIBLE bit, without invalidating the window. // (Also performs some internal housekeeping to ensure that window // DC clip regions are computed correctly). DWP_SetRedraw(hWnd, (BOOL)wParam); break;
case WM_WINDOWPOSCHANGING: // If the window's size is changing, and the window has // a size border (WS_THICKFRAME) or is a main window (WS_OVERLAPPED), // then adjust the new width and height by sending a WM_MINMAXINFO message. #define ppos ((WINDOWPOS FAR *)lParam) if (!(ppos->flags & SWP_NOSIZE)) AdjustSize(hWnd, &ppos->cx, &ppos->cy); #undef ppos break;
case WM_WINDOWPOSCHANGED: // If (!(lpswp->flags & SWP_NOCLIENTMOVE) // send WM_MOVE message // If (!(lpswp->flags & SWP_NOCLIENTSIZE) // send WM_SIZE message with wParam set based on // current WS_MINIMIZED/WS_MAXIMIZED style. // If DefWindowProc() is not called, WM_MOVE and WM_SIZE messages // will not be sent to the window.
HandleWindowPosChanged(hWnd, (WINDOWPOS FAR *)lParam);break;
case WM_CTLCOLOR: // Set up the supplied DC with the foreground and background // colors we want to use in the control, and return a brush // to use for filling. switch (HIWORD(lParam)) { case CTLCOLOR_SCROLLBAR: // Background = white // Foreground = black // brush = COLOR_SCROLLBAR. SetBkColor((HDC)wParam, RGB(255, 255, 255)); SetTextColor((HDC)wParam, RGB(0, 0, 0)); hbr = sysClrObjects.hbrScrollbar;
// The scroll bar color may be dithered, so unrealize it. UnrealizeObject(hbr); break;
case WM_SETCURSOR: // wParam == hWndHit == hWnd that cursor is over
// lParamL == codeHT == Hit test area code (result of WM_NCHITTEST) // lParamH == msg == Mouse message number (may be 0) // Strategy: First forward WM_SETCURSOR message to parent. If it // returns TRUE (i.e., it set the cursor), just return. Otherwise, // set the cursor based on codeHT and msg. return (LRESULT)(LONG)DWP_SetCursor(hWnd, (HWND)wParam, LOWORD(lParam), HIWORD(lParam));
case WM_MOUSEACTIVATE:// First give the parent a chance to process the message. hWndT = GetChildParent(hWnd); if (hWndT) { i = (int)(DWORD)SendMessage(hWndT, WM_MOUSEACTIVATE, wParam, lParam); if (i != 0) return (LRESULT)(LONG)i; } // If the user clicked in the title bar, don't activate now: // the activation will take place later when the move or size occurs. if (LOWORD(lParam) == HTCAPTION) return((LRESULT)(LONG)MA_NOACTIVATE); return((LRESULT)(LONG)MA_ACTIVATE);
case WM_SHOWWINDOW: // If we are being called because our owner window is being shown, // hidden, minimized, or un-minimized, then we must hide or show // show ourself as appropriate. // // This behavior occurs for popup windows or owned windows only. // It's not designed for use with child windows. if (LOWORD(lParam) != 0 && (TestwndPopup(hWnd) || hWnd->hWndOwner)) { // The WFHIDDENPOPUP flag is an internal flag that indicates // that the window was hidden because its owner was hidden. // This way we only show windows that were hidden by this code, // not intentionally by the application.
// // Go ahead and hide or show this window, but only if: // // a) we need to be hidden, or // b) we need to be shown, and we were hidden by // an earlier WM_SHOWWINDOW message if ((!wParam && TestWF(hWnd, WFVISIBLE)) || (wParam && !TestWF(hWnd, WFVISIBLE) && TestWF(hWnd, WFHIDDENPOPUP))) { // Remember that we were hidden by WM_SHOWWINDOW processing ClrWF(hWnd, WFHIDDENPOPUP); if (!wParam) SetWF(hWnd, WFHIDDENPOPUP); ShowWindow(hWnd, (wParam ? SW_SHOWNOACTIVATE : SW_HIDE)); } } break;
case WM_NCLBUTTONDOWN: case WM_NCLBUTTONUP: case WM_NCLBUTTONDBLCLK: case WM_NCMOUSEMOVE: // Deal with mouse messages in the non-client area. DWP_NCMouse(hWnd, message, wParam, lParam); break;
case WM_KEYDOWN: // Windows 2.0 backward compatibility: // Alias F10 to the menu key // (only for apps that don't handle WM_KEY* messages themselves) if ((WORD)wParam == VK_F10) fF10Status = TRUE; break;
case WM_SYSKEYDOWN: // Is the ALT key down? if (HIWORD(lParam) & SYS_ALTERNATE) { // Toggle only if this is not an autorepeat key if ((HIWORD(lParam) & SYS_PREVKEYSTATE) == 0) { if (((WORD)wParam == VK_MENU) && (!fMenuStatus)) fMenuStatus = TRUE; else fMenuStatus = FALSE; } fF10Status = FALSE; DWP_ProcessVirtKey((WORD)wParam); } else { if ((WORD)wParam == VK_F10) { fF10Status = TRUE; } else { if ((WORD)wParam == VK_ESCAPE) { if (GetKeyState(VK_SHIFT) < 0) { SendMessage(hWnd, WM_SYSCOMMAND,(WPARAM)SC_KEYMENU, (LPARAM)(DWORD)MENUSYSMENU); } } } } break;
case WM_KEYUP: case WM_SYSKEYUP: // Press and release F10 or ALT. Send this only to top-level // windows, otherwise MDI gets confused. The fix in which // DefMDIChildProc() passed up the message was insufficient in the // case a child window of the MDI child had the focus. // if ( ((WORD)wParam == VK_MENU && (fMenuStatus == TRUE)) || ((WORD)wParam == VK_F10 && fF10Status) ) {
case WM_SYSCHAR: // If syskey is down and we have a char... */ fMenuStatus = FALSE;
if ((WORD)wParam == VK_RETURN && TestWF(hWnd, WFMINIMIZED)) { // If the window is iconic and user hits RETURN, we want to restore this window. PostMessage(hWnd, WM_SYSCOMMAND, (WPARAM)SC_RESTORE, 0L); break; }
if ((HIWORD(lParam) & SYS_ALTERNATE) && wParam) { if ((WORD)wParam == VK_TAB || (WORD)wParam == VK_ESCAPE) break;
// Send ALT-SPACE only to top-level windows. if (((WORD)wParam == MENUSYSMENU) && (TestwndChild(hWnd))) SendMessage(hWnd->hWndParent, message, wParam, lParam); else SendMessage(hWnd, WM_SYSCOMMAND, (WPARAM)SC_KEYMENU, (LPARAM)(DWORD)(WORD)wParam); } else { // Ctrl-Esc produces a WM_SYSCHAR, but should not beep if ((WORD)wParam != VK_ESCAPE) MessageBeep(0); } break;
case WM_CLOSE: // Default WM_CLOSE handling is to destroy the window. DestroyWindow(hWnd); break;
case WM_QUERYOPEN: case WM_QUERYENDSESSION: return((LRESULT)(LONG)TRUE);
case WM_ISACTIVEICON: return ((LRESULT)(DWORD)(BOOL)(TestWF(hWnd, WFFRAMEON) != 0));
case WM_CHARTOITEM: case WM_VKEYTOITEM: // Return -1 to cause default processing return((LRESULT)-1L);
case WM_DRAWITEM: #define lpdis ((LPDRAWITEMSTRUCT)lParam) if (lpdis->CtlType == ODT_LISTBOX) LBDefaultListboxDrawItem(lpdis); #undef lpdis break;
case WM_GETHOTKEY: return((LRESULT)(LONG)DWP_GetHotKey(hWnd)); break;
case WM_SETHOTKEY: return((LRESULT)(LONG)SetHotKey(hWnd, (WORD)wParam));
break;
case WM_QUERYDRAGICON: return((LRESULT)(DWORD)(WORD)DWP_QueryDragIcon(hWnd)); break;
case WM_QUERYDROPOBJECT: // If the application is WS_EX_ACCEPTFILES, return TRUE. if (TestWF(hWnd, WEFACCEPTFILES)) return (LRESULT)(DWORD)TRUE;
return (LRESULT)(DWORD)FALSE;
case WM_DROPOBJECT: return (LRESULT)(DWORD)DO_DROPFILE;
Cracker - Macros | Portabilität | Win32 | Win16 | Tastatur - Nachrichten | Tasten - Scan - Code | Tabelle der WM - Tastatur - Nachrichten ||./img/key1.gif | Virtual - Tasten - Code | Tabelle der Virtual - Tasten - Codes | Tasten - Zustand - Flags | Wie kann eine gedrücke SHIFT - Taste abgefragt werden? | Wie kann eine Berechnung abgebrochen werden? | Wie kann eine gedrückte CTRL - Taste( VK_CONTROL ) per Programm simuliert werden? | Wie kann die CAPS - LOCK - Taste( VK_CAPITAL ) invertiert werden? | Wie kann ein "floating-pop-up-menu"nach der Anzeige sichtbar bleiben? | lParam - Tastenflags | Maus - Nachrichten | WM_MOUSE - Nachrichten | Nachrichtenverfolgung
↑ NachrichtenWindows ist ein Nachrichten - gesteuertes System. Die Behandlung von Nachrichten ist ein zentraler Bestandteil des Betriebssystems. Es gibt eine Maus (mit
zugehörigem einer System-Message-Queue). Es gibt eine tastatur (mit zugehörigem einer System-Message-Queue). Zu jeder Applikation wird eine Applikation-
Message-Queue eingerichtet, in die jene Nachrichten (standardisiert) gestellt werden, die zu dieser Applikation gehören. Beispiel für den Nachrichten-Fluß bei einer
Tasten-Nachricht:
KEY-BOARD
(Ereignis)
Keyboard-Device-Driver
holt Scan-Codevom
Keyboard und stellt
diesen in
SYSTEM-MESSAGE-
QUEUE(geräte-
spezifisch)
Windows bringt
die geräte-spezifische
Nachricht aufstandardisierte
MSG-Form (WM_...),
stellt diese in
APPLICATION-MESSAGE-
QUEUE(Thread-
Message-Queue)(MSG: WM_...)
APPLICATION-NACHRICHTEN-
Schleife
DispatchMessage(&msg)
ruft die CALLBACK-Funktion auf,die zumsg.hWingehört
↑ System-Message-Queue
Die Maus- und Tastatur - Ereignisse werden der System - Message - Queue( Hardware - Buffer ) entnommen und in ein einheitliches MSG - Format gebracht. Dann
werden die Nachrichten in die Application - Message - Queue( Nachrichten an unser Fenster ) gestellt. Durch GetMessage() werden die Nachrichten dem Application -
Buffer entnommen. Sollen z.B. sämtliche Nachrichten an alle Anwendungen abgehorcht werden, so ist direkt hinter der System - Message - Queue ( Hardware - Buffer )
ein Hook ( z.B. CallNextHookEx ) einzubauen.
↑ Application-Message-Queue
Jede Anwendung hat eine eigene Application - Message - Queue. Ist diese leer, so können in der Zwischenzeit andere Programme ausgeführt werden ( kooperatives
Multitasking ).
● Mit der Window - Funktion PostMessage() kann per Programm eine Nachricht hinten in die Application - Message - Queue geschrieben
werden.
● Mit SendMessage() kann per Programm eine Nachricht direkt an unser Fenster geschickt werden. SendMessage() überholt alle
Nachrichten, die sich in der eigene Application - Message - Queue befinden.
Für die Nachrichten verwendet Windows den MSG-Typ:
↑ Tabelle der Nachrichten-PrefixePrefix Message category
ABM Application desktop toolbar
BM Button control
CB Combo box control
CBEM Extended combo box control
CDM Common dialog box
DBT Device
DL Drag list box
DM Default push button control
DTM Date and time picker control
EM Edit control
Prefix Message category
HDM Header control
HKM Hot key control
IPM IP address control
LB List box control
LVM List view control
MCM Month calendar control
ABM Application desktop toolbar
PBM Progress bar
PGM Pager control
PSM Property sheet
RB Rebar control
Prefix Message category
SB Status bar window
ABM Application desktop toolbar
SBM Scroll bar control
STM Static control
TB Toolbar
TBM Trackbar
TCM Tab control
TTM Tooltip control
TVM Tree-view control
UDM Up-down control
WM General window
Die msg-Nachricht enthält auch msg.message. Durch message wird die Art der Nachricht eindeutig spezifiziert.
Jede Nachricht kann in msg.wParam, msg.lParam zusätzliche Informationen hinterlegen. Die genaue Bedeutung der msg.wParam, msg.lParam - Bits hängt von
msg.message ab. Für viele einfache Nachrichten reichen die Bits von wParam, lParam aus. In msg.lParam kann auch ein Zeiger auf benötigte Informationen enthalten
sein.
msg.time enthält die Ereignis - Zeit.
Die Cursor - Koordinaten ( zur Ereignis-Zeit ) werden in pt übergeben.
Soll z.B. die nächste Nachricht aus der Application-Message-Queue geholt werden, so wird mit GetMessage( & msg ) diese Nachricht in die ( vorher angelegte )
Variable
MSG msg ;
gespeichert. Haupt - Nachrichten - Schleife ( nach WinMain ) ist eine ( beinahe ) Unendlich-Schleife, die nur durch die WM_QUIT - Nachricht verlassen werden kann.
Durch RegisterClass() wurde unsere ( Klassen - ) CALLBACK - Funktion WNDCLASS. lpfnWndProc = ( WNDPROC ) WndProc ; eingetragen. Durch
DispatchMessage ( & msg ) wird die aktuelle Nachricht an diese Funktion weiter gereicht, d.h. die WndProc() wird mit den msg - Paramtern aufgerufen. Jedes Fenster
hat ein eindeutiges Handle. Deshalb kann DispatchMessage ( & msg ) mit Hilfe von msg.hWnd die Nachricht über die ( globalen ) Klassen - Daten - Struktur an die
CALLBACK - Funktion weiter geben. Die Haupt - Nachrichten - Schleife wird bei einer WM_QUIT - Botschaft abgebrochen. Nach dem Eintreffen von
WM_DESTROY fügen wir in der Application - Message - Queue durch PostQuitMessage() die Nachricht WM_QUIT ein. Wenn GetMessage() die WM_QUIT -
Nachricht entnimmt, so wird die Haupt - Nachrichten - Schleife beendet.
↑ Message - Cracker - Macros
In windowsX.h sind die Message - Cracker - Macros enthalten. Durch diese Macros wird das Nachrichten - Carsting vermieden und die Win16/Win32 - Portabilität
Viele HANDLE_ - Macros ( z.B. HANDLE_WM_CHAR ) zerlegen die Nachrichten typentreu in die enthaltenen Nachrichten - Parameter und rufen damit die
Funktion ( hier fn ) auf. Die FORWARD_ - Macros machen diesen Vorgang rückgängig und erzeugen wieder die ursprüngliche ( hWnd, uMsg, wParam, lParam ) -
Nachricht.
Mit dem HANDLE_MSG - Macro hat eine CALLBACK - Funktion etwa den folgenden Aufbau:
16 Bit 32 Bit |----------------|---------------------------------| | wParam | lParam | |----------------|---------------------------------|
| | | | | wmID | wmCMD | wmHWND |
Der Button sendet Nachrichten an das Parent - Window, wenn sich sein Zustand ändert. Der Button - Identifizierer wird mit wmID, die Notification Messages ( z.B.
BN_CLICKED ) wird mit wmCMD und das Control - Handle mit wmHWND bezeichnet. Wegen der WIN16/WIN32 - Portabilität sind die windoesX.h - Macros
sinnvoll:
Nachrichten - Casting WindosX.h-Macros
#ifdef WIN16 int wmCMD = HIWORD( lParam ) ; #else int wmCMD = HIWORD( wParam ) ; #endif int wmID = LOWORD( wParam ); HWND wmHWND= (HWND)(UINT)lParam;
int wmCMD = GET_WM_COMMAND_CMD (wParam,lParam); int wmID = GET_WM_COMMAND_ID (wParam,lParam); HWND wmHWND= GET_WM_COMMAND_HWND(wParam,lParam);
↑ 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 = # 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 .codePUBLIC key_readkey_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 bx, [bp+4] ;ASCII returned MOV [bx], al MOV bx, [bp+6] ;Extended code returned MOV [bx], ah POP bp RETkey_read ENDP END
↑ Tasten - Scan - Code
Der folgende Tasten - Scan - Code ist festgelegt worden:
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 ( uMsg, 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 uMsg ist die
Tasten - Nachricht eindeutig identifizierbar. Mit wParam, lParam können die Tasten unterschieden werden.
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_CHAR ( wParam enthält ASCII von a, wie z.B. für a-Taste = '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 CALLBACK WndProc - Funktion etwa wie folgt benutzt werden.
Bei einer WM_KEYDOWN - Nachricht wird in LOWORD(wParam) der ( standardisierte ) Virtual - Key - Code übergeben. Die folgende Tabelle enthält die #define`s.
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
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.
↑ Wie kann eine gedrücke SHIFT - Taste abgefragt werden?
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
gewechselt, wenn das 0. Bit gleich 1 ist ( tggled ). Normalerweise ist eine Taste nicht gedrückt, dann ist das 0. Bit gleich 1.
↑ Wie kann eine gedrückte CTRL - Taste( VK_CONTROL ) per Programm simuliert werden?
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.
↑ 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 ) - Bit Bit HIWORD( lParam ) - Bit Bit HIWORD( lParam ) - Bit Bit HIWORD( lParam ) - Bit
151 if the key is up;0 if the key is down.
141 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. 81 if the key is extended;0 if it is not.
7 generally 0. 6..0hardware-scan code( used mainly in the translation of ALT+number-pad character code input )
↑ 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 ( uMsg, 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 uMsg ist die
Die Behandlung von Maus - Ereignisses geschieht vielfach in der CALLBACK - Funktion. In lParam wird die aktuelle Maus - Position an die CALLBACK - Funktion
übergeben.
LRESULT CALLBACK WndProc( HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam ) { static int xPos,yPos; switch ( uMsg ) { ... case WM_LBUTTONDOWN : xPos = (int) LOWORD(lparam); // 16 BIT yPos = (int) HIWORD(lparam); // pt = MAKEPOINT(lparam); // 32 BIT, pt vom Typ Point break; ... } ... return DefWindowProc( hWnd, uMsg, 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 wc={ 0 }; wc.cbSize=sizeof(WNDCLASSEX); ... wc.style = ... | CS_DBLCLKS; // Zeitgeber ½ sec. RegisterClass( & wc );
erforderlich.
↑ WM_MOUSE - 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
Nachricht wParam, lParam enthalten ...
WM_CAPTURECHANGED hwndNewCapture = (HWND) lParam; // handle of window to gain mouse capture
fwKeys = wParam; // key flagsxPos = LOWORD(lParam); // horizontal position of cursoryPos = HIWORD(lParam); // vertical position of cursor 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.
WM_MOUSEACTIVATE hwndTopLevel = (HWND) wParam; // handle of top-level parentnHittest = (INT) LOWORD(lParam); // hit-test valueuMsg = (UINT) HIWORD(lParam); // mouse message 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
WM_MOUSEWHEEL fwKeys = LOWORD(wParam); // key flagszDelta = (short) HIWORD(wParam); // wheel rotationxPos = (short) LOWORD(lParam); // horizontal position of pointeryPos = (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.
WM_NCHITTEST xPos = LOWORD(lParam); // horizontal screen position of cursoryPos = 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 borderHTBOTTOM In the lower horizontal border of a windowHTBOTTOMLEFT In the lower-left corner of a window borderHTBOTTOMRIGHT In the lower-right corner of a window borderHTCAPTION In a title barHTCLIENT In a client areaHTCLOSE 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 buttonHTHSCROLL In a horizontal scroll barHTLEFT In the left border of a windowHTMENU In a menuHTMAXBUTTON In Maximize buttonHTMINBUTTON In Minimize buttonHTNOWHERE On the screen background or on a dividing line between windowsHTREDUCE In a Minimize buttonHTRIGHT In the right border of a windowHTSIZE In a size box (same as HTGROWBOX)HTSYSMENU In a System menu or in a Close button in a child windowHTTOP In the upper horizontal border of a windowHTTOPLEFT In the upper-left corner of a window borderHTTOPRIGHT In the upper right corner of a window borderHTTRANSPARENT In a window currently covered by another windowHTVSCROLL In the vertical scroll bar
nHittest = (INT) wParam; // hit-test valuepts = MAKEPOINTS(lParam); // position of cursor nHittest see WM_NCHITTEST
Das Maus - Rad ( WM_MOUSEWHEEL ) kann z.B. zur Steuerung von Scroll - Bars eingesetzt werden.
↑ Nachrichtenverfolgung
Um die Folge von Nachrichten zu untersuchen, soll die folgende Funktion schreibe_nachrichten(UINT uMsg,WPARAM wParam,LPARAM lParam) die Folge der
Nachrichten anzeigen. Der Header-File enthält die #define's für die Nachrichten, die in einen Array der Art { "WM_DESTROY", WM_DESTROY}// 0x0002 hinterlegt
werden. Steht der Aufruf schreibe_nachrichten(uMsg,wParam,lParam) in einer CALLBACK-Funktion, so durchläuft for(int i = 0;i < n; i++) {...} alle Array-Einträgt
und gibt den gefundenen aus.
Das stdout_to()-Macro ermöglicht (mit Hilfe der freopen()-Funktion), die Standard-Ausgabe der printf's (einer Console-Applikation) in den aktuellen Quelltext-File
(__FILE__) umzuleiten. Die Benutzung von stdout_to erfolgt etwa gemäss:
Die folgende Funktion schreibe_nachrichten(UINT uMsg,WPARAM wParam,LPARAM lParam) wird in der CALLBACK-Funktion aufgerufen. In
schreibe_nachrichten() wird beijeder ankommenden Nachricht die Nachrichten-Tabelle msgdesc[] durchlaufen und bei Übereinstimmung wird der Name der aktuellen
uMsg-Nachricht (und auch wParam,lParam) ausgegeben.
for(int i = 0; i < len; i++) { if(uMsg == msgdesc[i].uMsg) { printf("\n// %03u %04x %s", j++, i, msgdesc[i].psz); if(uMsg == WM_COMMAND) printf(" wPar=0x%08x lPar=0x%08x",wParam,lParam); } } }
Es gibt Werkzeuge, die eine fortgeschrittene Verfolgung der Nachrichten erlauben (z.B. spy++).
============================================= ACHTUNG! Nicht lauffähig! Nur Pseudo Code!=============================================
LRESULT API IDefDlgProc( HWND hWnd, WORD iMsg, WPARAM wParam, LPARAM lParam) { HWND hWndT1; HWND hWndT2; BOOL result; ((PDLG)hWnd)->resultWP = 0L; result = FALSE; // Call the dialog proc if it exists if (((PDLG)hWnd)->lpfnDlg == NULL || !(result = CallDlgProc(hWnd, iMsg, wParam, lParam))) {
// Make sure window still exists. if (!IsWindow(hWnd)) { DebugErr(DBF_ERROR, "Dialog window destroyed in dialog callback"); goto ReturnIt; }
switch (iMsg) { case WM_ERASEBKGND: FillWindow(hWnd, hWnd, (HDC)wParam, (HBRUSH)CTLCOLOR_DLG); return((LRESULT)(LONG)TRUE);
case WM_SHOWWINDOW: // If hiding the window, save the focus. If showing the window // by means of a SW_* command and the fEnd bit is set, do not // pass to DWP so it won't get shown. if (!wParam) SaveDlgFocus(hWnd); else if (LOWORD(lParam) && pdlg->fEnd) break; return(DefWindowProc(hWnd, iMsg, wParam, lParam));
case WM_SYSCOMMAND: // If we're minimizing and a dialog control has the focus, // save the hWnd for that control if ((int) wParam == SC_MINIMIZE) SaveDlgFocus(hWnd); return( DefWindowProc ( hWnd, iMsg, wParam, lParam ) ) ;
case WM_SETFOCUS: if (!pdlg->fEnd && !RestoreDlgFocus(hWnd)) DlgSetFocus(GetFirstTab(hWnd)); break;
case WM_CLOSE: // Make sure cancel button is not disabled before sending the // IDCANCEL. Note that we need to do this as a message instead // of directly calling the dlg proc so that any dialog box // filters get this. hWndT1 = GetDlgItem( hWnd, IDCANCEL ) ; if ( hWndT1 && TestWF( hWndT1, WFDISABLED ) ) MessageBeep(0); else PostMessage(hWnd, WM_COMMAND, (WPARAM)IDCANCEL, MAKELPARAM(hWndT1, BN_CLICKED)); break;
case WM_NCDESTROY: fDialog = FALSE; /* clear this flag */
// Make sure we are going to terminate the mode loop, in case DestroyWindow // was called instead of EndDialog. We'll RIP in DialogBox2. ((PDLG)hWnd)->fEnd = TRUE; if (!(hWnd->style & DS_LOCALEDIT)) { if (((PDLG)hWnd)->hData) { GlobalUnlock(((PDLG)hWnd)->hData); ReleaseEditDS(((PDLG)hWnd)->hData); ((PDLG)hWnd)->hData = NULL; } }
// Delete the user defined font if any if (((PDLG)hWnd)->hUserFont) { DeleteObject((HANDLE)((PDLG)hWnd)->hUserFont); ((PDLG)hWnd)->hUserFont = NULL; } // Always let DefWindowProc do its thing to ensure that // everything associated with the window is freed up. DefWindowProc(hWnd, iMsg, wParam, lParam); break;
case DM_SETDEFID: if (!(((PDLG)hWnd)->fEnd)) { // Make sure that the new default button has the highlight. // We need to ignore this if we are ending the dialog box // because hWnd->result is no longer a default window id but // rather the return value of the dialog box. // // Catch the case of setting the defid to null or setting // the defid to something else when it was initially null.
case DM_GETDEFID: if (!((PDLG)hWnd)->fEnd && ((PDLG)hWnd)->result) return(MAKELRESULT(((PDLG)hWnd)->result, DC_HASDEFID)); else return(0L);
case WM_NEXTDLGCTL: // This message is so TAB-like operations can be properly handled // (simple SetFocus won't do the default button stuff) // hWndT2 = hWndFocus; if (LOWORD(lParam)) { if (hWndT2 == NULL) hWndT2 = hWnd; // wParam contains the hWnd of the ctl to set focus to hWndT1 = (hWnd)wParam; } else { if (hWndT2 == NULL) { // Set focus to the first tab item. hWndT1 = GetFirstTab(hWnd); hWndT2 = hWnd; } else { // If window with focus not a dlg ctl, ignore message. if (!IsChild(hWnd, hWndT2)) return((LRESULT)(LONG)TRUE); // wParam = TRUE for previous, FALSE for next hWndT1 = GetNextDlgTabItem(hWnd, hWndT2, (BOOL)wParam);
case WM_ENTERMENULOOP: case WM_LBUTTONDOWN: case WM_NCLBUTTONDOWN: // PLEASE NOTE: The following code is a VERY UGLY compatibility // hack. NEVER write code that looks at the window proc address // in order to determine the window type. The following code will // not work with subclassed combo or edit controls. // if (hWndT1 = hWndFocus) { if (hWndT1->pcls->lpfnWndProc == ComboBoxCtlWndProc) { // If user clicks anywhere in dialog box and a combo box (or // the editcontrol of a combo box) has the focus, then hide // it's listbox. SendMessage(hWndT1, CB_SHOWDROPDOWN, FALSE, 0L); } else { if (hWndT1->pcls->lpfnWndProc == EditWndProc && hWndT1->hWndParent->pcls->lpfnWndProc==ComboBoxCtlWndProc) { SendMessage(hWndT1->hWndParent,CB_SHOWDROPDOWN, FALSE, 0L); } } } return(DefWindowProc(hWnd, iMsg, wParam, lParam));
case WM_GETFONT: return (LRESULT)(DWORD)(WORD)((PDLG)hWnd)->hUserFont;
// We don't want to pass the following messages to DefWindowProc: // instead, return the value returned by the dialog proc (FALSE) case WM_VKEYTOITEM: case WM_COMPAREITEM: case WM_CHARTOITEM: case WM_INITDIALOG: break;
ReturnIt: // These messages are special cased in an unusual way: the return value // of the dialog function is not BOOL fProcessed, but instead it's the // return value of these messages. // if (iMsg == WM_CTLCOLOR || iMsg == WM_COMPAREITEM || iMsg == WM_VKEYTOITEM || iMsg == WM_CHARTOITEM || iMsg == WM_QUERYDRAGICON || iMsg == WM_INITDIALOG) { return((LRESULT)(DWORD)result); } return(((PDLG)hWnd)->resultWP);}
SetConsoleCtrlHandler _spawn functions CreateProcess system CreateProcess
↑ Klassen - Objekte
↑ Fenster - Objekte
Alle existierenden Fenster-Objekte können in einer Schleife durchlaufen werden. Im folgenden Beispiel wird von einem existierenden hWnd-
Fenster gestartet und das erste Fensterhandle mit GetWindow( hWnd, GW_HWNDFIRST ) geholt. Die verkettete Liste endet mit hNext ==
NULL.
↑ Beispiel CreateWindow(), DestroyWindow()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.
Die Liste der vorhandenen Fenster-Objekte kann durchlaufen werden. Mit dem erhaltenen Handle können die zugänglichen Fenster-Daten
ausgelesen bzw. vewendet werden. Hie ein Beispiel:
Wurde mit WNDCLASS.cbWndExtra=sizeof( void * ) bei Windows für jedes Fenster zusätzlicher Benutzer - Speicher ( 4 Byte ) reserviert, so
kann z.B. mit SetWindowLong() ein Zeiger auf einen vom Benutzer allokierten MYSTRUCT - Heap - Speicher hinterlegt werden.
MYSTRUCT * p = ( MYSTRUCT * ) GetWindowLong( hNext, DWL_USER ) ; if ( ! IsBadReadPtr( p, sizeof(MYSTRUCT) ) { ... // mit p kann lesend auf MYSTRUCT zugegriffen werden }
Beim Zugriff auf diesen Speicher kann mit IsBadReadPtr( p, sizeof(MYSTRUCT) geprüft werden, ob dieser Speicher gültig und benutzbar ist.
↑ GDI - Objekte
Die GDI - DLL enthält ( viele ) Funktionen. Hier sollen lediglich einige GDI - Funktionen zum Zeichnen und Schreiben ausgewählt und
behandelt werden. Das Erstellen und Aktualisieren des Bildschirmes erfolgt durch die WM_PAINT - Nachricht.
↑ Device Kontext
Die meisten GDI - Funktionen benutzen globale Daten ( Seiten - Effekt ) aus dem als Device - Kontext. Der Funktions - Parameter ist HDC
hDC. Bei der WM_NCPAINT und WM_NCACTIVATE - Nachrichten - Behandlung wird der Device - Kontext benutzt.
Unter case uMsg = WM_PAINT wird der Device - Kontext z.B. gemäß
Die DrawText() - Funktion benutzt den Device Kontext hDC, der u.a. den ausgewählten Font, die Text - Farbe und die Text - Hintergrund -
Farbe enthält.
● Die DrawText() - Funktion schreibt einen String *lpString in ein umschließendes Rechteck *lpRect.
Falls die Anzahl der auszugebenden Zeichen nCount = -1 ist, so muß *lpRect ein 0 terminierter String sein. Der Text kann gemäß expandierender
Tabs, der Ausrichtung ( Linksbündig, Rechtsbündig, Zentriert ), der Umbrüche am Zeilenrand, usw. justiert werden. Diese Funktion verwendet
intern TextOut(). Die DrawText() gibt die Höhe des Textes zurück.
int DrawText( HDC hDC, // handle to device context LPCTSTR lpString, // pointer to string to draw int nCount, // string length, in characters LPRECT lpRect, // pointer to struct with formatting dimensions UINT uFormat // text-drawing flags );
Für uFormat können die Konstanten
DT_BOTTOM, DT_CALCRECT, DT_CENTER, DT_EDITCONTROL, DT_END_ELLIPSIS oder DT_PATH_ELLIPSIS, DT_EXPANDTABS, DT_EXTERNALLEADING,
Die *.RC - Resourcen - Files ( ASCII ) enthalten z.B.
● Filenamen für Bilder ( Mauszeiger, Rasterbilder, Icons ),
● Text - und Hotkey - Tabellen,
● Menu - und Dialog - Beschreibungen.
Die *.RC - Resourcen - Files ( ASCII ) können "von Hand" geschrieben werden, aber vielfach ist die "visuelle Erstellung" mit einem Tool ( Resourcen Workshop ) bequemer. Das Tool
benutzt einen binäre Hilfsfiles und generiert automatisch den *.RC - ASCII - File und den zugehörigen *.H-File für die Identifizierer. Die *.RC - Syntax wird bei der automatsichen
Generierung berücksichtigt und braucht nicht gelernt werden. Durch den Resourcen-Compiler wird der *.RC - File in einen binären *.RES - File übersetzt.
Eine "visuelle Erstellung" ändert, ergänzt und überschreibt den alten *.RC - ASCII - File automatisch. Eine *.RC - Erstellung sollte entweder "von Hand" oder durchgängig "visuelle" mit
einem Tool erstellt werden.
Weil im *.RC - File auch WS_ - , DS_ -, SS_ - Windows - Konstanten benutzt werden, so ist deren Bedeutung bei der Erzeugung von Dialog-Rssourcen ( trotz Automatik ) zu kennen.
↑ *.RC-Syntax
Die *.RC - ASCII - Datei wird mit dem Resourcen-Compiler in eine *.RES - Binärdatei übersetzt. Der allgemeiner Aufbau einer *.RC Zeile ist:
ID - Identität RC-Typ Speicheroperationen Datenquelle auch BEGIN ... END
Die Speicher - Operationen PRELOAD ( nur Win16: mit *.exe geladen), LOADONCALL ( nur Win16: bei Ausführung geladen), FIXED ( nur Win16: Resource bleibt an fester Adresse ),
MOVEABLE ( nur Win16: Resource kann verschoben werden ), DISCARDABLE ( nur Win16: Resource kann entfernt werden ).
Im C/C++ - Programm wird mit der ID - Identität ( identifizierende Zahl ) auf die Resource zugegriffen. Die Resourcen entsprechen einer Aufzählung von benötigten, lesbaren Daten.
Deshalb ist im *.RC-File die Reihenfolge der Resourcen nicht wesentlich.
Für Dialoge werden Control Parameter ( wie z.B. PUSHBUTTON or CHECKBOX ) verwendet. Die Breite cx wird in 1/4-character units angegeben. Die Höhe cy wird in 1/8-character
units angegeben. Controls ( innerhalb eines Rssourcen-Templates ) haben die Syntax:
Diese CONTOLS gehören zu einer ( in Windows enthaltenen ) Klasse, wie z:b: "BUTTON", "EDIT", "LISTBOX", "SCROLLBAR", "COMBOBOX". Alternativ können Klassen ( mit
Prefix: 0xFFFF ) auch identifiziert werden. Zu jeder Klasse ist eine zugehörige CALLBACK-Funktion implizit verfügbar. Mit Hilfe von GetClassInfoEx() können die Daten in wcx
geschrieben werden. Die Dialog-Klasse MAKEINTRESOURCE(0x8002) z.B. durch GetClassInfoEx(GetModuleHandle(0),"#32770", &wcx). Beispiele:
Der Kern des Betriebssystems vewaltet Atome. Einem String wird ein Hash - Code zugeordnet. Bei Resourcen werden i.a. WORD ID_ ... - Identifizierer verwendet. Benötigt eine
Windows - Funktion den zugeordneten String, so kann das MAKEINTRESOURCE() - Macro verwendet werden. Das MAKEINTRESOURCE() - Macro ist definiert durch
Ressourcen-Tools ( AppWizard zur Erzeugung der *.RC - Quelltexte ) benutzen i.a. typische Präfixe für die Identifizierer ( z.B. #define IDD_DIALOG1 1000: (I)(D)entifiziere-
einen_(D)ialog 1 ). Diese Identifizierer sind WORD - Zahlen und werden oft durch MAKEINTRESOURCE(IDD_DIALOG1) übergeben. In dem jeweiligen Kontext müssen die
Identifizierer so geählt werden, daß diese eindeutig sein. Die MFC - Konvention schlägt die folgenden Präfixe vor.
Prefix Type of Symbol Example Range
IDR_Identification shared by multipleresources of different types
IDR_MAINFRAME 1 to 0x6FFF
IDD_ Dialog resource IDD_SPELL_CHECK 1 to 0x6FFF
HIDD_ Dialog-resource Help context HIDD_SPELL_CHECK 0x20001 to 0x26FF
IDB_ Bitmap resource IDB_COMPANY_LOGO 1 to 0x6FFF
IDC_ Cursor resource IDC_PENCIL 1 to 0x6FFF
IDI_ Icon resource IDI_NOTEPAD 1 to 0x6FFF
ID_ _ Command from menu item or toolbar ID_TOOLS_SPELLING 0x8000 to 0xDFFF
HID_ Command Help context HID_TOOLS_SPELLING 0x18000 to 0x1DFFF
IDP_ Message-box prompt IDP_INVALID_PARTNO 8 to 0xDFFF
HIDP_ Message-box Help context HIDP_INVALID_PARTNO 0x30008 to 0x3DFFF
IDS_ String resource IDS_COPYRIGHT 1 to 0x7FFF
IDC_ Control within dialog box IDC_RECALC 8 to 0xDFFF
↑ Benutzerdefinierte Resourcen - Macros
Damit die unterschiedliche Syntax und Bezeichner im *.RC, *.H und *.CPP Files bei den Übersetzungen unterschieden werden können, gibt es vordefinierte Konstanten ( z.B.
wird während der Resourcen - Übersetzung anstelle von ID(x) das Macro MAKEINTRESOURCE(x) verwendet und sonst die Zahl x direkt. Für die Erstellung eines *.RC - Resourcen -
Files ( ASCII ) "von Hand" können die folgenden Macros hilfreich sein. Durch solche Macros kann eine einheitliche, übersichtliche Gestaltung des *.RC - Files erreicht werden. Im C/C++
- Programm wird eine Resource durch einen Idetifizierer ( idRes = ID_ ... ) angesprochen.
Resourcen werden mit Load...()-Funktionen verfügbar. Diese Load...()-Funktionen benötigen die Instance hInstance des usführenden Programmes. Zur Vermeidung von globalen Variablen
hInstance wird oft hInstance = GetModuleHandle(0) verwendet. Auch bei DLL's funktioniert die folgende Funktion:
Ein Maus - Cursor wird definiert durch zwei 16x16 Bitmaps und einen kennzeichnenden Punkt ( Hotspot ). Die erste 16x16 Bitmap wird mit dem Hintergrund AND- und die zweite XOR-
verknüpft. Der Hotspot gibt innerhalb der Maske die Pixel - Position an, welche z.B. die Spitze des Pfeils symbolisiert. Die Erstellung eines Maus - Cursor - Bitmap durch den Benutzer ist
nur dann erforderlich, wenn die verfügbaren Maus - Cursor - Bitmaps nicht ausreichen.
↑ Icon - Resource
Ist ein Icon in dem File "c:\\pfad\\...\\myName.ico" enthalten, so kann dieses Icon gemäß
Tabellen von Strings werden für Fehler - Meldungen, statische Anzeigetexte und Ausgaben benutzt. Das C/C++ - Programm läd bei Bedarf diese Strings. Wird eine Applikation in eine
andere Landes - Sprachen übersetzt, so muß nur die Stringtabellen auswechselt werden. Bei C/C++ wird ein String "..." automatisch mit einem zusätzlichem \0 - Zeichen abgeschlossen.
● Ein *.RC - String wird nicht automatisch mit einem \0 abgeschlossen.
● Sonderzeichen innerhalb eines *.RC - Strings müssen oktal eingegeben werden ( ein "für" wird zu "f\374r" ).
Im *.RC sieht eine STRINGTABLE etwa wie folgt aus:
STRINGTABLE DISCARDABLE BEGIN IDS_STRING1, "Error in Runtime 1" .... IDS_STRING16, "Wert = %d" END
Eine Tabelle sollte maximal 16 Strings enthalten. Die Strings aus der Resourcen - String - Tabelle werden dann gemäß
geladen. hInstance = GetModuleHandle(0) entspricht der Anfangsadresse des ausgeführten Programmes. Der WinMain( ) - Aufruf übergibt den Parameter hInstance an das Programm.
hInstance wird in unterschiedlichen Funktionen benötigt. Deshable kann hInstance ( anstelle des Aufrufes GetModuleHandle(0) ) auch in einer globale Variablen gespeichert werden.
Alternativ kann hInstance auch beim WM_CREATE - Ereignis ( infolge von CreateWindow ) durch
my_hInstance = ( LPCREATESTRUCT ) lParam -> hInstance erhalten werden.
Eine vereinfachte Funktion Load_String( int idRes ) gibt den Zeiger auf den geladenen String zurück.
erfolgen. Sollen drei Strings gleichzeitig, nebeneinander benutzt werden ( nrStr = 0, 1, 2 ), so kann eine erweitert Funktion Load_String_into() geschrieben werden.
// Die drei static Buffer können mehrfach geladen und // p0, p1, p2 können unabhängig voneinander benutzt werden.LPSTR p0 = Load_String_into( 0, IDS_STRING0 );LPSTR p1 = Load_String_into( 1, IDS_STRING1 );LPSTR p2 = Load_String_into( 2, IDS_STRING2 );
geladen werden. Mit (NULL!=FindResource(GetModuleHandle(0),MAKEINTRESOURCE((idRes>>4)+1),RT_STRING)) kann geprüft werden, ob die String-Ressource im 16-Block
existiert.
Die Zeichenanzahl (Länge von Stringressourcen) wird benötigt, wenn vor dem LoadString-Aufruf hinreichend Buffer-Speicher zur Verfügung stehen soll.
UINT GetResourceStringLen(UINT uID){ HGLOBAL hGlobal; LPWSTR pwstr; HRSRC hrsrc; UINT uLen = 0, x; HINSTANCE hInst = GetModuleHandle(0); // String-Ressourcen sind in 16er Gruppen gepackt. // Hier finden wir das Segment, // in dem sich der gesuchte String befindet: if(NULL == (hrsrc = FindResource(hInst,MAKEINTRESOURCE((uID/16)+1),RT_STRING))) return(0); if(NULL == (hGlobal = LoadResource(hInst,hrsrc))) return(0); if(NULL != (pwstr = (LPWSTR)LockResource(hGlobal))) { // Die 16 (UNICODE-)Strings sind nacheinander und nicht // null-terminiert gespeichert. Im ersten Character steht die Länge // des Strings. for(x = (uID % 16) + 1; x; --x) { uLen = *pwstr; pwstr += (uLen + 1); } UnlockResource(hGlobal); } FreeResource(hGlobal); // uLen++; wegen abschliessendem \0-Zeichen return(uLen);}
↑ Menu - Resourcen
Ein *.RC - File kann etwa wie folgt aufgebaut werden:
eingetragen. Bei einem Menu - Klick wird die CALLBACK - Funktion mit case iMsg = WM_COMMAND aufgerufen. In LOWORD( wParam ) wird der Resourcen - Identifizierer
Das Windows - System verwendet ( oben links ) das System - Menu ( Wiederherstellen, Verschieben, Größe ändern, Minimieren, Maximieren, Schließen, Nächstes ). Das System - Menu
Mit Beschleuniguungs - Tasten ( Alt - Hot - Keys ) kann das Menu schneller bedient werden. Hierzu wird im Menu - Text das '&' - Markierungs - Zeichen verwendet. Es können aber
auch andere Tasten einem Menu - Punkt zugeordnet werden. Der bMain.rc - File enthält z.B.
in die WndProc - CALLBACK - Funktion eingefügt werden.
↑ LoadMenuIndirect
Ein Menu kann per Programm im Speicher aufgebaut werden und dann durch LoadMenuIndirect() aufgebaut und mit SetMenu() dem Fenster hinzugefügt werden. Im Speicher beginnt ein
Menu mit dem MENUITEMTEMPLATEHEADER ( meist versionNumber=0; offset=0, falls nachfolgend MENUITEMTEMPLATE-Struktur kommt ). Dann folgen die
MENUITEMTEMPLATE-Einträge.
Header für Menu-Ressourcen
Kopf eines MenuMENUITEMTEMPLATEHEADER
Jedes Popup/ItemMENUITEMTEMPLATE
typedef struct { WORD versionNumber; // 0 WORD offset; // 0 } MENUITEMTEMPLATEHEADER;
typedef struct { WORD mtOption; // Item-Flag z.B. 0/MF_POPUP/MF_END WORD mtID; // ID, fehlt bei Popup-Eintrag WCHAR mtString[1]; // 00-beendeter Text } MENUITEMTEMPLATE;
Beispiel für den Menu-Ressourcen-Aufbau ( WORD-aligned )
Beispiel:
0 VersionNumber von MENUITEMTEMPLATEHEADER
0 Offset von MENUITEMTEMPLATEHEADER
MF_POPUP Kennzeichen für einen Pupup-Eintrag
'Pop1' als Pupup-Text Unicode-Word-Text mit 00-Ende
0 Kennzeichen für einen Item-Eintrag
IDM_100 Identifizierer für das Menu; WM_COMMAND, LOWORD(wParam)
'Item 100' als Item-Text Unicode-Word-Text mit 00-Ende
0 Kennzeichen für einen Item-Eintrag
IDM_110 Identifizierer für das Menu; WM_COMMAND, LOWORD(wParam)
'Item 110' als Item-Text Unicode-Word-Text mit 00-Ende
MF_END Kennzeichen für das letzte Item, das zu einem Popup gehören
IDM_120 Identifizierer für das Menu; WM_COMMAND, LOWORD(wParam)
'Item 120' als Item-Text Unicode-Word-Text mit 00-Ende
MF_POPUP| MF_END Kennzeichen für den letzten Pupup-Eintrag
'Pop2' als Pupup-Text Unicode-Word-Text mit 00-Ende
0 Kennzeichen für das letzte Item, das zu einem Popup gehören
IDM_200 Identifizierer für das Menu; WM_COMMAND, LOWORD(wParam)
'Item 200' als Item-Text Unicode-Word-Text mit 00-Ende
MF_END Kennzeichen für das letzte Item, das zu einem Popup gehören
IDM_210 Identifizierer für das Menu; WM_COMMAND, LOWORD(wParam)
'Item 210' als Item-Text Unicode-Word-Text mit 00-Ende
verwendete User-Struktur Alternative mit LoadMenuIndirect()
typedef struct _MENU_STRUCT { WORD _id; // Menu-Id's, etwa ab 100 LPSTR _txt; // Menu-Popup/Item-Text MENUFUNC _fn; // auzurufende Funktion} MENU_STRUCT;
Ein DLGTEMPLATE kann auch ohne Ressourcen ( ohne *.RC, *.RES ) im C/C++-Programm "bitweise zusammengebastelt" werden und dann durch die Funktion CreateDialogIndirect()
aufgerufen werden. Bei solchen Ressourcen ( im Speicher ) ist das Alignment ( WORD- bzw. DWORD-weise ) wesentlich. Dies bedeutet z.B., dass ein LPSTR-Strings lpAnsiIn
WORDweise in p geschrieben werden muss und das Stringende durch 0x0000 gekennzeichnet ist.
int nCopyAnsiToWideChar(LPWORD p, LPSTR lpAnsiIn) { int nChar = 0; do { *p++ = (WORD) *lpAnsiIn; nChar++; } while (*lpAnsiIn++); return nChar; }
Aufbau der CDLGTEMPLATE-Struktur für CreateDialogIndirect()
[Resource header (type = 5)]struct DialogBoxHeader { DWORD lStyle; DWORD lExtendedStyle; WORD NumberOfItems; WORD x,y,cx,cy; [Name or Ordinal] MenuName; [Name or Ordinal] ClassName; WCHAR szCaption[]; WORD wPointSize; //nur bei DS_SETFONT WCHAR szFontName[];//nur bei DS_SETFONT};
Jedes Control beginnt an DWORD-Grenzestruct ControlData { DWORD lStyle;//WS_CHILD,WS_VISIBLE... DWORD lExtendedStyle; WORD x,y,cx,cy; WORD wId; [Name or Ordinal] ClassId; [Name or Ordinal] Text; WORD nExtraStuff; // soll 0x0000 sein};
Die Bezeichnung [Name or Ordinal] bedeutet, dass hier z.B. für eine für LISTBOX stehen darf: entweder 0xFFFF gefolgt von 0x0083 oder ein String mit 0x0000-Ende. Intern wird für das Auslesen verwendet if (*pw == (WORD)-1) pw += 2; else while(*pw++);
Für einen Dialog wird DLG_STRUCT dlg1[] = {... } ( beginnend mit "DIALOG" ) besetzt, bevor dann durch den CREATE_DLG_INDIRECT()-Aufruf der Dialog erzeugt wird. Als
Ctrl-Identifizierer wird der Index i von [i] verwendet. Die 0-enn ( 1. Spalte von DLG_STRUCT ) werden mit dem Ctrl-Handles dlg1[i].hwnd überschrieben. dlg1[0].hwnd ist das Handle
des Dialog-Fensters. Sind die Ctrl-Handles bekannt, so werden keine Identifizierer benötigt.
/////////////////////////////////////////////// verwendete Struktur zur Ctrl-Beschreibung://///////////////////////////////////////////
typedef struct _DLG_STRUCT { HWND hwnd; // wird später eingesetzt LPSTR pKlasse; // z.B. "BUTTON" LPSTR pText; // wird in das Ctrl geschrieben WORD x,y,cx,cy; // Position} DLG_STRUCT;
HMODULE hExe = LoadLibrary("notepad.exe"); err_if(!hExe,"LoadLibrary"); // Locate the dialog box resource in the .EXE file. HRSRC //RT_ACCELERATOR,RT_BITMAP,RT_DIALOG,RT_MENU,RT_STRINGhRes = FindResource(hExe, "#14", RT_DIALOG); err_if(!hRes,"FindResource");
HRSRC // Load the dialog box into global memory hResLoad = (HRSRC)LoadResource(hExe, hRes); err_if(!hResLoad, "LoadResource"); LPVOID // Lock the dialog box into global memory. lpResLock = LockResource(hResLoad); err_if(!lpResLock, "LockResource"); // Open the file to which // you want to add the dialog box resource. HANDLE //buf = "ziel.exe"hUpdateRes = BeginUpdateResource(buf, FALSE); err_if(!hUpdateRes, "BeginUpdateResource");
BOOL // Add the dialog box resource to the update list. ok = UpdateResource(hUpdateRes, // update resource handle RT_DIALOG, // change dialog box resource
"#14", // dialog box name MAKELANGID(LANG_NEUTRAL,SUBLANG_NEUTRAL),// neutral language lpResLock, // ptr to resource info SizeofResource(hExe, hRes));// size of resource info. err_if(!ok, "UpdateResource");// Write changes to FOOT.EXE and then close it. ok = EndUpdateResource(hUpdateRes, FALSE); err_if(!ok, "EndUpdateResource"); ok = FreeLibrary(hExe); err_if(!ok, "FreeLibrary"); return ;}
| Dialoge | Eingebaute klassen zur Ereignisbehandlung | Modale Dialoge | MessageBox() | Beispiele: MessageBox || ./img/messagebox0.gif || ./img/messagebox1.gif || ./img/messagebox4.gif || ./img/messagebox3.gif || ./img/messagebox2.gif || ./img/messagebox5.gif | DialogBox() | Beispiel: DialogBox als Hauptprogramm | About-Dialog | *.RC-File-Ausschnitt | Aufruf des About-Dialogs: | Modless Dialoge | für Modeless: Haupnachrichten-Schleife | für Modeless: in der CALLBACK | für Modeless: Aufruf | für Modeless: im Fenster hinterlegen | CreateDialog() - Aufruf | für Modeless: | *.RC enthält | *.CPP enthält | Interne Dialog - CALLBACK - Funktion | Standard - Dialoge | Controls | Static Text Control | Button Control | Edit Control | Beispiel zu Edit | List Box Control | Combo Box Control | Beispiel: Stringtable | Scroll Bar Control | Arrow - Keys und Notification Nachrichten || ./img/scroll.gif | Keyboard - Interface für Scroll - Bars | Custom Controls | Hex-Rechner1 mit *.rc || ./img/rechner.gif | Hex-Rechner1 ohne *.rc | hex_rechner2 | Eingebaute Klassen (Methode 1) | Eingebaute Klassen (Methode 2) | Sub-Classing | Dialog-Erzeugung | Hauptnachrichten-Schleife für Modeless | Textausgabe in Control | Taschenrechner mit Texteingabe
↑ Dialoge
↑ Eingebaute klassen zur Ereignisbehandlung
Der Entwickler kann eigene Klassen anlegen (RegisterClass) und dort eine CALLBACK-Funktion für die Ereignissteuerung hinterlegen. Es existieren auch
bereits verfügbare Windows-Klassen, die der Ereignissteuerung dienen und die bereits eine CALLBACK-Funktion enthalten. Die ersten Windows-
Versionen enthielten in User(32).dll und Comctl(32).dll die Klassen:
0x0080 "Button", 0x0081 "Edit", 0x0082 "Static", 0x0083 "ListBox", 0x0084 "ScrollBar", 0x0085 "ComboBox" und die Dialog Box Klasse "#32770".
Wie können Informationen über existierende Klassen (hier z.B. Dialog Box Klasse #32770) beschafft werden?
WNDCLASSEX tem = {0}; tem.cbSize = sizeof(WNDCLASSEX); BOOL ok = GetClassInfoEx(GetModuleHandle(0),TEXT("#32770"), &tem);
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 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 ( exclamation-point )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 The first button is the default button. MB_DEFBUTTON2 The second button is the default button. MB_DEFBUTTON3 The third button is the default button. MB_DEFBUTTON4 The 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
↑ Beispiele: MessageBoxMessageBox() als einfacher ( Benachrichtigungs-) Dialog
MessageBox( 0,"Client-Bereich",
0, MB_OK );
MessageBox( hwnd, "Client-Bereich",
"Titel", MB_OK );
MessageBox( hwnd,"MB_ICONSTOP",
"Titel",MB_OK|MB_ICONSTOP);
MessageBox(hwnd,"MB_ICONINFORMATION",
"Titel",MB_OK|MB_ICONINFORMATION);
MessageBox(hwnd,"MB_ICONQUESTION",
"Titel",MB_OK|MB_ICONQUESTION);
int mb_val = MessageBox(hwnd,"Rückgabewert", Titel",
MB_OKCANCEL|MB_DEFBUTTON2);mb_val wirdt IDOK oder IDCANCEL
↑ DialogBox()
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äß
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);
hInstance kann durch GetModuleHandle( NULL) oder unter WM_CREATE durch static HINSTANCE hInstance = ( LPCREATESTRUCT ) lParam-> hInstance ermittelt werden.
↑ Beispiel: DialogBox als Hauptprogramm
Existiert eine IDD_DIALOG-Dialog-Ressource und die dlg-CALLBACK-Funktion dlgProc), so kann das Hauptprogramm etwa wie folgt aussehen:
● 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.
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:
Die folgende Funktion Print_Lines() holt aus einer Multi - Line - Edit - Box alle Zeilen und gibt diese durch PrintInWindow() aus. Print_Lines() wird in
unterschiedlicher Schreibweise ( mit/ohne den Edit_GetLineCount-, Edit_GetLine - Macros aus WINDOWS.H ) angegeben.
void Print_Lines( HWND hEdit, WHND hDisplay ) { int line; int lineLast = (int) SendMessage( hEdit, EM_GETLINECOUNT, 0, 0L ); for ( line = 0; line < lineLast; line ++ ) { int cch; char ach[256]; *( (LPINT) ach ) = sizeof( ach ); cch = (int) SendMessage( hEdit, EM_GETLINE, line, (LONG)(LPSTR) ach );PrintInWindow( ach, hDisplay); }}
Mit den Funktionen SetScrollInfo(), SetScrollPos(), SetScrollRange(), GetScrollInfo(), GetScrollPos() und GetScrollRange() können Scroll - Bars
eingerichtet werden. Scroll - Bars werden mit der Maus bedient. Das System unterstützt die Maus - Ereignisse. Wenn z.B. bei einer vertikalen Scroll Bar
ein Scroll - Ereignies eintritt, so wird die WM_VSCROLL - Nachricht an das Fenster gesendet. Die WM_VSCROLL - Nachricht enthält in wParam
und lParam die folgenden Anteile.
WM_VSCROLL - Nachricht
● nScrollCode = ( int ) LOWORD( wParam ); // scroll bar value
● nPos = ( short int ) HIWORD( wParam ); // scroll box position
● hwndScrollBar = ( HWND ) lParam; // handle of scroll bar
Der nScrollCode - Parameter kann die Werte
● SB_BOTTOM ( Scrolls to the lower right),
● SB_ENDSCROLL ( Ends scroll ),
● SB_LINEDOWN ( Scrolls one line down ),
● SB_LINEUP ( Scrolls one line up ),
● SB_PAGEDOWN ( Scrolls one page down ),
● SB_PAGEUP ( Scrolls one page up ),
● SB_THUMBPOSITION ( der Benutzer hat die scroll box ( Thumb ) gezogen ( dragged ) und losgelassen. Dann gibt nPos (
16 bits ) die Los-Lass-Position an ),
● SB_THUMBTRACK ( der Benutzer ist noch am Ziehen ( dragging ). nPos ist die aktuelle Thumb - Position ),
● SB_TOP ( Scrolls to the upper left )
nPos wird nur bei SB_THUMBPOSITION oder SB_THUMBTRACK benutzt. hwndScrollBar ist NULL, wenn die Nachricht nicht von einem Scroll - Bar
kommt.
Scroll Bars Nachrichten
● Die CALLBACK - Funktion sollte 0 zurück geben, wenn die CALLBACK - Funktion die abschließende Bearbeitung
übernommen hat.
↑ Keyboard - Interface für Scroll - Bars
Ein Keyboard - Interface für Scroll - Bars ermöglicht die zusätzliche Bedienung mit der Tastatur. Wenn ein Sroll Bar den Keyboard - Focus hat, so
werden bei einer Pfeil - Taste ( Arrow - Key ) an das Eltern - Fenster die WM_HSCROLL - bzw. WM_VSCROLL - Nachricht gesendet.
Taste sendetvirtuellerKey-Code
und soll dieMaus-Notification-Nachrichtauslösen ...
DOWN VK_DOWN SB_LINEDOWN oder SB_LINERIGHT
UP VK_UP SB_LINEUP oder SB_LINELEFT
END VK_END SB_BOTTOM
HOME VK_HOME SB_TOP
PGDN VK_NEXT SB_PAGEDOWN oder SB_PAGERIGHT
PGUP VK_PRIOR SB_PAGEUP oder SB_PAGELEFT
LEFT VK_LEFT SB_LINEUP oder SB_LINELEFT
RIGHT VK_RIGHT SB_LINEDOWN oder SB_LINERIGHT
Ein Inteface soll eine z.B. SB_TOP bzw. SB_BOTTOM Notification - Nachricht senden, wenn VK_HOME bzw. VK_END eintrifft. Diese VK_ -
Nachrichten werden unter iMsg == WM_KEYDOWN abgehört und die zugeordnete Notification - Nachricht gesendet.
Ein Keyboard - Interface für Scroll - Bars kann dann z.B. gemäß
LRESULT CALLBACK WndProc( HWND hWnd, UINT iMsg,WPARAM wParam,LPARAM lParam) { switch ( iMsg ) {... case WM_KEYDOWN : { UINT w = -1; switch ( LOWORD(wParam) ) { case VK_HOME: w = SB_TOP; break; case VK_END: w = SB_BOTTOM; break; case VK_UP: w = SB_LINEUP; break; case VK_DOWN: w = SB_LINEDOWN; break; case VK_LEFT: case VK_PRIOR: w = SB_PAGEUP; break; case VK_RIGHT: case VK_NEXT: w = SB_PAGEDOWN; break; ... } if ( w != -1 ) SendMessage( hWnd, WM_VSCROLL, MAKELONG(w,0), 0L ); } break;... } return DefWindowProc( hWnd, iMsg, wParam, lParam ) ;}
aufgebaut werden. Hier wurden nur UINT iMsg und WPARAM wParam verwendet. In LPARAM lParam sind weitere, spezielle Tasten - Scan - Anteile
enthalten.
↑ Custom Controls
Eine Applikation kann benutzerdefinierte Controls erstellen, die über die verfügbaren Controls hinaus gehen. Dies kann aus verschiedene Arten erfolgen:
● Benutzung von Buttons, Listbox -, Combobox - Nachrichten zum benutzerdefinierten Zeichnen ( owner-drawn ),
● Subclassing einer existierenden Control - Klasse,
● Vollständige Neugestaltung, Registrierung einer eigenen Window - Klasse.
↑ Hex-Rechner1 mit *.rcAls Beispiel soll ein Hex-Rechner betrachtet werden. Die Buttons, Combo-Control, Edit-Control werden in einem *.rc-File abgelegt. Die Konstanten
(IDC_BUTTON0, IDC_BUTTON1, IDC_BUTTON2, IDC_BUTTON3, IDC_BUTTON4, IDC_BUTTON5, IDC_COMBO1, IDC_EDIT1 und
IDD_DIALOG_HEXCALC) entsprechen WORD-Zahlen ( z.B. ab 5000), die im *.rc-File und im *.CPP-Filt gebraucht werden. Diese Konstanten werden
meistens im *.h-File definiert (z.B. #define IDC_BUTTON0 5000 ).
können Dialogähnliche Controls in ein Fenster auch ohne *.rc-Resourcen gesetzt werden. Allerdings fehlt dann die Dialog-Klasse, die z.B. eine Bedienung der Controls mit der Tab-Taste ermöglicht. Die Funktionen my_button(), my_combo(), my_edit() vereinfachen die Tipp-Arbeit und die zurück gelieferten HWND hCombo; HWND hEdit; werden direkt verwendet, anstelle von HWND hCombo = GetDlgItem(hwnd,IDC_COMBO); HWND hEdit = GetDlgItem(hwnd,IDC_EDIT);
void my_button(HWND hwnd, int x,int y, int cx,int cy, char *txt, WORD idRes){
// Bei idRes = 0 wird für idRes der Txt-ASCII-Wert verwendet: // Beisp.: txt = "A" erzeugt idRes = 65 if(idRes <= 0) idRes = (WORD) *txt; CreateWindowEx(0,"BUTTON",txt, WS_CHILD|WS_VISIBLE|BS_PUSHBUTTON|WS_TABSTOP, x,y,cx,cy,hwnd,(HMENU)idRes,GetModuleHandle(0),0);}/////////////////////////////////////////////////HWND my_combo( HWND hwnd, int x,int y, int cx,int cy, char *txt, WORD idRes){ HWND hCombo = CreateWindowEx(WS_EX_CLIENTEDGE,"COMBOBOX",txt, WS_CHILD|WS_VISIBLE|WS_VSCROLL|CBS_AUTOHSCROLL|CBS_DROPDOWN, x,y,cx,cy,hwnd,(HMENU)idRes,GetModuleHandle(0),0); //RECT rc; // existiert Combo-Liste kann getestet werden mit: //SendMessage(hCombo,CB_GETDROPPEDCONTROLRECT,0,(LPARAM)&rc);return hCombo;}/////////////////////////////////////////////////HWND my_edit(HWND hwnd, int x,int y, int cx,int cy, char *txt, WORD idRes){ HWND hEdit = CreateWindowEx(WS_EX_CLIENTEDGE,"EDIT",txt, WS_CHILD|WS_VISIBLE|WS_VSCROLL|SS_LEFT |ES_MULTILINE|ES_AUTOVSCROLL|ES_WANTRETURN, x,y,cx,cy,hwnd,(HMENU)(void*)idRes,GetModuleHandle(0),0);return hEdit;}
Hier ein *.cpp-Testprogramm (braucht keinen *.rc):
// HEX-Rechner als Haupt-Fenster: int X = 100, Y = 100, DX = 204, DY = 380; HWND hwnd = CreateWindowEx(WS_EX_LEFT,wc.lpszClassName,"HEX-Rechner", WS_POPUP|WS_VISIBLE|WS_CAPTION|WS_SYSMENU|DS_MODALFRAME, X,Y,DX,DY,0,0,hInst,0);
char * pInfo = "MC löscht M Speicher\r\nAC löscht Combo-Anzeige\r\n" "EC löscht diese Anzeige\r\nMR zeigt M an\r\n" "M+ addiert zu M \r\nM- subtr. von M\r\n";
WORD IDC_EDIT = 2000; hEdit = my_edit(hwnd,x0,y+4,188,140,pInfo,IDC_EDIT); Edit_LimitText(hEdit, MAX_EDIT_CHAR);
↑ hex_rechner2Zu den Dialogen gehört die Dialog-Klasse "#32770", die bereit vom System mit RegisterClassEx() angelegt wurde. Die Dialog-Klasse "#32770" enthält die
"eingebaute" CALLBACK-Funktion. Diese setzt z.B. mit der Tab-Taste den Focus für Tasteneingaben auf das nächste Control, falls bei diesem Control im
Window-Style das WS_TABSTOP-Bit gesetzt ist.
↑ Eingebaute Klassen (Methode 1)
Es gibt Eingebaute Klassen (incl. CALLBACK-Funktion). Wie kann diese Klasse erhalten werden? Mit
wird wc "gefüllt" und der Funktionszeiger wc.lpfnWndProc kann erhalten werden. Nun können in wc die zu ändernden Komponenten wc.xxx neu gesetzt werden (z.B. wc.lpszClassName = "my_dlg_class";). Mit
RegisterClassEx(&wc);
wird eine modifizierte "my_dlg_class" mit eigener CALLBACK-Funktionen angelegt werden.
Innerhalb jeder NewWndProc-CALLBACK-Funktionen kann dann am Ende anstelle von
return FALSE; nun return CallWindowProc(OldWndProc,hwnd,uMsg,wParam,lParam);
aufgerufen werden. Dadurch werden die unbearbeiteten Nachrichten an die OldWndProc-Funktion weiter gereicht.
↑ Sub-Classing
Öfters ist es erforderlich, an die eingebaute CALLBACK-Funktion "heran zu kommen" und deren Nachrichten vorher durch eine vorgeschaltete eigene
CALLBACK-Funktion zu schicken. Die eigene CALLBACK-Funktion kann dann Änderungen und Ergänzungen vor der eingebauten CALLBACK-
Funktion vornehmen. Ist das Handle eines Controls hCtrl bekannt, Die folgende Funktion wird einmal externen Aufruf (ausserhalb der CALLBACK)
aufgerufen, richtet dabei ein sub-Classing ein, hinterlegt sich als Zeiger selbst in den Window-daten (d.h. hinterlegt sich selbst als CALLBACK-Funktion)
und ist bei jedem folgenden AUfruf selbst die gewünschte CALLBACK-Funktion, die die Nachrichten bearbeitet. Am Ende wird die alte CALLBACK-
Funktion aufgerufen.
/////////////////////////////////////////////////// initialisierender Sub-Class-Aufruf gemäss:// dlg_proc_bekommt_alle_keys_von(hwnd_combo_hex,0,0,0);// Dann schickt// if(uMsg==WM_GETDLGCODE){return DLGC_WANTALLKEYS;}// alle Tasten an die Parent-CALLBACK-Funktion // und dort wird bei DM_GETDEFID der (hier ENTER key)// abgefangen.//// Achtung! Hinweis:// Das folgende Sub-Classing-Muster ist zwar // "Kompliziert" aber in sich "geschlossen". // WNDPROC entspricht den "alten" LONG FAR PASCAL// WNDPROC führt (leider) bei Win98/NT zu // "schweren Laufzeitabstürzen".
// Deshalb wurde LONG FAR PASCAL und // if (cb<4)SetClassLong(hCtrl,GCL_CBWNDEXTRA,4);// verwendet. /////////////////////////////////////////////////LONG FAR PASCAL dlg_proc_bekommt_alle_keys_von(HWND hCtrl,UINT uMsg,WPARAM wParam,LONG lParam){ err_if(!IsWindow(hCtrl),"!IsWindow(hCtrl)"); FARPROC oldCtrlProc=(FARPROC)GetWindowLong(hCtrl,GWL_USERDATA); if(!oldCtrlProc) { //nur einmal hinterlegen int cb = GetClassLong(hCtrl,GCL_CBWNDEXTRA); if (cb<4)SetClassLong(hCtrl,GCL_CBWNDEXTRA,4); oldCtrlProc =(FARPROC) SetWindowLong(hCtrl,GWL_WNDPROC, (DWORD)dlg_proc_bekommt_alle_keys_von); err_if(!oldCtrlProc,"!oldCtrlProc"); SetWindowLong(hCtrl,GWL_USERDATA,(LONG)(WNDPROC)oldCtrlProc); }
Modeles-Dialoge werden mit CreateDialog...() erzeugt. Hierzu wird die Dialog-CALLBACK-Funktion myDlgProc gebraucht, die bei jedem Ereignis
aufgerufen wird.
a) Wenn das Dialog-Temlate IDD_... im *.rc existiert: hDlg = CreateDialog(hInst, MAKEINTRESOURCE(IDD_...), hParent, (DLGPROC)myDlgProc );
b) Wenn hDlg = CreateDialogParam(hInst, MAKEINTRESOURCE(IDD_...), hParent,(DLGPROC)dlgProc,(LPARAM)p); p erscheint einmalig unter WM_INITDIALOG in der CALLBACK-Funktion
c) Wenn das Dialog-Temlate im RAM (hier buf) existiert: hDlg = CreateDialogIndirect(hInst, (LPDLGTEMPLATE)buf, hParent,(DLGPROC)dlgProc);
Create... deutet darauf hin, dass die Speicherfreigabe mit DestroyWindow(hDlg) durch den User erfolgen soll.
↑ Hauptnachrichten-Schleife für Modeless
Für Modeless-Dialoge wird die Hauptnachrichten-Schleife ergänzt. Existiert ein globaler Array für Modeles-Handles HWND ghwnd[10], so kann
ghwnd[0] für die "Umschaltung" auf das jeweils aktuellen (Eingabe-) Dialog verwendet werden, indem JEDE CALLBACK-Funktion bei
WM_ACTIVATE das aktuelle handle ghwnd[0] setzt.
case WM_ACTIVATE: if ( WA_INACTIVE == LOWORD(wParam) ) { ghwnd[0] = NULL; //becoming inactive } else {ghwnd[0] = hwnd;}//becoming active break; case WM_DESTROY:{ PostQuitMessage(0); break;}
Bei einem Ereignis ruft in der Hauptnachrichten-Schleife die Funktion IsDialogMessage(ghwnd[0],&msg)) die zu dem Modeless-Dialog gehörende CALLBACK-Funktion auf.
hEdit = GetDlgItem(ghwnd,IDC_EDIT); char * pInfoText = "MC löscht M Speicher\r\nAC löscht Combo-Anzeige\r\n" "EC löscht diese Anzeige\r\nMR zeigt M an\r\n" "M+ addiert zu M \r\nM- subtr. von M\r\n"; Edit_LimitText(hEdit,2048); Edit_SetText(hEdit, pInfoText );
Dynamisches Linken ( dynamic linking ) verknüpft die Bibliotheken zur Laufzeit. DLLs werden nicht in die Applikation kopiert, sondern
haben einen eigenen Adressraum und können von mehreren Anwendungen genutzt werden. Wenn eine DLL genutzt werden soll, so läd das
Operating-System die DLL ( aufgrund des File-Namens ) in en Speicher. Wird eine DLL von keiner Alpplikation benötigt, so wird die DLL
vom Operating-System ( unload ) aus dem Speicher entfernt. Der Lade/Entlade-Mechanismus kann explizit durch die Applikation oder
implizit Operating-System ausgelöst werden.
↑ Unterschiede zwischen Static-Dynamic-LinkingWDifferences Between Static-Link Libraries and Windows DLLs Windows DLLs differ considerably from static-link libraries. Basic differences between the two are as follows:
● Statische Bibliotheken sind in *.LIB-Files ( object files ) enthalten
● Jede Applikation hat eine Kopie der statischen Bibliothek.
● Die statische Bibliotek nutzt den Adressraum der Applikation.
● Dynamische Bibliotheken sind in ladbaren, auführbaren Files ( *.exe explizit ladbar mit LoadLibrary, *.dll
implizit ladbar ) untergebracht.
● Dynamische Bibliotheken können Maschinen-Code, Daten, Ressourcen ( z.B. Bitmaps, Icons, Cursors, usw.
) enthalten.
● Beispiele für DLLs sind: A DLL is a Windows dynamic link library residing in a .DLL file. System DLLs
may have .EXE extensions, for example, USER.EXE, GDI.EXE, KRNL286.EXE, KRNL386.EXE, .DRV (
device driver, wie z.B. MOUSE.DRV, KEYBOARD.DRV ) Nur .DLL-Extension können automatisch durch
das Operating-System geladen werden.
● Applikationen enthalten beim dynamischem Linken nur die Namen der benötigten DLLs und implizit
hinzugefügte ( oder explizit angegebene ) Ladeanweisungen.
● Eine DLL kann von vielen Applikationen benutzt werden.
● Eine DLL hat oft seinen eigenen Daten-Adress-Raum ( shared ), der in den Adress-raum der Applikation
gemappt wird.
↑ shared data segment
What makes a data segment shared?
These three pragma statements override the default data segment behavior and creates a shared data segment. See MyClass.cpp in the DLL.
// Aufbau etwa wie folgt: // Hier stehen globale und // static Variablen( "nicht shared" )...... // Anfang vom shared data segment#pragma data_seg("SHARED") // Definition von einfachen Variablen, // wie z.B. int, char[] arrays, zeiger // Keine Klassen verwenden, die einen // tiefen Copy Constructors brauchen
// Endd des "shared data segment" // Zurück zum normalen Daten-Segment-Bereich#pragma data_seg()
// Das folgende Linker-Pragma veranlasst den Linker // die notwendigen initialisierungen für das // "shared data segment" zu erzeugen#pragma comment(linker, "/section:SHARED,RWS")
// hole Adresse der ANSI-Version von "MessageBoxA": MSGBOX MsgBox = (MSGBOX) GetProcAddress(hDLL,"MessageBoxA"); err_if(!pMsgBox,"!pMsgBox");
//////////////////////////////////////////////////////////// // Achtung! Windows.h hat typedef int (CALLBACK* FARPROC)(); // FARPROC liefert error C2197: // 'int (__stdcall *)(void )' : too many actual parameters //////////////////////////////////////////////////////////// MsgBox(NULL,inhalt,titel,MB_OK);// MessageBox() aufrufen FreeLibrary(hDLL); // USER32.DLL freigeben}
| MFC | Grober Zusammenhang mit ATL | Entwicklungskriterien | MFC und Nachrichten | MFC-Klassen-Typen | MFC-Schreibweise | Hinweise zur Programmierung | Beispiel für CWND_Member-Funktion | CArray-Beispiel | Handles und MFC | MFC-Klassenhirachie (CE) || ./img/mfc_hierachy_categories.gif || ./img/mfc_1.gif || ./img/mfc_2.gif | MFC-Klassenhirachie | Hinweise zum Übersezungsvorgang
↑ MFCSoftware-Syteme entwickeln sich und damit können sich Änderungen des Programmiermodell, der Entwicklungsumgebung, der Klassen-Bibliotheken, der API-
Funktionssammlung ergeben. Achtung! Trotz vieler on-line-Hilfen, Class Library Reference, MFC Technical Notes, MFC-specific articles, Visual C++ Programmer’s
Guide, MFC Samples and Tutorials, , Quelltext-Generatoren, Werzeugen, usw. darf die Einarbeitungszeit nicht unterschätzt werden ).
Es gibt Versionsfortschreibungen, wie z.B.:
MFC Visual C++MFC, Version 1.0 Microsoft C/C++, Version 7.0MFC, Version 2.0 Visual C++, Version 1.0MFC, Version 2.5 Visual C++, Version 1.5MFC, Version 3.0 Visual C++, Version 2.0MFC, Version 3.1 Visual C++, Version 2.1MFC, Version 3.2 Visual C++, Version 2.2MFC, Version 4.0 Visual C++, Version 4.0MFC, Version 4.1 Visual C++, Version 4.1MFC, Version 4.2 Visual C++, Version 4.2MFC, Version 4.21 (noch mit mfc42.dll) Visual C++, Version 5.0MFC, Version 6.0 (noch mit mfc42.dll) Visual C++, Version 6.0MFC, Version 7.0 (mfc70.dll) Visual C++ .NET 2002MFC, Version 7.1 (mfc71.dll) Visual C++ .NET 2003
Literaturhinweise H. M. Deitel et al.: Visual C++ .NET, How to program,
Pearson Education (Prentice Hall) 2004 D. J. Kruglinski: Inside Visual C++, Version 6.0, MS Press Jeff Prosise: Windows Programmierung mit MFC, MS Press Jeffrey Richter: Microsoft Windows, Programmierung für Experten, MS Press Jeffrey Richter: Microsoft .NET Framework Programmierung, MS Press J. Templeman/ A. Olsen: Visual C++ .NET, Schritt für Schritt, MS Press I. Griffiths et al.: Mastering Visual Studio .NET, O'Reilly Microsoft: Online-Dokumentation zu Visual C++ .NET
Versionsfortschreibung: Mit der Verwendung von Visual Studio .NET müssen vorher erstellte DLL- oder LIB-Dateien neu erstellt werden. MFC-Dialoganwendungen
entsprechen bei .NET Windows-Forms-Anwendungen. Bis ATL 3.0 (Visual C++ 6.0) wurden Zeichenfolgenkonvertierungen immer mittels der Makros (atlconv.h,
ANSI-Codeseite des Systems, CP_ACP) durchgeführt. Ab ATL 7.0 (Visual C++ .NET) werden Zeichenfolgenkonvertierungen (ohne
_CONVERSION_DONT_USE_THREAD_LOCALE) mit der standardmäßigen ANSI-Codeseite des aktuellen Threads durchgeführt.
// Versionsprüfung:void versionstest(void) {
DWORD dwVersion = GetVersion(); DWORD dwWindowsMajorVersion = (DWORD)(LOBYTE(LOWORD(dwVersion))); err_if(dwWindowsMajorVersion<5,"leider zu alte Windows-Version ...");
DWORD dwWindowsMinorVersion = (DWORD)(HIBYTE(LOWORD(dwVersion))); DWORD dwBuild = 0; if (dwVersion < 0x80000000) // Windows NT dwBuild = (DWORD)(HIWORD(dwVersion)); else if (dwWindowsMajorVersion < 4) // Win32s dwBuild = (DWORD)(HIWORD(dwVersion) & ~0x8000); else dwBuild = 0; // Windows Me/98/95}
////////////////////////////////////////////////// DllVersionsprüfung:if(GetDllVersion(TEXT("comctl32.dll")) >= PACKVERSION(4,71)) { //Proceed.} else { // Use an alternate approach for older DLL versions.}
MFC ist eine Abkürzung für "Microsoft Foundation Class Library". MFC kapselt mit C++ einen Teil der umfangreiche Windows API-Schnittstelle, die in C
programmiert wurde. Die MFC-Verwendung bietet Portabilität zwischen unterschiedlichen Betriebssystemen und zwischen verschiedenen Prozessoren. Die MFC ist
zwar in C++ geschrieben, geht aber über den hinaus (DLL's, CALLBACK-Funktionen, sprachspezifische STRINGTABLE-Ressourcen, usw.) und ist deshalb nicht mit
dem C++-ANSI-Standard kompatibel.
↑ Grober Zusammenhang mit ATL MFC "Microsoft Foundation Class" oder "MFC-Quelltext-Bibliothek"; Framework-Klassen von Windows-API-Funktionen zur Erstellung von Anwendungen;
MFC Classes, Hierarchy Chart, Class Library Overview, MFC Macros and Globals, MFC Technical Notes, usw.
ATL "Active Template Library"; C++-Klassen, die die Programmierung von COM-Objekten vereinfachen (ATL 3.0 ab Visual C++ 6.0).
ATL Server C++-Klassen, zum Erstellen von Webanwendungen, XML-Webdienste und andere Serveranwendungen
Unterstüzung Beispielcodes, Microsoft Macro Assembler (MASM), Plattform SDK-Tools wie z.B.:Debugger-Tools (DBMon=Debug Monitor, MapSym=MAPSYM, NTSD=Symbolic Debuggers, WinDbg=WinDbg Debugger), Spy-Tools, File-Mangement-Tools (Where, WinDiff),Performance-Tools ( Bind = Minimizes application load time, ExCtrLst = Extensible counter list utility, PerfMtr = Performance meter, Performance = Monitor Performance monitor, PStat = Performance statistics, VADUMP = Virtual address dump),Testing-Tools (PfMon = Monitors process faults, SC = Tests a service program) ,Cryptography-Tools (Cert2SPC = Creates a test software publisher certificate, CertMgr = Manages certificates, certificate trust lists, and certificate revocation lists. MakeCat = Creates a catalog file, MakeCert = Creates an X.509 certificate, MakeCTL = Creates a certificate trust list, SetReg = Sets registry values to control the certificate verification process, SignTool = Digitally signs a file, verifies signatures in files, or time stamps files),Rebase, usw.
↑ Entwicklungskriterien
Die MFC-Klassen-Bibliothek wurde unter den folgenden Kriterien und Richtlinien entwickelt:
● Ausführungsgeschwindigkeit höchstens 5% geringer als bei C-Language Win-API
● Vereinfachung der Windows-Programmierung, geringe Einarbeitungszeit gegenüber der API-Programmierung
● Entwickler können Win-API-Functionen ( an bel. Stelle ) direkter aufrufen ( global scoping operator ::, wie z.B. ::GetSystemMetrics )
● Geringer Nativ-Code-Overhead
● Einfache Konvertierung von existierenden C-Programmen nach C++/MFC
● Quelltext-Generatoren mit Kommentaren für Constructors, Attributes, Operations, Overridables, Implementation. Die //{{...//}}
Klammerung dient als Positionsangabe zum Einfügen/Entfernen von Mapping-Makros ( z.B. ON_WM_SETFOCUS() ) durch den
Klassen-Assistenten
//{{AFX_MSG_MAP(CMainFrame)
ON_WM_CREATE() // kein ; ON_WM_SIZE() // kein ; ON_WM_SETFOCUS() // kein ;
//}}AFX_MSG_MAP
↑ MFC und Nachrichten
Menü- und Button-Ereignisse ergeben WM_COMMAND-Nachrichten. Die MFC versteckt diese "case WM_COMMAND: switch(LOWORD(wParam))..."-
Konstruktioen in einer MESSAGE_MAP-Tabelle. MFC verwendet Tabellen, um die Funktionszeiger von auszuführenden Funktionen zu hinterlegen. Ein
Tabelleneintrag enthält die Nachricht ( z.B. WM_...) und die auszuführenden Funktionen. Die Macroaufrufe einer messageMap-Tabelle sehen etwa wie folgt aus:
// Beispiel:BEGIN_MESSAGE_MAP(CMdiApp, CWinApp)// kein ; //{{AFX_MSG_MAP(CMdiApp) ON_WM_CREATE() // kein ; ON_WM_SIZE() // kein ; ON_WM_SETFOCUS() // kein ; ON_COMMAND(IDM_ABOUT, OnAbout) // kein ; ON_COMMAND_EX_RANGE(IDM_1, IDM_16, On...) // kein ; //}}AFX_MSG_MAPEND_MESSAGE_MAP()// kein ;
Das BEGIN_MESSAGE_MAP-Macro erstellt eine Funktion GetMessageMap(), die die Adresse dieser Tabelle zurückgibt, bevor eine messageMap aus afxwin.h
definiert wird. Die BEGIN_MESSAGE_MAP und END_MESSAGE_MAP Macros haben etwa den folgenden Aufbau:
struct AFX_MSGMAP_ENTRY //Tabellenstruktur{ UINT nMessage; // windows message UINT nCode; // control code or WM_NOTIFY code UINT nID; // control ID (or 0 for windows messages) UINT nLastID; // used for entries specifying a range of control id's UINT nSig; // signature type (action) or pointer to message # AFX_PMSG pfn; // routine to call (or special value)};
enum AfxSig { // Typenbeschreibung (signature type action) AfxSig_end = 0, // [marks end of message map] AfxSig_bb, // BOOL (BOOL) ... AfxSig_is, // int (LPTSTR) ... AfxSig_vv, // void (void)...};
#define CN_COMMAND 0 // void ()#define ON_COMMAND(id, memberFxn) \ { WM_COMMAND, CN_COMMAND, (WORD)id, (WORD)id, AfxSig_vv,(AFX_PMSG)&memberFxn }, // ON_COMMAND ( id, OnFoo) is the same as // ON_CONTROL (0, id, OnFoo) or // ON_BN_CLICKED(0, id, OnFoo)#define ON_WM_CREATE() \ { WM_CREATE, 0, 0, 0, AfxSig_is, \ (AFX_PMSG)(AFX_PMSGW)(int (AFX_MSG_CALL CWnd::*)(LPCREATESTRUCT))&OnCreate },
Der afxmsg_.h-File beschreibt 9 Format-Möglichkeiten, wie diese Tabelleneinträge gestaltet werden können:
// Entries in a message map (a 'AFX_MSGMAP_ENTRY') table can be of 9 formats//// 1) control notification message (i.e. in response to WM_COMMAND)// WM_COMMAND, nNotifyCode, nControlID, nControlID, signature type, parameterless member function// (eg: WM_COMMAND, LBN_SELCHANGE, IDC_LISTBOX, AfxSig_vv, ... )// 2) control notification message range (i.e. in response to WM_COMMAND)// WM_COMMAND, nNotifyCode, nControlIDFirst, nControlIDLast, signature type, parameterless member function// (eg: WM_COMMAND, LBN_SELCHANGE, IDC_LISTBOX1, IDC_LISTBOX5, AfxSig_vw, ... )// 3) WM_NOTIFY notification// WM_NOTIFY, nNotifyCode, nControlID, nControlID, signature type, ...)// 3) Update Command UI// -1, 0, nControlID, 0, signature Unknown, parameterless member function// 4) Update Command UI Range// -1, 0, nControlIDFirst, nControlIDLast, signature Unknown, parameterless member function// 5) menu/accelerator notification message (i.e. special case of first format)// WM_COMMAND, 0, nID, 0, signature type, parameterless member function// (eg: WM_COMMAND, 0, IDM_FILESAVE, 0, AfxSig_vv, ... )// 6) menu/accelerator notification message range// WM_COMMAND, 0, nIDFirst, nIDLast, signature type, parameterless member function// (eg: WM_COMMAND, 0, IDM_FILE_MRU1, IDM_FILE_MRU4, AfxSig_vw, ... )// 7) constant windows message// nMessage, 0, 0, 0, signature type, member function// (eg: WM_PAINT, 0, ...)// 8) variable windows message (using RegisterWindowMessage)// 0xC000, 0, 0, 0, &nMessage, special member function//// The end of the message map is marked with a special value// 0, 0, AfxSig_end, 0
Weil zum Verteilen der Nachrichten die Klasse CWnd verwendet wird ist bei der MFC ist eine CALLBACK-Funktion meist nicht selbst zu schreiben. Die Funktion
nWndMsg() ruft z.B. bei WM_COMMAND die Funktion OnCommand(wParam, lParam) auf:
for (pMessageMap != NULL; pMessageMap = pMessageMap->pBaseMap) { // Note: catch not so common but fatal mistake!! // BEGIN_MESSAGE_MAP(CMyWnd, CMyWnd) // registered windows message lpEntry = pMessageMap->lpEntries; while ((lpEntry = AfxFindMessageEntry(lpEntry,0xC000,0,0)) != NULL){ UINT* pnID = (UINT*)(lpEntry->nSig); ... lpEntry++; } return FALSE;
LDispatch: union MessageMapFunctions mmf; mmf.pfn = lpEntry->pfn;
switch (nSig){ // lResult = (this->*mmf.pfn_bD)(CDC::FromHandle((HDC)wParam)); case AfxSig_vw: (this->*mmf.pfn_vw)(wParam);break; case AfxSig_bb: ... case AfxSig_bD: ... case AfxSig_bWww: ... case AfxSig_bWCDS: .case AfxSig_bHELPINFO: ... case AfxSig_hDWw: case AfxSig_hDw: case AfxSig_iwWw: ... case AfxSig_iww: case AfxSig_iWww: case AfxSig_is: ... case AfxSig_lwl: case AfxSig_lwwM: case AfxSig_vv:... case AfxSig_vww: case AfxSig_vvii: case AfxSig_vwww: case AfxSig_vwii: case AfxSig_vwl: case AfxSig_vbWW: case AfxSig_vD: case AfxSig_vM: case AfxSig_vMwb: case AfxSig_vW: case AfxSig_vW2: case AfxSig_vWww: case AfxSig_vWp: case AfxSig_vWh: case AfxSig_vwW: case AfxSig_vwWb: case AfxSig_vwwW: case AfxSig_vwwx: case AfxSig_vs: case AfxSig_vws: case AfxSig_vOWNER: case AfxSig_iis: case AfxSig_wp: case AfxSig_wv: case AfxSig_vCALC: case AfxSig_vPOS: case AfxSig_vwwh: case AfxSig_vwp: case AfxSig_vwSIZING:case AfxSig_bwsp: default:break; } goto LReturnTrue;
LDispatchRegistered: // for registered windows messages ASSERT(message >= 0xC000); mmf.pfn = lpEntry->pfn; lResult = (this->*mmf.pfn_lwl)(wParam, lParam);
LReturnTrue: if (pResult != NULL)*pResult = lResult; return TRUE;}
↑ MFC-Klassen-Typen
MFC-Klassen-Bibliothek ist eine ( "dünne" ) Software-Schicht über der API-Schnittstelle ( WOSA: Windows Open Services Architecture APIs ) und unterstützt z.B.
die ( Framework- ) Programmierung von Windows-Applikationen mit Dialog boxes, Device Contexts, Common GDI Objekte.
Die Microsoft Foundation Class Library (MFC) basiert auf einigen Hauptklassen ( CObject, CWnd, ... ). Die Klassen kapseln einen großen Teil des Application
Programming Interface (Win32-APIs). Anstelle von HINSTANCE hInst = GetModuleHandle(0) wird nun z.B. HINSTANCE hInst = AfxGetInstanceHandle()
verwendet. Anstelle von RegisterClass() wird nun AfxRegisterWndClass (UINT nClassStyle,HCURSOR hCursor,HBRUSH hbrBackground, HICON hIcon)
verwendet. Anstelle von WM_CREATE-Einträgen in der CALLBACK-Funktion wird ( automatisch ) PreCreateWindow(CREATESTRUCT& cs) aufgerufen.
Andere Klassen kapseln Anwendungskonzepte wie Dokumente, Ansichten und die Anwendung, sowie OLE-Funktionen und ODBC- und DAO-Datenzugriffe. Das
Win32-Konzept eines Fensters wird z. B. durch die MFC-Klasse CWnd eingekapselt.
● Die CWnd-Klasse kapselt die internen Win32-API-Daten,
-Funktionen für ein Windows-Fenster.
● Die CDialog-Klasse kapselt die Win32-Dialogfelder.
● Die Member-Funktionen der Klasse haben meistens ähnliche
● Wegen der Ausführungsgeschwindigkeit werden zahlreiche Macros benutzt
( z.B. afx.h: DECLARE_DYNAMIC, IMPLEMENT_DYNAMIC, DECLARE_SERIAL, IMPLEMENT_SERIAL, usw. )
MFC hat wenige abstrakte Basis-Klassen ( CObject, CCmdTarget ). MFC benutzt 2 Klassen-Typen: "value"-Klassen ( kapseln eine Struktur, wie z.B. Strings oder
Koordinaten, CPoint vereinfacht die Benutzung der vorhandenen API-Funktionalität ) "framework"-Klassen ( abgeleitet von CObject, z.T. "dünne" Kapselung der
Windows-Funktionalität ).
Value- gegenüber Framework-Klassen
Characteristics Value Framework
Hat einevirtual Funktion?
Nein Ja
Ist eine Basis-Klasse? Nein CObject derived
Kann direkt benutzt werden? Ja Maybe
Kann abgeleitet werden? Nein Ja
Hat einen "="-Operator? meist Nein
Hat einen Copy-Konstruktor? meist Nein
Wirkt wie ein eingebauter Type? meist Nein
Vergleich möglich? Usually Nein
Vergleichsreferenz möglich? Nein Ja (Addresse ist identisch)
↑ MFC-Schreibweise
MFC verwendet eine General Prefix Naming Conventions ( vereinfacht ungarische Notation ). Die Klassen enthalten als Member-Variable u.a. Daten vom Typ
HWND. CWnd::m_hWnd, and an accessor function, CWnd::GetSafeHwnd. Static member Variablen ( Klassen-Variablen ) haben einen "global class namespace" und
werden ohne Prefix verwendet.
Prefix
Prefix: C Type: Class or structure Example: CDocument, CPrintInfo
Prefix: m_ Type: Member variable Example: m_pDoc, m_nCustomers
Gegenüberstellung
Value-Objekte Framework-Objekte
Value-Übergabe( wenige Bytes )
void Do(CMyValue val); Referenz-Übergabe
( umfangreiche Size ) void Do( const CMyValue& val );
const Zeiger-Übergabe void Do( const CMyView* pob );
return-Werte einesValue-Objektes
CMyValue GetCurrentValue(); return-Werte eines
Framework-Objektes CMyView* GetCurrentView();
↑ Hinweise zur Programmierung
Overloading-Operatoren und Copy-Konstructoren sollten vermieden werden ( insbesondere bei Framework-Klassen ). Falls dennoch erforderlich, so sollte der Copy-
Konstructor vom Argument "const classname&" sein.
↑ Beispiel für CWND_Member-Funktion
Die internen Fensterdaten werden bei der Klasse CWnd mit der API-Funktion CreateEx() angelegt. Die Klasse CWnd entspricht eine "Wrapper"-Funktion Create bzw.
CArray myarray1; CArray myarray2; ... (insertion of data)
myarray2.RemoveAll(); myarray2.Append(myarray1);
↑ Handles und MFC*
Die meisten OLE-Daten-Typen sind als COle-Variant class "gewrapped".
Andere MFC Klassen benutzen COleVariant
( COleDateTime, COleDateTimeSpan, COleCurrency ). 1 GDI-Objekte werden meist als lokale Variablen
auf dem Stack-Frame angelegt ( z.B. CPen pen; ). 2 Controls werden meist zusammen mit dem Parent-Window
angelegt. Enthält z.B. ein CDialog ein CButton-Object,
so wird ides als CButton m_button; deklariert.
Abhängigkeiten zwischen MFC- und Windows Handles, Controls, Strukturen
WindowsType
ExampleVariable
MFC Class ExampleObject
HWND hWnd; CWnd* pWnd;
HDLG hDlg; CDialog* pDlg;
HDC hDC; CDC* pDC;
HGDIOBJ hGdiObj; CGdiObject* pGdiObj;
HPEN hPen; CPen* pPen;1
HBRUSH hBrush; CBrush* pBrush;1
HFONT hFont; CFont* pFont;1
HBITMAP hBitmap; CBitmap* pBitmap;1
HPALETTE hPalette; CPalette* pPalette;1
HRGN hRgn; CRgn* pRgn;1
HMENU hMenu; CMenu* pMenu;1
HWND hCtl; CStatic* pStatic;2
HWND hCtl; CButton* pBtn;2
HWND hCtl; CEdit* pEdit;2
HWND hCtl; CListBox* pListBox;2
HWND hCtl; CComboBox* pComboBox;2
HWND hCtl; CScrollBar* pScrollbar;2
HSZ hszStr; CString pStr;2
POINT pt; CPoint pt;
SIZE size; CSize size;
RECT rect; CRect rect;
↑ MFC-Klassenhirachie (CE)
MFC-Library für Windows CE in tabellarischer Darstellung:
Von der Klasse CObject(root class) abgeleitet (CE):
Application Architecture Classes Internet Services Classes
Array Classes List Classes
Control Bar Classes Map Classes
Control Classes Menu Classes
Control Support Classes Property Sheets
Dialog Box Classes Synchronization Classes
Exception Classes View Classes
NICHT von der KlasseCObject abgeleitet (CE):
ActiveX Type Wrappers Support Classes
Automation Types Synchronization Support
Run-Time Object Model Support Typed Template Collections
Simple Value Types Windows CE Database Classes
Structures
(allg.)
Internet Server API Run-Time Object Model Support
File Service Classes Window Class Categories
Frame Windows and Splitter Windows Windows CE Database Classes
Graphical Drawing Classes Windows Sockets Classes
Graphical Drawing Object Classes
Structures Simple Value Types
Support Classes Typed Template Collections
OLE Type Wrappers OLE Automation Types
Synchronization
↑ MFC-Klassenhirachie
Grobe MFC-Hierachy-Categories von CObject:
MFC-Grafische Darstellung der Objekt-Hierachie:
Die MFC-Klassen-Deklarationen sind in stdafx.h enthalten. stdafx.h verwendet als MFC-Kern- und -Standardkomponenten afxwin.h. In afxwin.h sind die folgenden
Klassen deklariert:
class CSize; class CPoint; class CRect;
class CGdiObject; // CDC drawing tool class CPen; // a pen / HPEN wrapper class CBrush; // a brush / HBRUSH wrapper class CFont; // a font / HFONT wrapper class CBitmap; // a bitmap / HBITMAP wrapper class CPalette; // a palette / HPALLETE wrapper class CRgn; // a region / HRGN wrapper
class CDC; // a Display Context / HDC wrapper class CClientDC; // CDC for client of window class CWindowDC; // CDC for entire window class CPaintDC; // embeddable BeginPaint struct helper
class CMenu; // a menu / HMENU wrapper
class CCmdTarget; // a target for user commands class CWnd; // a window / HWND wrapper class CDialog; // a dialog
// standard windows controls class CStatic; // Static control class CButton; // Button control class CListBox; // ListBox control class CCheckListBox; // special listbox with checks class CComboBox; // ComboBox control class CEdit; // Edit control
class CScrollBar; // ScrollBar control
// frame windows class CFrameWnd; // standard SDI frame class CMDIFrameWnd; // standard MDI frame class CMDIChildWnd; // standard MDI child class CMiniFrameWnd; // half-height caption frame wnd
// views on a document class CView; // a view on a document class CScrollView; // a scrolling view
class CWinThread; // thread base class class CWinApp; // application base class
class CDocTemplate; // template for document creation class CSingleDocTemplate;// SDI support class CMultiDocTemplate; // MDI support
class CDocument; // main document abstraction
//CObject//CException//CSimpleException class CResourceException;// Win resource failure exception class CUserException; // Message Box alert and stop operation
| C Sharp (Einführung) | Was ist .NET? | C#-Entwickler-Tools | C#-keywords | C#-keywords | Typen in C# | Boxing and Unboxing | dll-Funktionen in C# | C#-Console-Applikation | Beispiel für cs-Console-Applikation
↑ C Sharp (Einführung)
↑ Was ist .NET?
.NET enthält einen Satz von Software-Technologien (.NET Framework, Umgebung für Entwicklung, Einsatz und Ausführung von Windows-Anwendungen und Services) und kann gemeinsame Objekte (geräteübergreifend,
integrale Windows-Komponenten, Software-Integration) erstellen und verwenden. XML Web Services werden unterstützt.
↑ Was ist C Sharp?
C# (C Sharp) ist eine einfache, objekt-orientierte, typ-sichere Programmiersprache. C# hat Ähnlichkeiten zu C/C++/Java und ist für C-/C++/Java-Programmierer leicht zu lernen. C# ist ein Teil der .NET Framework Initiative und
wurde von Anders Hejlsberg, Scott Wiltamuth und Peter Golde entwickelt. Die internationale Normung der C# Language Specification (Standard ECMA-334, 2nd edition, Dez. 2002) basiert auf der Zusammenarbeit von Hewlett-
Packard, Intel, Microsoft. In ECMA-334 steht: The name C# is pronounced "C Sharp".
CLI : Common Language Infrastructure, ECMA-335, 2nd Edition, December 2002CLS : Common Language Specification BCL : Base Class Library (simple file access, custom attributes, security attributes, string manipulation, formatting, streams, and collections) IEC : the International Electrotechnical Commission IEEE: the Institute of Electrical and Electronics Engineers ISO : the International Organization for Standardization Extended Array Library (ISO/IEC 23271: 2002)
Das .NET Framework SDK enthält zahlreiche Tools, die der Software-Erstellung dienen. Hier einige:
Assembly Binding Log Viewer (Fuslogvw.exe) ist ein Windows-based Tool zum Untersuchen des Assembly und der Resourcen-Bindungen.
Assembly Linker (Al.exe) ist für das Erstellen des assembly manifests, satellite assemblies, und dem Arbeiten mit dem Global Assembly Cache (GAC).
Der MSIL Disassembler (Ildasm.exe) ist ein Windows-basiertes Tool zum Untersuchen der manifest-Einträge (containing metadata) und des MSIL-Codes im Assemblies.
Der Resource Editor (RESEDITOR) ist ein Windows-based Editor der .resx und .resources-Files erzeugt.
Der Resource File Generator (Resgen.exe) ist eine Consolen-Applikation die Text-Files und .resx-Files in binäre .resourcen-Files wandelt. Der ResX Generator (RESXGEN) ist eine Console-Applikation, die Bilder in XML-
umformattieren und .resx-Files umformatieren kann.
Der Windows Forms Resource Editor (Winres.exe) ist eine Windows-basierte Applikation, für Anpassungen an unterschiedliche Weltsprachen.
Die Common Language Runtime (CLR) basiert auf einer abstrakten Stack-Maschine, die ausschließlich Anweisungen des Zwischencodes MSIL (Microsoft Intermediate Language) verarbeitet. Programm Executable (PE)
verwendet zur Ausführung das Virtual Execution System, das aus dem Class Loader (Verifier und JIT) besteht, der den Managed Code erzeugt.
Programm Executable (PE)
Virtual Execution System besteht aus:
Compiler:
Verifier JIT
Managed Code besteht aus:
GabageCollector
Security ThreadSupport
...
Ein Assembly enthält den ausführbaren Code (falls erforderlich in mehreren Modulen mit den bereitgestellten Typen). Jedes Assembly enthält außerdem eine Manifest-Anteil mit detaillierten Informationen.
Assemblybesteht
aus:
Manifest Attribute
Name, Version, Shared Name, Hash, Custom Attributes Files, Referenced Assemblies, Types, Security, Product Information Ein Assembly kann durch die folgenden Attribute modifiziert werden:
using System.Reflection;using System.Runtime.CompilerServices;
↑ C#-Entwickler-ToolsC# - Konfigurations- und Weitergabetools
ASP.NET IIS-Registrierungstool (Aspnet_regiis.exe)
Ermöglicht einem Administrator bzw. einem Installationsprogramm, die Skriptzuordnungen für eine ASP.NET-Anwendung so zu aktualisieren, dass sie auf die mit dem Tool verknüpfte ASP.NET ISAPI-Version zeigen. Sie können mit dem Tool auch andere ASP.NET-Konfigurationsvorgänge ausführen. Hinweis: Aspnet_regiis.exe befindet sich in %windir%\Microsoft.NET\Framework\v1.1.xxxx, wobei xxxx die Buildnummer des verwendeten .NET Frameworks ist.
Assembly Cache Viewer (Shfusion.dll) Ermöglicht das Anzeigen und Ändern der Inhalte des globalen Assemblycache mit Windows Explorer. Hinweis: Shfusion.dll befindet sich in %windir%\Microsoft.NET\Framework\v1.1.xxxx, wobei xxxx die Buildnummer des verwendeten .NET Frameworks ist.
Assembly-Linker (Al.exe) Generiert eine Datei mit einem Assemblymanifest aus einer oder mehreren Ressourcendateien bzw. aus Microsoft Intermediate Language-Dateien (MSIL). Hinweis: Al.exe befindet sich in %windir%\Microsoft.NET\Framework\v1.1.xxxx, wobei xxxx die Buildnummer des verwendeten .NET Frameworks ist.
Assemblyregistrierungstool (Regasm.exe) Liest die Metadaten in einer Assembly und fügt die erforderlichen Einträge zur Registrierung hinzu, damit COM-Clients die .NET Framework-Klassen transparent erstellen können. Hinweis: Regasm.exe befindet sich in %windir%\Microsoft.NET\Framework\v1.1.xxxx, wobei xxxx die Buildnummer des verwendeten .NET Frameworks ist.
Assemblybindungs-Protokollanzeige (Fuslogvw.exe)
Zeigt die Details für fehlgeschlagene Assemblybindungen an. Mit diesen Informationen können Sie festzustellen, weshalb .NET Framework eine Assembly zur Laufzeit nicht finden kann.
Globales Assemblycache-Tool (Gacutil.exe)
Ermöglicht das Anzeigen und Ändern des Inhalts im globalen Assemblycache und Downloadcache. "Shfusion.dll" stellt ähnliche Funktionen bereit. Sie können "Gacutil.exe" in Buildskripts, Makefile-Dateien und Batchdateien verwenden.
Installer-Tool (Installutil.exe) Ermöglicht das Installieren und Deinstallieren von Serverressourcen durch Ausführen der Installerkomponenten einer angegebenen Assembly. Hinweis: Installutil.exe befindet sich in %windir%\Microsoft.NET\Framework\v1.1.xxxx, wobei xxxx die Buildnummer des verwendeten .NET Frameworks ist.
Tool für den isolierten Speicher (Storeadm.exe)
Entfernt oder listet den gesamten Speicher für den angemeldeten Benutzer auf.
Tool zum Generieren von systemeigenen Abbildern (Ngen.exe)
Erstellt ein systemeigenes Abbild von einer verwalteten Assembly und installiert es im systemeigenen Abbildcache auf dem lokalen Computer. Hinweis: Ngen.exe befindet sich in %windir%\Microsoft.NET\Framework\v1.1.xxxx, wobei xxxx die Buildnummer des verwendeten .NET Frameworks ist.
.NET Framework-Konfigurationstool (Mscorcfg.msc)
Stellt eine grafische Oberfläche zum Verwalten der .NET Framework-Sicherheitsrichtlinie und der Anwendungen bereit, die Remotedienste verwenden. Dieses Tool ermöglicht daneben das Verwalten und Konfigurieren von Assemblys im globalen Assemblycache. Hinweis: Mscorcfg.msc befindet sich in %windir%\Microsoft.NET\Framework\v1.1.xxxx, wobei xxxx die Buildnummer des verwendeten .NET Frameworks ist.
Installationstool für die .NET-Dienste (Regsvcs.exe)
Fügt durch Laden und Registrieren der Assembly und durch Erzeugen, Registrieren und Installieren der Typbibliothek in einer vorhandenen COM+ 1.0-Anwendung verwaltete Klassen zu den Windows 2000-Komponentendiensten hinzu. Hinweis: Regsvcs.exe befindet sich in %windir%\Microsoft.NET\Framework\v1.1.xxxx, wobei xxxx die Buildnummer des verwendeten .NET Frameworks ist.
Soapsuds-Tool (Soapsuds.exe) Unterstützt Sie bei der Kompilierung von Clientanwendungen, die über die sog. Remoting-Technik mit XML-Webdiensten kommunizieren.
Typbibliothek-Exportierprogramm (Tlbexp.exe)
Generiert eine Typbibliothek aus einer CLR-Assembly (Common Language Runtime).
Typbibliothek-Importierprogramm (Tlbimp.exe)
Konvertiert die Typendefinitionen in einer COM-Typbibliothek in äquivalente Definitionen im verwalteten Metadatenformat.
Generiert Code für XML-Webdienste und XML-Webdienstclients aus WSDL-Dateien (Web Services Description Language), XSD-Dateien (XML Schema Definition) und .discomap-Discoverydokumenten.
Webdienste-Suchtool (Disco.exe) Sucht die URLs von auf einem Webserver befindlichen XML-Webdiensten und speichert die mit den einzelnen XML-Webdiensten zusammenhängenden Dokumente auf einem lokalen Datenträger.
Tool für die XML-Schemadefinition (Xsd.exe)
Generiert XML-Schemas, die der XML-Schema Definition (XSD) des World Wide Web Consortiums (W3C) entsprechen. Das Tool generiert Common Language Runtime- und DataSet-Klassen aus einer XSD-Schemadatei.
Debugtools
Microsoft CLR Debugger (DbgCLR.exe) Stellt Debugdienste mit einer grafischen Oberfläche bereit, damit Entwickler Laufzeitprobleme in Programmen finden und beheben können. Weitere Informationen finden Sie unter Der CLR Debugger in der .NET Framework SDK-Dokumentation. Hinweis: Der Microsoft CLR Debugger (DbgCLR.exe) befindet sich in dem Ordner Microsoft.NET\SDK\v1.1\GuiDebug.
Laufzeit-Debugger (Cordbg.exe) Stellt mit der Common Language Runtime Debug-API Befehlszeilen-Debugdienste bereit. Verwenden Sie dieses Tool, um Probleme in Programmen zu finden und zu beheben, die mit der Laufzeit in Verbindung stehen.
Sicherheitstools
Tool für die Zertifikatserstellung (Makecert.exe)
Generiert X.509-Zertifikate, die nur zu Testzwecken dienen.
Tool für die Zertifikatsverwaltung (Certmgr.exe)
Verwaltet Zertifikate, Zertifikatsvertrauenslisten und Zertifikatssperrlisten (CRLs).
Zertifikatsüberprüfungstool (Chktrust.exe)
Überprüft die Gültigkeit einer Datei, die mit einem X.509-Zertifikat signiert wurde.
Sicherheitsrichtlinientool für den Codezugriff (Caspol.exe)
Ermöglicht das Überprüfen und Ändern von Sicherheitsrichtlinien für den Codezugriff von Computern, Benutzern sowie auf Unternehmensebene. Hinweis: Caspol.exe befindet sich in %windir%\Microsoft.NET\Framework\v1.1.xxxx, wobei xxxx die Buildnummer des verwendeten .NET Frameworks ist.
Tool für die Dateisignierung (Signcode.exe)
Signiert eine PE-Datei (Portable Executable) mit einer digitalen Authenticode-Signatur.
Tool zum Anzeigen von Berechtigungen (Permview.exe)
Zeigt die minimalen, optionalen und verweigerten Berechtigungen an, die von einer Assembly angefordert werden. Sie können mit diesem Tool auch die von einer Assembly verwendete deklarative Sicherheit anzeigen.
PEVerify-Tool (PEverify.exe) Überprüft die MSIL-Typensicherheit und die Gültigkeit der Metadaten für eine angegebene Assembly.
Secutil-Tool (Secutil.exe) Extrahiert öffentliche Schlüsselinformationen für starke Namen oder Authenticode-Publisherzertifikate aus einer Assembly in einem Format, das in Code eingebunden werden kann.
Registrierungstool (Setreg.exe) Ermöglicht das Ändern der Registrierungseinstellungen für die Schlüssel Software Publishing State, die das Verhalten der Zertifikatsüberprüfung steuern.
SPC-Testtool (Cert2spc.exe) Erstellt ausschließlich zu Testzwecken ein SPC (Software Publisher's Certificate), das aus mindestens einem X.509-Zertifikat besteht.
Strong Name-Tool (Sn.exe) Hilft beim Erstellen von Assemblys mit starken Namen. Sn.exe bietet Optionen für die Schlüsselverwaltung, die Signaturgenerierung und die Signaturüberprüfung.
Allgemeine Tools
Common Language Runtime-Minidumptool (Mscordmp.exe)
Erstellt eine Datei, die Informationen zum Analysieren von Systemproblemen zur Laufzeit enthält. Das Tool Microsoft Dr. Watson (Drwatson.exe) startet dieses Programm automatisch.
Lizenzencompiler (Lc.exe) Liest Textdateien, die Lizenzinformationen enthalten, und erstellt eine .licenses-Datei, die in einer ausführbaren Common Language Runtime-Datei eingebettet werden kann.
Management Strongly Typed Class Generator (Mgmtclassgen.exe)
Ermöglicht das schnelle Generieren einer früh gebundenen Klasse in C#, Visual Basic oder JScript für eine angegebene WMI-Klasse (Windows Management Instrumentation).
MSIL-Assembler (Ilasm.exe) Generiert eine PE-Datei aus MSIL (Microsoft Intermediate Language). Sie können diese Datei ausführen, die den MSIL-Code und die erforderlichen Metadaten enthält, um zu überprüfen, ob der MSIL-Code ordnungsgemäß ausgeführt wird. Hinweis: Ilasm.exe befindet sich in %windir%\Microsoft.NET\Framework\v1.1.xxxx, wobei xxxx die Buildnummer des verwendeten .NET Frameworks ist.
MSIL-Disassembler (Ildasm.exe) Erstellt aus einer PE-Datei, die MSIL-Code enthält, eine Textdatei, die als Eingabe für den MSIL-Assembler (Ilasm.exe) verwendet werden kann.
Generierungstool für Ressourcendateien (Resgen.exe)
Konvertiert Textdateien und .resx-Dateien (XML-basiertes Ressourcenformat) in .resources-Dateien der .NET Common Language Runtime, die in einer ausführbaren Laufzeit-Binärdatei eingebettet oder in Satellitenassemblys kompiliert werden können.
Visual J#-Binärkonvertierungstool (JbImp.exe)
Dieses Tool konvertiert bestimmte Bytecodedateien in der Programmiersprache Java (.class-Dateien) zu MSIL (Microsoft® Intermediate Language). Mit diesem Tool können Entwickler die meisten Bibliotheken und Anwendungen der JDK 1.1.4–Ebene, die nur als Bytecodedateien verfügbar sind, in MSIL-Assemblys umwandeln und sie mit dem Visual J# Redistributable Package auf .NET Framework ausführen. Verwenden Sie dieses Tool nur, wenn die Java-Quellen für die Anwendungen bzw. Bibliotheken nicht verfügbar sind. Wenn die Java-Quellen verfügbar sind, sollten Sie stattdessen den Visual J#-Compiler (vjc.exe) verwenden. Hinweis: Zur Verwendung dieses Tools muss das Visual J# .NET Redistributable Package, Version 1.1, installiert sein. Visual J# Redistributable Package wird installiert.
Importierprogramm für Windows Forms ActiveX-Steuerelemente (Aximp.exe)
Konvertiert Typendefinitionen in einer COM-Typbibliothek für ein ActiveX-Steuerelement in einem Windows Forms-Steuerelement.
Windows Forms-Klassenanzeige (Wincv.exe)
Sucht verwaltete Klassen, die mit den angegebenen Suchkriterien übereinstimmen, und zeigt mit der Reflektions-API Informationen über die Klassen an.
Ressourcen-Editor für Windows Forms (Winres.exe)
Ermöglicht das einfache und schnelle Lokalisieren von Windows Forms-Formularen.
↑ C#-keywords
In C# gibt es die folgenden "Schlüsselworte":
abstract as base bool break byte case catch char checked
class const continue decimal default delegate do double else enum
event explicit extern false finally fixed float for foreach goto
if implicit in int interface internal is lock long namespace
new null object operator out override params private protected public
readonly ref return sbyte sealed short sizeof stackalloc static string
struct switch this throw true try typeof uint ulong unchecked
unsafe ushort using virtual void volatile while
Ein Vergleich mit den Schlüsselwörtern des CPP-Betriessystem-Compilers zeigt Unterschiede auf. Neuerungen (z.B. Einführung von DLL's) ändern auch die Unterstützung durch "Standard-CPP-Compiler". CPP-Schlüsselwörter
(hier MS-Keywords) sind reservierte, vordefinierte Identifizierer, die eine besondere Bedeutung haben und deshalb im eigenen C++-Quelltext nicht frei verwende werden können. Identifizierer mit führenden Underscores ("__...")
continue default delete deprecated dllexport dllimport do double
dynamic_cast else enum explicit extern false float for
friend goto if inline int
long mutable naked namespace new noinline noreturn nothrow
novtable operator private property protected public register reinterpret_cast
return selectany short signed sizeof static static_cast struct
switch template this thread throw true try typedef
typeid typename union unsigned using declaration, using directive
uuid virtual void
volatile wchar_t,__wchar_t while
↑ Typen in C#c# hat class-Modifizierer: new, public, protected, internal, private, abstract, sealed Das Common Type System (CTS) umfasst einen reichhaltigen Satz von Datentypen, die sich grob in "Value Types" und "Reference Types"
klassifizieren lassen.
Value Types
System Value Types Enumerations User Value Types
Referenz Types
Pointers Self-describng typesa) Classes: Delegates,User-Defined,Boxed Values) b) Arrays
Interface
Reference (class) "wie eine Adresse"
Value (struct) "wie ein Stück Speicher"
Variable holds
Reference Eine Refrenztyp-Variable zeigt auf die Heap-Instanz des Objektes. A a = new A("Fred"); A b = a; b.Name = "xxx";//mutator Es gibt immutable class
Actual value int i = 123; int j = i; i = 55; hat keinen Einfluß auf j
Value lives On the heap Inline (on the stack, or inline with an object)
Default Value Null Zeroed
= means Copy reference Copy value
↑ Boxing and Unboxing
int value = 123;object o = value; // box int into an object boxint value2 = (int) o; // unbox into value2
Das Folgende zeigt lediglich das "Carsting"-Prinzip (alles ist ein Objekt, Boxing and Unboxing), wie es etwa in C (auf der unteren Ebene) implementiert ist.
case VT_I8://* LONGLONG VT_I8 printf( "%ld", v.llVal );break; case VT_I4: //* LONG VT_I4 printf( "%d", v.lVal ); break; case VT_UI1://* BYTE VT_UI1 printf( "%d", v.bVal); break; case VT_I2: //* SHORT VT_I2 printf( "%d", v.iVal); break; case VT_I1: //* CHAR VT_I1 printf( "%d", v.cVal); break; case VT_UI2: //* USHORT VT_UI2 printf( "%d", v.uiVal); break; case VT_UI4://* ULONG VT_UI4 printf( "%d", v.ulVal); break; case VT_UI8: //* ULONGLONG VT_UI8 printf( "%ld", v.ullVal); break; case VT_INT: //* INT VT_INT printf( "%d", v.intVal); break; case VT_UINT://* UINT VT_UINT printf( "%d", v.uintVal);break; default: printf( "<Not implemented>" ); break; }}
↑ dll-Funktionen in C#
Bei mehr als 1000 DLL'S (ca. 40 000 API-Funktionen) gibt es viele Nativ-Funktionen, die exportiert werden. Wie können diese DLL-Funktionen, die sich in DLL's befinden, in C# genutzt werden?
Wie werden in C# Funktionen aus den dll's genutzt?
Als Beispiel soll die Funktion bool Beep(int frequency, int duration); benutzt werden, die von "kernel32.dll" exportiert wird. Durch [DllImport("kernel32.dll")] oder [DllImport("kernel32.dll", CharSet = CharSet.Auto)] wird eine Import-Einbindung in unsere Klasse veranlaßt. Nach [DllImport("...dll")] folgt der Prototyp public static extern bool Beep(int frequency, int duration);, der dem C#-Compiler bei der "Typsicherheit hilft".
Für einen akustischen Hinweis ist meist die C++-Funktion BOOL MessageBeep(UINT soundtype) günstiger, die in C# als bool MessageBeep(BeepType beepType); benutzt werden kann. Im C++-Header File winuser.h sind Konstanten definiert, wie z.B. "MB_ICONHAND", die nach C# gewandelt werden können, etwa:
using System; using System.Runtime.InteropServices;
class myClass_nutzt_dll_funktion { [DllImport("kernel32.dll")] public static extern bool Beep(int frequency, int duration);
static void Main(string[] args) { Random random = new Random(); for (int i = 0; i < 100; i++) { Beep(random.Next(10000),100); } } }
benutze: [DllImport("user32.dll")] public static extern bool MessageBeep(BeepType beepType);
C# Aufruf: MessageBeep(BeepType.IconQuestion);
using System;
class IndexerClass {
private int [] myArray = new int[100];
public int this [int index] {//Indexer declaration get { if (index < 0 || index >= 100) return 0; else return myArray[index]; } set { if (!(index < 0 || index >= 100)) myArray[index] = value; } } }
public class MainClass { public static void Main() {
IndexerClass b = new IndexerClass();
b[2] = 1024; b[3] = 256;
for (int i=0; i < 5; i++) { Console.WriteLine("Element #{0} = {1}", i, b[i]); } } }
Ausgabe: Element #0 = 0 Element #1 = 0 Element #2 = 1024
Element #3 = 256 Element #4 = 0
↑ C#-Console-Applikation
Eine C#-Console-Applikation wird mit csc.exe /t:exe übersetzt. Als Beispiel wird hier auch der Aufruf einer statischen Methode bei einem "nested namespace" angegeben.
#define P01
#if P01 class HalloWelt { static void Main() { System.Console.WriteLine ("Hallo Welt! Ohne using System;"); } } #endif
//- - - - - oder - - - - -
#if P02 using System;
class HalloWelt { static void Main() { Console.WriteLine ("Hallo Welt! Mit \nusing System;"); } } #endif
#if P03 using System;
namespace SomeNameSpace { public class MyClass { [STAThread] public static void Main() { Nested.NestedNameSpaceClass.SayHello(); } }
namespace Nested { // a nested namespace public class NestedNameSpaceClass { public static void SayHello() { Console.WriteLine("Hello"); } } } } #endif
#if P01/////////////////////////////////////////////////// ohne using System; /////////////////////////////////////////////////class HalloWelt { static void Main() { System.Console.WriteLine( "\n*** Hallo Welt!" +"\n*** Ohne Verwendung von" +"\n*** using System;");
} }#endif
#if P02/////////////////////////////////////////////////// mit using System; /////////////////////////////////////////////////using System;
class HalloWelt { static void Main() { Console.WriteLine( "\n*** Hallo Welt!" +"\n*** Mit Verwendung von" +"\n*** using System;"); } }#endif
#if P03/////////////////////////////////////////////////// Starte das übersetzte Programm myproc.exe mit // Kommandozeilen-Argumenten, wie z.B.:// myproc.exe A B C D// und xml-Extraktion/////////////////////////////////////////////////using System;
public class HalloWelt03 { public static void Main(string[] args) { Console.WriteLine("Hallo! Mit Main(string[] args)"); Console.WriteLine("Anzahl = {0}", args.Length ); for (int i=0; i < args.Length; i++) { Console.WriteLine("args[{0}] = {1}",i,args[i]); } }}#endif
#if P04namespace P04 {/////////////////////////////////////////////////// mehrer Kommandozeilen eingeben///////////////////////////////////////////////// using System; /// <summary> /// Zusammenfassung für P04 /// </summary> class HalloWelt04 { /// <summary> /// Der Haupteinstiegspunkt für die Anwendung /// ist Main(string[] args)