Beispiel 3: Splitter-Window

Inhalt:

Schritt 1: Anwendungsgerüst
Schritt 2: Zweite FormView zufügen
Schritt 3: Splitter anpassen
Schritt 4: Code für Verschieben von Daten zwischen Views

Dieses Beispiel zeigt die Verwendung einer Splitter-Window mit zwei Form-Views.
Hier gibt es das Beispiel zum Download: Splitter.zip

Schritt 1: Anwendungsgerüst

Das Erstellen des Anwendungsgerüsts (SDI-Anwendung) erfolgt wie in den bisherige Beispielen, das Projekt heißt "Splitter".
Im Schritt "Benutzeroberflächenfeatures" aktivieren wir die Checkbox "Geteiltes Fenster":
Splitter aktivieren
Im letzten Schritt "Generierte Klassen" wählen wir als View-Basisklasse "CFormView" und benennen sie in "CSplitterLeftView" um (Zusatz "Left", da wir auch eine rechte FormView anlegen). Beim Umbenennen auch die .h- und .cpp-Datei umbenennen !
Linke View
Um dem Styleguide zu folgen sollten auch die Dateien zu Document- und MainFrame-Klasse mit dem Präfix "C" versehen werden !

Dummerweise gibt Visual Studio der Resource als Default den Projekt-Namen statt des Datei-Namens. Deshalb wählen wir die Ressource in der Ressourcenansicht und gehen in die Eigenschaften. Hier ändern wir den Namen auf "IDD_SPLITTERLEFTVIEW".
View-Resource umbenennen
In "CSplitterLeftView.h" ändern wir den Namen der enum für den Dialogfeld-Namen:
	public:
		enum{ IDD = IDD_SPLITTERLEFTVIEW }; 


Schritt 2: Zweite FormView zufügen

Im "Projektmappen-Explorer" dem Projekt eine neue Klasse zufügen ("Hinzufügen -> Klasse..."). Als Typ der Klasse wird "MFC-Klasse" gewählt.
Rechte View zufügen (1)
Eine neue FormView namens "CSplitterRightView" zufügen. Dateinamen werden wieder mit dem Präfix "C" versehen.
Rechte View zufügen (2)

Schritt 3: Splitter anpassen

In MainFrm.cpp wechseln, Methode "OnCreateClient". Hier wird der Befehl "return m_wndSplitter.Create ..." entfernt und durch folgendes ersetzt:
	BOOL bolReturn = TRUE;
	bolReturn = this->m_wndSplitter.CreateStatic (this, 1, 2);
	SIZE size;
	size.cx = 300;
	size.cy = 300;
	bolReturn = bolReturn && this->m_wndSplitter.CreateView (0, 0, RUNTIME_CLASS (CSplitterLeftView), size, pContext);
	bolReturn = bolReturn && this->m_wndSplitter.CreateView (0, 1, RUNTIME_CLASS (CSplitterRightView), size, pContext);

	return bolReturn;
Außerdem müssen die Headerdateien der Views eingebunden werden:
	#include "CSplitterRightView.h"
	#include "CSplitterLeftView.h"

Aus mir unbekannten Gründen trat nach diesem Schritt in "CSplitterLeftView" ein Compilefehler auf, ich mußte noch in "CSplitterLeftView.h" (also in der Header-Datei der vom Anwendungsassistenten generierten View-Klasse) die Header-Datei des Documents einbinden:
	#include "SplitterDoc.h" 

Schritt 4: Code für Verschieben von Daten zwischen Views

Auf den beiden FormViews jeweils ein Textfeld IDC_EDIT_LEFT bzw. IDC_EDIT_RIGHT und einen Button "Nach rechts verschieben" (IDC_BUTTON_LEFT) bzw. "Nach links verschieben" (IDC_BUTTON_RIGHT).

In "CSplitterDoc" eine Membervariable "m_sText" sowie Get- und Set-Methode dafür zufügen (siehe Beispiel "MFCBasics"). Achtung, hier könnte der Visual-Studio-Bug mal wieder zuschlagen, der dafür sorgt dass die Variable sowie die beiden Funktionen private werden obwohl letztere im Assistenten als "public" gewählt wurden.

Wir benutzen in beiden Views den DataExchange-Mechanismus für das Setzen/Auslesen der Textfelder. Deshalb in jeder View das Textfeld anklicken und im Contextmenü "Add Variable..." wählen.
Variable zufügen (Left View)
In beiden Views ein BN_CLICKED-Event für den "Nach xyz"-Button zufügen. In der linken View mit diesem Code:
	//Text auslesen:
	this->UpdateData (TRUE);

	//In Document schreiben:
	this->GetDocument()->SetText (this->m_sText);
	//Sich selbst vom Update-Event ausschließen:
	this->GetDocument()->UpdateAllViews(this);
Für die rechte View (die nachträglich zugefügte) gibt es keine automatisch generierte typsichere Methode "GetDocument", deshalb müssen wir hier die Rückgabe von "GetDocument" auf "CSplitterDoc" casten.
	//Text auslesen:
	this->UpdateData (TRUE);

	//In Document schreiben:
	((CSplitterDoc*) this->GetDocument() )->SetText (this->m_sText);
	//Sich selbst vom Update-Event ausschließen:
	this->GetDocument()->UpdateAllViews(this);
Außerdem muss der Header der Document-Klasse eingebunden werden:
	#include "CSplitterDoc.h" 
Abschließend in beiden FormViews die Methode "OnUpdate" überladen und folgenden Code einfügen:
	//Aktuellen Text aus Document holen und in Membervariable packen.
	this->m_sText = this->GetDocument ()->GetText();
	//Jetzt in Textfeld schreiben:
	this->UpdateData (FALSE); 
In der rechten View muss das Document auf "CSplitterDoc" gecastet werden.



Version 1.0.0.1, Stand 15.05.2006
Historie:
1.0.0.0 (23.04.2005) Beispiel zugefügt.
1.0.0.1 (14.05.2006) Kleine Ergänzung in Abschnitt 3.