Beispiel 2: Grundlagen der MFC

Inhalt:

Schritt 1: Anwendungsgerüst
Schritt 2: In der Document-Klasse eine Membervariable anlegen
Schritt 3: FormView bestücken
Schritt 4: Dialog zufügen
Schritt 5: Dialog anzeigen
Serialisierung
Klassendiagramm
Unit-Test

Dieses Beispiel zeigt die Grundlagen der MFC:
-FormView
-Dialog
-Document-View-Architektur

In der Document-Klasse wird ein String gehalten.
In einer FormView wird in einem nicht editierbaren Textfeld dieser String angezeigt.
Das Bearbeiten erfolgt über einen separaten Dialog in der FormView.
Der String ist in einer Datei serialisierbar.
Es gibt einen Unit-Test.
Hier gibt es das Teil zum Download: MFCBasics.zip

Schritt 1: Anwendungsgerüst

Erstellen des Anwendungsgerüsts (SDI-Anwendung) gemäß Beschreibung von Hr. Dreher, die Anwendung soll "MFCBasics" heißen.
Im Schritt "Zeichenfolgen für Dokumentvorlagen" habe ich eine "Dateierweiterung" namens "mfcbasics" angegeben, da das Speichern in Dateien unterstützt werden soll.
Dokumentvorlagen
Im Schritt "Generierte Klassen" wird als Basisklasse der "CMFCBasicsView" eine "CFormView" gewählt.
Generierte Klassen

Schritt 2: In der Document-Klasse eine Membervariable anlegen

In der Klassenansicht die Document-Klasse anwählen und per Rechtsklick "Hinzufügen" -> "Variable hinzufügen..." wählen.
Variable zufügen (1)
Im erscheinenden Dialog wählt man den Gültigkeitsbereich der Variablen (natürlich private !), den Datentyp ("CString" muss beim ersten Mal im Textfeld eingegeben werden) und gibt ihr einen Namen. Unter "Comment" kann man einen Kommentar eingeben, der in der Header-Datei für die Variable angezeigt wird.
Variable zufügen (2)
Außerdem fügen wir eine Get- und eine Set-Methode zu. Dazu per Rechtsklick in der "Klassenansicht" die Option "Hinzufügen" -> "Funktion hinzufügen" wählen.
Einstellungen für GetText:
GetText zufügen
Den Code ändern wir auf:
	return this->m_Text;

Einstellungen für SetText:
SetText zufügen
Den Code ändern wir auf:
	this->m_Text = pText; 
An dieser Stelle hat bei mir ein Bug zugeschlagen: obwohl ich bei den Funktionen public-Zugriff gewählt hatte landeten sie in der Header-Datei im private-Bereich. Deshalb: in "CMFCBasicsDoc" das rote markierte "public:" zufügen:
// Generierte Funktionen für die Meldungstabellen
protected:
	DECLARE_MESSAGE_MAP()
private:
	// Der Wert dieser Variablen wird in der FormView angezeigt
	CString m_Text;
public:
	// Liefert den Text aus der Document-Klasse zurück
	CString GetText(void);
	// Setzen des Texts im Document
	void SetText(CString pText);
}; 

Schritt 3: FormView bestücken

Die FormView öffnen, indem man in der "Ressourcenansicht" in der Kategorie "Dialog" auf IDD_MFCBASICS_FORM doppelklickt.
Die Resourcenansicht öffnet man entweder über Menü "Ansicht" -> "Ressourcenansicht" oder per Doppelklick auf die Datei "MFCBasics.rc" im Projektmappen-Explorer unter "Resourcendateien".
Jetzt holen wir aus der Toolbox ein "Edit Control" und platzieren es auf der FormView.
Per Rechtsklick gehen wir in die "Eigenschaften" und geben dem Ding unter "ID" einen gescheiten Namen (statt IDC_EDIT1). Außerdem setzen wir "Schreibgeschützt" auf "true", da wir den Text per Dialog eingeben wollen.
Edit Control zufügen
Wir könnten den Wert aus der Document-Klasse von der MFC setzen lassen (siehe dazu später den Dialog), doch diesmal machen wir es manuell: Wir wechseln in die "Klassenansicht" unserer View-Klasse. Hier überladen wir die Methode "OnUpdate". Der Weg dahin ist sehr verschlungen und führt über einen unscheinbaren Button: Wir öffnen die cpp-Datei der View in der "Klassenansicht" (im Projektmappen-Explorer funktioniert das so nicht !). Dann wechseln wir zum Eigenschaften-Fenster. In der Toolbar-Leiste gibt es einen Button mit unscheinbarem Icon und dem Tooltip "Überschreibungen". Klickt man diesen an sieht man alle überladbaren Methoden aus den Basisklassen. Wir suchen "OnUpdate" und wählen in der Combobox die Option " OnUpdate" (da wir noch keine bestehende Methode haben).
OnUpdate
Wir werden in den Codeeditor gesprungen und sehen eine neue Methode vor uns.
Folgende Codezeile wird eingefügt:
	((CEdit *) this->GetDlgItem (IDC_EDIT_TEXT))->SetWindowText ( this->GetDocument ()->GetText()); 

Schritt 4: Dialog zufügen

Wir erzeugen eine Dialogklasse zum Eingeben eines Strings. Dazu z.B. im Contextmenü des "Projektmappen-Explorer" die Option "Hinzufügen" -> "Klasse..." wählen. In dem Dialog wird in der Kategorie "MFC" die Option "MFC-Klasse" gewählt.
Dialog zufügen (1)
Im nächsten Dialog folgende Einstellungen vornehmen:
Dialog zufügen (2)
Hier: wir geben einen Namen an und ändern die Basisklasse auf CDialog. Der Assistent schlägt automatisch einen Namen für die Dialogfeld-Resource vor.

Wir plazieren ein Edit Control namens IDC_EDIT_TEXT im Dialog.
Dieses verknüpfen wir mit einer Membervariable, deren Wert automatisch von der MFC ins Textfeld geschrieben wird. Hierzu Rechtsklick auf das Edit Control, im Contextmenü "Variable hinzufügen..." wählen. In dem erscheinenden Assistenten gibt man links einen Variablen-Namen ein. Im rechten Teil können wir wählen, mit welchem Control dieser Wert verknüpft werden soll. Da wir vom Textfeld kommen, ist IDC_EDIT_TEXT bereits gewählt. Unter "Kategorie" müssen wir allerdings noch von "Control" auf "Value" umschalten, da ansonsten nur eine Membervariable vom Typ "CEditControl" angelegt würde. Durch Ändern der "Kategorie" wird links automatisch der "Variablentyp" geändert. Aus Faulheit belassen wir die Variable auf "public".
Variable für Textfeld zufügen

Schritt 5: Dialog anzeigen

Auf der FormView einen Button "Edit" mit dem Namen IDC_BUTTON_EDIT plazieren. Einen Handler für das Klick-Event zufügen. Hierzu gibt es verschiedene Möglichkeiten:
a) Rechtsklick auf den Button, "Ereignishandler hinzufügen...". Es erscheint folgender Dialog:
Button-Click-Handler, Variante 1
b) In den Eigenschaften auf den Button "Steuerelementereignisse" gehen und bei "BN_CLICKED" einen Handler zufügen.
Button-Click-Handler, Variante 2
In der so erzeugten Methode "OnBnClickedButtonEdit" folgendes einfügen:
	MFCBasicsDialog* dialog = new MFCBasicsDialog(this);
	dialog->m_Text = this->GetDocument()->GetText();
	if (dialog->DoModal () == IDOK)
	{
		this->GetDocument()->SetText ( dialog->m_Text);
		//Beim UpdateAllViews NULL übergeben, damit auch
		//unser Fenster sein Update bekommt.
		this->GetDocument()->UpdateAllViews (NULL);
	}
	//Speicher wieder freigeben.
	delete dialog;
Natürlich muss vorher noch der Header des Dialogs eingebunden werden.
	#include "MFCBasicsDialog.h"

Serialisierung

Hierzu die Methode "Serialize" unserer Document-Klasse so modifizieren:
	void CMFCBasicsDoc::Serialize(CArchive& ar)
	{
		if (ar.IsStoring())
		{
			// TODO: Hier Code zum Speichern einfügen
			ar << this->m_Text;
		}
		else
		{
			// TODO: Hier Code zum Laden einfügen
			ar >> this->m_Text;
		}
	}
Fertisch !

Anmerkungen

Wenn man das Beispiel nicht mehr benötigt, sollte man die Registry ausmisten. Welche Keys vom Programm erzeugt werden kann man in der Datei "MFCBasics.reg" ablesen, die im Anwendungsverzeichnis liegt. Diese alle löschen !

Klassendiagramm

Hier gibt es das Klassendiagramm als Together-Architect-1.1-XML-Export (Default-Dateiformat-Option): MFCBasics.xml
Klassendiagramm


Unit-Test

Es soll ein Unit-Test erfolgen, dieser soll einen ganzen Logikblock prüfen, nämlich ob das Speichern und anschließende Laden des Documents korrekt implementiert ist.
Die Anleitung folgt im großen und ganzen den Anweisungen von Hr. Dreher. Es wird ein Projekt namens "MFCBasicsTest" vom Anwendungstyp "Auf Dialogfeldern basierend" erstellt.
WICHTIGER HINWEIS: Im Gegensatz zu Hr. Drehers Anleitung habe ich den Haken "Unicode-Bibliotheken verwenden", der im Default gesetzt ist, nicht entfernt. Das bedeutet dass wir später eine andere Testrunner.dll referenzieren müssen !
Unit-Test-Anwendung erstellen
Wie in Hr. Drehers Anleitung folgende Schritte erledigen: Eine Übersicht über die CPPUnit-Prüfmakros findet man in der Doku übrigens in der Datei "group___assertions.html".


Version 1.2.1.0, Stand 16.04.2006
Historie:
1.0.0.0 Beispiel erstellt (02.04.2006).
1.1.0.0 Klassendiagramm (10.04.2006)
1.2.0.0 Unit-Test zugefügt (14.04.2006)
1.2.1.0 Alle Dateien mit DoxyGen-Kommentaren versehen (16.04.2006)