第三课: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()函数的包装,对于消息处理部分同样也有类似的包装,在此不多举例。

评论