,很多面向对象的语言都这样做了。
但定义一个虚函数要生成一个虚函数表,要占用系统空间,虚函数越多,表就越大,有时得不偿失!这里哆嗦几句,是因为往后要说明的消息映射中大家更加会体验到这一点,好了,就此打往。
上面我们自己解决了一个问题,就是在 CCmdTarge 写一个 virtual BOOL InitInstance。
要我们 MFC“隐大家再下想,我们还藏”更多的东西 WinMain :函数,设计窗口类,窗口注册,消息循环,回调函数……我们马上想到封装想 【封装他们】 。
大家似乎隐约地感觉到封装 WinMain不容易 觉得 WinMain是一个特殊的函数, 许多时候 【 以前写它代表了一个程序的起始和终结】。
所以在程序的时候,我们写程序 习 惯 从 WinMain的左大括写起,到右大括弧返回、结束程序。
我们 【换一个角度去想】,有什么东西 【拿到 WinMain可以外面去做】?(此处特指全局对象在 winmain 之外做的工作)许多初学者们,总觉得 WinMain函数天大的函数,什么函数都好象要在它里面才能真正运行。
其实这样了解【很片面,甚至错误】。
我们可以写一个这样的 C程序:////////////////////////////////////////////////////include <iostream.h>class test public: testcout<<quot请改变你对 main函数的看法!quot<<endltest test1//void main//////////////////////////////////////////////////// 在上面的程序里,入口的 main函数表面上什么也不做,但程序执行了(注:实际入口函数做了一些我们可以不了解的事情),并输出了一句话(注: 全局对象】 main首先运行 ) 现在大家可以知道 【 比 。
我们的 WinMain函数可以什么都不做,程序依然可以运行,但没有这个入口函数程序会报错。
那么 WinMain函数会放哪个类上面呢,请看下面程序:include <afxwin.h>class MyApp : public CWinApp public: BOOL InitInstance //②程序入点 AfxMessageBoxquot程序依然可以运行!quot return true MyApp theApp //① 【建立应用程序】 。
大家可以看到,我并没有构造框架,而程序却可以运行了——弹出一个对话框(如果没有 WinMain函数程序会报错)。
上面我这样写还是为了直观起见,其实我们只要写两行程序:include <afxwin.h>CWinApp theApp【整个程序】// 【只构造一个 CWinApp 类对象】 ,程序就可以运行! 所以说,只要我们构造了 CWinApp 对象,就可以执行 WinMain函数。
我们马上相信WinMain函数是在 CWinApp 类或它的基类中,而不是在其他类中。
其实 这种看法是错误的, 不可能让你在 我们知道编写 C程序的时候,一个类中包含入口函数,WinMain 是由系统调用,跟我们的平 当时程序自身调用的函数有着本质的区别。
我们可以暂时简单想象成,CWinApp 对象构造完的时候,WinMain跟着执行。
【通用代码 (我 现在大家明白了,大部分的“们想封装隐藏的东 】西) 都可以放到 CWinApp 类中 ” ,那么它又是怎样运行起来的呢?为什么构造了 CWinApp 类对象就“自动”执行那么多东西。
大家再仔细想一下,CWinApp【类对象构造之后】,它会“自动”执行自己的构造函数。
那么我们可以 把想要“自动”执行的代码放到 CWinApp 类的构造函数中。
那么 CWinApp 类可能打算这样设计(先不计较正确与否):class CWinApp : public CWinThead public: virtual BOOL InitInstance //解释过的程序的入点 CWinApp ::CWinApp //构造函数 //////////////////////// WinMain //这个是大家一眼看出的错误 Create //设计、创建、更新显示窗口 Run //消息循环 ////////////////////// 写完后,大家又马上感觉到似乎不对,WinMain函数在这里好象真的一点用处都没有,并且能这样被调用吗(请允许我把手按在圣经上声明一下:WinMain不是普通的函数,它要肩负着初始化应用程序,包括全局变量的初始化 ,是由系统而不是程序本身调用的,WinMain返回之后,程序就结束了,进程撤消)。
再看Create函数,它能确定设计什么样的窗口,创建什么样的窗口吗? 如果能在 CWinApp 的构造函数里确定的话,我们以后设计 MFC 程序时【窗口就一个样】,变得写程序【没有必要】。
再看 Run函数,它能在 WinMain函数外面运行吗? 可以让 WinMain 回过头来,我们函数一条语句都不包含吗?不可以 ,我们看一下 WinMain 函数的四个参数:WinMainHINSTANCE HINSTANCE LPSTR int 其 中 第 一 个 参 数 指 向 一 个 实 例 句 柄 , 我 们 在 设计WNDCLASS 的时候一定要【指定实例句柄】 窗口编程,肯定要设计窗口类。
。
我们所以, WinMain再简单也要这样写:int WinMainHINSTANCE hinst HINSTANCE hPrevInstance LPSTR lpCmdLine intnCmdShow hInstancehinst 既然 【实例句柄】要等到【程序开始执行】才能知道,那么我们用于创建窗口的 Create函数也要【在 WinMain()内部】才能执行因为如果等到 WinMain()执行完毕后,程序结束,进程撤消,当然 Create也不可能创建窗口 【消息循环】就是相同的那 那么 Run消息循环放在那里执行好呢?众所周知,么几句代码,但我们也不要企图把它放在 WinMain()函数之外执行。
所以我们在 WinMain()函数里面,我们程序要象以下这样写WinMain(……) ……窗口类对象执行【创建窗口函数】…… ……程序类对象执行【消息循环函数】…… 对于 WinMain()的问题,得总结一下,我们封装的时候是不可以把它封装到 CWinApp 【WinMain()的不类里面, 但由 于变性(或者说有规律可循)】 帮我 ,MFC 完全有能力在我们构造 CWinApp 类对象的时候,们完成【那几行代码】 。
转了一个大圈,我们仿佛又回到了 SDK 编程的开始。
但现在我们现在能清楚地知道, 表面上 MFC 与 SDK 编程截然不同,但实质上 MFC 只是【用类的形式封装了SDK 函数】 ,封装之后,我们在 WinMain()函数中只需要几行代码,就 可以完成一 个窗口程序 。
我们也由 此知道了应如 何 去 封装应 用程序 类(CWinApp)和主框架窗口类(CFrameWnd) 。
下面马上开始设计这两个类。
为了简单起见,我们忽略这两个类的基类和派生类的编写,可能大家会认为这是一种很不负责任的做法,但本人觉得这既可减轻负担,又免了大家在各类之间穿来穿去,更好理解一些(我们在关键的地方作注明)。
还有,我把全部代码写在同一个文件中,让大家看起来不用那么吃力,但这是【最不提倡】的写代码方法,大家不要学哦!include <windows.h>HINSTANCE hInstanceclass CFrameWnd HWND hwnd public: CFrameWnd //也可以在这里调用 Create virtual CFrameWnd int Create //类就留意这一个函数就行了! BOOL ShowWndclass CWinApp1 public: CFrameWnd m_pMainWnd//在真正的 MFC 里面 //它是 CWnd 指针,但这里由于不写 CWnd 类 //只要把它写成 CFrameWnd 指针 CWinApp1 m_pCurrentWinApp//指向应用程序对象本身 CWinApp1 virtual CWinApp1 !! virtual BOOL InitInstance//原本是 MFC 必须重载的函数,最重要的函数!! virtual BOOL Run//消息循环CFrameWnd::CFrameWndCFrameWnd::CFrameWndint CFrameWnd::Create //封装创建窗口代码 WNDCLASS wndcls wndcls.style0 wndcls.cbClsExtra0 wndcls.cbWndExtra0 wndcls.hbrBackgroundHBRUSHGetStockObjectWHITE_BRUSH wndcls.hCursorLoadCursorNULLIDC_CROSS wndcls.hIconLoadIconNULLIDC_ARROW wndcls.hInstancehInstance wndcls.lpfnWndProcDefWindowProc//默认窗口过程函数。
上一篇:
【精品文档】基于WEB的智能搜索应用技术探讨 计算机应用论文工学论文_6413
下一篇:
群体性突发事件论文:“边界冲突”:农村群体性事件的县域分析