世上的事,会则不难,难则不会~
WIN32学习起来也并不简单,而到了MFC,框架6大机制相当复杂,学习就更加困难。
每个人都需要有自己的学习方法,对于我这一类人,没有形像的东西或者没有在大脑里设计出它的具体形象,往往就搞不明白。
于是,我想了个故事:
先来看关于MFC第一个机制,程序运行机制:
前提1:MFC 程序搭建: 1. 打开VS,新建WIN32项目(注意是WIN32),可以是空项目 2. 配置3步(ALT+F7进入属性): 1) MFC的使用--在静态库中使用MFC 2)字符集--未设置 3) C/C++->预编译头-----不使用 3. 自己写如下代码: |
#include <afxwin.h> //1 class CMyFrameWnd: public CFrameWnd //2 { }; class CMyWinApp : public CWinApp //3 { public: CMyWinApp(){}; //7 virtual BOOL InitInstance(); //4 };
CMyWinApp theApp; //全局对象 //5 BOOL CMyWinApp::InitInstance() //6 { CMyFrameWnd *pFrame = new CMyFrameWnd(); pFrame->Create(NULL,"MFCBase"); this->m_pMainWnd = pFrame; pFrame->ShowWindow(SW_SHOW); pFrame->UpdateWindow(); return TRUE; } |
现在开始介绍故事背景: 在某个时空中,有一个特别行动处(Special Action Team-SAT),接受特别任务。 已经很久没有任务了,所有的人员都进入了休眠状态,一切都死气沉沉。(类是死的) 这一天,一个黑衣人来到SAT的门口。 “前台的小MM,醒来吧,我有任务委托”,黑衣人低沉的说到,然后把手提箱送到了前台接待窗口中。 // CMyWinApp theApp; “啊!居然有委托了~ 好的,我这就帮你进行登记,提交后行动组会有专人来负责~” //进入构造函数: CMyWinApp(){}; //7 “啊,这是个S级的任务,我需要上升到客服经理专门为您服务” //CWinApp::CWinApp 进入父类的构造函数 经理快速过来,“小张,把箱子登记下来,然后送到台” //AFX_MODULE_STATE* pModuleState = _AFX_CMDTARGET_GETSTATE(); “传送台?”黑衣人冷笑到,“就是通过全息分解然后传送到你们内部的机器?” //#define _AFX_CMDTARGET_GETSTATE() (m_pModuleState) “那箱子的第一层有重要物品”黑衣人悠悠的提醒到,”你要确保送到!” //ENSURE(pModuleState); “啊! 收到, 小张,把重要物品登记在案后,也送到传送台” //AFX_MODULE_THREAD_STATE* pThreadState = pModuleState->m_thread;
“本组人员先测试传送台工作是否正常, 老王, 先清理传送台,防止意外发生!” //ASSERT(AfxGetThread() == NULL); “清理完毕”,老王报告。 “OK,开启传送!传送重要物品” //pThreadState->m_pCurrentWinThread = this; “老王,确认传送!” //ASSERT(AfxGetThread() == this); “报告,传送OK!”老王说。 “好的,老李,相同步骤传送和确认箱子!” //ASSERT(afxCurrentWinApp == NULL); // only one CWinApp object please //pModuleState->m_pCurrentWinApp = this; //ASSERT(AfxGetApp() == this); “完成!” “Good Job! 现在就看行动组吧~” //构造函数任务完成:1. 把当前对象地址保存到全局变量(线程状态的一个成员中) 2. 把当前对象地址保存到全局变量(模块状态的一个成员中) 3. 完成接待和登记工作,以便于后面函数取得对象~ //我们称:CMyWinApp theApp(爆破点) |
在构造函数完成后,需要进入到主函数,我们知道在控制台程序中主函数是main();而在WIN32程序中主函数是WinMain(),然后我们自己写的这些代码里根本就没有入口函数。 这是由于MFC把WinMain给封装起来了,当构造函数完成后,行动组就已经开始工作了~ |
接下来我们看程序的执行过程,继续我们的故事: 当然,把前提2先介绍一下,我们怎样才能进到WinMain()函数中去? 步骤: 1) 在自己写的函数第一句打断点 2) F5 调试运行到断点 3) ALT + 7 “调用堆栈”---查看哪个函数调用了当前这个函数 4) 很明显,AfxWinMain()调用当前函数,而WinMain()调用了AfxWinMain() 5) 双击进入WinMain()函数,打上断点 6) 退出本次调试,重新调试,F11进入AfxWinMain()函数
|
特别行动组控制室内,由于长期没有任务,大家都在睡觉。 “起来啦,快起来,咱们有事做了”,一个人眼尖,看到了任务提示的灯闪了起来。 “恩,重要物品,登记先~ 还有个箱子,也登记上“ //CWinThread* pThread = AfxGetThread(); //CWinApp* pApp = AfxGetApp(); “好了,休息了这么久,我们也要工作了!”组长走了出来“各就各位,把地上的垃圾给我收拾了,桌子给我端过来, 小何,倒杯咖啡过来~” 大家开始各种的整理和准备工作。 “好了,初始化工作完成,现在我们来看看这个任务实际需要我们做些什么?” //InitInstance() 回到自己写的代码,即InitInstance()虚函数中~ “恩,任务是建造一个工厂,名字叫“MFCBase”,好可笑的名字”组长笑道“哦,已经选好地皮了,连坐标都已经定下了!” //CMyFrameWnd *pFrame = new CMyFrameWnd(); //pFrame->Create(NULL,"MFCBase"); “来,把我们的工厂建造专家m_pMainWnd叫来,告诉他这个工厂在哪,让他去搞定~” //this->m_pMainWnd = pFrame; “还要打广告,而要不断刷新点击率? 好好好,给他弄上~” //ShowWindow();UpdateWindow() “其他客户没有想到的,经验丰富的兄弟们,把它们做掉吧,我们的目标是超越客户的期望~”
|
好了,第一个机制程序运行机制的故事就先讲到这里。
记完这个故事,至少心里对MFC又多了一份认识;前进的路上曲折是难免的,坚持很重要。任何一行,不是看你走得多快,而是需要你走得更稳,走得更远。
20151014夜