With MFC, one can use the wizard to generate a template from which one can proceed to code. Especially for a beginner like me this is a necessary tool. However such a template consists of a large amount of code which is hard to understand an makes it really difficult to understand MFC at the beginning.
In the following is an example for a project using a Dialog-based-application. All other variants like SDI or MDI contain much more overhead. And this example does not even use the document-view concept.
One can see that the code is filled with stuff that is hard to understand without experience and knowledge of the API. I have not worked with other APIs yet, but I hope one can do this better in principle.
In the end I have learned to understand most of the code and how ot change it.
DialogBasedProject.h
// DialogBasedProject.h : Hauptheaderdatei für die PROJECT_NAME-Anwendung // #pragma once #ifndef __AFXWIN_H__ #error "\"stdafx.h\" vor dieser Datei für PCH einschließen" #endif #include "resource.h" // Hauptsymbole // CDialogBasedProjectApp: // Siehe DialogBasedProject.cpp für die Implementierung dieser Klasse // class CDialogBasedProjectApp : public CWinApp { public: CDialogBasedProjectApp(); // Überschreibungen public: virtual BOOL InitInstance(); // Implementierung DECLARE_MESSAGE_MAP() }; extern CDialogBasedProjectApp theApp; |
DialogBasedProjectDlg.h
// DialogBasedProjectDlg.h : Headerdatei // #pragma once // CDialogBasedProjectDlg-Dialogfeld class CDialogBasedProjectDlg : public CDialog { // Konstruktion public: CDialogBasedProjectDlg(CWnd* pParent = NULL); // Standardkonstruktor // Dialogfelddaten enum { IDD = IDD_DIALOGBASEDPROJECT_DIALOG }; protected: virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV-Unterstützung // Implementierung protected: HICON m_hIcon; // Generierte Funktionen für die Meldungstabellen virtual BOOL OnInitDialog(); afx_msg void OnSysCommand(UINT nID, LPARAM lParam); afx_msg void OnPaint(); afx_msg HCURSOR OnQueryDragIcon(); DECLARE_MESSAGE_MAP() }; |
DialogBasedProject.cpp
// DialogBasedProject.cpp : Definiert das Klassenverhalten für die Anwendung. // #include "stdafx.h" #include "DialogBasedProject.h" #include "DialogBasedProjectDlg.h" #ifdef _DEBUG #define new DEBUG_NEW #endif // CDialogBasedProjectApp BEGIN_MESSAGE_MAP(CDialogBasedProjectApp, CWinApp) ON_COMMAND(ID_HELP, &CWinApp::OnHelp) END_MESSAGE_MAP() // CDialogBasedProjectApp-Erstellung CDialogBasedProjectApp::CDialogBasedProjectApp() { // TODO: Hier Code zur Konstruktion einfügen // Alle wichtigen Initialisierungen in InitInstance positionieren } // Das einzige CDialogBasedProjectApp-Objekt CDialogBasedProjectApp theApp; // CDialogBasedProjectApp-Initialisierung BOOL CDialogBasedProjectApp::InitInstance() { // InitCommonControlsEx() ist für Windows XP erforderlich, wenn ein Anwendungsmanifest // die Verwendung von ComCtl32.dll Version 6 oder höher zum Aktivieren // von visuellen Stilen angibt. Ansonsten treten beim Erstellen von Fenstern Fehler auf. INITCOMMONCONTROLSEX InitCtrls; InitCtrls.dwSize = sizeof(InitCtrls); // Legen Sie dies fest, um alle allgemeinen Steuerelementklassen einzubeziehen, // die Sie in Ihrer Anwendung verwenden möchten. InitCtrls.dwICC = ICC_WIN95_CLASSES; InitCommonControlsEx(&InitCtrls); CWinApp::InitInstance(); // Standardinitialisierung // Wenn Sie diese Features nicht verwenden und die Größe // der ausführbaren Datei verringern möchten, entfernen Sie // die nicht erforderlichen Initialisierungsroutinen. // Ändern Sie den Registrierungsschlüssel, unter dem Ihre Einstellungen gespeichert sind. // TODO: Ändern Sie diese Zeichenfolge entsprechend, // z.B. zum Namen Ihrer Firma oder Organisation. SetRegistryKey(_T("Vom lokalen Anwendungs-Assistenten generierte Anwendungen")); CDialogBasedProjectDlg dlg; m_pMainWnd = &dlg; INT_PTR nResponse = dlg.DoModal(); if (nResponse == IDOK) { // TODO: Fügen Sie hier Code ein, um das Schließen des // Dialogfelds über "OK" zu steuern } else if (nResponse == IDCANCEL) { // TODO: Fügen Sie hier Code ein, um das Schließen des // Dialogfelds über "Abbrechen" zu steuern } // Da das Dialogfeld geschlossen wurde, FALSE zurückliefern, sodass wir die // Anwendung verlassen, anstatt das Nachrichtensystem der Anwendung zu starten. return FALSE; } |
DialogBasedProjectDlg.cpp
// DialogBasedProjectDlg.cpp : Implementierungsdatei // #include "stdafx.h" #include "DialogBasedProject.h" #include "DialogBasedProjectDlg.h" #ifdef _DEBUG #define new DEBUG_NEW #endif // CAboutDlg-Dialogfeld für Anwendungsbefehl "Info" class CAboutDlg : public CDialog { public: CAboutDlg(); // Dialogfelddaten enum { IDD = IDD_ABOUTBOX }; protected: virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV-Unterstützung // Implementierung protected: DECLARE_MESSAGE_MAP() }; CAboutDlg::CAboutDlg() : CDialog(CAboutDlg::IDD) { } void CAboutDlg::DoDataExchange(CDataExchange* pDX) { CDialog::DoDataExchange(pDX); } BEGIN_MESSAGE_MAP(CAboutDlg, CDialog) END_MESSAGE_MAP() // CDialogBasedProjectDlg-Dialogfeld CDialogBasedProjectDlg::CDialogBasedProjectDlg(CWnd* pParent /*=NULL*/) : CDialog(CDialogBasedProjectDlg::IDD, pParent) { m_hIcon = AfxGetApp()->LoadIcon(IDR_MAINFRAME); } void CDialogBasedProjectDlg::DoDataExchange(CDataExchange* pDX) { CDialog::DoDataExchange(pDX); } BEGIN_MESSAGE_MAP(CDialogBasedProjectDlg, CDialog) ON_WM_SYSCOMMAND() ON_WM_PAINT() ON_WM_QUERYDRAGICON() //}}AFX_MSG_MAP END_MESSAGE_MAP() // CDialogBasedProjectDlg-Meldungshandler BOOL CDialogBasedProjectDlg::OnInitDialog() { CDialog::OnInitDialog(); // Hinzufügen des Menübefehls "Info..." zum Systemmenü. // IDM_ABOUTBOX muss sich im Bereich der Systembefehle befinden. ASSERT((IDM_ABOUTBOX & 0xFFF0) == IDM_ABOUTBOX); ASSERT(IDM_ABOUTBOX < 0xF000); CMenu* pSysMenu = GetSystemMenu(FALSE); if (pSysMenu != NULL) { CString strAboutMenu; strAboutMenu.LoadString(IDS_ABOUTBOX); if (!strAboutMenu.IsEmpty()) { pSysMenu->AppendMenu(MF_SEPARATOR); pSysMenu->AppendMenu(MF_STRING, IDM_ABOUTBOX, strAboutMenu); } } // Symbol für dieses Dialogfeld festlegen. Wird automatisch erledigt // wenn das Hauptfenster der Anwendung kein Dialogfeld ist SetIcon(m_hIcon, TRUE); // Großes Symbol verwenden SetIcon(m_hIcon, FALSE); // Kleines Symbol verwenden // TODO: Hier zusätzliche Initialisierung einfügen return TRUE; // Geben Sie TRUE zurück, außer ein Steuerelement soll den Fokus erhalten } void CDialogBasedProjectDlg::OnSysCommand(UINT nID, LPARAM lParam) { if ((nID & 0xFFF0) == IDM_ABOUTBOX) { CAboutDlg dlgAbout; dlgAbout.DoModal(); } else { CDialog::OnSysCommand(nID, lParam); } } // Wenn Sie dem Dialogfeld eine Schaltfläche "Minimieren" hinzufügen, benötigen Sie // den nachstehenden Code, um das Symbol zu zeichnen. Für MFC-Anwendungen, die das // Dokument/Ansicht-Modell verwenden, wird dies automatisch ausgeführt. void CDialogBasedProjectDlg::OnPaint() { if (IsIconic()) { CPaintDC dc(this); // Gerätekontext zum Zeichnen SendMessage(WM_ICONERASEBKGND, reinterpret_cast<wparam>(dc.GetSafeHdc()), 0); // Symbol in Clientrechteck zentrieren int cxIcon = GetSystemMetrics(SM_CXICON); int cyIcon = GetSystemMetrics(SM_CYICON); CRect rect; GetClientRect(&rect); int x = (rect.Width() - cxIcon + 1) / 2; int y = (rect.Height() - cyIcon + 1) / 2; // Symbol zeichnen dc.DrawIcon(x, y, m_hIcon); } else { CDialog::OnPaint(); } } // Die System ruft diese Funktion auf, um den Cursor abzufragen, der angezeigt wird, während der Benutzer // das minimierte Fenster mit der Maus zieht. HCURSOR CDialogBasedProjectDlg::OnQueryDragIcon() { return static_cast<hcursor>(m_hIcon); } |