Der erste Dialog


Fangen wir nun an mit unserem echten ersten Dialog.

Wenn wir im PSDK unter DIALOG nachschlagen, sehen wir, dass als optionale (aber dennoch relevante) Statements CAPTION, CLASS, EXSTYLE, FONT, LANGUAGE, MENU und STYLE verfügbar sind. Auf die drei etwas exotischeren werde ich später genauer eingehen. Ein einfacher Dialog sähe also folgendermaßen aus:

100 DIALOG 0, 0, 200, 100
STYLE WS_VISIBLE | WS_CAPTION | WS_SYSMENU | WS_MAXIMIZEBOX |
  WS_MINIMIZEBOX | DS_NOFAILCREATE | DS_CENTER
CAPTION "Ein einfacher Dialog"
FONT 8, "MS Sans Serif"
{
  CTEXT "Ein Text als Beispiel", 101, 1, 3, 197, 11, WS_BORDER
  PUSHBUTTON "Klick mich", 102, 74, 50, 50, 16
}

Lädt man diesen Dialog, hat man ein normales Fenster mit einem zentrierten, umrandeten Text und einem Button darauf. An das Fenster werden natürlich die Messages der Children geschickt, daher kann man in der "DlgProc" ohne Weiteres "WM_COMMAND" abfangen und auf die BN_CLICKED-Notification des Buttons reagieren (die ID ist 102). Hier unterscheiden sich die selbst gestrickten Dialoge in keiner Weise von den Resultaten eines Dialogeditors.
Wir sehen auch, dass die Styles des Dialoges (genauso wie alle anderen verknüpfbaren Ausdrücke auch) mit einem bitweisen ODER verknüpft werden (allerdings in der C-Schreibweise als Pipe |) zu erhalten mit AltGr + <.
Alle *TEXT-Controls sind mit normalen STATICs vergleichbar, die aus dem Label-Tutorial bekannt sind. Das Sternchen steht hier für drei Buchstaben: L (linksbündig), R (rechtsbündig) und C (zentriert).


Exoten

Die drei Statements eines Dialoges, die nicht besonders häufig verwendet werden und auch nicht immer Verwendung finden, sind CLASS, LANGUAGE und MENU.

Das CLASS-Statement ermöglicht es, dem Dialog eine bestimmte Fensterklasse zuzuweisen. Diese muss natürlich im Programm, das die Ressource lädt, vorher definiert und mit RegisterClass im System registriert werden. Der Parameter des Statements ist ein String, der in doppelten Anführungszeichen steht:

100 DIALOG 0, 0, 200, 150
CLASS "TestClass"

Definiert wird also ein Dialog, dessen Klassenname "TestClass" lautet. Die Zuweisung der Fensterklasse muss jetzt wie folgt aussehen:

wc: TWndClassEx = (
  lpszClassName   : 'TestClass';
  cbWndExtra      : DLGWINDOWEXTRA;
  // weitere Klasseneigenschaften
  // [...]
);

Was auffällt ist, dass cbWndExtra der Wert DLGWINDOWEXTRA zugewiesen wird. Das hat den Grund, dass ein Dialog zusätzliche Informationen speichert und somit mehr Speicher benötigt. Mit

cbWndExtra := DLGWINDOWEXTRA

reservieren wir eben diesen zusätzlichen Speicher, und zwar vollkommen automatisch. Würden wir den Wert auf 0 lassen, würde es zu Abstürzen kommen. Macht Ihr Programm also plötzlich Sachen, die es nicht machen sollte, überprüfen Sie zuerst, ob die Klasse korrekt definiert ist.
Diese Art von Subclassing ermöglicht es auch, auf einfachste Art und Weise eine echte "WndProc" für einen Dialog zu erzeugen (und so auch "WM_CREATE" abzufangen).

Das LANGUAGE-Statement dient dazu, Ressourcen für mehrere Sprachen anzubieten. Die Ressource hat den gleichen Identifier, aber eine unterschiedliche Sprachsignatur. Eine solche Signatur setzt sich aus einem primären und einem sekundären Language-Identifier zusammen, z.B.

100 DIALOG 0, 0, 200, 100
STYLE WS_VISIBLE | WS_CAPTION | WS_SYSMENU | DS_NOFAILCREATE
CAPTION "Ein einfacher Dialog"
FONT 8, "MS Sans Serif"
LANGUAGE LANG_GERMAN, SUBLANG_GERMAN_SWISS
{
}

für einen deutschen Dialog mit schweizerischen Sondermerkmalen. Eine vollständige Liste aller Identifiers findet sich im SDK.

Das MENU-Statement dient dazu, einem Dialog ein Menü zuzuweisen. Das Laden und Zuweisen zur Laufzeit entfällt also. Als Parameter nimmt das MENU-Statement den Identifier (entweder als Zahl oder als String ohne Anführungszeichen) des Menüs an:

100 MENU // oder "hello MENU" als String-Identifier
{
  MENUITEM "&Some menu item", 101
}

200 DIALOG 0, 0, 200, 100
STYLE WS_VISIBLE | WS_CAPTION | WS_SYSMENU | DS_NOFAILCREATE
CAPTION "Ein einfacher Dialog"
FONT 8, "MS Sans Serif"
MENU 100 // oder "MENU hello" als String-Identifer
{
}

Menü-Ressourcen werde ich noch eingehender beschreiben.


Das war eine kleine Einführung in eine einfache Dialog-Ressource. Dialog-Ressourcen können genauso komplex werden wie "normale" Fenster. Allerdings gibt es in der Komplexität der Dialog-Ressourcen in der Win9x-Reihe bis einschließlich Windows ME die Einschränkung von 255 Controls pro Dialog. Braucht man mehr, empfiehlt das SDK die restlichen Controls in der "WM_INITDIALOG"-Message zu erzeugen.