一個典型的 MFC 應用程式並沒有 WinMain 函式,也不會呼叫 RegisterClass 或是 CreateWindow 這兩個函式。
MFC 是一組由 Microsoft 所提供的 C++ 類別函式庫,它將 Windows API 用物件導向的方式包裝起來。
MFC 以全域函式的形式提供了一組 API,它們的名稱都以 Afx 開頭。
下面是書中 MFC 的範例應用程式碼
///////////////////////////////////////////
// Hello.h
class CMyApp : public CWinApp
{
public:
virtual BOOL InitInstance();
};
class CMainWindow : public CFrameWnd
{
public:
CMainWindow();
protected:
afx_msg void OnPaint();
DECLARE_MESSAGE_MAP()
};
///////////////////////////////////////////
// Hello.cpp
#include
#include "Hello.h"
CMyApp myApp;
// CMyApp member functions
BOOL CMyApp::InitInstance()
{
m_pMainWnd = new CMainWindow;
m_pMainWnd->ShowWindow(m_nCmdShow);
m_pMainWnd->UpdateWindow();
return TRUE;
}
// CMainWindow message map and member functions
BEGIN_MESSAGE_MAP(CMainWindow, CFrameWnd)
ON_WM_PAINT()
END_MESSAGE_MAP()
CMainWindow::CMainWindow()
{
Create(NULL, _T("The Hello Application"));
}
void CMainWindow::OnPaint()
{
CPaintDC dc(this);
CRect rect;
GetClientRect(&rect);
dc.DrawText(_T("Hello, MFC"), -1, &rect, DT_SINGLELINE | DT_CENTER | DT_VCENTER);
}
應用程式物件 (important !!)
MFC 應用程式的核心,就是衍生自 CWinApp 類別的應用程式物件。
CWinApp 提供了訊息迴路來擷取訊息,當引用標頭檔 Afxwin.h 後,CWinApp 及其它 MFC
類別即被引入你的程式之中。MFC 有唯一的應用程式物件,且該物件必須被宣告成全域變
數,以讓它在程式一開始就被放到記憶體中。
上述範例程式碼中,Hello 的應用程式類別稱為 CMyApp,而它就被宣告成一個全域變數,
CMyApp 中只改寫一個繼承自 CMyApp 的 InitInstance 函式,它是在應用程式生命週期中
早期被呼叫,時間點是在應用程式開始後,視窗建立之前,所以必須要在 InitInstance
中建立一個視窗,否則程式中是不會有視窗顯示的。
InitInstance 的回傳值決定了框架下一步要做什麼;回傳 FALSE 時會關閉應用程式,反之則
讓程式繼續執行。你也可以將程式執行時所需要做初始化的動作放置在此處。
若想在 MFC 程式中呼叫一般的 API 函式,就必須在函式名稱前面加上全域解析運算子(::),
如 ::UpdateWindow(hwnd);
如此一來,即使呼叫者本身也有相同名稱的成員函式時,也能確保呼叫到該 API 函式。
Message Mapping
將訊息與成員函式關聯起來的表格。
CMainWindow 類別的 WM_PAINT 訊息映射實作如下:
BEGIN_MESSAGE_MAP(CMainWindow, CFrameWnd) // (theClass, baseClass)
ON_WM_PAINT()
END_MESSAGE_MAP()
ON_WM_PAINT 是 Map entry,而相對的 Function prototype 為 afx_msg void OnPaint();
此對映之關係可參考 MSDN。
DECLARE_MESSAGE_MAP()
宣告類別所定義的訊息對映。每一個 CCmdTarget 衍生類別必需要提供一個訊息對映來處理訊息。
當想要處理一個 MFC 沒有提供訊息映射巨集的訊息時,可以用具有一般性的 ON_MESSAGE 巨集
來建立該訊息項目。
PS. 以上 note 參考 "Windows 程式設計使用 MFC" 中文版
MFC 是一組由 Microsoft 所提供的 C++ 類別函式庫,它將 Windows API 用物件導向的方式包裝起來。
MFC 以全域函式的形式提供了一組 API,它們的名稱都以 Afx 開頭。
下面是書中 MFC 的範例應用程式碼
///////////////////////////////////////////
// Hello.h
class CMyApp : public CWinApp
{
public:
virtual BOOL InitInstance();
};
class CMainWindow : public CFrameWnd
{
public:
CMainWindow();
protected:
afx_msg void OnPaint();
DECLARE_MESSAGE_MAP()
};
///////////////////////////////////////////
// Hello.cpp
#include
#include "Hello.h"
CMyApp myApp;
// CMyApp member functions
BOOL CMyApp::InitInstance()
{
m_pMainWnd = new CMainWindow;
m_pMainWnd->ShowWindow(m_nCmdShow);
m_pMainWnd->UpdateWindow();
return TRUE;
}
// CMainWindow message map and member functions
BEGIN_MESSAGE_MAP(CMainWindow, CFrameWnd)
ON_WM_PAINT()
END_MESSAGE_MAP()
CMainWindow::CMainWindow()
{
Create(NULL, _T("The Hello Application"));
}
void CMainWindow::OnPaint()
{
CPaintDC dc(this);
CRect rect;
GetClientRect(&rect);
dc.DrawText(_T("Hello, MFC"), -1, &rect, DT_SINGLELINE | DT_CENTER | DT_VCENTER);
}
應用程式物件 (important !!)
MFC 應用程式的核心,就是衍生自 CWinApp 類別的應用程式物件。
CWinApp 提供了訊息迴路來擷取訊息,當引用標頭檔 Afxwin.h 後,CWinApp 及其它 MFC
類別即被引入你的程式之中。MFC 有唯一的應用程式物件,且該物件必須被宣告成全域變
數,以讓它在程式一開始就被放到記憶體中。
上述範例程式碼中,Hello 的應用程式類別稱為 CMyApp,而它就被宣告成一個全域變數,
CMyApp 中只改寫一個繼承自 CMyApp 的 InitInstance 函式,它是在應用程式生命週期中
早期被呼叫,時間點是在應用程式開始後,視窗建立之前,所以必須要在 InitInstance
中建立一個視窗,否則程式中是不會有視窗顯示的。
InitInstance 的回傳值決定了框架下一步要做什麼;回傳 FALSE 時會關閉應用程式,反之則
讓程式繼續執行。你也可以將程式執行時所需要做初始化的動作放置在此處。
若想在 MFC 程式中呼叫一般的 API 函式,就必須在函式名稱前面加上全域解析運算子(::),
如 ::UpdateWindow(hwnd);
如此一來,即使呼叫者本身也有相同名稱的成員函式時,也能確保呼叫到該 API 函式。
Message Mapping
將訊息與成員函式關聯起來的表格。
CMainWindow 類別的 WM_PAINT 訊息映射實作如下:
BEGIN_MESSAGE_MAP(CMainWindow, CFrameWnd) // (theClass, baseClass)
ON_WM_PAINT()
END_MESSAGE_MAP()
ON_WM_PAINT 是 Map entry,而相對的 Function prototype 為 afx_msg void OnPaint();
此對映之關係可參考 MSDN。
DECLARE_MESSAGE_MAP()
宣告類別所定義的訊息對映。每一個 CCmdTarget 衍生類別必需要提供一個訊息對映來處理訊息。
當想要處理一個 MFC 沒有提供訊息映射巨集的訊息時,可以用具有一般性的 ON_MESSAGE 巨集
來建立該訊息項目。
PS. 以上 note 參考 "Windows 程式設計使用 MFC" 中文版
留言