第三课:MFC思想
学完第一课的Windows程序运行原理及第二课经典C++知识回顾,这一课我们主要来看看MFC是如何用面向对象的方式对传统的面象过程的Windows程序运行原理代码进行封装的。
先看看第一课中的Winmain()代码
int PASCAL WinMain(HINSTANCE hInstance,HINSTANCE hPrevInstance,LPSTR lpCmdLine,int nCmdShow)
{
WNDCLASS wndClass;
wndClass.style=CS_HREDRAW;
wndClass.lpfnWndProc=(WNDPROC)DefWndProc;
wndClass.cbClsExtra=0;
wndClass.cbWndExtra=0;
wndClass.hInstance=hInstance;
wndClass.hIcon=LoadIcon(hInstance,MAKEINTRESOURCE(IDI_ICON1));
wndClass.hCursor=LoadCursor(hInstance,MAKEINTRESOURCE(IDC_CURSOR1));
LOGBRUSH lgbr;
lgbr.lbStyle=BS_SOLID;
lgbr.lbColor=RGB(192,192,0);
lgbr.lbHatch=0;
wndClass.hbrBackground=CreateBrushIndirect(&lgbr);
wndClass.lpszMenuName=NULL;
wndClass.lpszClassName="xxxxx";
RegisterClass(&wndClass);
HWND hWnd;
hWnd=CreateWindow("xxxxx","http://www.it315.org",WS_OVERLAPPEDWINDOW & ~WS_MAXIMIZEBOX ,\
CW_USEDEFAULT,0,CW_USEDEFAULT,0,NULL,NULL,hInstance,NULL);
ShowWindow(hWnd,nCmdShow);
MSG msg;
while(GetMessage(&msg,NULL,0,0))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
return true;
}
在该段代码中,主要由三大部分组件,即设计窗口阶段(由WNDCLASS结构描述部分)、窗口的注册及创建显示过程、消息循环部分。以上的代码是标准的C语言代码,是面向过程的。在MFC中采用了面向对象的思想,即用面向对象的C++思想对以上代码进行了封装,也就是说将一些对窗口进行操作的API的函数封装到了一个类中,以下我将用简短的代码来演示一下这个过程:
class CIt315Wnd
{
public:
HWND m_hWnd;
BOOL Create();
BOOL ShowWindow();
};
BOOL CIt315Wnd::Create()
{
WNDCLASS wndClass;
wndClass.style=CS_HREDRAW;
wndClass.lpfnWndProc=(WNDPROC)DefWndProc;
wndClass.cbClsExtra=0;
wndClass.cbWndExtra=0;
wndClass.hInstance=hInstance;
wndClass.hIcon=LoadIcon(hInstance,MAKEINTRESOURCE(IDI_ICON1));
wndClass.hCursor=LoadCursor(hInstance,MAKEINTRESOURCE(IDC_CURSOR1));
LOGBRUSH lgbr;
lgbr.lbStyle=BS_SOLID;
lgbr.lbColor=RGB(192,192,0);
lgbr.lbHatch=0;
wndClass.hbrBackground=CreateBrushIndirect(&lgbr);
wndClass.lpszMenuName=NULL;
wndClass.lpszClassName="xxxxx";
RegisterClass(&wndClass);
HWND hWnd;
m_hWnd=CreateWindow("xxxxx","http://www.it315.org",WS_OVERLAPPEDWINDOW & ~WS_MAXIMIZEBOX ,\
CW_USEDEFAULT,0,CW_USEDEFAULT,0,NULL,NULL,hInstance,NULL);
if(m_hWnd!=NULL)
return true;
else
return false;
}
BOOL CIt315Wnd::ShowWindow()
{
return ShowWindow(hWnd,nCmdShow);
}
为了保证代码和以前的执行方式一样,Winmain()函数可以写成如下形式:
int PASCAL WinMain(HINSTANCE hInstance,HINSTANCE hPrevInstance,LPSTR lpCmdLine,int nCmdShow)
{
CIt315Wnd m_wnd;
m_wnd.Create();
m_wnd.ShowWindow();
MSG msg;
while(GetMessage(&msg,NULL,0,0))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
return true;
}
此时,如果再写一个新的类来对剩下的代码进行封装,代码如下:
class CIt315App
{
public:
CIt315Wnd* m_pMainWnd;
BOOL InitInstance();
BOOL Run();
CIt315App();
};
CIt315App::CIt315App()
{
if(InitInstance())
Run();
}
BOOL CIt315App::InitInstance()
{
CIt315Wnd m_wnd;
m_pMainWnd=&m_wnd;
m_pMainWnd->Create();
m_pMainWnd->ShowWindow();
return true;
}
BOOL CIt315App::Run()
{
MSG msg;
while(GetMessage(&msg,NULL,0,0))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
return true;
}
此时,在Winmain()函数中仅仅只需要写如下几行代码了,而且对于每个程序来说都是一样,既然如此,那每个程序都这样,微软就把这部分代码为我们写好了,所以,在我们的MFC的工程里,看不到Winmain()的函数。
CIt315App theApp; //全局变量
int PASCAL WinMain(HINSTANCE m_hInstance,HINSTANCE hPrevInstance,LPSTR lpCmdLine,int nCmdShow)
{
hInstance=m_hInstance;
}
因为theApp是一个全局变量,它的构造函数会自动的被调用,所以以上的代码就跟我们在第一课看到的代码的执行逻辑一样。加上Winmain()函数不用我们自己来写,所以要求我们写的类也就只有一个CIt315App类了,由于所有的应用程序的Run()函数都一样,也可以采用一个新的基类来实现Run()然后它的子类就自动的从它继承,也就是说其子类不用实现Run()函数了,也就是说 ,对我们的一般程序设计用户而言,在子类中仅仅只需要实现一个InitInstance()函数即可。而且此时,在我们一般的程序设计用户代码中,程序首先执行Initialize()函数。这也就是MFC程序的入口点。
此时代码演示如下:
class CMyWinApp
{
public:
CIt315Wnd* m_pMainWnd;
BOOL Run();
};
BOOL CMyWinApp::Run()
{
MSG msg;
while(GetMessage(&msg,NULL,0,0))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
return true;
}
class CIt315App:public CMyWinApp
{
public:
CIt315App();
BOOL InitInstance();
};
CIt315App::CIt315App()
{
if(this->InitInstance())
Run();
}
BOOL CIt315App::InitInstance()
{
CIt315Wnd m_wnd;
m_pMainWnd=&m_wnd;
m_pMainWnd->Create();
m_pMainWnd->ShowWindow();
return true;
}
CIt315App theApp;
int PASCAL WinMain(HINSTANCE m_hInstance,HINSTANCE hPrevInstance,LPSTR lpCmdLine,int nCmdShow)
{
hInstance=m_hInstance;
}
以上代码和变换仅仅只是一个代码游戏,但却反应了MFC的一种包装的思想,没有从本质上改变Windows程序的运行原理,但就是这种变换方便了我们的编程。在以上这些代码中,CIt315Wnd已经由MFC实现类名为CWnd,CMyWinApp在MFC中类名为CWnApp。
以上代码仅仅只是对Winmain()函数的包装,对于消息处理部分同样也有类似的包装,在此不多举例。
评论