Windows程序设计__孙鑫C++Lesson3《MFC 程序框架的剖析》
本节要点:
1.认识全局变量、全局对象与main函数执行顺序.
2.对应于Lesson1中的WinMain程序,跟踪MFC 单文档程序了解MFC对Windows程序的封装,了解MFC程序框架.
3.了解MFC中的类的关系,了解了CWnd类.通过添加Button,了解单文档程序的框架及创建过程
4.了解类的封装.
//************************************************************************************************************************
1.程序代码如下:
#include <iostream.h>
//int a=6;//main函数加载前 已经为全局变量分配了内存 并赋初值
class Cpoint
{
public:
Cpoint()
{
}
};
Cpoint pt;//全局对象也是在main函数调用之前 调用构造函数并分配内存空间
void main()
{
//cout<<a<<endl;
}
//************************************************************************************************************************
2.MFC对应于Lesson1中的WinMain实验的窗口创建过程。
窗口创建过程:
(1)产生全局对象 theApp
(2)进入WinMain
(3)调用虚函数InitInstance 完成窗口初始化工作,包括注册 创建 显示 更新
(4)主框架窗口显示及更新
(5)消息循环
整个过程运行的主要函数或过程如下:
//************************************************************************************************************************
//APPMODUL.cpp
extern "C" int WINAPI
_tWinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,
LPTSTR lpCmdLine, int nCmdShow)
{
// call shared/exported WinMain
return AfxWinMain(hInstance, hPrevInstance, lpCmdLine,
nCmdShow);
}
//************************************************************************************************************************
//WINMAIN.cpp
int AFXAPI AfxWinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,
LPTSTR lpCmdLine, int nCmdShow);
执行(!pThread->InitInstance())跳转到子类的InitInstance()过程。
//************************************************************************************************************************
//Test.cpp
BOOL CTestApp::InitInstance()
//************************************************************************************************************************
//WINCORE.cpp
BOOL AFXAPI AfxEndDeferRegisterClass(LONG fToRegister);
BOOL AFXAPI AfxRegisterClass(WNDCLASS* lpWndClass)
其中实现了WNDCLASS wndcls的设计和注册.
//************************************************************************************************************************
//WINFRM.cpp
BOOL CFrameWnd::Create(...);
//WINCORE.cpp
BOOL CWnd::CreateEx(...);
//MainFrm.cpp
BOOL CMainFrame::PreCreateWindow(CREATESTRUCT& cs);
子类先调用父类的PreCreateWindow在调用子类的PreCreateWindow;
CREATESTRUCT 让我们有机会修改窗口 CREATESTRUCT& cs引用形式调用在基类中
是能体现的 。
先判断窗口有没有注册.
//************************************************************************************************************************
//Test.cpp
m_pMainWnd->ShowWindow(SW_SHOW);
m_pMainWnd->UpdateWindow();
显示并更新窗口.
//************************************************************************************************************************
//THREADCORE.cpp
int CWinThread::Run()方法中调用PumpMessage和PeekMessage实现消息循环。
//************************************************************************************************************************
3.了解CWnd类及MFC单文档程序框架
(1)CTestApp包含的主要类:
CTestApp 应用程序类
CTestFrame CTestView(视类)窗口类
Cdocument 文档类
三者组合在一起是通过CSingleDocTemplate
CSingleDocTemplate* pDocTemplate;
pDocTemplate = new CSingleDocTemplate(
IDR_MAINFRAME,
RUNTIME_CLASS(CTestDoc),
RUNTIME_CLASS(CMainFrame),
(2)CWnd 类中有一个公有的数据成员 m_hWnd保存窗口的句柄
(3)创建Button要点:
1.局部变量 成员变量的生命周期问题 在CMainFrame::OnCreate定义CButton btn,并填写如下代码;
//************************************************************************************************************************
btn.Create("SDIEx",WS_CHILD|BS_PUSHBUTTON,CRect(0,0,100,100),this,1);//CWnd* pParentWnd 不能用m_hWnd
//btn.ShowWindow(SW_SHOWNORMAL);
不能显示button,因为局部CButton 生命周期到了 要析构 回收窗口资源。要将btn声明为成员变量CButton m_btn;
2.显示Button 创建button但要显示两种方法,一种是ShowWindow,另一种是创建时加上WS_VISIBLE风格,使用
m_btn.Create("SDIEx",WS_CHILD|WS_VISIBLE|BS_AUTO3STATE,CRect(0,0,100,100),GetParent(),1);
3.在CFrameWnd中在OnCreate处添加代码;在View类首先添加消息处理WM_CREATE
,然后再其中添加代码;在View类中把Button放在主框架上使用GetParent函数获
取主框架指针。
创建button的窗口效果如图:
4.类的封装
实验代码如下,代码并不能执行,只是做说明用.
//************************************************************************************************************************
#include <Windows.h>
class CWnd //自定义的类CWnd 但方法实现中封装了Win32 SDK平台的函数
{ //代码不能执行 仅作封装的说明
public:
BOOL CreateEx(...);
BOOL ShowWindow(int nCmdShow );
BOOL UpdateWindow();
public:
HWND m_hWnd;
);
BOOL CWnd::CreateEx(...)
{
m_hWnd=::CreateWindowEx(dwExStyle,lpClassName,lpWindowName,dwStyle,x,y,
nWeight,nHeight,hWndParent,hMenu,hInstance,lpParam);
if(m_hWnd!=NULL)
return TRUE;
esle
return FALSE;
}
BOOL CWnd::ShowWindow(int nCmdShow )
{
return ::ShowWindow(m_hWnd,nCmdShow);//Win32 的API函数引用使用:: 避免类函数名冲突
}
BOOL CWnd::UpdateWindow()
{
return ::UpdateWindow(m_hWnd);
}
int WINAPI WinMain(
HINSTANCE hInstance, // handle to current instance
HINSTANCE hPrevInstance, // handle to previous instance
LPSTR lpCmdLine, // command line
int nCmdShow // show state
)
{
WNDCLASS WndCls;
WndCls.style=CS_HREDRAW|CS_VREDRAW;
.....
RegisterClass(&WndCls);
CWnd wnd;
wnd.CreateEx(...);
wnd.ShowWindow();
wnd.UpdateWindow();
...Msg Dealer
//窗口和对象的生命周期是不一样的 窗口和对象之间的纽带是句柄保存了窗口资源的地址
//窗口销毁后对象可以存在,但是对象销毁时窗口被回收也一定被销毁了
HWND hWnd;
hWnd=::CreateWindow();
::ShowWindow(hWnd,SW_SHOWNORMAL);
::UpdateWindow(hWnd);
}
本节小结:
本节通过程序断电跟踪调试,让我们看到了MFC内部的封装,了解了在MFC框架下的Windows应用程序处理过程;另外还学习了单文档程序的框架和CWnd类的一些特性以及Win32 SDK 平台的类的封装.