VS和MFC编程入门之4MFC应用程序框架分析文档格式.docx
《VS和MFC编程入门之4MFC应用程序框架分析文档格式.docx》由会员分享,可在线阅读,更多相关《VS和MFC编程入门之4MFC应用程序框架分析文档格式.docx(8页珍藏版)》请在冰豆网上搜索。
WNDCLASSEXmyWin;
myWin.cbSize=sizeof(myWin);
myWin.style=CS_HREDRAW|CS_VREDRAW;
myWin.lpfnWndProc=myWndProc;
myWin.cbClsExtra=0;
myWin.cbWndExtra=0;
myWin.hInstance=hInstance;
myWin.hIcon=0;
myWin.hIconSm=0;
myWin.hCursor=0;
myWin.hbrBackground=(HBRUSH)(COLOR_WINDOW+1);
myWin.lpszMenuName=0;
myWin.lpszClassName=appName;
//Register
if(!
RegisterClassEx(&
myWin))return0;
constHWNDhWindow=CreateWindow(
appName,
WS_OVERLAPPEDWINDOW,
CW_USEDEFAULT,
0,
hInstance,
0);
ShowWindow(hWindow,iCmdShow);
UpdateWindow(hWindow);
{
MSGmsg;
while(GetMessage(&
msg,0,0,0))
TranslateMessage(&
msg);
DispatchMessage(&
}
return(int)msg.wParam;
}
LRESULTCALLBACKmyWndProc(HWNDhWindow,UINTmsg,WPARAMwParam,LPARAMlParam)
if(msg==WM_PAINT)
PAINTSTRUCTps;
constHDChDC=BeginPaint(hWindow,&
ps);
RECTrect;
GetClientRect(hWindow,&
rect);
DrawText(hDC,TEXT("
HELLOWORLD"
),-1,&
rect,DT_SINGLELINE|DT_CENTER|DT_VCENTER);
EndPaint(hWindow,&
return0;
elseif(msg==WM_DESTROY)
PostQuitMessage(0);
returnDefWindowProc(hWindow,msg,wParam,lParam);
上面的程序运行的流程是:
进入WinMain函数->
初始化WNDCLASSEX,调用RegisterClassEx函数注册窗口类->
调用ShowWindow和UpdateWindow函数显示并更新窗口->
进入消息循环。
关于消息循环再简单说下,Windows应用程序是消息驱动的,系统或用户让应用程序进行某项操作或完成某个任务时会发送消息,进入程序的消息队列,然后消息循环会将消息队列中的消息取出,交予相应的窗口过程处理,此程序的窗口过程函数就是myWndProc函数,窗口过程函数处理完消息就完成了某项操作或任务。
本例是要显示“HELLOWORLD”字符串,UpdateWindow函数会发送WM_PAINT消息,但是此消息不经过消息队列而是直接送到窗口过程处理,在窗口过程函数中最终绘制了“HELLOWORLD”字符串。
MFC应用程序
下面是MFC应用程序的运行流程,通过MFC库中代码进行分析:
首先在HelloWorld.cpp中定义全局对象theApp:
CHelloWorldApptheApp;
。
调用CWinApp和CHelloWorldApp的构造函数后,进入WinMain函数(位于appmodul.cpp中)。
extern"
C"
intWINAPI
_tWinMain(HINSTANCEhInstance,HINSTANCEhPrevInstance,
_In_LPTSTRlpCmdLine,intnCmdShow)
#pragmawarning(suppress:
4985)
//callshared/exportedWinMain
returnAfxWinMain(hInstance,hPrevInstance,lpCmdLine,nCmdShow);
在TCHAR.h中,有此定义:
#define_tWinMainWinMain,所以这里的_tWinMain就是WinMain函数。
它调用了AfxWinMain函数(位于WinMain.cpp中)。
intAFXAPIAfxWinMain(HINSTANCEhInstance,HINSTANCEhPrevInstance,LPTSTRlpCmdLine,intnCmdShow)
.............略
//Appglobalinitializations(rare)
if(pApp!
=NULL&
&
!
pApp->
InitApplication())
gotoInitFailure;
pThread->
InitInstance())
.........略
//Run函数位于THRDCORE.cpp中,由此函数进入消息循环
nReturnCode=pThread->
Run();
..............略
returnnReturnCode;
上面InitInstance函数的代码如下:
BOOLCTestApp:
:
InitInstance()
CSingleDocTemplate*pDocTemplate;
pDocTemplate=newCSingleDocTemplate(
IDR_MAINFRAME,
RUNTIME_CLASS(CTestDoc),
RUNTIME_CLASS(CMainFrame),//mainSDIframewindow
RUNTIME_CLASS(CTestView));
pDocTemplate)
returnFALSE;
AddDocTemplate(pDocTemplate);
//Parsecommandlineforstandardshellcommands,DDE,fileopen
CCommandLineInfocmdInfo;
ParseCommandLine(cmdInfo);
//ProcessShellCommand位于AppUI2.cpp中,注册并创建窗口
ProcessShellCommand(cmdInfo))
m_pMainWnd->
ShowWindow(SW_SHOW);
UpdateWindow();
returnTRUE;
InitInstance中的ProcessShellCommand函数又调用了CMainFrame的LoadFrame函数注册并创建了窗口,执行完ProcessShellCommand函数以后,调用了m_pMainWnd的ShowWindow和UpdateWindow函数显示并更新框架窗口。
这些是不是与上面的SDK程序十分类似?
接下来该是消息循环了,上面的AfxWinMain函数中调用了pThread的Run函数(位于THRDCORE.cpp中),在Run中包含了消息循环。
Run函数的代码如下:
intCWinThread:
Run()
//phase2:
pumpmessageswhileavailable
do
//pumpmessage,butquitonWM_QUIT
PumpMessage())
returnExitInstance();
//reset"
noidle"
stateafterpumping"
normal"
message
if(IsIdleMessage(&
m_msgCur))
bIdle=TRUE;
lIdleCount=0;
}while(:
PeekMessage(&
m_msgCur,NULL,NULL,NULL,PM_NOREMOVE));
BOOLCWinThread:
PumpMessage()
returnAfxInternalPumpMessage();
BOOLAFXAPIAfxInternalPumpMessage()
_AFX_THREAD_STATE*pState=AfxGetThreadState();
GetMessage(&
(pState->
m_msgCur),NULL,NULL,NULL))
...............略
if(pState->
m_msgCur.message!
=WM_KICKIDLE&
AfxPreTranslateMessage(&
m_msgCur)))
:
TranslateMessage(&
m_msgCur));
DispatchMessage(&
我们看到PumpMessage中通过调用GetMessage、TranslateMessage、DispatchMessage等建立了消息循环并投递消息。
窗口过程函数AfxWinProc形式如下:
LRESULTCALLBACKAfxWndProc(HWNDhWnd,UINTnMsg,WPARAMwParam,LPARAMlParam)
……
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中的数据,并根据对视图类的操作修改文档类的数据。
一个视图类只能跟一个文档类相联系,而一个文档类可以跟多个视图类相联系。
关于视图类和文档类的关系后面会详细讲解。
本节VC++/MFC编程入门教程内容比较多,主要是让大家对MFC应用程序的运行原理有大概的了解。
对于以后的MFC开发有很多好处。