MFC封装API

本文详细解析了Win32应用程序架构的基本组成部分及其运行流程,并对比介绍了MFC框架如何封装Windows API以简化开发过程。从MFC项目的结构到执行流程,再到窗口的设计与创建,全面阐述了MFC应用程序的工作原理。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

一、Win32Application Architecture

一个Win32 Application Architecture的代码结构如下:

LRESULT CALLBACK WinWordsProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam);  //定义回调处理消息函数

 

int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nShowCmd){

         // 创建一个窗口类分为三步:1.设计窗口类 2.注册窗口类 3.创建窗口 4.显示及更新窗口

         // 步骤1.设计窗口类

         WNDCLASS wc;

……

         // 步骤2:注册窗口类

         RegisterClass(&wc);

         // 步骤3:创建窗口

         HWND hw = NULL;  

         hw = CreateWindow("Icanth2011", "My Fist Win32 Application Project!~", WS_OVERLAPPEDWINDOW, CW_USEDEFAULT, 0, 600, 400, NULL, NULL, hInstance, NULL);

         // 步骤4:显示及更新窗口

         ShowWindow(hw, SW_SHOWNORMAL);

         UpdateWindow(hw);

         // 消息循环

         MSG msg;

         BOOL bRet;

         while((bRet=GetMessage(&msg, NULL, 0, 0))!=0){

                   if(-1 == bRet){

                            return -1;

                   }

                   TranslateMessage(&msg);

                   DispatchMessage(&msg);

         }

         return msg.wParam;

}

 
 


由此可见,Win32 Application 程序的组成分为如下几个部分:

1.       找到WinMain程序入口,并开始执行

2.       创建并设计窗口类

3.       注册窗口类

4.       创建窗口

5.       显示及更新窗口

6.       循环获取消息,经处理,交还系统让其调用相关回调消息处理函数进行处理。

 

二、MFCArchitecture

由于Windows API过多,不方便程序员使用,并且非面对象。于是MFC被用于对Windows API进行封装,MFC始终实际运行过程就是Win32 Application程序的运行过程。

 

1.      MFC的项目结构

利用MFC AppWipzard自动生成的项目包括五个文件:CMyFirstMFCApp、CMainFrame、CFirstMFCDoc、CMyFirstCView、CAboutDlg。CMyFirstMFCApp继承自CWinApp,CMainFrame、CMyFirstCView、CAboutDlg都继承自CWnd,CFirstMFCDoc继承自CDocument,体现“文档/视图”结构。其项目结构如下所示:

 

2.      MFC的执行过程

对于MFC框架运行过程进行剖析,最好的资料是MFC源代码,VC6位于“\Microsoft Visual Studio\VC98\MFC\SRC”下。执行过程如下:

定义theApp(:CMyFistMFCApp)

                   ——>执行构造函数:CWinApp()->CMyFistMFCApp()->

                                     ——>程序入口_tWinMain (宏,定义为WInMain)

——>执行AftxWinMain

 

 
 

 

 

 

 


2.1  MFC的WinMain

在\SRC\APPMODUL.CPP中,可找到如下代码:

MFC\SRC\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);

}

 

 
 

 

 

 

 

 

 

 

 

 

 


而其中_tWinMain其实就是WinMain函数的宏,定义如下:

 

#define _tmain      main

#define _tWinMain   WinMain

#ifdef  _POSIX_

#define _tenviron   environ

 

 
 

 

 

 


由此可见,WinMain中调用AfxWinMain进行处理。MFC包含此文件,故将找到此入口并自动调用执行。

 

2.2  theApp全局对象

在Project\CMyFirstMFCApp.CPP中,可找到一行代码发下:

Project\CMyFirstMFCApp.CPP:

 

/////////////////////////////////////////////////////////////////////////////

// The one and only CMyFistMFCApp object

CMyFistMFCApp theApp;

 

 
 

 

 

 

 


当定义theApp时,将先执行CWinApp(\MFC\SRC\APPCORE.CPP)的构造函数:

\MFC\SRC\APPCORE.CPP:

 

CWinApp::CWinApp(LPCTSTR lpszAppName) // 有在该类定义时有默认值NULL

{

         if (lpszAppName != NULL)

                   m_pszAppName = _tcsdup(lpszAppName);

         else

                   m_pszAppName = NULL;

 

         // initialize CWinThread state

         AFX_MODULE_STATE* pModuleState = _AFX_CMDTARGET_GETSTATE();

         AFX_MODULE_THREAD_STATE* pThreadState = pModuleState->m_thread;

         ASSERT(AfxGetThread() == NULL);

         pThreadState->m_pCurrentWinThread = this;

         ASSERT(AfxGetThread() == this);

         m_hThread = ::GetCurrentThread();

         m_nThreadID = ::GetCurrentThreadId();

 

         // initialize CWinApp state

         ASSERT(afxCurrentWinApp == NULL); // only one CWinApp object please

         pModuleState->m_pCurrentWinApp = this; // handle,this代表子类CMyFirstMFCApp对象

         ASSERT(AfxGetApp() == this);

……

}

 

 
 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 


2.3  AfxWinMain(WINMAIN.CPP)

 

1.AfxWindMain定义

 

\MFC\SRC\WINMAIN.CPP:

 

int AFXAPI AfxWinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,

         LPTSTR lpCmdLine, int nCmdShow)

{

         CWinThread* pThread = AfxGetThread();

         CWinApp* pApp = AfxGetApp();

         if (!AfxWinInit(hInstance, hPrevInstance, lpCmdLine, nCmdShow))

         if (pApp != NULL && !pApp->InitApplication())

                   goto InitFailure;

         if (!pThread->InitInstance())

         {

                   if (pThread->m_pMainWnd != NULL)

                   {

                            pThread->m_pMainWnd->DestroyWindow();

                   }

                   goto InitFailure;

         }

         nReturnCode = pThread->Run();

}

 

 
 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 


2.AfxGetThread

AfxGetThread(THRDCORE.CPP)中调用AfxGetApp,和afxGetApp返回同值,代码如下所示:

\MFC\SRC\ THRDCORE.CPP:

 

CWinThread* AFXAPI AfxGetThread()

{

         // check for current thread in module thread state

         AFX_MODULE_THREAD_STATE* pState = AfxGetModuleThreadState();

         CWinThread* pThread = pState->m_pCurrentWinThread;

         // if no CWinThread for the module, then use the global app

         if (pThread == NULL)

                   pThread = AfxGetApp();

         return pThread;

}

 

 
 

 

 

 

 

 

 

 

 

 

 

 

 


3.AfxGetApp

AfxGetApp(AFXWIN1.INL)中定义:

AFXWIN1.INL:

 

_AFXWIN_INLINE CWinApp* AFXAPI AfxGetApp(){ return afxCurrentWinApp; }

 

 
 

 

 

 

 


而afxCurrentWinApp定义位于AFXWIN.H文件中,如下:

AFXWIN.H:

 

#define afxCurrentWinApp AfxGetModuleState()->m_pCurrentWinApp

 

 
 

 

 

 


即为CWinApp构造函数时初始化为this的m_pCurrentWinApp。

 

4.InitInstance

类CWinAPP(APPCORE.CPP)中InitInstance函数定义为:

\MFC\SRC\ APPCORE.CPP:

 

// overrides for implementation

virtual BOOL InitInstance();

 

 
 

 

 

 


类InitInstance即为虚函数,根据多态性,将调用CMyFirstMFCApp类的InitInstance。

 

2.4  InitInstance(CMyFirstMFCAPP.CPP)

\MFC\SRC\ CMyFirstMFCAPP.CPP:

 

BOOL CMyFistMFCApp::InitInstance()

{

         CSingleDocTemplate* pDocTemplate;

         pDocTemplate = new CSingleDocTemplate(

                   IDR_MAINFRAME,

                   RUNTIME_CLASS(CMyFistMFCDoc),

                   RUNTIME_CLASS(CMainFrame),       // main SDI frame window

                   RUNTIME_CLASS(CMyFistMFCView));

         AddDocTemplate(pDocTemplate);

         m_pMainWnd->ShowWindow(SW_SHOW);

         m_pMainWnd->UpdateWindow();

}

 

 
 

 

 

 

 

 

 

 

 

 

 

 

 


2.5  MFC框架窗口

CFirstMyMFC有两个窗口,其中一个是CMainFrame。

 

2.5.1 设计和注册窗口

 

1.       CMainFrame::PreCreateWindow定义(\Project\CMainFrame.cpp)

\MFC\SRC\ CMyFirstMFCAPP.CPP:

 

BOOL CMainFrame::PreCreateWindow(CREATESTRUCT& cs)

{

         if( !CFrameWnd::PreCreateWindow(cs) )

                   return FALSE;

         return TRUE;

}

 

 
 

 

 

 

 

 


2.       CFrameWnd::PreCreateWindow(CREATESTRUCT& cs) (\MFC\SRC\WINFRM.CPP)

 

 

\MFC\SRC\ CMyFirstMFCAPP.CPP:

 

BOOL CFrameWnd::PreCreateWindow(CREATESTRUCT& cs)

{

         if (cs.lpszClass == NULL)

         {

                   VERIFY(AfxDeferRegisterClass(AFX_WNDFRAMEORVIEW_REG));

                   cs.lpszClass = _afxWndFrameOrView;  // COLOR_WINDOW background

         }

         return TRUE;

}

 

 
 

 

 

 

 

 

 

 

 


其中,AfxDeferRegisterClass即为AfxEndDeferRegisterClass的宏定义,位于AFXIMPL.H文件中:

AFXIMPL.H:

 

#define AfxDeferRegisterClass(fClass) AfxEndDeferRegisterClass(fClass)

 

 
 

 

 

 


3.       AfxEndDeferRegisterClass (位于WINCORE.CPP中)

此处指定DefWindowProc函数来处理回调消息。 (!~)

MFC\SRC\WINCORE.CPP:

 

BOOL AFXAPI AfxEndDeferRegisterClass(LONG fToRegister)

{

         // mask off all classes that are already registered

         AFX_MODULE_STATE* pModuleState = AfxGetModuleState();

         fToRegister &= ~pModuleState->m_fRegisteredClasses;

         if (fToRegister == 0)

                   return TRUE;

         LONG fRegisteredClasses = 0;

         // common initialization

         WNDCLASS wndcls;

         memset(&wndcls, 0, sizeof(WNDCLASS));   // start with NULL defaults

         wndcls.lpfnWndProc = DefWindowProc;

         wndcls.hInstance = AfxGetInstanceHandle();

         wndcls.hCursor = afxData.hcurArrow;

         INITCOMMONCONTROLSEX init;

         init.dwSize = sizeof(init);

         // work to register classes as specified by fToRegister, populate fRegisteredClasses as we go

         if (fToRegister & AFX_WND_REG)

         {

                   // Child windows - no brush, no icon, safest default class styles

                   wndcls.style = CS_DBLCLKS | CS_HREDRAW | CS_VREDRAW;

                   wndcls.lpszClassName = _afxWnd;

                   if (AfxRegisterClass(&wndcls))

                            fRegisteredClasses |= AFX_WND_REG;

         }

         ……

}

 

 
 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 


4.       AfxRegisterClass  (位于WINCORE.CPP中)

MFC\SRC\WINCORE.CPP:

 

BOOL AFXAPI AfxRegisterClass(WNDCLASS* lpWndClass)

{

         WNDCLASS wndcls;

         if (GetClassInfo(lpWndClass->hInstance, lpWndClass->lpszClassName,

                   &wndcls))

         {

                   // class already registered

                   return TRUE;

         }

         if (!::RegisterClass(lpWndClass))

         {

                   TRACE1("Can't register window class named %s\n",

                            lpWndClass->lpszClassName);

                   return FALSE;

         }

         return TRUE;

}

 

 
 

 

 

 

 

 

 

 

 

 

 

 

 

 

 


2.5.2 创建窗口

1. CFrameWnd::Create  (WINFRM.CPP)

MFC\SRC\WINFRM.CPP:

 

BOOL CFrameWnd::Create(LPCTSTR lpszClassName,

         LPCTSTR lpszWindowName,

         DWORD dwStyle,

         const RECT& rect,

         CWnd* pParentWnd,

         LPCTSTR lpszMenuName,

         DWORD dwExStyle,

         CCreateContext* pContext)

{

         HMENU hMenu = NULL;

         if (lpszMenuName != NULL)

         {

                   // load in a menu that will get destroyed when window gets destroyed

                   HINSTANCE hInst = AfxFindResourceHandle(lpszMenuName, RT_MENU);

                   if ((hMenu = ::LoadMenu(hInst, lpszMenuName)) == NULL)

                   {

                            TRACE0("Warning: failed to load menu for CFrameWnd.\n");

                            PostNcDestroy();            // perhaps delete the C++ object

                            return FALSE;

                   }

         }

         m_strTitle = lpszWindowName;    // save title for later

         if (!CreateEx(dwExStyle, lpszClassName, lpszWindowName, dwStyle,

                   rect.left, rect.top, rect.right - rect.left, rect.bottom - rect.top,

                   pParentWnd->GetSafeHwnd(), hMenu, (LPVOID)pContext))

         {

                   TRACE0("Warning: failed to create CFrameWnd.\n");

                   if (hMenu != NULL)

                            DestroyMenu(hMenu);

                   return FALSE;

         }

         return TRUE;

}

 

 
 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 


3.       CWnd:CreateEx (WINCORE.CPP)

MFC\SRC\WINFRM.CPP:

 

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)

{

         // allow modification of several common create parameters

         CREATESTRUCT cs;

         cs.dwExStyle = dwExStyle;

         ……

         if (!PreCreateWindow(cs)) //完成注册窗口类工作

         {

                   PostNcDestroy();

                   return FALSE;

         }

 

         AfxHookWindowCreate(this);

         HWND hWnd = ::CreateWindowEx(cs.dwExStyle, cs.lpszClass,

                            cs.lpszName, cs.style, cs.x, cs.y, cs.cx, cs.cy,

                            cs.hwndParent, cs.hMenu, cs.hInstance, cs.lpCreateParams);

         ……

}

 

 
 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 


以下是CREATESTRUCT和CreateWindowEx参数的对比:


由于CREATESTRUCT中的属性都定义为指针,故可在PreCreateWindow中更改属性,在CreateWindowEx中将更改显示。

 

4.      MFC的调用关系

① theApp

theApp(CMyFirstMFCApp.CPP)

——> CWinAPP ::CWinAPP(){ pModuleState->m_pCurrentWinApp = this;  }

 

 
 

 

 

 


② _tWinMain(APPMODUL.CPP)

_tWinMain ()

{

AfxWinMain(hInstance, hPrevInstance, lpCmdLine, nCmdShow);

}

 

 
 

 

 

 

 

 

 

  


③ AfxWinMain(WinMain.CPP)

int AFXAPI AfxWinMain()

{

CWinThread* pThread = AfxGetThread(); //——>return AfxGetApp() (:THRDCORE.CPP)

         CWinApp* pApp = AfxGetApp();

//——>return afxCurrentWInApp (:AFXWIN1.INL)

//——>return AfxGetModuleState()->m_pCurrentWinApp (:AFXWIN.H)

AfxWinInit(hInstance, hPrevInstance, lpCmdLine, nCmdShow);

pApp->InitApplication();

pThread-> InitInstance ();

         //——> CMyFirstMFCApp::InitInstance

                   //——> AddDocTemplate(pDocTemplate);

                            //——> m_pMainWnd->ShowWindow(SW_SHOW);

                   //——> m_pMainWnd->UpdateWindow();

pThread->Run();

}

 

 
 

 

 

 

 

 

 

 

 

 

 

 

 

 


④ 窗口

设计和注册窗口:

CMainFrame::PreCreateWindow (\Project\ CMainFrame.cpp)

         ——>CFrameWnd::PreCreateWindow

                   ——>AfxDeferRegisterClass(宏= AfxEndDeferRegisterClass)

——>AfxEndDeferRegisterClass

——>AfxRegisterClass

         ——>::RegisterClass (SDK)

 

 
 

 

 

 

 

 

 

 


创建窗口:

CFrameWnd::Create()

         ——>CFrameWnd::CreateEx()

——>CWnd::CreateEx()

         ——>virsual CWnd::PreCreateWIndow(虚函数,调用子类中CFrameWnd:: PreCreateWIndow),

:: CreateWIndowEx()

使用C++代码封装的win32操作类, 与MFC相似,对于学习SDK与C++是巨好的参考 Tutorials Menu of tutorials Tutorial 1: The Simplest Window Tutorial 2: Using Classes and Inheritance Tutorial 3: Using Messages to Create a Scribble Window Tutorial 4: Repainting the Window Tutorial 5: Wrapping a Frame around our Scribble Window Tutorial 6: Customising Window Creation Tutorial 7: Customising the Toolbar Tutorial 8: Loading and Saving Files Tutorial 9: Printing Tutorial 10: Finishing Touches Tutorial 1: The Simplest Window The following code uses Win32++ to create a window. This is all the code you need (in combination with Win32++) to create and display a simple window. Note that in order to add the Win32++ code to our program, we use an #include statement as shown below. #include "../Win32++/Wincore.h" INT WINAPI WinMain(HINSTANCE, HINSTANCE, LPTSTR, int) { //Start Win32++ CWinApp MyApp; //Create a CWnd object CWnd MyWindow; //Create (and display) the window MyWindow.Create(); //Run the application return MyApp.Run(); } This program has four key steps: Start Win32++. We do this here by creating a CWinApp object called MyApp. Create a CWnd object called MyWindow. Create a default window by calling the Create function. Start the message loop, by calling the Run function. If you compile and run this program, you'll find that the application doesn't end when the window is closed. This is behaviour is normal. An illustration of how to use messages to control the windows behaviour (including closing the application) will be left until tutorial 3.
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值