Letzte Änderung: 2.11.97 von B. Tritsch
Zurück zum Index "PC- und MS-Windows-Support"
Die MFC ist eine Klassenbibliothek, die das gesamte Windows-API kapselt. Sie besitzt daher Klassen für folgende Windows-Bestandteile:
Die "Mutter" (fast) aller Klassen in der MFC ist CObject.Sie verzweigt grob gesehen in die folgende Klassenhierarchie:
| Applikations-Architektur (CWinApp) |
|
| Fensterunterstützung (CWnd) |
|
| Graphikunterstützung |
|
| Systemunterstützung |
|
Klassen, die nicht von CObject abgeleitet werden:
Die Klassenhierarchie läßt sich jedoch zu einer alternativen Betrachtungsweise in acht Gruppen unterteilen:
Im Detail läßt sich Klassenhierarchie folgendermaßen anzeigen:
Klassen für die Anwendungsarchitektur
CObject
Allgemein nützliche Klassen
CObject
Visual Object-Klassen
CObject
CObject - CCmdTarget
Die Collection-Klassen
CObject
Die OLE2-Klassen
CObject
Datenbank-Klassen
CObject
Standard-Steuerelemente
CObject
Die Socket-Klassen
CObject
Ein MFC-Programm besteht mindestens aus einer aus der Anwendungsklasse CWinApp abgeleiteten Klasse. Sie besorgt die Programmabarbeitung, jedoch nicht die Fenstererstellung. Im Programm-Code wird die CWinApp-Methode InitInstance() mit den zur Fenstererzeugung und -anzeige nötigen Befehlen überladen. Es gibt daher auch keine WinMain()-Funktion mehr!
Die Klasse CWnd ist die Basisklasse aller MFC-Fenster. Von ihr leiten sich alle weiteren wichtigen Fensterklassen ab:
In der Klasse CWnd setzt der Mechanismus zur Abarbeitung der Nachrichten in einer Fensterfunktion an. Er wird mittels sogenannter Message Maps und zugehöriger Makros realisiert.
Die Member Functions der CWnd-Klasse unterteilen sich in die folgenden Kathegorien:
Die Klasse CFrameWnd (abgeleitet von CWnd) besitzt alle Eigenschaften eines normalen Popup-Windows. Es kann somit als Hauptfenster einer Anwendung dienen. Es sind darin allerdings keine weiteren Funktionalitäten realisiert!
Weitere von CWnd abgeleitete Klassen machen es auf einfache Art möglich weitere graphische Gestaltungselemente in ein Fenster einzuführen:
Die Klasse zur Erstellung und Verwaltung von Menüs ist CMenu. Der Zugriff auf die Systemmenüs erfolgt auch durch eine Methode dieser Klasse und wird nicht über eine eigens eingeführte Klasse realisiert.
Zur Erzeugung und Verwaltung von Dialogen wird die Klasse CDialog genutzt. Natürlich wird auch bei diesen Dialogen zwischen modal und nicht-modal unterschieden.
Von CDialog ausgehend sind weitere Sonderklassen definiert, die den Dialogen entsprechen, die in der Datei COMMDLG.DLL für alle Windows-Programmierer vorgegeben sind:
Die Ausgabe von Text und Zeichnungen erfolgt über Gerätekontexte. In der MFC stammen diese von der Klasse CDC ab. Abgeleitete Kontexte hiervon sind:
Zur Ausgabe von Graphiken wurden die Klassen der wichtigsten Werkzeuge definiert:
Die MFC stellt auch viele Funktionen und Klassen zur Verfügung, die die Handhabung von Documents und Views vereinfachen sollen. Damit können Dokumente durch mehrere von ihnen abhängige Ansichten dargestellt werden. Die beteiligten Klassen sind:
Das folgende MFC-Programm stellt ein Grundgerüst dar. Klickt man mit der linken Maustaste auf die Client Area, wird eine Message Box ausgegeben.
#include <afxwin.h>
/* 2*/
/* 3*/ class CAnwendung : public CWinApp
/* 4*/ {
/* 5*/ public:
/* 6*/ BOOL InitInstance();
/* 7*/ };
/* 8*/
/*11*/ class CHauptfenster : public CFrameWnd
/*12*/ {
/*13*/ public:
/*14*/ CHauptfenster();
/*15*/ afx_msg void OnLButtonDown(UINT, CPoint);
/*16*/ DECLARE_MESSAGE_MAP();
/*17*/ };
/*18*/
/*19*/ BEGIN_MESSAGE_MAP(CHauptfenster, CFrameWnd)
/*20*/ ON_WM_LBUTTONDOWN()
/*21*/ END_MESSAGE_MAP()
/*22*/
/*23*/ void CHauptfenster::OnLButtonDown(UINT, CPoint)
/*24*/ {
/*25*/ MessageBox("Da bin ich", "Achtung", MB_OK);
/*26*/ }
/*27*/
/*28*/ static CAnwendung Anwendung;
/*29*/
/*30*/ BOOL CAnwendung::InitInstance()
/*31*/ {
/*32*/ m_pMainWnd = new CHauptfenster;
/*33*/ m_pMainWnd->ShowWindow(m_nCmdShow);
/*34*/ return TRUE;
/*35*/ }
/*36*/
/*37*/ CHauptfenster::CHauptfenster()
/*38*/ {
/*39*/ Create(NULL, "Erste MFC-Anwendung");
/*40*/ }
Zeile 1:
In der Header-Datei AFXWIN.H sind alle Deklarationen und
Konstanten enthalten der MFC enthalten oder über andere Includes
referenziert (inkl. WINDOWS.H).
Zeile 3 - 17:
Die Applikations-Anwendungsklasse und -Fensterklasse werden von
den entsprechenden MFC-Klassen abgeleitet.
Zeile 19 - 21:
Deklaration der Message Map. Die Macros dienen der
Nachrichtenverteilung aus der Nachrichtenschleife der
Apllikation. Die zugehörigen Member-Funktionen dirigieren die
Nachrichten an ihr Zielfenster, wie es auch
Nicht-MFC-Applikationen tun würden. Daher ist der primäre
Empfänger immer ein Fenster. Der Message Handler in einem
Objekt, das in der Lage ist Nachrichten zu empfangen, wertet
Nachrichten aus oder leitet sie weiter. Dies geschieht in einer
bestimmten Reihenfolge:
Zeile 23 - 26:
Programm-Code zur Reaktion auf die Mauseingabe
Zeile 28:
Erzeugt das Anwendung-Objekt und resultiert im Aufruf der InitInstance()-Funktion
Zeile 30 - 35:
Erzeugt ein neues CMainWindow-Objekt. Dies resultiert im Aufruf
des CMainWindow-Konstruktors
Zeile 37 - 40:
Überladener Konstruktor, ruft die Create()-Funktion
auf. Sie erzeugt das Programmfenster.
Soll das Programm graphische Elemente ausgeben und auf Benutzerinteraktion reagieren, müssen sowohl die Message Map als auch die entsprechenden Funktionsaufrufe erweitert werden:
/*19 */ BEGIN_MESSAGE_MAP(CHauptfenster, CFrameWnd) /*20 */ ON_WM_LBUTTONDOWN() /*20A*/ ON_WM_PAINT() /*20B*/ ON_COMMAND(IDM_SHOW, OnShowText) /*21 */ END_MESSAGE_MAP()
Zeile 20A - 20B:
Die erste Zeile sorgt für das "Repaint", die zweite
für die initiale Darstellung einer Graphik als Reaktion auf eine
Benutzereingabe (z.B. über einen Menüpunkt). Die ausführenden
Funktionen sind von zwei entsprechenden Klassen abgeleitet (CPaintDC,
CClientDC).
void CHauptfenster::OnPaint()
{
CString string = "Repaint";
CPaintDC dc(this);
dc.TextOut(30, 30, string, string.GetLength));
}
void CHauptfenster::OnShowText()
{
CString string = "Initial";
CClientDC dc(this);
dc.TextOut(30, 30, string, string.GetLength));
}
Durch das Multiple Document Interface (MDI) wird es dem Anwender im Gegensatz zum Standard Sigle Document Interface (SDI) ermöglicht, in mehreren Kindfenstern unterschiedliche Objekte eines Typs oder aber ein Objekt in mehreren Darstellungsformen zu bearbeiten. Beispiele hierfür sind die "guten alten" Windows Datei- und Programm-Manager.
Eine MDI-Anwendung setzt sich aus drei Komponenten zusammen:
MDI-Applikationen sind stärker objektorientiert, was die Programmiertechniken etwas verändert. Aus diesem Grund ist ihre Unterstützung in der MFC besonders ausgeprägt.
MDI ist für professionelle Programmentwicklung äußerst wichtig, obwohl die Erstellung einer MDI-Applikation eine sehr komplexe Aufgabe ist (Beispiel: Word für Windows, etc.)
Die bisher vorgestellten MFC-Programme wurden "von Hand" editiert. Mit Hilfe des Microsoft Developer Studios, das integraler Bestandteil der Visual C++-Entwicklungsumgebung ist, sieht ein typisches Rahmenprogramm etwas aufwendiger aus. Dies liegt daran, daß das Developer Studio interaktiv Programmcharakteristika erfragt und mit diesen Informationen als Code-Generator fungiert. Dies nimmt dem Entwickler sehr viel Routinearbeit ab.
Erzeugt man innerhalb des Developer Studios mit dem AppWizzard ein neues SDI-Projekt mit dem Namen YAH, so werden eine ganze Reihe von Dateien erstellt:
| YAH.h | Dies ist das Haupt-Header-File der Applikation. Es inkludiert andere projektspezifische Header-Dateien und deklariert die CYAHApp-Klasse |
| YAH.cpp | Dies ist die zentrale Quelldatei, die die Applikationsklasse CYAHApp beinhaltet |
| YAH.rc | Die primäre Ressourcendatei, die das Programm verwendet. Sie beinhaltet Verweise auf die inkludierten Icons, Bitmaps und Cursors, die im RES-Unterverzeichnis abgelegt sind. Diese Datei wird direkt vom Developer Studio editiert |
| MainFrm.h MainFrm.cpp |
Diese Dateien beinhalten die Frame-Klasse CMainFrame, die von CFrameWnd abgeleitet ist und die SDI-Rahmen-Features kontrolliert |
| YAHDco.h YAHDoc.cpp |
Diese Dateien beinhalten die CYAHDoc-Dokumenten-Klasse. Sie müssen editiert werden, um spezielle Dokumentendaten hinzuzufügen und um das Datei laden bzw. Datei speichern zu implementieren |
| YAHView.h YAHView.cpp |
Diese Dateien beinhalten die CYAHView-View-Klasse. CYAHView-Objekte werden verwendet, um CYAHDoc-Objekte anzuzeigen |
| StdAfx.h StdAfx.cpp |
Diese Dateien werden verwendet, um eine vorkompilierten Header (PCH-File) mit dem Namen YAH.pch und eine vorkompilierte Typendatei mit dem Namen StdAfx.obj zu erzeugen |
| Resource.h | Dies ist die Standard-Headerdatei, in der neue Ressource IDs definiert werden. Das Developer Studio liest und beschreibt diese Datei |
Sieht man sich die Deklaration der CYAHApp-Klasse (abgeleitet von CWinApp) in YAH.h an, so findet man drei Member-Funktionen: Einen Constructor, eine überschriebene virtuelle Funktion InitInstance und eine Member-Funktion CAppAbout.
// YAH.h : main header file for the YAH application
//
#ifndef __AFXWIN_H__
#error include 'stdafx.h' before including this file for PCH
#endif
#include "resource.h" // main symbols
/////////////////////////////////////////////////////////////////////////////
// CYAHApp:
// See YAH.cpp for the implementation of this class
//
class CYAHApp : public CWinApp
{
public:
CYAHApp();
// Overrides
// ClassWizard generated virtual function overrides
//{{AFX_VIRTUAL(CYAHApp)
public:
virtual BOOL InitInstance();
//}}AFX_VIRTUAL
// Implementation
//{{AFX_MSG(CYAHApp)
afx_msg void OnAppAbout();
// NOTE - the ClassWizard will add and remove member functions here.
// DO NOT EDIT what you see in these blocks of generated code !
//}}AFX_MSG
DECLARE_MESSAGE_MAP()
};
In der Datei YAH.cpp folgt dann die Implemetierung der CYAHApp-Klasse und der CAboutDlg-Klasse. Zweitere ist für die Realisierung einer About-Dialogbox zuständig und soll uns hier nicht weiter interessieren. Viel zentraler ist die Member-Funktion InitInstance der CYAHApp-Klasse.
#include "stdafx.h"
#include "YAH.h"
#include "MainFrm.h"
#include "YAHDoc.h"
#include "YAHView.h"
#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif
/////////////////////////////////////////////////////////////////////////////
// CYAHApp
BEGIN_MESSAGE_MAP(CYAHApp, CWinApp)
//{{AFX_MSG_MAP(CYAHApp)
ON_COMMAND(ID_APP_ABOUT, OnAppAbout)
// NOTE - the ClassWizard will add and remove mapping macros here.
// DO NOT EDIT what you see in these blocks of generated code!
//}}AFX_MSG_MAP
// Standard file based document commands
ON_COMMAND(ID_FILE_NEW, CWinApp::OnFileNew)
ON_COMMAND(ID_FILE_OPEN, CWinApp::OnFileOpen)
// Standard print setup command
ON_COMMAND(ID_FILE_PRINT_SETUP, CWinApp::OnFilePrintSetup)
END_MESSAGE_MAP()
/////////////////////////////////////////////////////////////////////////////
// CYAHApp construction
CYAHApp::CYAHApp()
{
// TODO: add construction code here,
// Place all significant initialization in InitInstance
}
/////////////////////////////////////////////////////////////////////////////
// The one and only CYAHApp object
CYAHApp theApp;
/////////////////////////////////////////////////////////////////////////////
// CYAHApp initialization
BOOL CYAHApp::InitInstance()
{
// Standard initialization
// If you are not using these features and wish to reduce the size
// of your final executable, you should remove from the following
// the specific initialization routines you do not need.
#ifdef _AFXDLL
Enable3dControls(); // Call this when using MFC in a shared DLL
#else
Enable3dControlsStatic(); // Call this when linking to MFC statically
#endif
LoadStdProfileSettings(); // Load standard INI file options (including MRU)
// Register the application's document templates. Document templates
// serve as the connection between documents, frame windows and views.
CSingleDocTemplate* pDocTemplate;
pDocTemplate = new CSingleDocTemplate(
IDR_MAINFRAME,
RUNTIME_CLASS(CYAHDoc),
RUNTIME_CLASS(CMainFrame), // main SDI frame window
RUNTIME_CLASS(CYAHView));
AddDocTemplate(pDocTemplate);
// Enable DDE Execute open
EnableShellOpen();
RegisterShellFileTypes(TRUE);
// Parse command line for standard shell commands, DDE, file open
CCommandLineInfo cmdInfo;
ParseCommandLine(cmdInfo);
// Dispatch commands specified on the command line
if (!ProcessShellCommand(cmdInfo))
return FALSE;
// Enable drag/drop open
m_pMainWnd->DragAcceptFiles();
return TRUE;
}
In YAH.cpp wird ein globales Objekt des Typs CYAHApp mit dem Namen theApp deklariert. Mit ihm beginnt das Leben des Programms, da es zum Anfang der Laufzeit konstruiert wird. Dies impliziert, daß sein Konstruktor aufgerufen wird.
In der Member-Funktion InitInstance des CYAHApp-Objekts finden eine Reihe von Initialisierungen statt, z.B. das 3D-Aussehen der Applikation. Der wahrscheinlich wichtigste Initialisierungsschritt ist jedoch die Erzeugung eines Document Templates. Daher wird ein Objekt des Typs CSingleDocTemplate kreiert und zu den Document Templates der Applikation mit Hilfe der Funktion AddDocTemplate hinzugefügt. Die Information, die im Document Template gespeichert ist, wird bei der Verwendung des "New"-Kommandos aus dem Anwendungsmenü benötigt. Die Standard-Implementation dieses Kommandos ist die Funktion CWinApp::OnFileNew. Die Funktion nutzt die Template-Information um zu entscheiden was für ein Objekt sie erzeugen muß um ein neues Dokumentenobjekt und eine entsprechende Sichtweise (View) zu repräsentieren.
Soll mehr als ein Dokumententyp verwendet werden, muß die Anwendung als MDI-Applikation konzipiert werden!
In einer einfachen Nicht-MFC-Applikation würde man typischerweise ein Fenster erzeugen und seine Client Area zur Darstellung aller Ausgaben verwenden. MFC-Applikationen auf der anderen Seite verwenden mindestens zwei Fenster: Das Frame Windows und das View Window.
Das Frame Window verwaltet die Applikationsmenüs, Werkzeugleisten und all die anderen Komponenten der Benutzerschnittstelle. Das View Window ist vorgesehen, um Daten aus dem Applikationsdokument zu präsentieren. Hierbei ist das Dokumentenobjekt nicht sichtbar, es repräsentiert die Applikationsdaten oder korrespondiert mit dem Inhalt einer Datei. Das Dokumentenobjekt interagiert mit dem View Windows für die Darstellung der Daten und für die Benutzerinteraktion.
Das Frame Window einer Applikation wird durch die Klasse CMainFrame unterstützt. Die Dokumentenklasse einer Applikation wird von CDocument abgeleitet. Das View Fenster benötigt eine entsprechende Klasse abgeleitet von der CView-Klasse.
Die Klasse CView liefert die grundlegende Funktionalität, um benutzerdefinerte View-Klassen zu erzeugen. Dabei handelt es sich um Views, die mit Dokumenten verbunden sind und als Übersetzer oder Mittler zwischen dem Dokument und dem Benutzer fungieren, indem sie ein Abbild des Dokuments auf dem Bildschirm ausgeben und die Benutzereingaben als Operation für das Dokument interpretieren.
Auch wenn einem View nur ein Dokument beigeordnet sein kann, kann ein Dokument ohne weiteres mehrere Views haben, die jeweils andere Dokumentansichten zeigen. Ein View ist jedoch nicht dafür geschaffen die Daten zu speichern. Es liegt gänzlich im Verantwortungsbereich des Dokuments, den View mit den nötigen Informationen zu versorgen. Dies kann erreicht werden, indem es dem View ermöglicht wird, direkt oder über Member-Funktionen auf die Datenelemente zuzugreifen.
CString
Die CString-Klasse dient dazu, die alten C-Zeichenarrays zu ersetzen und bietet mächtige und flexible String-Operationen. Die CString-Klasse stellt Zeichenstrings variabler Länge und Operatoren zum Verketten (Konkatenation) und Vergleich bereit. Sie bietet darüber hinaus auch vereinfachte Speicherverwaltungsfunktionen und -operationen, die denen von Basic ähnlich sind.
Die Klasse CString basiert auf dem Datentyp TCHAR. Ist das Symbol als _UNICODE definiert, wird TCHAR als Typ wchar_t (ein 16-Bit Zeichentyp) definiert, ansonsten als normaler 8-Bit-Wert.
CString-Objekte weisen folgende Eigenschaften auf:
Ein kleines Beispiel zum Erzeugen eines CString-Objekts, der Anbindung eines zweiten Strings und der Ausgabe über einen Device Context mit dem Namen dc wird im folgenden aufgezeigt. Beim Device Context wird davon ausgegangen, daß er vorher über die Klasse CPaintDC oder CClientDC erzeugt wurde.
#include <strstrea> // Header-File für Strings/Strams CString AString; // Erzeugt ein CString-Objekt AString = "Der vollstaendige String "; AString += "ist so lang."; dc.TextOut(10, 10, AString, AString.GetLength());
Die CString-Klasse hat eine Reihe von Member-Funktionen. Einige sollen hier aufgeführt werden:
Der Übergang zwischen einem CString-Objekt und einem normalen Zeiger auf einen Zeichenpuffer ist ebenfalls recht einfach möglich. Damit lassen sich auch die String-Funktionen aus dem ANSI- und dem Windows-API-Sprachumfang leicht parallel verwenden.
char * pCharBuffer = (const char *) AString;
CFile
Die MFC-Bibliothek stellt die CFile-Klasse für Dateizugriffe zur Verfügung. Die Funktionen sehen denen aus DOS recht ähnlich. Die am meisten verwendeten Member-Funktionen werden hier aufgeführt:
Weiterhin gibt es Funktionen zur Manipulation der Datei-Modi, z.B. zum Datei erzeugen und zum Setzen von Read-only, Read/Write bzw. Write-only Flags.
CTime
Die CTime-Klassenobejekte geben das absolute Datum und die Uhrzeit an. Hierbei kapseln sie den ANSI-Datentyp time_t und seine verwandten Laufzeitfunktionen, einschließlich der Fähigkeit, in die Gregorianische Zeitrechnung sowie 24-Stunden-Anzeigen umzurechnen. CTime-Werte basieren auf UCT (Universal Coordinate Time oder Greenwich Mean Time), wobei die lokale Zeitzone durch die TZ-Umgebungsvariable identifiziert wird.
Da die CTime-Klasse die strftime-Funktion benutzt, die nicht von den Windows-DLLs unterstützt wird, kann die CTime-Klasse nicht innerhalb einer DLL eingesetzt werden!