Microsoft Foundation Class (MFC) |
Visual C++ besitzt zwei Codegeneratoren: den AppWizard und den ClassWizard. AppWizard ist derjenige, der nach File-New- Projects - MFC-AppWizard gestartet wird. Er erstellt das Grundgerüst, nachdem er erfragt hat, ob es eine SDI oder MDI ist.
Auf der Document-View-Architektur setzen verschiedene
durch den AppWizard erzeugte Elemente auf.
Trennung zwischen Dokument und View
Das Dokument hält die Daten, während ein View eine Sicht der Daten realisiert.
Die Kommunikation findet vom View zum Dokument durch den Aufruf
der Funktion GetDocument statt, die einen Zeiger auf
die Dokumentklasse liefert. Ein Dokument kann eine Änderung
in den Daten durch die Funktion UpdateAllViews
auslösen. Ein View erhält eine solche Information
durch die Member-Funktion OnUpdate.
Der AppWizard
Der AppWizard erstellt für eine normale SDI-Anwendung die vier Klassen:
| CxxxApp | public CWinApp |
| CxxxDoc | public CDocument |
| CxxxView | public CView |
| CMainFrame | public CFrameWin |
Er erstellt eine Instanz namens theApp von CxxxApp.
Soll in einer SDI-Anwendung das Hauptfenster ein Formular
sein, also mit Steuerungselementen versehen sein, wird im
letzten Fenster des AppWizard statt CView die Einstellung
CFormView verwendet.
Der ClassWizard
Das Einfügen einer neuen Nachricht erfolgt am einfachsten
über View - ClassWizard. Hier wird die Klasse ausgewählt.
Anschließend wird unter Message ausgewählt, welches Ereignis bearbeitet
werden soll.
Der Wizard fügt die Funktion im Header in der Klassendefinition ein,
erstellt die Funktionen und trägt die Map nach.
((CButton *)(GetDialogItem(RB_NEW)))->SetCheck(true); |
Programmieren mit der MFC
Die Message Map
Die Ereignisverteilung erfolgt über eine Message Map. In
der Klasse des Fensters erfolgt der Aufruf DECLARE_MESSAGE_MAP().
Es folgt
BEGIN_MESSAGE_MAP(MeineKlasse, MFCKlasse) ON_COMMAND(WM_XXXXX, UserFunktion) END_MESSAGE_MAP() |
Normalerweise wird diese MAP vom ClassWizard erzeugt.
MDI: Multi Document Interface
Das Framewindow
Der Frame wird von CMDIFrameWnd abgeleitet.
IMPLEMENT_DYNAMIC(CMainFrame, CMDIFrameWnd)
BEGIN_MESSAGE_MAP(CMainFrame, CMDIFrameWnd)
//{{AFX_MSG_MAP(CMainFrame)
ON_COMMAND(IDM_BOUNCE, OnBounce)
ON_COMMAND(IDM_HELLO, OnHello)
//}}AFX_MSG_MAP
END_MESSAGE_MAP()
|
Über das Menü wird das Erzeugen der Kindfenster gesteuert. Damit ist auch schon die wichtigste Aufgabe des Rahmens erledigt.
void CMainFrame::OnBounce()
{
CBounceWnd *pBounceWnd = new CBounceWnd;
if (!pBounceWnd->Create(_T("Bounce"), WS_CHILD|WS_VISIBLE|WS_OVERLAPPEDWINDOW, rectDefault, this))
return;
}
void CMainFrame::OnHello()
{
CHelloWnd *pHelloWnd = new CHelloWnd;
if (!pHelloWnd->Create(_T("Hello"),
WS_CHILD | WS_VISIBLE | WS_OVERLAPPEDWINDOW,
rectDefault, this))
return;
}
|
Der PostNcDestroy-Behandlung wird das Objekt löschen, wenn es zerstört wird.
Im ClassWizard wählt man die ID des Menüpunktes. Es erscheinen in der nebenstehenden Dialogbox die Einträge COMMAND und UPDATE_COMMAND_UI. Letzterer wird doppelt angeklickt. Es erscheint das Angebot, eine Funktion zu erstellen mit dem Namen OnUpdateXXXXX. Die entstehende Funktion hat etwa folgendes Aussehen:
void xxxx::OnUpdateXXXXX(CCmdUI *pCmdUI)
{
pCmdUI->Enable(Bedingung); // schaltet das Item grau oder enable
pCmdUI->SetCheck(Bedingung); // setzt bzw. löscht einen Haken
}
|
CFileDialog DiaOpen(true); CFileDialog DiaSaveAs(false); |
Der Konstruktor lautet vollständig:
CFileDialog( BOOL, // Oeffnen (true) oder Schliessen (false) LPCTSTR, // Default Extension =NULL LPCTSTR, // Initial FileName =NULL DWORD, // Flags wie OPENFILENAME LPCTSTR, // Stringpaare als Filter CWnd *) // Parentwindow |
CFileDialog hat eine Membervariable m_ofn vom Typ OPENFILENAME.
Wichtige Memberfunktionen sind:
Es kann in der OnCreate-Funktion des Elternfensters angelegt werden durch Aufruf der Memberfunktion Create. Etwa:
Liste.Create(WS_VISIBLE|WS_BORDER|LVS_REPORT, CRect(20,20,120,150),this,LIST_ID); |
In einer Dialogbox ist ein solcher Create nicht erforderlich, da
die Liste durch die Ressource beschrieben ist und im Zuge des Aufbaus
der Dialogbox entsteht.
Spalten
Das Anlegen der Spalten erfolgt recht simpel durch den Aufruf der Memberfunktion
Liste.InsertColumn(i, char *Titel); |
Wenn Spalten gelöscht werden sollen, betrifft das meist alle Spalten. Dies erfolgt schnell und elegant durch
while (Liste.DeleteColumn(0)); |
Dabei wird immer die erste Spalte gelöscht, bis als Fehlermeldung eine 0 zurückgegeben wird.
Zeilen
Für jede Zeile wird ein Item dem ListView-Element hinzugefügt.
LVITEM Item = {0};
Item.mask = LVIF_TEXT;
Item.iItem = 0; // immer oben einhaengen
Item.pszText = TextPointer;
Liste.InsertItem(&Item);
|
Dadurch wird zunächst die linke Spalte gefüllt. Die anderen Spalten sind nur SubItems, die einfach mit
Liste.SetItemText(iItem, iSubItem, TextPointer); |
Dabei ist
| iItem | die Zeilennummer |
| iSubItem | die Spaltennummer |
| TextPointer | der angezeigte Text |
Um alle Zeilen zu löschen, kann
Liste.DeleteAllItems(); |
verwendet werden.
IDE und Editor
Strg-F2 setzt eine Bookmark an der aktuellen Stelle, die man später mit
F2 (vorwärts) und Shift-F2 (zurück) anspringen kann. Bookmarks bleiben nach erneutem
Laden nicht erhalten.
Dies und das
CWnd hat das HWND in seiner Member-Variablen m_hWnd.
ODBC-Einbindung findet sich unter dem Thema Datenbanken
Literatur
| Homepage | (C) Copyright 1999 Arnold Willemer |