Man kommt mit der ZU-FUSS-PROGRAMMIERUNG der WIndows
Api einigermaßen in die Füße.
ZU FUSS heißt, alles per Texteditor eingeben. Also die ganz harte Tour.
Je komplexer die Anwendung allerdings wird, umso zahlreicher und undurchschaubarer werden die Fußangeln.
Mal ein Beispiel:
Wir beginnen mit einem Fenster, und als erstes müssen wir uns um eine MenüStruktur bekümmern, damit der Anwender mit dem Fenster überhaupt irgendwas anfangen kann.
Dazu legen wir 20 Buttons an. Jeder der Buttons ist eine Menü-Auswahl.
Die Buttons legen wir an als eigenständige Fenster mit CreateWindow der Klasse "button"
b[i] = CreateWindowEx (
0, /* Extended possibilites for variation */
"button", /* Classname */
Das machen wir nicht so, daß wir sagen: button1, button2, button3 und so weiter, sondern als Array, damit wir die Fenster anschließend in einer Schleife ansprechen können:
HWND b[20]; // Deklaration für 20 Handler für 20 Fenster b[0],b[1] usf.
Da die Namen der buttons auf dem Bildschirm als Menü-Optionen erscheinen, müssen wir sie zuvor definieren, z. B. so:
void init()
{
sprintf(btext[1],"Kontur zeichnen");
sprintf(btext[2],"Kkontur entfernen");
sprintf(btext[3],"Fräskontur 1 einblenden");
sprintf(btext[4],"Fräskontur 2 einblenden");
sprintf(btext[5],"Fräskontur bearbeiten");
sprintf(btext[6],"Hilfsradius ändern");
sprintf(btext[7],"Fräskontur speichern");
sprintf(btext[8],"Abbrechen ohne zu speichern");
}
... für die ersten 8 Buttons.
Nun deklarieren wir die mit CreateWindow und initialisieren mit der bezeichneten Zeile :
for (i=1;i<MAXBUTTON;i++)
{
b[i] = CreateWindowEx (
0, /* Extended possibilites for variation */
"button", /* Classname */
btext[i], /* Title Text <----------------------------------- da ist die Button-Aufschrift wie oben definiert */
WS_CHILD|WS_THICKFRAME, /* default window */
0, /* Windows decides the position */
(i-1)*by+nfy, /* where the window ends up on the screen */
bx, /* The programs width <-------------------------------------- die aus der Schleife errechneten Koordinaten */
by, /* and height in pixels */
hwnd, /* The window is a child-window to desktop */
(HMENU)i, /* <----------------------------------------------------- Nr. des Buttons ist i, also fortlaufend 1..n */
hThisInstance, /* Program Instance handler */
NULL /* No Window Creation data */
);
}
Die Platzierung der Buttons ergibt sich in der Schleife wie oben zu sehen abhängig von ihrer Größe, nämlich untereinandergestapelt wäre das:
Button_hoehe=30;
Macht für die Vertikale Position by=Button_hoehe*i-30, ergibt dann 0,30,60,90 usf.
Das Ergebnis ist dann ein Fenster mit den definierten Buttons, die man nach Bedarf angeordnet und beschriftet hat.
Nun gehen wir in die WndProc, also die Ereignisschleife, und fragen ab, welcher Button gedrückt wurde. Das liefert uns Windows gratis, mit der Message WM_COMMAND. WM_COMMAND liefert den Wert für (HMENU), den wir mit i in der Schleife fortlaufend numeriert haben.
Also erhalten wir dann für 1 dasjenige, was unter text[1] auf dem Button steht.
Da wir nicht jedesmal nachschlagen wollen, was wir mit 1 , 5, oder 8 durchnummeriert haben, machen wir uns eine ENUM-Liste für die Optionen, Z. B:
enum auswahl {GK_ZEICHNEN=1,GK_ENTFERNEN,FK1_ZEICHNEN,FK2_ZEICHNEN,FK_BEARBEITEN,RADIUS_AENDE
RN,
FK_SPEICHERN,ABBRECHEN};
Die beginnt mit 1 für GK_ZEICHNEN, und endet mit ABBRECHEN, wir können nun statt 1,2,5,... diese Bezeichner verwenden, nämlich:
case WM_COMMAND: // Menuvorgaben der Buttons durchprüfen
switch(LOWORD(wParam)) // == liefert den angeklickten Button
{
case GK_ZEICHNEN: // die Menüoption Zeichnen
ausgabe_Grundkoerper(ZEICHNEN);
SetFocus(hwnd); // Focus zurückholen
return(0);
case GK_ENTFERNEN:
ausgabe_Grundkoerper(LOESCHEN); // löschen
SetFocus(hwnd);
return 0;
case FK1_ZEICHNEN:
modus=GERADE;
ausgabe_fraeskontur(modus,LOESCHEN); // erst löschen
modus=UNGERADE;
ausgabe_fraeskontur(modus,ZEICHNEN); // dann ausgeben
SetFocus(hwnd);
return 0;
... und so weiter, wie das Menü eben aussehen soll,
Der Default ist dann sehr wichtig:
default:
return DefWindowProc (hwnd, message, wParam, lParam);
Das heißt, was hier nicht abgefangen wird, wird an die WndProc zurückgegeben, damit es nicht im Nirwana versinkt.
Bei dieser DIRECT SIMPLE Programmierung tut sich ein Problem auf, was man im Programmauszug schon erahnen kann:
Wir haben plötzlich keine Tastaturkommandos mehr. Solche Anweisungen, wie sie auch in der SWITCH-Anweisung der Wnd Proc stehen, wie:
case WM_KEYDOWN: // TASTE GEDRÜCKT?????
switch (LOWORD(wParam))
{
case VK_LEFT: // PFEILTASTE LINKS ...
case VK_RIGHT:
case VK_UP:
case VK_DOWN: // PFEILTASTE UNTEN ...
aendere_fraeskontur(modus,EDIT,LOWORD(wParam));
SetFocus(hwnd);
return 0;
default: /* for messages that we don't deal with */
return DefWindowProc (hwnd, message, wParam, lParam);
(Man sieht, auch hier in dieser Unter-Verzweigung von switch-case-switch ist der Default wieder sorgfältig reingesetzt, macht man das nicht, wird das Programm auf die Dauer oder auch schon sofort sehr merkwürdig reagieren).
laufen dann ins Leere.
Die Tastatur ist tot.Das liegt daran, daß bei Verwendung mehrere Fenster zwar die Maus alle Fenster erreichen kann, aber die Tastatur natürlich nicht wissen kann, was auf dem Bildschirm geschieht. Daher erhält irgendein Fenster, nämlich das aktuelle, die Ereignisschleife für WM_KEYDOWN, wenn aber das Fenster die Klasse
"button"
hat, gibt dieses die Info nicht weiter, sondern verschluckt die Tastaturkommandos, bis auf das Leerzeichen.
Das ganze nennt sich "Focus".
Um wieder Herr über die Tastatur zu werden, sieht man oben, wie ich das gemacht habe:
case FK1_ZEICHNEN:
modus=GERADE;
ausgabe_fraeskontur(modus,LOESCHEN); // erst löschen
modus=UNGERADE;
ausgabe_fraeskontur(modus,ZEICHNEN); // dann ausgeben
SetFocus(hwnd); <===================== setzt den Focus, also die Tastaturabfrage, wieder auf das Hauptfenster zurück
// ist aber nicht sauber, weil diese Anweisung ohne weitere Prüfung auch in Fremdprogramme reinpfuscht, die dann dasselbe
// Problem haben wie wir hier mit den Buttons. Soll nur als Beispiel dienen, wie man das abfangen kann.
Die ganze Chose sieht dann so aus wie in der Abbildung zu sehen.
Und sie funktioniert!
Denn nun können wir zwischen den Switch-Case Verzweigern die gewünschten Funktionen reinsetzen, alles was wir wollen, rechnen, Texteditieren, Grafikfunktionen etc. , wie im Programmschnipsel zu sehen.
Damit hätten wir den Rahmen für ein Windows-Programm, welches mit Menü-Optionen arbeitet, wobei alles Zu Fuß programmiert ist.
Die Sache mit dem Focus findet man bei Petzold irgendwo jenseits von S. 500- S1000, man muß gezielt danach suchen, sonst findet man sie niemals.
Und an dieser Stelle hatte ich den Entschluß gefaßt: Es muß noch was anderes geben als zu Fuß. Und das gibt es auch.
Das Stichwort h eißt:
R A D
Rapid
Application
Developement
= QUICK AND DIRTY
Das Werkzeug dazu ist keinesfalls der MSVC++, sondern ein wirklich geniales Werkzeug, um in Minutenschnelle Windows-Applikationen zu erstellen, der
Borland C++ Builder.
Ich hab ihn mir gebraucht gekauft in der Version 5.0, so für 250 Euro ist der dann zu haben, neueste Version ist sonstwas, aber der 5.0 reicht für meine Zwecke vollkommen aus.
Zu dem, wie man damit arbeitet, gleich noch ein kleiner Anschlußbeitrag und dann die Tage gelegentlich mehr davon.
Das ganze ist als TIPP zu verstehen für Leute, die man schnell eine GRAFISCHE Windows-Oberfläche brauchen, einigermaßen fit sind in C/C++,
sich aber in die Niederungen der Windows-Programmierung einzuarbeiten keinen Bock haben.
Für solche Leute (zu denen ich auch gehöre) ist der Borland C++BUilder eine (die) optimale Lösung.
Gruß Sharky
Der Beitrag wurde von sharky bearbeitet: 17.03.2011, 19:11 Uhr
Angehängte Datei(en)
sharky001.jpg ( 100.45KB )
Anzahl der Downloads: 99