有网站源代码 怎么样建设网站,创建网址快捷方式,企业信用管理系统,微信备份如何转换为wordpress上一讲鸡啄米讲的是VS2010应用程序工程中文件的组成结构#xff0c;可能大家对工程的运行原理还是很模糊#xff0c;理不出头绪#xff0c;毕竟跟C编程入门系列中的例程差别太大。这一节鸡啄米就为大家分析下MFC应用程序框架的运行流程。 一.SDK应用程序与MFC应用程序运行过…上一讲鸡啄米讲的是VS2010应用程序工程中文件的组成结构可能大家对工程的运行原理还是很模糊理不出头绪毕竟跟C编程入门系列中的例程差别太大。这一节鸡啄米就为大家分析下MFC应用程序框架的运行流程。 一.SDK应用程序与MFC应用程序运行过程的对比 程序运行都要有入口函数在之前的C教程中都是main函数而Windows应用程序的入口函数是WinMain函数MFC程序也是从WinMain函数开始的。下面鸡啄米就给出用Windows SDK写的“HelloWorld”程序与应用程序框架进行对比这样能更好的了解框架是怎样运行的。Windows SDK开发程序就是不使用MFC类库直接用Windows API函数进行软件开发。鸡啄米不是要讲解SDK开发只是为了对比而简单介绍至于SDK开发可以在大家学完MFC以后选择是否要研究一般来说有简单了解就可以了。 SDK应用程序 首先给出Windows SDK应用程序“HelloWorld”的源码 C代码 #include windows.h LRESULT CALLBACK myWndProc(HWND hWindow, UINT msg, WPARAM wParam, LPARAM lParam); int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, PSTR szCmdLine, int iCmdShow) { const static TCHAR appName[] TEXT(Hello world); WNDCLASSEX myWin; 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)) return 0; const HWND hWindow CreateWindow( appName, appName, WS_OVERLAPPEDWINDOW, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, 0, 0, hInstance, 0); ShowWindow(hWindow,iCmdShow); UpdateWindow(hWindow); { MSG msg; while(GetMessage(msg,0,0,0)) { TranslateMessage(msg); DispatchMessage(msg); } return (int)msg.wParam; } } LRESULT CALLBACK myWndProc(HWND hWindow, UINT msg, WPARAM wParam, LPARAM lParam) { if (msgWM_PAINT) { PAINTSTRUCT ps; const HDC hDC BeginPaint(hWindow,ps); RECT rect; GetClientRect(hWindow,rect); DrawText(hDC,TEXT(HELLO WORLD),-1,rect, DT_SINGLELINE | DT_CENTER | DT_VCENTER); EndPaint(hWindow,ps); return 0; } else if (msgWM_DESTROY) { PostQuitMessage(0); return 0; } return DefWindowProc(hWindow,msg,wParam,lParam); } 上面的程序运行的流程是进入WinMain函数-初始化WNDCLASSEX调用RegisterClassEx函数注册窗口类-调用ShowWindow和UpdateWindow函数显示并更新窗口-进入消息循环。关于消息循环再简单说下Windows应用程序是消息驱动的系统或用户让应用程序进行某项操作或完成某个任务时会发送消息进入程序的消息队列然后消息循环会将消息队列中的消息取出交予相应的窗口过程处理此程序的窗口过程函数就是myWndProc函数窗口过程函数处理完消息就完成了某项操作或任务。本例是要显示“HELLO WORLD”字符串UpdateWindow函数会发送WM_PAINT消息但是此消息不经过消息队列而是直接送到窗口过程处理在窗口过程函数中最终绘制了“HELLO WORLD”字符串。 MFC应用程序 下面是MFC应用程序的运行流程通过MFC库中代码进行分析 首先在HelloWorld.cpp中定义全局对象theAppCHelloWorldApp theApp;。调用CWinApp和CHelloWorldApp的构造函数后进入WinMain函数位于appmodul.cpp中。 C代码 extern C int WINAPI _tWinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, _In_ LPTSTR lpCmdLine, int nCmdShow) #pragma warning(suppress: 4985) { // call shared/exported WinMain return AfxWinMain(hInstance, hPrevInstance, lpCmdLine, nCmdShow); } 在TCHAR.h中有此定义#define _tWinMain WinMain所以这里的_tWinMain就是WinMain函数。它调用了AfxWinMain函数位于WinMain.cpp中。 C代码 int AFXAPI AfxWinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,LPTSTR lpCmdLine, int nCmdShow) { .............略 // 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 no idle state after pumping normal message 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*pWndCWnd::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开发有很多好处。如果有问题请在鸡啄米博客留言交流。谢谢。 原文地址http://www.jizhuomi.com/software/145.html转载于:https://www.cnblogs.com/wodehao0808/p/6702660.html