VC++深入详解 笔记 第三章(2) 一个单文档MFC应用程序的创建过程

      在Win32 SKD应用程序编程中,创建一个窗口程序的简单过程如下:1.设计一个窗口类;2.注册该窗口类;3.创建一个基于该类的窗口;4.显示及更新窗口;5.进入消息循环。另外还要编写窗口过程函数。在MFC编程中,其实也是有这些步骤的,就是比较隐蔽罢了。以创建一个MFC单文档应用程序为例进行说明。
P66 对于一个单文档应用程序,都有一个CMainFrame类,一个以"C+工程名+App"为名字的类,一个以"C+工程名+Doc"为名字的类和一个以"C+工程名+View"为名字的类。假设建立一个名字为 Test 的工程,肯定会包含下面几个类:CMainFrame类,CTestApp类,CTestDoc类,CTestView类。如下图所示:

      在ClassView标签页的类名上双击,右边工作区窗格就会打开定义该类的头文件。
      CTestView类派生于CView类,而CView类是由CWnd类派生出来的。
      CMainFrame类派生于CFrameWnd类,而CFrameWnd类是由CWnd类派生出来的。
P68 WinMain()函数在APPMODUL.CPP文件中。
P69 CTestApp类派生于CWinApp类,后者表示应用程序类。
P73 为什么要定义一个全局对象theApp,让它在WinMain()函数之前执行呢?该对象的作用是什么呢?该对象就表示了应用程序本身。
      使用Win32SDK编写应用程序时,应用程序的句柄由实例句柄来标识。而使用MFC编写应用程序时,应用程序的句柄由一个应用程序类的对象来唯一标识。
P75 AfxWinMain()函数在WINMAIN.CPP文件中。
      Afx前缀的函数代表应用程序框架(Application Framework)函数。在MFC中,以Afx为前缀的函数都是全局函数,可以在程序的任何地方调用它们。
P76 CWinApp类派生于CWinThread类
      AfxGetThread()函数在THRDCORE.CPP文件中。
P77 AfxGetApp()函数位于AFXWIN1.INL中。
      afxCurrentWinApp宏的定义在AFXWIN.H文件中。
1.设计一个窗口类
P78 MFC已经为我们预定义了一些默认的标准窗口类,只需要选择所需的窗口类,然后注册窗口就可以了。所以就不需要再设计窗口类了。
2.注册该窗口类
P78 窗口类的注册是由AfxEndDeferRegisterClass()函数完成的,该函数的定义在WINCORE.CPP文件中。
P80 上面的那个函数内部是调用AfxRegisterClass()函数来注册窗口类的,这个函数的定义在WINCORE.CPP文件中。
P81 AfxRegisterClass()函数最终还是会调用RegisterClass()函数来注册窗口类,这就是Win32 SDK中的函数。
到此为止,就注册了窗口了。
3.创建一个窗口:涉及到CWnd类,CFrameWnd类,CMainFrame类
      CFrameWnd类的声明在AFXWin.h文件中:class CFrameWnd : public CWnd
                          定义在WinFrm.cpp文件中:CFrameWnd::CFrameWnd()
      CMainFrame类的声明在AFXWin.h文件中:class CMainFrame : public CFrameWnd
                          定义在MainFrm.cpp文件中:CMainFrame::CMainFrame()
      CWnd类有一个函数成员CreateEx:

class CWnd : public CCmdTarget { ………… public: // advanced creation (allows access to extended styles) BOOL CreateEx(DWORD dwExStyle, LPCTSTR lpszClassName, LPCTSTR lpszWindowName, DWORD dwStyle, int x, int y, int nWidth, int nHeight, HWND hWndParent, HMENU nIDorHMenu, LPVOID lpParam = NULL); ………… }

      CFrameWnd类有两个函数成员:Create和LoadFrame:

class CFrameWnd : public CWnd { ………… public: BOOL Create(LPCTSTR lpszClassName, LPCTSTR lpszWindowName, DWORD dwStyle = WS_OVERLAPPEDWINDOW, const RECT& rect = rectDefault, CWnd* pParentWnd = NULL, // != NULL for popups LPCTSTR lpszMenuName = NULL, DWORD dwExStyle = 0, CCreateContext* pContext = NULL); // dynamic creation - load frame and associated resources virtual BOOL LoadFrame(UINT nIDResource, DWORD dwDefaultStyle = WS_OVERLAPPEDWINDOW | FWS_ADDTOTITLE, CWnd* pParentWnd = NULL, CCreateContext* pContext = NULL); ………… }

      CFrameWnd类的LoadFrame()函数会调用Create()函数,而Create()函数又会调用CWnd类的CreateEx()函数。

P82 窗口的创建功能是有CWnd类的CreateEx函数实现的。
P81 我们创建的这个MFC应用程序Test,实际上有两个窗口。
P81 CMainFrame()类有一个PreCreateWindow()函数。
P81 该函数首先会调用CFrameWnd的PreCreateWindow函数,后者在WINFRM.CPP文件中。
4.显示及更新窗口:涉及到CWinThread类,CWinApp类,和CTestApp类;CWnd类。
      CWinThread类的声明在AFXWin.h文件中:class CWinThread : public CCmdTarget
                               定义在ThrdCore.cpp文件中:CWinThread::CWinThread(AFX_THREADPROC pfnThreadProc,LPVOID pParam)
      CWinApp类的声明在AFXWin.h文件中:class CWinApp : public CWinThread
                          定义在AppCore.cpp文件中:CWinApp::CWinApp(LPCTSTR lpszAppName)
      CTestApp类的声明在Test.h文件中:class CTestApp : public CWinApp
                           定义在Test.cpp文件中:CTestApp::CTestApp()
      CWinThread类的一个变量成员是:

class CWinThread : public CCmdTarget { ………… public: CWnd* m_pMainWnd; ………… }

      这个变量的类型是CWnd类型。
      CWnd类的声明在AFXWin.h文件中:class CWnd : public CCmdTarget
                      定义在WINCore.cpp文件中:CWnd::CWnd()
      CWnd类的两个函数成员是:

class CWnd : public CCmdTarget { ………… public: BOOL ShowWindow(int nCmdShow); void UpdateWindow(); ………… }

      CWinApp类以public的方式继承CWinThread类,CTestApp类以public的方式继承CWinApp类,所以在CTestApp类中仍然可以访问这个变量成员,而且m_pMainWnd这个变量成员的对外访问属性仍然为public。而m_pMainWnd变量是CWnd类型的,所以这个变量具有ShowWindow()和UpdateWindow()两种属性。在CTestApp类的InitInstance函数中如下代码:

// The one and only window has been initialized, so show and update it. m_pMainWnd->ShowWindow(SW_SHOW); m_pMainWnd->UpdateWindow();

5.进入消息循环:涉及到CWinThread类,CWinApp类,和CTestApp类
      CWinThread类有两个函数成员:

class CWinThread : public CCmdTarget { ………… public: virtual int Run(); virtual BOOL PumpMessage(); // low level message pump ………… }

      CWinApp类以public方式继承CWinThread类之后,重写了Run()函数,但没有重写PumpMessage()函数。

class CWinApp : public CWinThread { ………… public: virtual int Run(); ………… }

      CWinThread类的Run()函数就是完成消息循环这一任务的,该函数是在AfxWinMain()函数中被调用的:nReturnCode = pThread->Run();。
      虽然CTestApp类以public方式继承了CWinApp类,但是CTestApp类并没有重写Run()函数。所以这里调用的Run()函数是CWinApp类中的函数成员。其实在CWinApp类的Run()函数内部还调用了CWinThread类的Run()函数,呵呵。CWinThread类的Run()函数内部还调用了一个PumpMessage()函数,这个函数中就包括了win32SDK中的GetMessage(),TranslateMessage(),DispatchMessage()函数等。

参考:http://blog.csdn.net/subfly/archive/2010/08/11/5805283.aspx

         http://blog.csdn.net/huahuamoon/archive/2008/01/02/2010269.aspx

你可能感兴趣的:(VC++深入详解,笔记)