mfc编程 孙鑫_孙鑫VC++视频教程笔记-(3)MFC程序框架的剖析 附1-SDI程序流程图
1,尋找WinMain人口:
在安裝目錄下找到MFC文件夾下的SRC文件夾,SRC下是MFC源代碼。
路徑:MFC|SRC|APPMODUL.CPP:
_tWinMain(HINSTANCE?hInstance,?HINSTANCE?hPrevInstance,
LPTSTR?lpCmdLine,?int?nCmdShow)
{
//?call?shared/exported?WinMain
return?AfxWinMain(hInstance,?hPrevInstance,?lpCmdLine,?nCmdShow);
}
注意:(#define?_tWinMain?WinMain)
2,對于全局對象或全局變量來說,在程序運行即WINMAIN函數加載的時候,已經為全局對象或全局變量分配了內存和賦初值。
所以:CTEApp?theApp;->CTEApp?::CTEApp(){}->_tWinMain(){}
說明:每一個MFC程序,有且只有一個從WinApp類派生的類(應用程序類),也只有一個從應用程序類所事例化的對象,表示應用程序本身
。在WIN32程序當中,表示應用程序是通過WINMAIN入口函數來表示的(通過一個應用程序的一個事例號這一個標識來表示的)。在基于MFC應用
程序中,是通過產生一個應用程序對象,用它來唯一的表示了應用程序。
3,通過構造應用程序對象過程中調用基類CWinApp的構造函數,在CWinApp的構造函數中對程序包括運行時一些初始化工作完成了。
CWinApp構造函數:MFC|SRC|APPCORE.CPP
CWinApp::CWinApp(LPCTSTR?lpszAppName){...}//帶參數,而CTEApp構造函數沒有顯式向父類傳參,難道CWinApp()有默認參數?見下:
(在CWinApp類定義中,CWinApp(LPCTSTR?lpszAppName?=?NULL);)
注意:CWinApp()函數中:
pThreadState->m_pCurrentWinThread?=?this;
pModuleState->m_pCurrentWinApp?=?this
(this指向的是派生類CTEApp對象,即theApp)
調試:CWinApp::CWinApp();->CTEApp?theApp;(->CTEApp?::CTEApp())->CWinApp::CWinApp()->CTEApp?::CTEApp()->_tWinMain(){}
4,_tWinMain函數中通過調用AfxWinMain()函數來完成它要完成的功能。(Afx*前綴代表這是應用程序框架函數,是一些全局函數,應用程序
框架是一套輔助生成應用程序的框架模型,把一些類做一些有機的集成,我們可根據這些類函數來設計自己的應用程序)。
AfxWinMain()函數路徑:MFC|SRC|WINMAIN.CPP:
在AfxWinMain()函數中:
CWinApp*?pApp?=?AfxGetApp();
說明:pApp存儲的是指向WinApp派生類對象(theApp)的指針。
//_AFXWIN_INLINE?CWinApp*?AFXAPI?AfxGetApp()
//?{?return?afxCurrentWinApp;?}
調用pThread->InitInstance()
說明:pThread也指向theApp,由于基類中virtual?BOOL?InitApplication()定義為虛函數,所以調用pThread->InitInstance()時候,調用的是
派生類CTEApp的InitInstance()函數。
nReturnCode?=?pThread->Run();
說明:pThread->Run()完成了消息循環。
5,注冊窗口類:AfxEndDeferRegisterClass();
AfxEndDeferRegisterClass()函數所在文件:MFC|SRC|APPCORE.CPP
BOOL?AFXAPI?AfxEndDeferRegisterClass(LONG?fToRegister){...}
說明:設計窗口類:在MFC中事先設計好了幾種缺省的窗口類,根據不同的應用程序的選擇,調用AfxEndDeferRegisterClass()函數注冊所選擇的窗口類。
調試:
CWinApp::CWinApp();->CTEApp?theApp;(->CTEApp?::CTEApp())->CWinApp::CWinApp()->CTEApp?::CTEApp()->_tWinMain(){}//進入程序
->AfxWinMain();->pApp->InitApplication();->pThread->InitInstance()//父類InitInstance虛函數;
->CTEApp::InitInstance()//子類實現函數;
->AfxEndDeferRegisterClass(LONG?fToRegister)//注冊所選擇的窗口類(出于文檔管理,注冊提前,正常的應在PreCreateWindow中進行注冊
)//之后進入創建窗口階段(以下再不做調試)
6,PreCreateWindow()://主要是注冊窗口類
BOOL?CMainFrame::PreCreateWindow(CREATESTRUCT&?cs)
{
if(?!CFrameWnd::PreCreateWindow(cs)?)
return?FALSE;
return?TRUE;
}
說明:
CFrameWnd::PreCreateWindow()函數所在文件:MFC|SRC|WINFRM.CPP
BOOL?CFrameWnd::PreCreateWindow(CREATESTRUCT&?cs)
{
if?(cs.lpszClass?==?NULL)
{
VERIFY(AfxDeferRegisterClass(AFX_WNDFRAMEORVIEW_REG));
//判斷AFX_WNDFRAMEORVIEW_REG型號窗口類是否注冊,如果沒有注冊則注冊
cs.lpszClass?=?_afxWndFrameOrView;?//?COLOR_WINDOW?background
//把注冊后的窗口類名賦給cs.lpszClass
}
if?((cs.style?&?FWS_ADDTOTITLE)?&&?afxData.bWin4)
cs.style?|=?FWS_PREFIXTITLE;
if?(afxData.bWin4)
cs.dwExStyle?|=?WS_EX_CLIENTEDGE;
return?TRUE;
}
其中:
virtual?BOOL?PreCreateWindow(CREATESTRUCT&?cs);//PreCreateWindow()是個虛函數,如果子類有則調用子類的。
#define?VERIFY(f)?ASSERT(f)
#define?AfxDeferRegisterClass(fClass)?AfxEndDeferRegisterClass(fClass)
define?AFX_WNDFRAMEORVIEW_REG?0x00008
const?TCHAR?_afxWndFrameOrView[]?=?AFX_WNDFRAMEORVIEW;//WINCORE.CPP文件中,定義為全局數組。
//#define?AFX_WNDFRAMEORVIEW?AFX_WNDCLASS("FrameOrView")
7,創建窗口:
Create()函數路徑:MFC|SRC|WINFRM.CPP:
CFrameWnd::Create(...){
...
CreateEx(...);//從父類繼承來的,調用CWnd::CreateEx().
...
}
CWnd::CreateEx()函數路徑:MFC|SRC|WINCORE.CPP
BOOL?CWnd::CreateEx(...){
...
if?(!PreCreateWindow(cs))//虛函數,如果子類有調用子類的。
{
PostNcDestroy();
return?FALSE;
}
...
HWND?hWnd?=?::CreateWindowEx(cs.dwExStyle,?cs.lpszClass,
cs.lpszName,?cs.style,?cs.x,?cs.y,?cs.cx,?cs.cy,
cs.hwndParent,?cs.hMenu,?cs.hInstance,?cs.lpCreateParams);
...
}
說明:CreateWindowEx()函數與CREATESTRUCT結構體參數的對應關系,使我們在創建窗口之前通過可PreCreateWindow(cs)修改cs結構體成員來
修改所要的窗口外觀。PreCreateWindow(cs))//是虛函數,如果子類有調用子類的。
HWND?CreateWindowEx(
DWORD?dwExStyle,
LPCTSTR?lpClassName,
LPCTSTR?lpWindowName,
DWORD?dwStyle,
int?x,
int?y,
int?nWidth,
int?nHeight,
HWND?hWndParent,
HMENU?hMenu,
HINSTANCE?hInstance,
LPVOID?lpParam
);
typedef?struct?tagCREATESTRUCT?{?//?cs
LPVOID?lpCreateParams;
HINSTANCE?hInstance;
HMENU?hMenu;
HWND?hwndParent;
int?cy;
int?cx;
int?y;
int?x;
LONG?style;
LPCTSTR?lpszName;
LPCTSTR?lpszClass;
DWORD?dwExStyle;
}?CREATESTRUCT;
8,顯示和更新窗口:
CTEApp類,TEApp.cpp中
m_pMainWnd->ShowWindow(SW_SHOW);//顯示窗口,m_pMainWnd指向框架窗口
m_pMainWnd->UpdateWindow();//更新窗口
說明:
class?CTEApp?:?public?CWinApp{...}
class?CWinApp?:?public?CWinThread{...}
class?CWinThread?:?public?CCmdTarget
{?...
public:
CWnd*?m_pMainWnd;
...}
9,消息循環:
int?AFXAPI?AfxWinMain()
{?...
//?Perform?specific?initializations
if?(!pThread->InitInstance()){...}
//完成窗口初始化工作,完成窗口的注冊,完成窗口的創建,顯示和更新。
nReturnCode?=?pThread->Run();
//繼承基類Run()方法,調用CWinThread::Run()來完成消息循環...
}
CWinThread::Run()方法路徑:MFC|SRC|THRDCORE.CPP
int?CWinThread::Run()
{?...
//?phase2:?pump?messages?while?available
do//消息循環
{
//?pump?message,?but?quit?on?WM_QUIT
if?(!PumpMessage())//取消息并處理
return?ExitInstance();?...
}?while?(::PeekMessage(&m_msgCur,?NULL,?NULL,?NULL,?PM_NOREMOVE));
...
}
說明:
BOOL?PeekMessage(,,,,)函數說明
The?PeekMessage?function?checks?a?thread?message?queue?for?a?message?and?places?the?message?(if?any)?in?the?specified
structure.
If?a?message?is?available,?the?return?value?is?nonzero.
If?no?messages?are?available,?the?return?value?is?zero.
/
BOOL?CWinThread::PumpMessage()
{?...
if?(!::GetMessage(&m_msgCur,?NULL,?NULL,?NULL))//取消息
{...}?...
//?process?this?message
if?(m_msgCur.message?!=?WM_KICKIDLE?&&?!PreTranslateMessage(&m_msgCur))
{
::TranslateMessage(&m_msgCur);//進行消息(如鍵盤消息)轉換
::DispatchMessage(&m_msgCur);//分派消息到窗口的回調函數處理(實際上分派的消息經過消息映射,交由消息響應函數進行處理。)
}
return?TRUE;
}
10,文檔與視結構:
可以認為View類窗口是CMainFram類窗口的子窗口。
DOCument類是文檔類。
DOC-VIEW結構將數據本身與它的顯示分離開。
文檔類:數據的存儲,加載
視類:數據的顯示,修改
11,文檔類,視類,框架類的有機結合:
在CTEApp類CTEApp::InitInstance()函數中通過文檔模板將文檔類,視類,框架類的有機組織一起。...
CSingleDocTemplate*?pDocTemplate;
pDocTemplate?=?new?CSingleDocTemplate(
IDR_MAINFRAME,
RUNTIME_CLASS(CTEDoc),
RUNTIME_CLASS(CMainFrame),?//?main?SDI?frame?window
RUNTIME_CLASS(CTEView));
AddDocTemplate(pDocTemplate);//增加到模板...
----------------------------------------------------------------------------->
//AfxWinMain()函數在WINMAIN.CPP文件中,它主要調用以下函數
AfxWinInit();
pApp->InitApplication();?//內部初始化管理
pThread->InitInstance();?//調用子類中的InitInstance()
CTestApp::InitInstance();
┣━ProcessShellCommand(cmdInfo);?//對命令行進行解釋
┃?CTestDoc::CTestDoc();?//構造文檔類對象
┃?CMainFrame::CMainFrame();?//構造框架窗口對象
┃?CFrameWnd::LoadFrame();?//WINFRM.CPP
┃?┣━AfxEndDeferRegisterClass();?//WINCORE.CPP,注冊窗口類
┃?┃?AfxRegisterClass();?//WINCORE.CPP
┃?┣━CMainFrame::PreCreateWindow();
┃?┃?CFrameWnd::PreCreateWindow();
┃?┃?AfxEndDeferRegisterClass();
┃?┣━AfxRegisterClass();
┃?┗━CFrameWnd::Create();?//創建CMainFrame窗口
┃?CWnd::CreateEx();
┃?CMainFrame::PreCreateWindow();
┃?CFrameWnd::PreCreateWindow();
┃?CTestView::CTestView();?//構造CTestView對象
┃?CWnd::CreateEx();?//創建CTestView窗口
┃?AfxEndDeferRegisterClass();
┃?AfxEndDeferRegisterClass();
┃?CWnd::CreateEx();?//創建CToolBar工具欄
┃?AfxEndDeferRegisterClass();
┃?CWnd::CreateEx();?//創建CStatusBar狀態欄
┃?AfxEndDeferRegisterClass();
┃?AfxRegisterClass();
┃?CWnd::CreateEx();?//創建CDockBar
┃?AfxEndDeferRegisterClass();
┃?CWnd::CreateEx();?//創建CDockBar
┃?AfxEndDeferRegisterClass();
┃?CWnd::CreateEx();?//創建CDockBar
┃?AfxEndDeferRegisterClass();
┃?CWnd::CreateEx();?//創建CDockBar
┣━m_pMainWnd->ShowWindow(SW_SHOW);?//顯示窗口
┗━m_pMainWnd->UpdateWindow();?//更新窗口
nReturnCode?=?pThread->Run();?//進入消息循環
總結
以上是生活随笔為你收集整理的mfc编程 孙鑫_孙鑫VC++视频教程笔记-(3)MFC程序框架的剖析 附1-SDI程序流程图的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: oracle 取mac地址,java执行
- 下一篇: collection转换为list_JA