?? .............略
?? // App global initializations (rare)
?? if (pApp != NULL && !pApp->InitApplication()) ?? goto InitFailure; ??
?? if (!pThread->InitInstance()) ?? {
?? .........略 ?? } ??
?? // Run函数位于THRDCORE.cpp中,由此函数进入消息循环 ?? nReturnCode = pThread->Run(); ??
?? ..............略 ??
?? return nReturnCode; ?? }
上面InitInstance函数的代码如下:
C++代码
?? BOOL CTestApp::InitInstance() ?? {
?? .............略
?? CSingleDocTemplate* pDocTemplate; ?? pDocTemplate = new CSingleDocTemplate( ?? IDR_MAINFRAME,
?? RUNTIME_CLASS(CTestDoc),
?? RUNTIME_CLASS(CMainFrame), // main SDI frame window ??? RUNTIME_CLASS(CTestView)); ??? if (!pDocTemplate) ??? return FALSE;
??? AddDocTemplate(pDocTemplate);
??? // Parse command line for standard shell commands, DDE, file open ???
??? CCommandLineInfo cmdInfo;
??? ParseCommandLine(cmdInfo); ???
??? //ProcessShellCommand位于AppUI2.cpp中,注册并创建窗口 ??? if (!ProcessShellCommand(cmdInfo)) ??? return FALSE; ???
??? m_pMainWnd->ShowWindow(SW_SHOW); ??? m_pMainWnd->UpdateWindow(); ???
??? return TRUE; ??? }
InitInstance中的ProcessShellCommand函数又调用了CMainFrame的LoadFrame函数注册并创建了窗口,执行完ProcessShellCommand函数以后,调用了m_pMainWnd的ShowWindow和UpdateWindow函数显示并更新框架窗口。这些是不是与上面的SDK程序十分类似?
接下来该是消息循环了,上面的AfxWinMain函数中调用了pThread的Run函数(位于THRDCORE.cpp中),在Run中包含了消息循环。Run函数的代码如下:
C++代码
??? int CWinThread::Run() ??? {
??? .............略
??? // phase2: pump messages while available ??? do ??? {
??? // pump message, but quit on WM_QUIT ??? if (!PumpMessage()) ??? return ExitInstance(); ???
??? // reset \ ??? if (IsIdleMessage(&m_msgCur)) ??? {
??? bIdle = TRUE; ???
??? lIdleCount = 0;
??? ??? }
??? } while (::PeekMessage(&m_msgCur, NULL, NULL, NULL, PM_NOREMOVE)); ??? ..............略 ??? } ???
??? BOOL CWinThread::PumpMessage() ??? {
??? return AfxInternalPumpMessage(); ??? } ???
??? BOOL AFXAPI AfxInternalPumpMessage() ??? {
??? _AFX_THREAD_STATE *pState = AfxGetThreadState(); ???
??? if (!::GetMessage(&(pState->m_msgCur), NULL, NULL, NULL)) ??? {
??? .............略 ??? }
??? ...............略 ??? if
(pState->m_msgCur.message
!=
WM_KICKIDLE
&& !AfxPreTranslateMessage(&(pState->m_msgCur))) ??? {
??? ::TranslateMessage(&(pState->m_msgCur)); ??? ::DispatchMessage(&(pState->m_msgCur)); ??? } ???
??? return TRUE; ??? }
我们看到PumpMessage中通过调用GetMessage、TranslateMessage、DispatchMessage等建立了消息循环并投递消息。 窗口过程函数AfxWinProc形式如下:
C++代码
??? LRESULT CALLBACK AfxWndProc(HWND hWnd,UINT nMsg,WPARAM wParam, LPARAM
lParam) ??? { ??? ……
??? CWnd*pWnd=CWnd::FromHandlePermanent(hWnd);
??? ReturnAfxCallWndProc(pWnd,hWnd,nMsg,wParam,lParam); ??? }
两者运行过程对比
到此,通过对比可以发现,MFC应用程序的运行流程与SDK程序是类似的,都是先进行一些初始化过程,再注册并创建窗口,然后显示、更新窗口,最后进入消息循环,消息都由窗口过程函数处理。现在大家是不是觉得有些头绪了?在运行流程上有基本的掌握即可。
二.MFC应用程序框架主要类之间的关系
在第二讲中,给大家演示了如何利用应用程序向导生成单文档应用程序框架,可以看到程序的基本框架和必要的代码都自动生成了,上一讲又讲解了文件组成结构,实际上在前面自动生成的框架中比较重要的类包括以下几个:CHelloWorldApp、CMainFrame、CHelloWorldDoc和CHelloWorldView,至于其他的类比如CClassView、CFileView等都是在框架窗口(CMainFrame)上创建的面板等,不是必要的。
鸡啄米就四个主要类的关系简单讲下,CHelloWorldApp类处理消息,将收到的消息分发给相应的对象。CMainFrame是视图CHelloWorldView的父窗口,视图CHelloWorldView就显示在CMainFrame的客户区中。视图类CHelloWorldView用来显示文档类CHelloWorldDoc中的数据,并根据对视图类的操作修改文档类的数据。一个视图类只能跟一个文档类相联系,而一个文档类可以跟多个视图类相联系。关于视图类和文档类的关系后面会详细讲解。
VS2010/MFC编程入门之五(MFC消息映射机制概述)
分类标签: 编程入门 VC++ MFC VS2010
上一讲鸡啄米为大家简单分析了MFC应用程序框架,这一讲是关于MFC消息映射机制的内容。
前面已经说过,Windows应用程序是消息驱动的。在MFC软件开发中,界面操作或者线程之间通信都会经常用到消息,通过对消息的处理实现相应的操作。比较典型的过程是,用户操作窗口,然后有消息产生,送给窗口的消息处理函数处理,对用户的操作做出响应。
什么是消息
窗口消息一般由三个部分组成:1.一个无符号整数,是消息值;(2)消息附带的WPARAM类型的参数;(3)消息附带的LPARAM类型的参数。其实我们一般所说的消息是狭义上的消息值,也就是一个无符号整数,经常被定义为宏。
什么是消息映射机制
MFC使用一种消息映射机制来处理消息,在应用程序框架中的表现就是一个消息与消息处理函数一一对应的消息映射表,以及消息处理函数的声明和实现等代码。当窗口接收到消息时,会到消息映射表中查找该消息对应的消息处理函数,然后由消息处理函数进行相应的处理。SDK编程时需要在窗口过程中一一判断消息值进行相应的处理,相比之下MFC的消息映射机制要方便好用的多。
Windows消息分类
先讲下Windows消息的分类。Windows消息分为系统消息和用户自定义消息。Windows系统消息有三种:
1.标准Windows消息。除WM_COMMAND外以WM_开头的消息是标准消息。例如,WM_CREATE、WM_CLOSE。
2.命令消息。消息名为WM_COMMAND,消息中附带了标识符ID来区分是来自哪个菜单、工具栏按钮或加速键的消息。
3.通知消息。通知消息一般由列表框等子窗口发送给父窗口,消息名也是WM_COMMAND,其中附带了控件通知码来区分控件。
CWnd的派生类都可以接收到标准Windows消息、通知消息和命令消息。命令消息还可以由文档类等接收。
用户自定义消息是实际上就是用户定义一个宏作为消息,此宏的值应该大于等于WM_USER,然后此宏就可以跟系统消息一样使用,窗口类中可以定义它的处理函数。
消息映射表
除了一些没有基类的类或CObject的直接派生类外,其他的类都可以自动生成消息映射表。下面的讲解都以前面例程HelloWorld的CMainFrame为例。消息映射表如下:
相关推荐: