




已阅读5页,还剩2页未读, 继续免费阅读
版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领
文档简介
MFC源程序设计-计算机安全 MFC源程序设计MFC程序设计之来龙去脉(),到后来就没有再管了,其实那只是冰山一角.具体MFC是怎么运行的,还是没有交待清楚。说明:1、本文作者在VS2003中跟踪代码,此代码为VS2003中拷贝,使用MFC7。 2、不同框架的MFC程序由所不同,本文以单文档为例。 3、本文读者需要有一定的SDK的基础,不需要太多,至少知道它的基本框架和来龙去脉即可! 4、文章只想起到说明作用,所以代码会有一些删除。学MFC,竟然还不知道MFC的MAIN函数在什么地方?怎么运行的?实在不高明。看过候捷(JJHOU)老师的深入浅出MFC的,对它一定很熟悉。呵呵,本文是献给没有看过那本书,但是又很希望学习MFC程序设计的朋友的。(没有看过那本书的朋友还不赶快去买?)其实本文,主要是对深入浅出MFC第六章的一个总结和补充罢了!(本文有该书不同的地方,也有一些笔者自己的见解!)言归正传。假如你用AppWizard一步一步NEXT下来,然后在CLASSVIEW中去找寻WINMAIN函数,那么你只有失望。MFC最大的特点是什么?封装!MFC的确封装的太好了,以至于很多想学习MFC的人都望而却步。闲话少说,还是继续我们今天的话题,MAIN函数!实话告诉你吧,即使你搜索所有的MFC生成的文件,都无法发现WINMAIN的字眼,那么它就近在什么地方呢?我相信你已经想到,MAIN函数应该在主要的应用程序文件中。难道是“您定义的程序名.cpp”这个文件?不错就是它。再Crtl+F一下,看有没有我们要找的WINMAIN函数?看来你又要失望了,但是你注意有这样一句:/ The one and only CMyApp object CMyApp theApp; /本人建立的工程名为My。是不是很特别,再注意一下那句注释“The one and only CMyApp object”,每个应用程序有且只用一个CMyApp对象。我想你应该想到了,WinMain函数每个程序也只能有一个,那么这个全局对象跟WinMain函数肯定有莫大的关系?没错,相信你的直觉。特别注意:深晓C+细节的人一定知道,全局对象优先于MAIN函数执行的道理。如果你不知道也没关系,那么我在这里告诉你:“全局对象优先于MIAN函数执行,且构建于栈中,切记,切记!”现在,我们该深入WinMain运行机制了,确切的说,应该是MFC的机制!首先,看看MFC的库文件把,它能给我们带来许多惊喜。(vc6的相应的目录是Microsoft Visual StudioVC98MFCSRC;VC7相应的目录是Microsoft Visual Studio .NET 2003Vc7atlmfcsrcmfc)现在我们就从这个全局下手,开始今天的旅途。CMyApp theApp; 此时,系统会执行CMyApp的父类(CWinApp)构造函数,再执行CMyApp的构造函数。(先有老爹,再有儿子!),此时就会调用CWinApp的构造函数。CWinApp的构造函数(在VC提供的MFC代码中以“文中的一个字或词组”的方式查询关键字,此时打开APPCORE.CPP,以下使用相同搜索方式,不再复述。)找到以下内容:CWinApp:CWinApp(LPCTSTR lpszAppName) 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; ASSERT(AfxGetApp() = this);. .OK,就到这里就可以了,仔细看上面代码,它已经完成了应用程序线程额的启动,它给予了我们程序的生命。现在请注意: pThreadState-m_pCurrentWinThread = this;pModuleState-m_pCurrentWinApp = this; 这两行代码其实都是做的一件事儿。 这段代码的意思是,获得了CMyApp的全局对象的this指针。(此时你肯定要疑问,为什么是CMyApp的指针?this目前是在CWinApp中啊? 对此我的答案是,可是你是由CMyApp的对象引发的CWinApp的构造啊!)这个指针可非一般的人物,稍后我们的很多工作都要靠它完成。 CWinApp之中的成员变量将因为theApp这个全局对象的诞生而获得配置和初始值。 构造完父类,现在构造子类。可是我们看到,AppWizard给我们的子类里它什么也没做?是的,这一切都听从你的安排! CMyApp:CMyApp() / TODO: add construction code here,/ Place all significant initialization in InitInstance 接下来就是今天的主角儿了,搜索关键字“WinMain”,出现很多文件。别急,因为现在我们应该先看看WinMain的声明。打开appmodul.cpp: _tWinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,LPTSTR lpCmdLine, int nCmdShow)/ call shared/exported WinMainreturn AfxWinMain(hInstance, hPrevInstance, lpCmdLine, nCmdShow);这里_tWinMain是为了支持UNICODE而命名的一个宏,真正起作用的是AfxWinMain,注意看看它的参数,是不是和SDK的WinMain函数一样?现在再搜索下AfxWinMain,其实在winmain.cpp中:int AFXAPI AfxWinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,LPTSTR lpCmdLine, int nCmdShow)ASSERT(hPrevInstance = NULL);int nReturnCode = -1;CWinThread* pThread = AfxGetThread();CWinApp* pApp = AfxGetApp();/ AFX internal initializationif (!AfxWinInit(hInstance, hPrevInstance, lpCmdLine, nCmdShow) goto InitFailure;/ App global initializations (rare)if (pApp != NULL & !pApp-InitApplication() goto InitFailure;/ Perform specific initializationsif (!pThread-InitInstance() if (pThread-m_pMainWnd != NULL) TRACE(traceAppMsg, 0, Warning: Destroying non-NULL m_pMainWndn); pThread-m_pMainWnd-DestroyWindow(); nReturnCode = pThread-ExitInstance(); goto InitFailure;nReturnCode = pThread-Run();. .此段代码注意五个细节:CWinApp* pApp = AfxGetApp(); 意为获得对象指针,其实就是刚才那个THIS。不记得了?指向CMyApp的那个!还值得注意的是,Afx意是全局的,随时你都可以调用它。(AFX就是MFC开发小组的开发代号,意为Application Framework 传说X只是为了好看,没实在意思?!)if (!AfxWinInit(hInstance, hPrevInstance, lpCmdLine, nCmdShow)AfxWinInit完成了线程的初始化和窗框类的注册。具体参看appinit.cpp中的定义。if (pApp != NULL & !pApp-InitApplication()其实pApp和pThread是同一个指针,都是指向CMyApp的指针,这里因为CMyApp中没有定义InitApplication,实际上就调用的CWinApp:InitApplication(),完成了MFC的内容管理。if (!pThread-InitInstance()因为CMyApp中改写了它,所以调用CMyApp中的,其实它也是初始化工作。此时也完成了默认窗口类的定义。假如你熟悉SDK编程的话,一定不会忘记窗口类的设计、注册、创建、现实及更新的步骤,此时MFC以为你设计好了默认的窗口类。现在你不禁要疑问,InitApplication()和InitInstance()有何不同?答案是,假如你执行一个程序,于是两个函数都会被调用;当你在不关闭前一个程序的前提下,再执行一个程序,那么就只执行后一个函数。nReturnCode = pThread-Run();这个一步骤在深入浅出MFC中被成为程序的活水源头,在我看来它就是你开车踩油门的步骤。待会我们会具体阐述!在设计窗口类以后,就应该是注册,MFC自动调用(跳转到)AfxEndDeferRegisterClass(WINCORE.CPP中),为你注册了五个窗口类,分别是:AfxWnd,AfxCreateBar,AfxMDIFrame,AfxFrameOrView,AfxOleControl以上窗口类MFC将自动转化成独立无二的类名,供其调用。在窗口的注册以后,就应该是窗口的创建工作,此时会调用CFrameWnd:Create(),该代码位于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) TRACE(traceAppMsg, 0, Warning: failed to load menu for CFrameWnd.n); PostNcDestroy(); / perhaps delete the C+ object return FALSE; m_strTitle = lpszWindowName; / save title for laterif (!CreateEx(dwExStyle, lpszClassName, lpszWindowName, dwStyle, rect.left, rect.top, rect.right - rect.left, rect.bottom - rect.top, pParentWnd-GetSafeHwnd(), hMenu, (LPVOID)pContext) TRACE(traceAppMsg, 0, Warning: failed to create CFrameWnd.n); if (hMenu != NULL) DestroyMenu(hMenu); return FALSE;return TRUE;其中完成了窗口的创建工作,里面还涉及扩展风格的调用CreateEx,具体细节请参看MSDN。此时你不禁要问,我们的事儿都让MFC做完了?工业化生产出来的窗口都是千篇一律啊,我要有我自己的风格!别急,MFC给用户提供了一个修改窗口设计的机会那就是:PreCreateWindow(CREATESTRUCT& cs) 你在MSDN中查询一下CREATESTRUCT这个结构体,你会发现它和我们的CreateWindow几乎是一模一样,这个就是MFC留给你修改窗口的一个机会。在PreCreateWindow时,会跳到CWnd:PreCreateWindow,里面有一个宏:AfxDeferRegisterClass,它的作用是:如果该窗口类没有被注册,那么就注册它;如果注册了,就什么也不管!窗口类的设计、注册、创建都已经完成,现在只剩下更新和显示了。这些工作都交由 CMyApp:InitInstance()完成: m_pMainWnd-ShowWindow(SW_SHOW); m_pMainWnd-UpdateWindow();现在if (!pThread-InitInstance()的工作已经完成,按照MAIN函数的内容,接下来该:nReturnCode = pThread-Run()了此时应该调用CMyApp的Run()函数,但是在CMyApp类中,根本没有声明或定义这样一个函数,根据多态性的原则,指针迁升,指向CWinApp:Run(),其代码位于APPCORE.CPP中:int CWinApp:Run() if (m_pMainWnd = NULL & AfxOleGetUserCtrl() / Not launched /Embedding or /Automation, but has no main window! TRACE(traceAppMsg, 0, Warning: m_pMainWnd is NULL in CWinApp:Run - quitting application.n); AfxPostQuitMessage(0); return CWinThread:Run();最后你会发现,它又调用了一个CWinThread:Run(),此时你就看不到CWinThread:Run()的代码了(至少笔者没有找到,因为微软只提供了部分MFC代码。)但是你可以在MSDN中找到CWinThread:Run()的描述:Run 控制线程的函数。包含消息泵。一般不重写。 再具体点就是:Run acquires and dispatches Windows messages
温馨提示
- 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
- 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
- 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
- 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
- 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
- 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
- 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。
最新文档
- 2025甘肃金昌市人力资源和社会保障局招聘公益性岗位人员1人考前自测高频考点模拟试题附答案详解(突破训练)
- 2025年吉林省农业种植(玉米)买卖合同书
- 2025保健品销售合同范本参考
- 2025吉林白城市暨洮北区人才交流中心就业见习岗位和见习人员征集模拟试卷及完整答案详解1套
- 2025江苏省退役军人事务厅直属优抚医院招聘12人模拟试卷及答案详解(网校专用)
- 2025标准企业租赁合同范本:租赁协议模板
- 2025年三明市供电服务有限公司招聘61人考前自测高频考点模拟试题及答案详解(历年真题)
- 2025年湖南长沙天心区招聘32名勤务协助人员和体能测评的考前自测高频考点模拟试题及参考答案详解1套
- 衡阳初一考试题库及答案
- 安全教育培训会议通知课件
- 隧道施工应急预案方案
- 植物鉴赏课件
- 2025云南丽江市公安局警务辅助人员招聘29人考试参考题库及答案解析
- 压实度试验课件
- 配怀母猪饲养管理
- 2025-2026学年赣美版(2024)小学美术二年级上册(全册)教学设计(附目录P126)
- 林业调查安全培训
- 流感疫苗接种课件
- 2025至2030中国氧化钪行业需求状况及未来趋势前景研判报告
- 社会科学研究方法 课件 第二章 研究的类型
- 奇瑞试乘试驾协议书模板
评论
0/150
提交评论