In nahezu jeder Windows-Anwendung begegnet man Schaltflächen, Kontrollkästchen, Textfeldern und Dropdown-Listenfeldern. Man bezeichnet diese Komponenten als Steuerelemente, und viele dieser Steuerelemente sind in das Betriebssystem selbst integriert. In Visual C++ lassen sich diese allgemeinen Steuerelemente einsetzen, indem man sie einfach per Drag & Drop in einem Dialogfeld plaziert. Am heutigen Tag lernen Sie ...
Zum Betriebssystem Windows gehören verschiedene Standardsteuerelemente wie Schieberegler, Strukturansicht, Listenelement oder Statusanzeige. In der heutigen Lektion geht es zunächst einmal um ein halbes Dutzend Steuerelemente, die sich in fast jeder Windows-Anwendung finden:
Diese und andere Steuerelemente stehen zur sofortigen Nutzung in Visual C++-Anwendungen bereit. Sie sind in der Steuerelementpalette im Dialog-Editor des Visual Studios untergebracht (siehe Abbildung 2.1).
Abbildung 2.1:
Die in der Steuerelementpalette verfügbaren Standardsteuerelemente
Das Steuerelement Text verwendet man, um Text für den Benutzer anzuzeigen. Der Benutzer kann diesen Text weder ändern noch in anderer Form mit dem Steuerelement interagieren. Das Steuerelement ist als Nur-Lesen-Element vorgesehen. Allerdings kann man im Code der laufenden Anwendung den durch das Steuerelement angezeigten Text ohne weiteres ändern.
In einem Eingabefeld kann der Benutzer Text eingeben oder ändern. Das Steuerelement gehört zu den hauptsächlichen Werkzeugen, die dem Benutzer die Möglichkeit bieten, einer Anwendung bestimmte erforderliche Informationen bereitzustellen. Es ist in der Lage, beliebigen Text aufzunehmen, der sich auslesen und nach Bedarf weiterverarbeiten läßt. Das Eingabefeld akzeptiert ausschließlich reinen Text, Formatierungen stehen dem Benutzer nicht zur Verfügung.
Über eine Schaltfläche löst der Benutzer eine bestimmte Aktion aus. Die Beschriftung - der Titel - der Schaltfläche sollte einen Hinweis auf die Aktion liefern, die beim Klikken auf die Schaltfläche stattfindet. Eine Schaltfläche kann auch Bilder enthalten, die man - allein oder zusammen mit einer Textbeschreibung - benutzt, um den Zweck der Schaltfläche zu vermitteln.
Als Kontrollkästchen bezeichnet man die kleinen quadratischen Elemente, die der Benutzer durch Anklicken ein- (X) bzw. ausschaltet und damit einen bestimmten Wert setzt bzw. zurücksetzt. Grundsätzlich handelt es sich um Umschalter, gelegentlich mit einem dritten Zwischenzustand. Normalerweise verwendet man Kontrollkästchen, um diskrete Variablen vom Typ An/Aus zu steuern.
Ein Optionsfeld wird als Kreis dargestellt. Klickt der Benutzer ein Optionsfeld an, erscheint ein Punkt im Kreis. Das Optionsfeld ähnelt dem Kontrollkästchen, wird aber in einer Gruppe verwendet, in der nur ein Optionsfeld eingeschaltet sein kann. Normalerweise setzt man Optionsfelder in Gruppen mit mindestens drei Optionen ein, wobei die Optionsfelder von einem Gruppenfeld umgeben sind. Das Gruppenfeld gewährleistet die Unabhängigkeit der einzelnen Optionsfeldgruppen, wobei gleichzeitig in jeder Gruppe jeweils ein Optionsfeld eingeschaltet sein kann.
Ein Kombinationsfeld (oder Dropdown-Listenfeld) besteht aus einem Eingabefeld, dem eine Liste mit verfügbaren Werten zugeordnet ist. Mit einem Kombinationsfeld kann man eine Liste von Auswahlen bereitstellen, wobei der Benutzer einen Wert aus der Liste auswählen kann. Manchmal hat der Benutzer die Möglichkeit, selbst einen Wert einzutippen, wenn die Liste keinen passenden Wert enthält.
Die heute zu erstellende Anwendung soll eine Reihe von Steuerelementen in einem Dialogfeld enthalten, wie es aus Abbildung 2.2 hervorgeht. Diese Steuerelemente haben verschiedene Aufgaben. Am oberen Rand des Fensters befindet sich ein Eingabefeld, in das der Benutzer eine Nachricht eintippen kann, die in einem Meldungsfeld erscheint, wenn er auf die Schaltfläche neben dem Feld klickt. Unterhalb dieses Eingabefelds sind zwei Schaltflächen angeordnet, die entweder das Eingabefeld mit einer Standardmeldung füllen oder einen vorhandenen Eintrag löschen. Unter diesen Schaltflächen befindet sich ein Kombinationsfeld mit einer Liste von Windows-Standardanwendungen. Wählt der Benutzer eines dieser Programme aus und klickt auf die Schaltfläche neben der Dropdown-Liste, startet das ausgewählte Programm. Darunter sind zwei Gruppen von Kontrollkästchen angeordnet. Diese wirken auf die Steuerelemente im oberen Teil des Dialogfelds: die Steuerelemente für die Anzeige einer Benutzermeldung und die Steuerelemente für die Ausführung eines anderen Programms. Die Kontrollkästchen auf der linken Seite aktivieren und deaktivieren die einzelnen Gruppen von Steuerelementen. Mit den rechten Kontrollkästchen lassen sich die Gruppen der Steuerelemente anzeigen und ausblenden. Im unteren Teil des Dialogfelds befindet sich eine Schaltfläche, die das Schließen der Anwendung bewirkt.
Abbildung 2.2:
Die heutige Anwendung verwendet mehrere Standardsteuerelemente.
Mit den gestern erworbenen Kenntnissen können Sie jetzt ein neues Anwendungsgerüst erstellen und das Layout des Anwendungsdialogfelds entwerfen. Führen Sie dazu die folgenden Schritte aus:
1. Erstellen Sie mit dem Anwendungs-Assistenten einen neuen Projekt-Arbeitsbereich,
und nennen Sie das Projekt Tag2
.
2. Verwenden Sie im Anwendungs-Assistenten die gleichen Einstellungen wie gestern.
Legen Sie den Titel des Dialogfelds mit Visual C++-Steuerelemente
fest.
3. Nachdem Sie das Anwendungsgerüst erstellt haben, gestalten Sie das Hauptdialogfeld wie in der weiter oben gezeigten Abbildung 2.2.
4. Konfigurieren Sie die Eigenschaften der Steuerelemente gemäß Tabelle 2.1.
Beispiel einer Visual C++-Anwendung mit einer Reihe von Steuerelementen. | ||
5. Nachdem Sie alle genannten Steuerelemente im Dialogfeld plaziert und deren Eigenschaften konfiguriert haben, öffnen Sie das Eigenschaftsdialogfeld für das Kombinationsfeld erneut. Auf der Registerkarte Daten tragen Sie die folgenden Werte ein, wobei Sie zum zweiten bzw. dritten Eintrag mit der Tastenkombination (Strg)+(¢) weiterschalten (siehe Abbildung 2.3).
Abbildung 2.3:
Die Einträge in der Dropdown-Liste des Kombinationsfeldes legen Sie über das Eigenschaftsdialogfeld fest.
Nach der Anordnung der Steuerelemente im Fenster müssen Sie noch sicherstellen, daß der Benutzer bei der Navigation mit Hilfe der (ÿ__)-Taste die Steuerelemente in der von Ihnen gewünschten Reihenfolge anspricht. Die Tabulator-Reihenfolge legen Sie mit den nachstehenden Schritten fest:
1. Markieren Sie im Bearbeitungsbereich von Visual Studio entweder das Dialogfeld oder eines der Steuerelemente im Fenster.
2. Wählen Sie Layout / Tabulator-Reihenfolge. Daraufhin erscheinen im Fenster neben den Steuerelementen Nummern. Diese kennzeichnen die Reihenfolge, in der die Navigation durch das Dialogfeld verläuft (siehe Abbildung 2.4).
Abbildung 2.4:
Das Einschalten der Tabulator-Reihenfolge zeigt die Reihenfolge der Navigation durch das Dialogfeld an.
3. Klicken Sie mit der Maus die Nummernfelder in der Reihenfolge an, in der der Benutzer durch das Dialogfeld navigieren soll. Die Steuerelemente numerieren sich automatisch neu, wenn Sie sie nacheinander auswählen.
4. Nachdem Sie die Tabulator-Reihenfolge festgelegt haben, wählen Sie Layout / Tabulator-Reihenfolge erneut, um zum Dialog-Editor zurückzukehren.
Eine Zugriffstaste ist durch das unterstrichene Zeichen - den sogenannten mnemonischen
Code - in der Beschriftung (dem Titel) einer Schaltfläche, eines Kontrollkästchens,
eines Menüs oder eines anderen Steuerelements gekennzeichnet. Der Benutzer
kann den unterstrichenen Buchstaben in Kombination mit der (Alt)-Taste
drücken, um direkt zu diesem Steuerelement zu gelangen oder das angeklickte Ereignis
auf dem Steuerelement auszulösen. Um eine Zugriffstaste festzulegen, schreibt
man bei Eingabe des Titels ein kaufmännisches Und-Zeichen (&
) unmittelbar vor das
betreffende Zeichen. Achten Sie darauf, daß Sie für mehrere Zugriffstasten nicht dieselben
Zeichen im selben Fenster oder derselben Menügruppe vorsehen, da es den
Benutzer nur verwirrt, wenn er eine Zugriffstaste drückt und nicht die erwartete Reaktion
eintritt.
Bevor Sie sich mit dem Code der Anwendung beschäftigen, sollten Sie abschließend die Zugriffstasten auf Konflikte prüfen. Führen Sie dazu die folgenden Schritte aus:
1. Markieren Sie im Dialog-Editor das Dialogfeld oder eines der Steuerelemente. Klicken Sie mit der rechten Maustaste, und wählen Sie Zugriffstasten prüfen.
2. Wenn keine Konflikte bei Ihren mnemonischen Codes aufgetreten sind, zeigt Visual C++ ein entsprechendes Meldungsfeld an (siehe Abbildung 2.5).
Abbildung 2.5:
Eine Prüfung der Zugriffstasten zeigt, ob Konflikte vorliegen.
3. Falls Konflikte vorhanden sind, kennzeichnet das Dialogfeld den betreffenden Buchstaben und gibt Ihnen die Möglichkeit, die Steuerelemente mit den gegensätzlichen Einträgen auswählen zu lassen (siehe Abbildung 2.6).
Abbildung 2.6:
Doppelte mnemonische Codes lassen sich automatisch auswählen.
Wenn Sie bereits mit Visual Basic oder PowerBuilder programmiert haben, ahnen Sie sicherlich schon, daß es nun an der Zeit ist, etwas Code zu verfassen. Mit Visual C++ läuft dieser Prozeß allerdings nicht genauso ab. Bevor Sie mit der Codierung beginnen können, müssen Sie allen Steuerelementen, denen ein Wert zugewiesen ist, Variablen zuordnen - allen, außer dem statischem Text und den Schaltflächen. Auf die Variablen greifen Sie zurück, wenn Sie den Code für die Anwendung schreiben. Die Werte, die der Benutzer in die Bildschirmsteuerelemente eingibt, übernimmt das Programm zur Weiterverarbeitung in diese Variablen. Analog dazu werden alle Werte, die der Code Ihrer Anwendung in diese Variablen stellt, in den Steuerelementen des Fensters aktualisiert, damit sie der Benutzer sieht.
Wie deklariert man nun diese Variablen und verbindet sie mit den Steuerelementen, die man im Fenster plaziert hat? Führen Sie die folgenden Schritte aus:
1. Öffnen Sie den Klassen-Assistenten, wie Sie es gestern gelernt haben.
2. Aktivieren Sie die Registerkarte Member-Variablen (siehe Abbildung 2.7).
Abbildung 2.7:
Über die Registerkarte Member-Variablen des Klassen-Assistenten fügen Sie den Steuerelementen Variablen hinzu.
3. Markieren Sie die ID eines der Steuerelemente, denen Sie eine Variable zuordnen
möchten, beispielsweise IDC_MSG
.
4. Klicken Sie auf Variable hinzufügen.
5. Im Dialogfeld Member-Variable hinzufügen geben Sie den Variablennamen ein und legen die Kategorie sowie den Typ der Variablen fest wie es Abbildung 2.8 zeigt. Klicken Sie auf OK.
Abbildung 2.8:
Einem Steuerelement eine Variable zuordnen
6. Wiederholen Sie die Schritte 3 bis 5 für alle anderen Steuerelemente, für die Sie Variablen zuordnen müssen. In der heutigen Anwendung betrifft das die Variablen gemäß Tabelle 2.2.
7. Nachdem Sie alle erforderlichen Variablen hinzugefügt haben, klicken Sie auf OK, um den Klassen-Assistenten zu schließen.
Bevor Sie den Code für alle Steuerelemente in Ihrem Anwendungsfenster schreiben, ist zunächst etwas Code erforderlich, um die Variablen zu initialisieren, d.h. Startwerte für die meisten Variablen festzulegen. Führen Sie dazu folgende Schritte aus:
1. Starten Sie den Klassen-Assistenten, gehen Sie auf die Registerkarte Nachrichtenzuordnungstabellen
, und markieren Sie die Funktion OnInitDialog
in der
Liste der Member-Funktionen. Die Funktion suchen Sie im Listenfeld Member-
Funktionen auf, oder Sie wählen das Objekt CTag2Dlg
in der Liste Objekt-IDs
aus und markieren dann WM_INITDIALOG
im Listenfeld Nachrichten, wie es Abbildung
2.9 zeigt.
Abbildung 2.9:
Vorhandene Funktionen lassen sich mit dem Klassen-Assistenten auffinden.
2. Klicken Sie auf die Schaltfläche Code bearbeiten. Daraufhin gelangen Sie in den
Quellcode für die Funktion OnInitDialog
.
3. Gehen Sie zur Markierung ZU ERLEDIGEN
, die die Stelle kennzeichnet, wo Sie mit
der Codeeingabe beginnen. Geben Sie hier den Code aus Listing 2.1 ein.
Listing 2.1: TAG2DLG.CPP - In die Funktion OnInitDialog geben Sie den Initialisierungscode ein.
1: BOOL CTag2Dlg::OnInitDialog()
2: {
3: CDialog::OnInitDialog();
4:
5: .
6: .
7: .
8:
9: // ZU ERLEDIGEN: Hier zusätzliche Initialisierung einfügen
10:
11: ///////////////////////
12: // EIGENER CODE, ANFANG
13: ///////////////////////
14:
15: // Standardtext in Eingabefeld eintragen
16: m_strMessage = "Nachricht hier eingeben";
17:
18: // Alle Kontrollkästchen einschalten
19: m_bShowMsg = TRUE;
20: m_bShowPgm = TRUE;
21: m_bEnableMsg = TRUE;
22: m_bEnablePgm = TRUE;
23:
24: // Dialogfeld mit den Werten aktualisieren
25: UpdateData(FALSE);
26:
27: ///////////////////////
28: // EIGENER CODE, ENDE
29: ///////////////////////
30:
31: return TRUE; // Geben Sie TRUE zurück, außer ein Steuerelement soll den
ÂFokus erhalten
32: }
Der Initialisierungscode ist nicht weiter kompliziert. Das Programm stellt als erstes in das Eingabefeld eine anfängliche Nachricht, die Sie dem Benutzer anzeigen wollen, und setzt dann alle Kontrollkästchen in den eingeschalteten Zustand. Die letzte Zeile des hinzugefügten Codes verdient etwas mehr Beachtung.
Die Funktion UpdateData
bildet den Schlüssel für die Arbeit mit Steuerelementvariablen
in Visual C++. Die Funktion übernimmt die Daten aus den Variablen und aktualisiert
mit den Werten die Steuerelemente auf dem Bildschirm. Umgekehrt übernimmt
die Funktion die Daten aus den Steuerelementen und füllt die zugeordneten Variablen
mit allen vom Benutzer geänderten Werten. Die Richtung der Datenübertragung steuert
man mit dem an die Funktion UpdateData
übergebenen Argument. Ist das Argument
auf FALSE
gesetzt, werden die Werte in den Variablen an die Steuerelemente im
Fenster übertragen. Übergibt man TRUE
als Argument, erhalten die Variablen die aktuellen
Werte der Steuerelemente im Fenster. Welcher Wert an die Funktion zu übergeben
ist, hängt also davon ab, in welcher Richtung die Aktualisierung stattfinden soll.
Nachdem Sie eine oder mehrere Variablen in Ihrem Code aktualisiert haben, müssen
Sie UpdateData
aufrufen und FALSE
als Argument übergeben. Wenn Sie die Variablen
lesen müssen, um deren aktuellen Wert zu erhalten, ist UpdateData
mit dem Argument
TRUE
aufzurufen, bevor Sie irgendeinen Wert aus den Variablen verarbeiten. Ein
Gefühl für diese Vorgehensweise werden Sie entwickeln, wenn Sie mehr Code in Ihre
Anwendung aufnehmen.
Als erstes sollten Sie sich darum kümmern, daß der Benutzer die Anwendung schließen kann. Da Sie die Schaltflächen OK und Abbrechen gelöscht und eine neue Schaltfläche für das Schließen des Anwendungsfensters hinzugefügt haben, müssen Sie Code in die Funktion aufnehmen, die von der Schaltfläche Beenden ausgelöst wird, um das Fenster zu schließen. Führen Sie dazu die folgenden Schritte aus:
1. Fügen Sie mit dem Klassen-Assistenten eine Funktion zur Objekt-ID IDC_EXIT
für
die Nachricht BN_CLICKED
hinzu, wie Sie es gestern kennengelernt haben.
2. Klicken Sie auf die Schaltfläche Code bearbeiten, um in den Quelltext der neu hinzugefügten Funktion zu gelangen.
3. Geben Sie den Code von Listing 2.2 ein.
Listing 2.2: TAG2DLG.CPP - Die Funktion OnExit
1: void CTag2Dlg::OnExit()
2: {
3: // TODO: Code für die Behandlungsroutine der Steuerelement-
ÂBenachrichtigung hier einfügen
4:
5: ///////////////////////
6: // EIGENER CODE, ANFANG
7: ///////////////////////
8:
9: // Programm beenden
10: OnOK();
11:
12: ///////////////////////
13: // EIGENER CODE, ENDE
14: ///////////////////////
15: }
Ein einziger Funktionsaufruf in der Funktion OnExit
schließt das Fenster und beendet
die Anwendung. Woher kommt diese OnOK
-Funktion, und warum mußten Sie sie nicht
in der gestrigen Anwendung aufrufen? Zwei Funktionen, OnOK
und OnCancel
, sind in
der Basisklasse CDialog
definiert, von der Ihre Klasse CTag2Dlg
abgeleitet ist. In der
Klasse CDialog
hat die Nachrichtenzuordnungstabelle bereits die Objekt-IDs der
Schaltflächen OK und Abbrechen mit den Funktionen OnOK
bzw. OnCancel
verbunden,
so daß Schaltflächen mit diesen IDs automatisch die entsprechenden Funktionen aufrufen.
Wenn Sie die Objekt-ID der Schaltfläche Beenden mit IDOK
festgelegt hätten,
müßten Sie der Schaltfläche keinerlei Code zuordnen, solange Sie nicht die grundlegende
Funktionalität von OnOK
überschreiben möchten.
Es sollte ein Leichtes sein, die vom Benutzer in das Eingabefeld eingegebene Nachricht
anzuzeigen, da dieser Vorgang den gestern beschriebenen Abläufen ähnelt. Sie
können der Schaltfläche Nachricht zeigen eine Funktion zuordnen und die Funktion
MessageBox
aufrufen, wie es aus Listing 2.3 hervorgeht.
Listing 2.3: TAG2DLG.CPP - Die Funktion OnShwmsg zeigt die Benutzernachricht an.
1: void CTag2Dlg::OnShwmsg()
2: {
3: // TODO: Code für die Behandlungsroutine der Steuerelement-
ÂBenachrichtigung hier einfügen
4:
5: ///////////////////////
6: // EIGENER CODE, ANFANG
7: ///////////////////////
8:
9: // Nachricht anzeigen
10: MessageBox(m_strMessage);
11:
12: ///////////////////////
13: // EIGENER CODE, ENDE
14: ///////////////////////
15: }
Wenn Sie die Anwendung in dieser Phase kompilieren und ausführen, tritt ein Problem
mit diesem Code zutage. Es erscheint der String, mit dem Sie die Variable
m_strMessage
in der Funktion OnInitDialog
initialisiert haben, und nicht die Nachricht,
die der Benutzer in das Eingabefeld eingibt.
Das ist darauf zurückzuführen, daß Sie die Variable noch nicht mit dem Inhalt des
Steuerelements im Fenster aktualisiert haben. Es ist UpdateData
mit auf TRUE
gesetztem
Argument aufzurufen, um die Werte der Steuerelemente zu lesen und die Variablen
damit zu initialisieren, bevor Sie die Funktion MessageBox
aufrufen. Ändern Sie
die Funktion OnShwmsg
gemäß Listing 2.4 ab.
Listing 2.4: TAG2DLG.CPP - Aktualisierte Version der Funktion OnShwmsg
1: void CTag2Dlg::OnShowmsg()
2: {
3: // TODO: Code für die Behandlungsroutine der Steuerelement-
ÂBenachrichtigung hier einfügen
4:
5: ///////////////////////
6: // EIGENER CODE, ANFANG
7: ///////////////////////
8:
9: // Nachrichtenvariable mit Benutzereingabe aktualisieren
10: UpdateData(TRUE);
11:
12: // Nachricht anzeigen
13: MessageBox(m_strMessage);
14:
15: ///////////////////////
16: // EIGENER CODE, ENDE
17: ///////////////////////
18: }
Wenn Sie Ihre Anwendung jetzt kompilieren und ausführen, sollte die in das Eingabefeld eingegebene Meldung angezeigt werden, wie es Abbildung 2.10 verdeutlicht.
Abbildung 2.10:
Die in das Eingabefeld eingetippte Nachricht wird dem Benutzer angezeigt.
Falls der Benutzer ein leeres Eingabefeld vorfinden möchte, bevor er eine Nachricht
eintippt, können Sie der Schaltfläche Nachricht löschen eine Funktion zuordnen, um
den Inhalt des Eingabefeldes zu leeren. Die Funktion fügen Sie in der gewohnten Weise
über den Klassen-Assistenten hinzu. Die Funktionalität realisieren Sie ganz einfach,
indem Sie die Variable m_strMessage
auf einen leeren String setzen und dann die
Steuerelemente im Fenster aktualisieren, um diesen Wert wiederzugeben. Der entsprechende
Code ist in Listing 2.5 zu sehen.
Listing 2.5: TAG2DLG.CPP - Die Funktion OnClrmsg
1: void CTag2Dlg::OnClrmsg()
2: {
3: // TODO: Code für die Behandlungsroutine der Steuerelement-
ÂBenachrichtigung hier einfügen
4:
5: ///////////////////////
6: // EIGENER CODE, ANFANG
7: ///////////////////////
8:
9: // Nachricht löschen
10: m_strMessage = "";
11:
12: // Bildschirm aktualisieren
13: UpdateData(FALSE);
14:
15: ///////////////////////
16: // EIGENER CODE, ENDE
17: ///////////////////////
18: }
In bezug auf die Nachrichtensteuerelemente ist als letztes noch die Funktionalität für die Kontrollkästchen Nachrichtenaktion aktivieren und Nachrichtenaktion zeigen zu implementieren. Das erste dieser Kontrollkästchen aktiviert oder deaktiviert die Steuerelemente, die sich auf die Anzeige der Benutzernachricht beziehen. Wenn das Kontrollkästchen eingeschaltet ist, sind alle Steuerelemente aktiviert. Weist das Kontrollkästchen den ausgeschalteten Zustand auf, sind die betreffenden Steuerelemente deaktiviert. Analog dazu dient das zweite Kontrollkästchen dazu, dieselbe Gruppe der Steuerelemente anzuzeigen bzw. auszublenden. Listing 2.6 zeigt den Code für beide Funktionen.
Listing 2.6: TAG2DLG.CPP - Die Funktionen für die Kontrollkästchen Nachrichtenaktion aktivieren/zeigen.
1: void CTag2Dlg::OnCkenblmsg()
2: {
3: // TODO: Code für die Behandlungsroutine der Steuerelement-
ÂBenachrichtigung hier einfügen
4:
5: ///////////////////////
6: // EIGENER CODE, ANFANG
7: ///////////////////////
8:
9: // Aktuelle Werte vom Bildschirm holen
10: UpdateData(TRUE);
11:
12: // Kontrollkästchen 'Nachrichtenaktion aktivieren' eingeschaltet?
13: if (m_bEnableMsg == TRUE)
14: {
15: // Ja, dann alle Steuerelemente aktivieren,
16: // die für Anzeige der Nachricht relevant sind.
17: GetDlgItem(IDC_MSG)->EnableWindow(TRUE);
18: GetDlgItem(IDC_SHWMSG)->EnableWindow(TRUE);
19: GetDlgItem(IDC_DFLTMSG)->EnableWindow(TRUE);
20: GetDlgItem(IDC_CLRMSG)->EnableWindow(TRUE);
21: GetDlgItem(IDC_STATICMSG)->EnableWindow(TRUE);
22: }
23: else
24: {
25: // Nein, dann alle Steuerelemente deaktivieren,
26: // die für Anzeige der Nachricht relevant sind.
27: GetDlgItem(IDC_MSG)->EnableWindow(FALSE);
28: GetDlgItem(IDC_SHWMSG)->EnableWindow(FALSE);
29: GetDlgItem(IDC_DFLTMSG)->EnableWindow(FALSE);
30: GetDlgItem(IDC_CLRMSG)->EnableWindow(FALSE);
31: GetDlgItem(IDC_STATICMSG)->EnableWindow(FALSE);
32: }
33:
34: ///////////////////////
35: // EIGENER CODE, ENDE
36: ///////////////////////
37: }
38:
39: void CTag2Dlg::OnCkshwmsg()
40: {
41: // TODO: Code für die Behandlungsroutine der Steuerelement-
ÂBenachrichtigung hier einfügen
42:
43: ///////////////////////
44: // EIGENER CODE, ANFANG
45: ///////////////////////
46:
47: // Aktuelle Werte vom Bildschirm holen
48: UpdateData(TRUE);
49:
50: // Kontrollkästchen 'Nachrichtenaktion zeigen' eingeschaltet?
51: if (m_bShowMsg == TRUE)
52: {
53: // Ja, dann alle Steuerelemente anzeigen, die
54: // für Anzeige der Nachricht relevant sind.
55: GetDlgItem(IDC_MSG)->ShowWindow(TRUE);
56: GetDlgItem(IDC_SHWMSG)->ShowWindow(TRUE);
57: GetDlgItem(IDC_DFLTMSG)->ShowWindow(TRUE);
58: GetDlgItem(IDC_CLRMSG)->ShowWindow(TRUE);
59: GetDlgItem(IDC_STATICMSG)->ShowWindow(TRUE);
60: }
61: else
62: {
63: // Nein, dann alle Steuerelemente ausblenden, die
64: // für Anzeige der Nachricht relevant sind
65: GetDlgItem(IDC_MSG)->ShowWindow(FALSE);
66: GetDlgItem(IDC_SHWMSG)->ShowWindow(FALSE);
67: GetDlgItem(IDC_DFLTMSG)->ShowWindow(FALSE);
68: GetDlgItem(IDC_CLRMSG)->ShowWindow(FALSE);
69: GetDlgItem(IDC_STATICMSG)->ShowWindow(FALSE);
70: }
71:
72: ///////////////////////
73: // EIGENER CODE, ENDE
74: ///////////////////////
75: }
Den ersten Teil dieser Funktionen sollten Sie mittlerweile verstehen. Als erstes werden
die Variablen mit den aktuellen Werten der Steuerelemente im Fenster aktualisiert. Es
folgt ein Test der Booleschen Variablen, die mit dem jeweiligen Kontrollkästchen verbunden
ist. Enthält die Variable den Wert TRUE
, soll das Programm das Steuerelement
aktivieren oder anzeigen. Hat die Variable den Wert FALSE
, ist das Steuerelement zu
deaktivieren bzw. auszublenden.
Von jetzt an ist der Code nicht mehr ganz so durchsichtig. Die erste Funktion, GetDlgItem
, erhält als Parameter die ID des zu ändernden Steuerelements. Die Funktion liefert
das Objekt für das Steuerelement zurück. Mit dieser Funktion läßt sich das Objekt
für beliebige Steuerelemente im Fenster bei laufender Anwendung abrufen. Der nächste
Teil jedes Befehls ruft eine Member-Funktion des Steuerelementobjekts auf. Die
zweite Funktion ist eine Member-Funktion des von der ersten Funktion zurückgegebenen
Objekts. Falls Ihnen dieser Ablauf nicht ganz klar sein sollte, empfiehlt sich ein
Studium von Anhang A.
Die zweiten Funktionen in diesen Aufrufen, EnableWindow
und ShowWindow
, sehen
eher wie Funktionen für Fenster aber nicht für Steuerelemente aus. Natürlich sind sie
für Fenster vorgesehen. Zufällig sind es aber auch Elemente der Klasse CWnd
, die der
Vorfahr der Klasse CDialog
ist, von der Sie Ihre Klasse CTag2Dlg
abgeleitet haben. In
Windows sind nun mal alle Steuerelemente selbst Fenster, die völlig unabhängig von
dem Fenster sind, in dem sie sich befinden. Damit kann man Steuerelemente als Fenster
behandeln und Fensterfunktionen auf ihnen aufrufen. In der Tat sind alle Steuerelementklassen
von der Klasse CWnd
abgeleitet, was ihr wahres Gesicht als Fenster offenbart.
Wenn Sie jetzt Ihre Anwendung kompilieren und ausführen, können Sie die Kontrollkästchen Nachrichtenaktion aktivieren und Nachrichtenaktion zeigen ausprobieren. Die Funktionsweise sollte Abbildung 2.11 entsprechen.
Abbildung 2.11:
Die Steuerelemente für Benutzernachrichten lassen sich nun deaktivieren.
Als letzte größere Aufgabe müssen wir noch die Funktionalität für die Steuerelemente implementieren, die dem Start eines anderen Programms dienen. Weiter vorn haben Sie die Namen von drei Windows-Anwendungen in das Kombinationsfeld aufgenommen. Wenn Sie die Anwendung starten, erscheinen diese Namen in der Dropdown- Liste. Man kann einen Eintrag auswählen, und im Wertbereich des Kombinationsfelds erscheint der Name der jeweiligen Anwendung. Damit dieser Teil auch funktioniert, müssen Sie lediglich für die Schaltfläche Programm starten Code hinzufügen, um tatsächlich den Wert aus dem Kombinationsfeld zu ermitteln und das passende Programm zu starten. Nachdem Sie das Funktionsgerüst für die Schaltfläche Programm starten mit dem Klassen-Assistenten erstellt haben, fügen Sie den Code aus Listing 2.7 in die Funktion ein.
Listing 2.7: TAG2DLG.CPP - Die Funktion OnRunpgm startet andere Windows-Anwendungen.
1: void CTag2Dlg::OnRunpgm()
2: {
3: // TODO: Code für die Behandlungsroutine der Steuerelement-
ÂBenachrichtigung hier einfügen
4:
5: ///////////////////////
6: // EIGENER CODE, ANFANG
7: ///////////////////////
8:
9: // Aktuelle Werte vom Bildschirm holen
10: UpdateData(TRUE);
11:
12: // Lokale Variable zur Aufnahme des Programmnamens deklarieren
13: CString strPgmName;
14:
15: // Programmname in die lokale Variable kopieren
16: strPgmName = m_strProgToRun;
17:
18: // Programmname in Großbuchstaben umwandeln
19: strPgmName.MakeUpper();
20:
21: // Programm Paint gewählt?
22: if (strPgmName == "PAINT")
23: // Ja, Paint starten
24: WinExec("pbrush.exe", SW_SHOW);
25:
26: // Editor (Notepad) gewählt?
27: if (strPgmName == "EDITOR")
28: // Ja, Editor starten
29: WinExec("notepad.exe", SW_SHOW);
30:
31: // Solitär gewählt?
32: if (strPgmName == "SOLITÄR")
33: // Ja, Solitär starten
34: WinExec("sol.exe", SW_SHOW);
35:
36: ///////////////////////
37: // EIGENER CODE, ENDE
38: ///////////////////////
39: }
Wie zu erwarten, findet in dieser Funktion zunächst der Aufruf von UpdateData
statt,
um die Variablen mit den Werten der Steuerelemente im Fenster zu aktualisieren. Der
nächste Teil erscheint allerdings ein wenig eigentümlich. Es wird eine neue CString
-
Variable deklariert und in diese der Wert des Kombinationsfeldes kopiert. Ist es wirklich
notwendig, wenn der Wert bereits in einer CString
-Variablen steht? Das hängt
davon ab, wie sich Ihre Anwendung verhalten soll. Die nächste Codezeile enthält einen
Aufruf der CString
-Funktion MakeUpper
, die den String in Großbuchstaben konvertiert.
Wenn man die CString
-Variable verwendet, die mit dem Kombinationsfeld
verbunden ist, wird beim nächsten Aufruf von UpdateData
mit dem Argument FALSE
der Wert im Kombinationsfeld ebenfalls in Großbuchstaben angezeigt. Unter diesen
Umständen ist das wahrscheinlich ein ungünstiger Zeitpunkt, und das Verhalten entspricht
nicht den Vorstellungen. Deshalb kommt in der Funktion ein zusätzlicher
CString
zum Einsatz.
An die Umwandlung des Strings in Großbuchstaben schließt sich eine Folge von if
-
Anweisungen an, die den String mit den Namen der verschiedenen Programme vergleichen.
Bei einer gefundenen Übereinstimmung ruft der Code die Funktion WinExec
auf, um die betreffende Anwendung zu starten. Wenn Sie Ihre Anwendung jetzt kompilieren
und ausführen, können Sie eine der Anwendungen aus der Dropdown-Liste
auswählen und sie durch Klicken auf die Schaltfläche Programm starten öffnen.
Heute haben Sie gelernt, wie man Standardsteuerelemente von Windows in einer Visual C++-Anwendung einsetzt. Es wurde gezeigt, wie man Variablen deklariert, sie mit den Steuerelementen verbindet und wie man die Werte der Variablen mit den Steuerelementen synchronisiert. Weiterhin haben Sie gelernt, wie man Steuerelemente manipuliert, indem man die Steuerelementobjekte mittels ihrer Objekt-ID abruft, und wie man das Steuerelement manipuliert, indem man es als Fenster behandelt. Als nächstes wurde auf die Tabulator-Reihenfolge der Steuerelemente in einer Anwendung eingegangen. Damit legt man die Richtung und Reihenfolge fest, in der der Benutzer durch eine Windows-Anwendung navigiert. Schließlich haben Sie gelernt, wie man die Funktionalität einer Anwendung mit den Steuerelementen im Anwendungsfenster verbindet, wobei die verschiedenen Aktionen ausgelöst werden, wenn der Benutzer mit den jeweiligen Steuerelementen interagiert. Als Bonus wurde gezeigt, wie man andere Windows-Anwendung aus der eigenen Anwendung heraus aufrufen kann.
Frage:
Nachdem ich die Objekt-IDs der Steuerelemente im Fenster festgelegt habe, weisen
drei Steuerelemente dieselbe ID, IDC_STATIC
, auf. Bei diesen Steuerelementen
handelt es sich um den Text im oberen Teil des Fensters und die beiden Gruppenfelder.
Die zwei anderen statischen Textsteuerelemente hatten zuerst die
gleiche ID, bis ich sie geändert habe. Wieso haben diese Steuerelemente die gleiche
ID, und warum mußte ich die IDs der beiden statischen Textsteuerelemente an
dieser Stelle ändern?
Antwort:
Alle Steuerelemente, die normalerweise nicht für eine Benutzerinteraktion
vorgesehen sind, beispielsweise statischer Text und Gruppenfelder, erhalten
per Vorgabe die gleiche Objekt-ID. Das funktioniert, solange Ihre Anwendung
keine Aktionen auf diesen Steuerelementen ausführen muß. Wenn Sie eine
Interaktion mit einem dieser Steuerelemente beabsichtigen, wie es für den
statischen Text mit den Aufforderungen für das Eingabefeld und das Kombinationsfeld
geschehen ist, müssen Sie den betreffenden Steuerelementen eine
eindeutige ID zuweisen. In diesem Fall war die eindeutige ID erforderlich, damit
Sie das Steuerelementobjekt abrufen können, um das Steuerelement zu
aktivieren/zu deaktivieren bzw. anzuzeigen/auszublenden. Ebenfalls müssen
Sie eine eindeutige ID zuweisen, wenn Sie eine Variable mit einem Steuerelement
verbinden möchten, um die Beschriftung auf dem Steuerelement dynamisch
ändern zu können.
Die Anwendung verhält sich in unvorhergesehener Weise, wenn Sie eines der statischen Steuerelemente, die die gleiche ID haben, verändern. Als Faustregel gilt, daß man statischen Steuerelementen die gleiche ID zuweisen kann, wenn man die Steuerelemente überhaupt nicht ändert. Macht sich eine Interaktion mit den Steuerelementen erforderlich, müssen Sie jedem Steuerelement eine eindeutige Objekt-ID zuordnen.
Frage:
Gibt es eine andere Möglichkeit, die Steuerelemente zu manipulieren, als die Steuerelementobjekte
unter Verwendung ihrer Objekt-IDs abzurufen?
Antwort:
Man kann Variablen in der Kategorie Control deklarieren. Damit erhält man
grundsätzlich ein Objekt, das die MFC-Klasse des Steuerelements darstellt,
und man kann dann direkt das Steuerelement ändern und damit interagieren.
Für das Steuerelement lassen sich dann alle Funktionen der Klasse
CWnd aufrufen, wie Sie es beim Aktivieren/Deaktivieren bzw. Anzeigen/Ausblenden
der Steuerelemente in Ihrer Anwendung vorgenommen haben. Sie
können auch die Klassenmethoden der Steuerelemente aufrufen. Das bietet
Ihnen die Möglichkeit, im Code spezielle Aufgaben für den jeweiligen Steuerelementtyp
zu realisieren. Wenn Sie zum Beispiel dem Kombinationsfeld eine
weitere Variable zuordnen und festlegen, daß es sich um eine Variable der Kategorie
Control handelt, können Sie über diese Variable die Elemente in der
Dropdown-Liste des Steuerelements hinzufügen.
1. Warum muß man die Tabulator-Reihenfolge der Steuerelemente im Anwendungsfenster festlegen?
2. Wie kann man eine Zugriffstaste in ein statisches Textfeld einbinden, das den Benutzer zum Eingabefeld oder Kombinationsfeld neben dem Textsteuerelement bringt?
3. Warum muß man den statischen Textfeldern vor dem Eingabefeld und den Kombinationsfeldern eindeutige Objekt-IDs zuweisen?
4. Warum muß man die Funktion UpdateData
aufrufen, bevor man den Wert eines
Steuerelements überprüft?
OnRunpgm
, damit der Benutzer den Namen
des auszuführenden Programms selbst eingeben kann.