二、
完成WinMain函数主要完成窗口产生过程,即:
设计窗口,注册窗口,构造窗口,显示窗口,更新窗口,消息循环,处理消息。
1.CWinApp内部运行机制
CWinApp---在appmodul.cpp中
具体的可以参考CWinApp函数。
1)
pThreadState->m_pCurrentWinThread = this;
这里的this指针是指向CWinApp子类CTestApp对象theApp的指针;
2)
CWinApp运行完成,即基类构造函数完成,从而基子类CTestApp构造函数也初始化完成,然后
为子类CTestApp对象theApp分配完内存空间。接下来,进入入口函数WinMain中。
CWinApp在appcore.cpp中--全局对象theApp--子类构造函数调用CTestApp()--基类构造函数调用CWinApp()在appcore.cpp中
2.WinMain 即(_tWinMain()函数)函数
WinMain函数---在appcore.cpp中
AfxWinMain函数---在winmain.cpp中
(以Afx开头的是全局函数,可以被其它对象调用)
WinMain函数主要完成窗口产生过程,即:
设计窗口,注册窗口,构造窗口,显示窗口,更新窗口,消息循环,处理消息。
1)注册窗口前的初始化工作
由pThread->InitInstance()完成
AfxWinMain函数下面方法:
CWinThread* pThread = AfxGetThread();
CWinApp* pApp = AfxGetApp();
AfxGetThread()和 AfxGetApp() 都是获得在CWinApp中构造函数内赋给 pThreadState->m_pCurrentWinThread 对象
的this指针,也即是获得指向子类CTestApp对象theApp的指针,保存在pThread与pApp中。所以实际上pThread与pApp
都是保存的theApp指针。
pThread与pApp 共调用了三个方法,即子类对象theApp调用了三个方法:
pApp->InitApplication() MFC内部初始化管理所调用的函数
pThread->InitInstance() 因CWinThread类中InitInstance()为虚函数,由多态原理,所以这里调用的是子类CTestApp中的InitInstance()
pThread->Run() 完成消息循环
其中
pThread->InitInstance() 初始化完成后,即开始注册窗口
CWinApp在appcore.cpp中--全局对象theApp--子类构造函数调用CTestApp()--基类构造函数调用CWinApp()在appcore.cpp中
--_tWinMain()在appmodul.cpp中--AfxWinMain()中的pThread->InitInstance()在winmain.cpp中--调用CTestApp::InitInstance()在当前项目
--设计注册窗口
2)设计窗口
AfxEndDeferRegisterClass()完成(有很多if语句中).
AfxEndDeferRegisterClass()---在wincore.cpp中.
MFC中默认定义了几种窗口类,只是调用函数AfxEndDeferRegisterClass()就可以完成设计窗口过程。
在里面会根据应用程序要求的不同窗口类型设计不同的窗口,在很多if条件语句中。
3)注册窗口
在AfxEndDeferRegisterClass()函数中,由AfxRegisterClass()完成.
AfxEndDeferRegisterClass()---在wincore.cpp中.
在AfxRegisterClass()函数中
AfxCtxGetClassInfo() 判断要注册的窗口是否已经注册.
注意:
单文档结构和多文档结构在注册窗口上有不同的顺序.
单文档结构:先就调用AfxEndDeferRegisterClass() 进行窗口注册
多文档结构:先调用
子类CMainFrame::PreCreateWindow(CREATESTRUCT& cs)
再调用基类CFrameWnd::PreCreateWindow(CREATESTRUCT& cs)
再调用AfxEndDeferRegisterClass()进行窗口注册
4)产生窗口之前
(单文档结构)
CWinApp在appcore.cpp中--全局对象theApp--子类构造函数调用CTestApp()--基类构造函数调用CWinApp()在appcore.cpp中
--_tWinMain()在appmodul.cpp中--AfxWinMain()中的pThread->InitInstance()在winmain.cpp中--调用CTestApp::InitInstance()在当前项目
--设计窗口AfxEndDeferRegisterClass()在wincore.cpp中--注册窗口AfxEndDeferRegisterClass()中的AfxRegisterClass()在wincore.cpp中
--产生窗口之前调用子类CMainFrame::PreCreateWindow(CREATESTRUCT& cs)在MainFrm.cpp中--产生窗口之前调用基类CFrameWnd::PreCreateWindow(CREATESTRUCT& cs)在winfrm.cpp中
--注册窗口AfxDeferRegisterClass(AFX_WNDFRAMEORVIEW_REG)在wincore.cpp中
BOOL CMainFrame::PreCreateWindow(CREATESTRUCT& cs) 在当前工程的MainFrm.cpp中
BOOL CFrameWnd::PreCreateWindow(CREATESTRUCT& cs) 在winfrm.cpp中
调用AfxDeferRegisterClass(AFX_WNDFRAMEORVIEW_REG) 判断当然窗口类型有没有注册,实际是调用AfxDeferRegisterClass(fClass)
AfxDeferRegisterClass(AFX_WNDFRAMEORVIEW_REG)--在afximpl.h中
#define AfxDeferRegisterClass(fClass) AfxEndDeferRegisterClass(fClass) 是一个宏
产生两个窗口:CMainFrame和子窗口CTestView
CMainFrame--CFrameWnd--CWnd 凡是从CWnd派生出来的类都是窗口类
子窗口CTestView--CView--CWnd 子窗口也是一个窗口类
CMainFrame产生的窗口是框架窗口,其内部还可以有子窗口.
5)创建窗口
CreateWindow Function
CreateWindowEx Function
BOOL CWnd::CreateEx(DWORD dwExStyle,
LPCTSTR lpszClassName,
LPCTSTR lpszWindowName, DWORD dwStyle,
int x, int y, int nWidth, int nHeight,
HWND hWndParent, HMENU nIDorHMenu, LPVOID lpParam
)
在wincore.cpp中
BOOL CFrameWnd::Create(LPCTSTR lpszClassName,
LPCTSTR lpszWindowName,
DWORD dwStyle,
const RECT& rect,
CWnd* pParentWnd,
LPCTSTR lpszMenuName,
DWORD dwExStyle,
CCreateContext* pContext
)
在winfrm.cpp中
CWinApp在appcore.cpp中--全局对象theApp--子类构造函数调用CTestApp()--基类构造函数调用CWinApp()在appcore.cpp中
--_tWinMain()在appmodul.cpp中--AfxWinMain()中的pThread->InitInstance()在winmain.cpp中--调用CTestApp::InitInstance()在当前项目
--设计窗口AfxEndDeferRegisterClass()在wincore.cpp中--注册窗口AfxEndDeferRegisterClass()中的AfxRegisterClass()在wincore.cpp中
--产生窗口之前调用子类CMainFrame::PreCreateWindow(CREATESTRUCT& cs)在MainFrm.cpp中--产生窗口之前调用基类CFrameWnd::PreCreateWindow(CREATESTRUCT& cs)在winfrm.cpp中
--注册窗口AfxDeferRegisterClass(AFX_WNDFRAMEORVIEW_REG)在wincore.cpp中
--创建窗口调用子类BOOL CFrameWnd::Create()在winfrm.cpp中--创建窗口调用基类BOOL CWnd::CreateEx()在wincore.cpp中(--循环产生窗口--)
BOOL CWnd::CreateEx()在wincore.cpp中,调用PreCreateWindow(cs)和::AfxCtxCreateWindowEx(),为了在创建窗口之前,有机会修改窗口的外观样式.
PreCreateWindow在afxwn.h中定义为:
virtual BOOL PreCreateWindow(CREATESTRUCT& cs);
所以这里调用的是子类的BOOL CMainFrame::PreCreateWindow(CREATESTRUCT& cs),
AfxCtxCreateWindowEx是宏:
#define AfxCtxCreateWindowEx AfxCtxCreateWindowExW 在afxcomctl32.h中
在afxcomctl32.h中,AFX_ISOLATIONAWARE_STATICLINK_FUNC(HWND ,CreateWindowExW,(DWORD dwExStyle,LPCWSTR lpClassName,LPCWSTR lpWindowName,DWORD dwStyle,int X,int Y,int nWidth,int nHeight,HWND hWndParent,HMENU hMenu,HINSTANCE hInstance,LPVOID lpParam),(dwExStyle,lpClassName,lpWindowName,dwStyle,X,Y,nWidth,nHeight,hWndParent,hMenu,hInstance,lpParam),NULL)
CreateWindowEx也是宏:
#define CreateWindowEx CreateWindowExW
CREATESTRUCT与CreateWindowEx的定义:
typedef struct tagCREATESTRUCT {
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;
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
);
CREATESTRUCT中成员变量与CreateWindowEx中的参数是一致的,不过顺序相反.
利用CREATESTRUCT结构体主要为了产生窗口之前,有机会修改窗口外观.
6)显示窗口和更新窗口
在Test.cpp中的BOOL CTestApp::InitInstance()中.
当Test.cpp中ProcessShellCommand(cmdInfo)成功执行完后,表示窗口创建已经完成.
再通过:
m_pMainWnd->ShowWindow(SW_SHOW);
m_pMainWnd->UpdateWindow();
来完成窗口显示和窗口更新
m_pMainWnd是指向CMainFrm框架窗口对象的一个指针
7)消息循环
CWinThread::Run在THRDCORE.CPP中.
do while中的PumpMessage()--->CWinThread::PumpMessage()-->BOOL AFXAPI AfxInternalPumpMessage()再重复do while中的PumpMessage()
CWinApp在appcore.cpp中--全局对象theApp--子类构造函数调用CTestApp()--基类构造函数调用CWinApp()在appcore.cpp中
--_tWinMain()在appmodul.cpp中--AfxWinMain()中的pThread->InitInstance()在winmain.cpp中--调用CTestApp::InitInstance()在当前项目
--设计窗口AfxEndDeferRegisterClass()在wincore.cpp中--注册窗口AfxEndDeferRegisterClass()中的AfxRegisterClass()在wincore.cpp中
--产生窗口之前调用子类CMainFrame::PreCreateWindow(CREATESTRUCT& cs)在MainFrm.cpp中--产生窗口之前调用基类CFrameWnd::PreCreateWindow(CREATESTRUCT& cs)在winfrm.cpp中
--注册窗口AfxDeferRegisterClass(AFX_WNDFRAMEORVIEW_REG)在wincore.cpp中
--创建窗口调用子类BOOL CFrameWnd::Create()在winfrm.cpp中--创建窗口调用基类BOOL CWnd::CreateEx()在wincore.cpp中(--循环产生窗口--)
--显示窗口调用BOOL CTestApp::InitInstance()中的m_pMainWnd->ShowWindow(SW_SHOW)在Test.cpp(应用程序类)中;
--更新窗口调用BOOL CTestApp::InitInstance()中的m_pMainWnd->UpdateWindow()在Test.cpp(应用程序类)中;
--do while中的PumpMessage()--->CWinThread::PumpMessage()-->BOOL AFXAPI AfxInternalPumpMessage()(--再重复do while中的PumpMessage()--)