JLI Spieleprogrammierung Foren-Übersicht JLI Spieleprogrammierung

 
 FAQFAQ   SuchenSuchen   MitgliederlisteMitgliederliste   BenutzergruppenBenutzergruppen 
 medals.php?sid=c418848fe99f3a361535c7df7e67cb40Medaillen   RegistrierenRegistrieren   ProfilProfil   Einloggen, um private Nachrichten zu lesenEinloggen, um private Nachrichten zu lesen   LoginLogin 

HelloWin.c das Standardfenster

 
Neues Thema eröffnen   Neue Antwort erstellen    JLI Spieleprogrammierung Foren-Übersicht -> Tutorials
Vorheriges Thema anzeigen :: Nächstes Thema anzeigen  
Autor Nachricht
Terep
Mini JLI'ler



Anmeldedatum: 02.05.2008
Beiträge: 18
Wohnort: Hannover
Medaillen: Keine

BeitragVerfasst am: 06.05.2008, 21:16    Titel: HelloWin.c das Standardfenster Antworten mit Zitat

Will man unter C++ mit windows programmieren wird in der Regel ein vorgefertigter Quellcode verwendet und angepasst. Dieser Quellcode hat es in sich (obwohl es keine 100 Zeilen sind):
18 Funktionen,
Groß- und Kleinschreibung wird systematisch genutzt (wie HND hwnd),
Abkürzungen sind die Regelfälle,
andere Datentypen,
ungarische Notation
und überall verzweigt es sich in ungeahnte Tiefen. Nicht viele kennen sich damit wirklich aus. Mein Tutorial-Entwurf hat nicht den Anspruch, die Window-Erstellung als ganzes zu erläutern. Jeder ernsthaft Interessierte wird hier schnell genügend Lektüren finden. „Spieleprogrammierung mit DirectX“ ist ein guter Einstieg, landen wird man bei ernstem Interesse bestimmt bei Charles Petzold.
Der Quellcode stammt aus der 5. Auflage von Windows-Programmierung von Charles Petzold.
Ich möchte den Quellcode gemäß meiner persönlichen Sichtweise interpretieren und bemühe mich um einen lockeren Schreibstil:
Code:

/*-----------------------------------------------------------------------
   HELLOWIN.C – Zeigt "Hello, Windows 98!" in seinem Anwendungsbereich an
                 (c) Charles Petzold, 1998
  -----------------------------------------------------------------------*/
Mein Gott, 1998, das Ding stammt aus uralten Zeiten, macht das überhaupt Sinn hier weiter zu machen. Egal ich bin auch nicht frischer, im Vergleich zu meinem Alter ist das Ding eigentlich topaktuell. Also mache ich weiter.
Es handelt sich hier wohl um einen Basisquellcode, der solange Gültigkeit hat, wie C++ abwärtskompatibel ist. Hier werden quasi die Grundmechanismen erkennbar sein. Man wird sehen.
Code:

#include <windows.h>
Oh je, sofort eine Gemeinheit. Eine Headerdatei. Den Trick kennt man. In dieser Datei stecken zig andere Dateien. Somit sind die 100 Codezeilen nicht die Spitze des Eisberges sondern ein Tausendstel, kleiner? Noch kleiner? Keine Ahnung. Um das rauszukriegen, müsste ich einen Exkurs machen. Schließlich ist diese windows.h Teil der SDK = Software Development Kit zu gut deutsch „Softwareentwicklungspaket“ der Vermittler zwischen C++ und DirectX. Das nehme ich erstmal so hin.
Code:

LRESULT CALLBACK WndProc (HWND, UINT, WPARAM, LPARAM) ;
Aha, die erste der 18 Funktionen wird deklariert, Funktionsname mit 4 Parametern, schön in Klammern gesetzt. Sieht simpel aus, das ist verdächtig. Wieso steht als erstes Wort nicht void oder int?
LRESULT ist ein Windows Data Type (32-Bit-Rückgabewert)
Will ich etwas genauer wissen, klicke ich in meiner IDE = Integrated Developement Environment „Integrierte Entwicklungsumgebung“ auf F1. Im Microsoft Visual Studio kommt hier ein Wahnsinn an Informationsflut. Nach spätestens 10 Minuten weist Du nicht mehr, warum Du da hingegangen bist. Also schön beim Thema bleiben: Meine Ausbeute zu

LRESULT:
Signed result of message processing. This type is declared in WinDef.h as follows:
typedef LONG_PTR LRESULT;

Fußangeln, wo man nur hinguckt.
Dahinter versteckt sich ein PTR = Pointer zu deutsch Zeiger. Mit Sternchen wäre es ja zu einfach gewesen.

CALLBACK muss auch ein Atribut sein. Der Funktionsname ist ja WndProc. Mal sehen, was F1, die Hilfetaste, sagt:

CALLBACK
Calling convention for callback functions. This type is declared in WinDef.h as follows:
#define CALLBACK __stdcall
Ja, eine Vereinbarung, wie man Nachrichten bearbeitet (sehr freie Interpretation).

WndProc = WindowProcedur.

LRESULT CALLBACK WndProc kriegt 4 Parameter und gibt eine Nachricht in Form einer Zahl zurück. Der Satz hätte wohl auch gereicht.

Aber was ist mit den 4 Parametern?
HWND = HandleWindows „Fenstergriff“ ; der Fenstergriff ist eine ganze Zahl unter der das Betriebsystem den Zugriff auf das Fenster verwaltet. Das erste der 4 Parameter ist also eine Zugriffscodierung, hier auf das zu erstellende Windowsfenster.

UINT ist auch ein Windows Data Type, Integer = ganze Zahl.

WPARAM F1 sagt:
Der Wert dieses Felds hängt von der Meldung ab. Über das WParam-Feld können Sie für die Behandlung der Meldung wichtige Informationen abrufen. Dieses Feld wird i. d. R. zum Speichern kleiner Informationen wie Flags verwendet.

LPARAM F1 sagt:
Der Wert dieses Felds hängt von der Meldung ab. Über das LParam-Feld können Sie für die Behandlung der Meldung wichtige Informationen abrufen. LParam wird i. d. R. zum Speichern eines Objekts verwendet, wenn dieses von der Meldung benötigt wird. Mit der GetLParam-Methode können Sie Informationen aus dem LParam-Feld abrufen und diese in ein Objekt konvertieren.

Fassen wir zusammen. WndProc ist eine Nachrichtenfunktion, die 4 Parameter braucht um eine Antwort zu geben. Jetzt kommen wir der Sache schon näher. Warum ist das so kompliziert? Weil es so komplex ist. Hier kommen wir dem Betriebssystem sehr nahe. Mit einem HWND wird alles eindeutig erkannt. Jedes Fenster, Dialogsystem usw.. Egal was wir auf dem Screen tun. Windows registriert es und formuliert diese Aktivität wie „rechte Maustaste geklickt“ in diese 4 Parameter und posaunt das aus. Jeder Programmierer kann sich dadurch Zugriff zu jeder Nachricht verschaffen und dem Betriebssystem sagen, was es tun soll. Dieses leider in einer sehr formalen Weise.
Im Prinzip ist dieses Nachrichtensystem mit das Wesentlichste, was in diesem Quellcode steckt. Es wird uns auf Dauer beschäftigen.

Ende Teil 1
Macht es Sinn, dies fortzusetzen? Oder ist es zu verdreht und falsch interpretiert?

Terep Smile


Zuletzt bearbeitet von Terep am 11.05.2008, 14:42, insgesamt einmal bearbeitet
Nach oben
Benutzer-Profile anzeigen Private Nachricht senden
Jonathan_Klein
Living Legend


Alter: 31
Anmeldedatum: 17.02.2003
Beiträge: 3430
Wohnort: Siegerland
Medaillen: Keine

BeitragVerfasst am: 06.05.2008, 21:36    Titel: Re: HelloWin.c das Standardfenster Teil 1 Antworten mit Zitat

Terep hat Folgendes geschrieben:
Schließlich ist diese windows.h Teil der SDK = Software Development Kit zu gut deutsch „Softwareentwicklungspaket“ der Vermittler zwischen C++ und DirectX. Das nehme ich erstmal so hin.


Die Windows.h hat nix mit DX zu tun, sondern vermittelt (wenn man es so ausdrücken möchte) zwischen C++ und Windows.
Für DX gibt es ja noch eine Reihe eigene Headerdateien.
_________________
http://www.C3-Soft.de
http://www.nikodemus.net
Nach oben
Benutzer-Profile anzeigen Private Nachricht senden E-Mail senden Website dieses Benutzers besuchen
Deviloper
Junior JLI'ler



Anmeldedatum: 31.05.2006
Beiträge: 77

Medaillen: Keine

BeitragVerfasst am: 07.05.2008, 21:35    Titel: Antworten mit Zitat

Zwischen C und Windows Wink
Nach oben
Benutzer-Profile anzeigen Private Nachricht senden
David
Super JLI'ler


Alter: 33
Anmeldedatum: 13.10.2005
Beiträge: 315

Medaillen: Keine

BeitragVerfasst am: 08.05.2008, 12:06    Titel: Antworten mit Zitat

Mir gefällt der Schreibstil! Smile Mach ruhig weiter! Wink
Nach oben
Benutzer-Profile anzeigen Private Nachricht senden
DirectXer
Dark JLI'ler



Anmeldedatum: 05.02.2005
Beiträge: 1201
Wohnort: Köln
Medaillen: Keine

BeitragVerfasst am: 08.05.2008, 16:06    Titel: Antworten mit Zitat

David hat Folgendes geschrieben:
Mir gefällt der Schreibstil! :) Mach ruhig weiter! ;-)

dito ;) es ist wirklich nicht leicht, das thema so locker in worte zu fassen. respekt =)

Gruß DXer
Nach oben
Benutzer-Profile anzeigen Private Nachricht senden E-Mail senden
Jonathan_Klein
Living Legend


Alter: 31
Anmeldedatum: 17.02.2003
Beiträge: 3430
Wohnort: Siegerland
Medaillen: Keine

BeitragVerfasst am: 08.05.2008, 16:36    Titel: Antworten mit Zitat

Naja, es ist halt ein Einsteigertut, weil durch den sehr lockeren Schreibstil sind die Informationen eher sehr gestreut. Du hast also relativ zur Informationsmenge sehr viel Text.
Fürs verstehen ist das sicherlich gut, aber fürs nachschlagen eher weniger.

Da es sich aber an Leute richtet, die nciht nachschalgen, sondern lernen wollen, ist das denke ich so ok.
_________________
http://www.C3-Soft.de
http://www.nikodemus.net
Nach oben
Benutzer-Profile anzeigen Private Nachricht senden E-Mail senden Website dieses Benutzers besuchen
Hazel
JLI MVP
JLI MVP


Alter: 33
Anmeldedatum: 19.07.2002
Beiträge: 1761

Medaillen: Keine

BeitragVerfasst am: 08.05.2008, 16:52    Titel: Antworten mit Zitat

Der Schluss ist nicht so schön gelungen... Hauptsatz. Hauptsatz. Hauptsatz. Ansonsten sicherlich nett für Einsteiger. Was ich mich allerdings frage ist, ob das hier der richtige Ort dafür ist, da die meisten User hier durch Christians Buch gekommen sind und somit schon einen ordentlichen Einstieg hatten. Wir sind also größtenteils nicht deine Zielgruppe und können dir höchstens Verbesserungsvorschläge geben als wirklich Nutzen daraus zu ziehen.

[Edit] Nachtrag: Ich seh du bist auch Hannoveraner. Studierst du zufällig dort? ;)
_________________
*click* Dabuu!?
Twitter: http://twitter.com/Ollie_R
Nach oben
Benutzer-Profile anzeigen Private Nachricht senden
Terep
Mini JLI'ler



Anmeldedatum: 02.05.2008
Beiträge: 18
Wohnort: Hannover
Medaillen: Keine

BeitragVerfasst am: 11.05.2008, 14:40    Titel: Zweiter und letzter Teil Antworten mit Zitat

Wir sind noch ganz am Anfang. Ohne Kommentare nur 2 Zeilen Code. Tja, das schockt. Dafür kommt aber jetzt etwas was jeder kennt. Die Hauptfunktion, der Einstiegspunkt für das Programm. Das ist schon seit C so, C? , wir arbeiten die ganze Zeit nur in C. Für mich ist das so, wie im Urschleim wühlen. Mit Windows 1.0 gab es für die Windows-API = application programming interface (Programmierschnittstelle) nur ca. 450 Funktionen. Laut Petzold sind es heute mehrere Tausend Funktionen und bis auf die Kleinigkeit, das sich das System von 16 auf 32 Bit umgestellt hat, gibt es laut Petzold keine wirklich tiefgreifende Änderung. Interessant nicht wahr, ich beginne zu verstehen, warum Leute mit C# oder mit Java anfangen. Keine Altlasten, man muss keine Kompatibilität zu C halten. Stimmt, der Witz ist aber, dass das Betriebssystem trotzdem in C ist und Jawa aus C++Feder stammt. Also, aus dem Urschlamm C kommt alles. Wer verstehen will, wie es funktioniert, hat nur hier in den Anfängen eine Chance. Mehrere tausend Funktionen sind derart komplex, dass Du immer nur Detailwissen aufbaust, solange Du die Grundphilosophie nicht verstehst, die sich hier zeigt.
Wobei diese Sichtweise sehr relativ ist, ein Assemblerprogrammierer wird diese Inhalte ganz anders registrieren.
OK, das Vorwort zum 2. Teil ist zu Ende. Es geht weiter: Also wie gesagt die Hauptfunktion:
Code:

int WINAPI WinMain    (HINSTANCE hInstance,
HINSTANCE hPrevInstance,
                          PSTR szCmdLine,
int iCmdShow)


Beachte, die Hauptfunktion ist vorher nicht deklariert worden. Das Betriebssystem sucht und findet sie oder meckert. Die Funktion gab damals einen Integerwert zurück und dies ist heute auch noch so. Das Attribut WINAPI verlangt die Syntax. WinMain ist das Schlüsselwort für die Hauptfunktion. Wieder kommen 4 Parameter mit Auffälligkeiten:

HINSTANCE hInstance = Handle to an instance (Griff zu einer Instanz). Hier sind wir wieder ganz nah dran am Betriebssystem. Dies ist absolut wichtig:
Ein Handle ist eine Ganzzahlcodierung, mit der das Betriebssystem einen eindeutigen Zugriff sicherstellt. Hier handelt es sich um ein Handle für die Instanz. Wir wissen ja, das Original kriegen wir nie, aber kopieren dürfen wir wie die Weltmeister. Hiermit wird unser Hallo-Welt-Programm adressmäßig in hInstance codiert.

HINSTANCE hPrevInstance ist Ballast aus der Altvorderenzeit und wird respektvoll mitgeschleppt und dann vergessen.

PSTR szCmdLine:
PSTR = Pointer to a null-terminated string of 8-bit Windows (ANSI) (Typ char*).
Irgendwann kann man es nicht mehr ignorieren. Als case-sensitive Sprache unterscheidet C zwischen Groß- und Kleinschreibung. Alles was in Großbuchstaben steht, soll für konstante Werte stehen. Vermutlich wollte man früher von der Bevorzugung der englischen Sprache ablenken und verwendete daher noch zusätzlich die ungarische Notation (Falsch, zu Ehren des legendären MS-Programmier Charles Simonyi). Das bedeutet, dass vor dem eigentlichen Datentyp ein Präfix gesetzt wird.
szCmdLine = Präfix sz = ASCIIZ-String (ein String der mit \0 abgeschlossen ist)
CmdLine: Zeigt für das System die Größe der Befehlszeilenzeichenfolge an (lt MSDN).

int iCmdShow hier werden die Attribute für unser Fenster versteckt. So gut getarnt, dass es im Quellcode textlich gar nicht auftaucht, dafür finden wir aber wndclass.
Wir verlassen den Funktionskopf und gehen in den Rumpf:
Code:

{
     static TCHAR szAppName[] = TEXT ("HelloWin") ;
     HWND         hwnd ;
     MSG          msg ;
     WNDCLASS     wndclass ;

static TCHAR szAppName[] = TEXT ("HelloWin") ;
Es wird der String für den Fenstertitel hinterlegt. Wenn aber die Windows-Struktur definiert wird, kann der Text noch geändert werden.
TCHAR = an die MSDN muss man sich gewöhnen, daher F1 drücken, im Index TCHAR eingeben: Es erscheint eine Tabelle der Windows Data Types und runterscrollen:

A WCHAR if UNICODE is defined, a CHAR otherwise.
#ifdef UNICODE
typedef WCHAR TCHAR;
#else
typedef char TCHAR;
#endif

Wenn mit UNICODE programmiert wird, wird TCHAR zu WCHAR = wide Char (=16 bit UNICODE Zeichen). Ansonsten wird TCHAR als char ( ASCII) definiert.

Aber die Praxis zeigt es leider anders. Als Einsteiger hat man jede Menge Bücher-Codes, die nicht laufen, weil die IDE UNICODE will. Der Alt-Code hat kein PSTR szCmdLine sondern LPSTR lpzCmdLine stehen. Der Buchcode kann somit nicht mit UNICODE umgehen. Wenn ich mit dem Buchcode arbeiten will, deaktiviere ich UNICODE. Dies kann man in Projekteigenschaften/Konfigurationseigenschaften/Allgemein den Zeichensatz von Unicode auf „nicht festgelegt“ ändern (Bei MS Visual Studio 2005).

HWND hwnd ; hier wird der eindeutige Zugriff auf das Fenster selbst definiert.
MSG msg ; hier ist eine Datenstruktur für den Informationsaustausch mit dem Betriebssystem definiert.
Es gibt eine C++hoch_7 Version, die auf Gedankentelepathie basiert. Aus Selbstherrlichkeit heraus hat dieser Super-Programmierer nichts dokumentiert und dann einen WM_DESTROY Befehl aktiviert. Leider auf sich selbst. Das System hat alles gelöscht, interaktiv einschliesslich den Kopfinhalt des Programmierers. Das Wiederhochfahren vom Computer und Programmierer endet seitdem immer in der Endlosschleife Solitär (nicht ernstzunehmender Scherz).
Somit werden wir uns noch ausgiebig mit dem gegenwärtigen trivialen Nachrichtenaustausch per Eintippen beschäftigen müssen.

WNDCLASS wndclass ; Endlich etwas, was klar ist, die Windowsstruktur wird hier hinterlegt. Interessant die Großschreibung für die nicht änderbare Konstante WINDCLASS und kleingeschrieben unsere abgekupferte konkrete Klasse. So kennen wir es aus der Klassenanwendung.
Code:

     wndclass.style         = CS_HREDRAW | CS_VREDRAW ;
     wndclass.lpfnWndProc   = WndProc ;
     wndclass.cbClsExtra    = 0 ;
     wndclass.cbWndExtra    = 0 ;
     wndclass.hInstance     = hInstance ;
     wndclass.hIcon         = LoadIcon (NULL, IDI_APPLICATION) ;
     wndclass.hCursor       = LoadCursor (NULL, IDC_ARROW) ;
     wndclass.hbrBackground = (HBRUSH) GetStockObject (WHITE_BRUSH) ;
     wndclass.lpszMenuName  = NULL ;
     wndclass.lpszClassName = szAppName ;

Und wie es sich gehört, werden die Klasseneigenschaften mittels Punktoperator alle beim Eintippen gezeigt. Zu bemerken ist, dass hier wieder ein Präfix verwendet wird. CS = class style, IDI = ID icon usw... CS_HREDRAW | CS_VREDRAW gibt dem Fenster 2 Eigenschaften mit: Wird das Fenster in seiner Größe verändert: HREDRAW = handle re-draw für das horizentale Neuzeichnen, und VREDRAW für das vertikale Neuzeichnen. Die Nennung zwei oder mehrerer Merkmale ist mittels dem Operator bitweises OR | möglich. Möglich ist die Mehrfachnennung dadurch, dass die Konstanten, die mit CS_ beginnen, als Bitflags definiert sind. Das bedeutet, … man kann immer noch tiefer bohren, aber hier reicht es. Für eine OpenGL Anwendung wird zum Beispiel bei wndclass.style noch | CS_OWNDC hinzugefügt.
Auf diese wndclass-Struktur werde ich nicht weiter eingehen. Sie enthält Informationen über das Fenster, z. B. das Anwendungssymbol, die Hintergrundfarbe des Fensters, den Namen für die Anzeige in der Titelleiste, den Namen der Fensterprozedurfunktion usw., MSDN freut sich auf Euren Besuch.
Code:

     if (!RegisterClass (&wndclass))
     {    // UNICODE-Compilierung ist die einzige realistische Fehlermöglichkeit
          MessageBox (NULL, TEXT ("Programm arbeitet mit Unicode und setzt Windows NT voraus!"),
                      szAppName, MB_ICONERROR) ;
          return 0 ;
     }

Laut Petzold greift das if nur bei Win95 oder Win98. Hier kommt dann die Fehlermeldung per Meldebox. Schön übersichtlich. MessageBox mit 4 Parametern. Da wir neugierig sind, gucken wir mal ins MSDN, da steht:

int MessageBox(
HWND hWnd, (NULL,
LPCTSTR lpText, TEXT ("Programm arbeitet … voraus!"),
LPCTSTR lpCaption, szAppName,
UINT uType MB_ICONERROR) ;
);

Schade eigentlich, vorher sah es irgendwie klar und einfach aus.

HWND = Handle to a window. Wird dieser Zeiger aktiv, deaktiviert er das entsprechende Fenster, bis die Meldebox wieder geschlossen wird (ganz schön aufdringlich).

LPCTSTR L = Datentyp long P = pointer CT = caption STR = string
Der erste Parameter ist ein Zeiger vom Datentyp long (64 byte) der auf ein Windowshandle zeigt. Respekt, der Zeiger wird erst mal ordentlich auf NULL gesetzt. So haben wir es gelernt.

lpText l = Datentyp long p = pointer Text = Textausgabe innerhalb der Messagebox

lpCaption Text in der Titelleiste der Messagebox

UINT = unsigned int kennt man
u = ungarische Notation für int. Durch uType wird mittels Flag das Verhalten der Messagebox definiert. Zum Beispiel: Yes or no oder Abort, Retry, and Ignore.
Verlassen wir jetzt die Messagebox.
Code:

      hwnd = CreateWindow (szAppName,                 // Name der Fensterklasse
                  TEXT ("Das erste echte Programm"),  // Fenstertitel
                  WS_OVERLAPPEDWINDOW,                // Fensterstil
                  CW_USEDEFAULT,                      // X-Position des Fensters
                  CW_USEDEFAULT,                      // Y-Position des Fensters
                  CW_USEDEFAULT,                      // Fensterbreite
                  CW_USEDEFAULT,                      // Fensterhöhe
                  NULL,                               // übergeordnetes Fenster
                  NULL,                               // Menü
                  hInstance,                          // Programm-Kopiezähler (Programm-ID)
                  NULL) ;                             // zusätzliche Parameter
     

Wir sind immer noch in der WinMain. Wir haben uns die Window-Struktur in wndclass grob angeschaut, die if-Abfrage UNICODE registriert und jetzt wird es sichtbar. Wir wollen ein window kreieren. Dem anfangs definierten Zeiger hwnd wird die Struktur für unser Window konkretisiert übergeben. Erstaunlich wie hilfsbereit das System sich anbietet. Die Funktion CreateWindow hält alles mundgerecht bereit:
Präfix WS steht für Window Style; statt OVERLAPPEDWINDOW gibt es noch jede Menge andere wie W_CHILD (Kindfenster) , WS_Caption (Fenster mit Titelleiste, WS_SYSMENU (Fenster mit Menüsystem)
CW für CreateWindow generiert in angenehmer Weise einfach schon einmal Daten. Die gute Kommentierung erspart mir weitere Erläuterungen. Was nicht gebraucht wird, bekommt eine NULL (also alles Zeiger) und immer wieder der Hinweis MSDN.
Code:

     ShowWindow (hwnd, iCmdShow) ;
     UpdateWindow (hwnd) ;

Es wird ernst. ShowWindow erhält hwnd (handle window) von der Funktion CreateWindow und teilt dem Betriebssystem mit, zeige das window. Den Inhalt des Windows ist in dem zweiten Aufruf ShowWindow enthalten. ShowWindow gibt die Nachricht WM_PAINT mit den notwendigen Daten.
Code:

while (GetMessage (&msg, NULL, 0, 0))
     {
          TranslateMessage (&msg) ;
          DispatchMessage (&msg) ;
     }
     return msg.wParam ;
}

Nanu, schon der letzte Teil der WinMain. Eine schöne überschaubare while Schleife.
Wirklich, schau mal auf die Bedingung. Solange Nachrichten kommen, tue …. Eigentlich ein Witz, hast Du mit Deiner Maus ein paar Ehrenrunden auf dem Screen gedreht, sind schon ein paar tausend Nachrichten durch diese Schleife gegangen. Die Schleife hat die Bedingung. solange das Programm besteht, solange bin ich auch aktiv. Also eine Endlosschleife, es wurde keine Abbruchbedingung definiert. Wenn keine Nachrichten kommen… (geht bei der Philosophie des Betriebssystem nicht). Aber dafür ist diese Schleife mächtig, sehr mächtig. Alles was das Betriebssystem tut, muss es mittels Nachrichten anschieben. Und jede Nachricht wird für uns lesbar, wenn wir es wollen und wir wissen wie. Es sind also nur noch Kleinigkeiten zu erledigen um zu herrschen. Zum Beispiel, zu wissen wie so eine Nachricht aussieht, wenn ein paar Mausrunden schon zig Nachrichten produzieren. Das klingt sehr nach Massenabfertigung und Schema F. Die Funktion GetMessage hat 4 Parameter. Am Anfang der WinMain wurde MSG msg deklariert. Dahinter verbirgt sich die Struktur MSG:

typedef struct tagMSG // kein Quellcode zu Hello, Windows 98
{
HWND hwnd;
UINT message;
WPARAM wParam;
LPARAM lParam;
DWORD time;
POINT pt;
}

HWND hwnd = handle window Das Betriebssystem benennt hier das für die Nachricht zuständige Fenster als natürliche Zahl codiert.
UINT message; Die Art der Nachricht als Integerzahl definiert. Unbekannte Nachrichten kann es also nicht geben. (Theorie und Praxis) zumindest aus meiner persönlichen Sicht anzuzweifeln.
WPARAM wParam; Je nach message ergänzende Infos.
LPARAM lParam; Auch hier Ergänzungen zur message
Die maximale Anzahl von Nachrichtenkombinationen aus dem Produkt von (message * wParam * lParam) scheint kein Engpass zu sein.
DWORD time; Hält die Zeit fest, von wann die Nachricht ist.
POINT pt; Hier werden die X- und Y-Koordinaten festgehalten.

Eine Message enthält also den Empfänger, Inhalt und die Uhrzeit in einer standartisierten Form. Die while-Schleife liest sämtliche Nachrichten und gibt auch sämtliche Nachrichten an das Betriebssystem weiter. Also im Prinzip eine pefekte Abhöranlage.

Code:

LRESULT CALLBACK WndProc (HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
{
     HDC         hdc ;
     PAINTSTRUCT ps ;
     RECT        rect ;

Die Programmierpraktiker tummeln sich hier. Sie nutzen die Abhöranlage wie eine Speisekarte und suchen sich das aus was sie mögen. Die WndProc kennen wir bereits von der Deklaration ganz am Anfang. Es ist kein Zufall, dass es auch 4 Parameter sind und die sind auch noch inhaltsgleich mit der GetMessage().

HDC hdc = Handle to a device context (Window-Datentyp); ein Zugriff für Grafik
PAINTSTRUCT ps ; eine Datenstruktur
RECT rect ; ein mit XY Koordinaten definiertes Rechteck
Code:

     switch (message)
     {
     case WM_CREATE:
          PlaySound (TEXT ("hellowin.wav"), NULL, SND_FILENAME | SND_ASYNC) ;
          return 0 ;

     case WM_PAINT:
          hdc = BeginPaint (hwnd, &ps) ;
         
          GetClientRect (hwnd, &rect) ;
         
          DrawText (hdc, TEXT ("Hello, Windows 98!"), -1, &rect,
                    DT_SINGLELINE | DT_CENTER | DT_VCENTER) ;

          EndPaint (hwnd, &ps) ;
          return 0 ;
         
     case WM_DESTROY:
          PostQuitMessage (0) ;
          return 0 ;
     }
     return DefWindowProc (hwnd, message, wParam, lParam) ;
}

Wir nähern uns dem Ende. Mit switch filtern wir uns aus dem Nachrichtendienst heraus, was uns interessiert. Die Nachrichten haben das Präfix WM_ = WindowMessage. Kommt eine Nachricht, die uns interessiert, verzweigt das Programm zum Beispiel in case WM_Paint.
Alles was bis zum return an Anweisungen steht, wird durchgeführt und dann geht es weiter. Machst Du hier unsachgemäße Experimente, wirst Du näher an einem Reset sein als Du glaubst.

Der Quellcode ist lauffähig (mit copy paste übertragen).
Code:

      #pragma comment( lib, "WinMM.lib" )    

muss noch unter #include <windows> gesetzt werden.

Ende des Tutorials



Jonathan_Klein schreibt: es ist halt ein Einsteigertut

Er wird schon wissen, warum er es so kommentiert und er hat recht.

Seid kritisch im Übernehmen von Infos und überprüft es selbst. Mir hat es was gebracht, das Tutorial zu schreiben. Bin ich schon soweit, dass ich verstehe, was ich schreibe? Seid Ihr es?
Seid auch selbstkritisch, formuliert es einmal schriftlich, was man anders, besser oder sonstwie machen kann, schreibt Euer eigenes Tutorial.
Infos gibt es im Netz mehr als genug. Selbst als Video in MSDN.

Video How to: Creating Win32 Applications (C++)

Aber nur surfen bringt nichts, tun ist angesagt.

Terep Smile
Nach oben
Benutzer-Profile anzeigen Private Nachricht senden
Beiträge der letzten Zeit anzeigen:   
Neues Thema eröffnen   Neue Antwort erstellen    JLI Spieleprogrammierung Foren-Übersicht -> Tutorials Alle Zeiten sind GMT
Seite 1 von 1

 
Gehe zu:  
Du kannst keine Beiträge in dieses Forum schreiben.
Du kannst auf Beiträge in diesem Forum nicht antworten.
Du kannst deine Beiträge in diesem Forum nicht bearbeiten.
Du kannst deine Beiträge in diesem Forum nicht löschen.
Du kannst an Umfragen in diesem Forum nicht mitmachen.


Powered by phpBB © 2001, 2005 phpBB Group
Deutsche Übersetzung von phpBB.de

Impressum