记得VB中是怎么处理控件的吧,so easy 了。先在窗口上画出一个控件,然后给他起个名字name,然后代码中所有的对于该控件的操作都通过这个name来引用。例如,你要改变这个控件的某些属性,那么通过这个name调用它的属性,并相应的给属性赋上你期望的值,那么一切搞定。再如,你要条用该控件的一个方法,同样name.xxx,完事。就这样。
然而VC呢?也这么简单么?错了,完全错了,这里的东西都变得难于理解(当然是指在你刚刚学习的时候,任何新的东西都是难于接受的,在你的原有的固执的思维模式的淫威之下)。VC中的控件可以描述成五个部分:ID,控件实体,控件变量,属性函数,消息函数。
这里最重要的不再是name了,而是ID,系统通过各个控件的ID来识别他们。控件实体跟VB中的没有两样,都是在窗体上画出来的(至少表面上是这样子的)。控件变量就比较隐晦了,VB中我们通过name来引用控件,但是VC中没有了name这么个东西,相对等重要的是ID,然而ID能直接用么,不能!这个东西是MS专门设计出来个他们的系统用的(shit,就像一个国家的管理者往往通过自己的喜好来决定整个国家的命运样,这都罢了——按照马哲的观念,国家最终是要消亡的——,问题在于他们偏偏还能通过对整个国家的控制来改变整个民族,乃至民族中每个人。这就不可忍受了!可又能怎样?),系统通过这个ID来调度与空间相关的所有东西。究竟该怎么引用?那就是这个控件变量的事了,这个时候的控件变量就相当于VB中的name了。我们在VB中通过name来引用控件的时候,用的最多的就是name.propority,这样可以方便的设置和更改控件的属性。VC中这样做可以么?VC中不同了,为了所谓的保护成员数据,这里的属性值基本上都不允许name.propority,而改用了属性函数——name.SetPropority()和name.GetPropority()——来设置和取得控件相应的属性。这也就是控件属性函数的作用了。还有要命的消息函数。在VB中控件都给我们提供了许多事件函数,比如click,dblclick etc。这些函数帮我们完成了响应单击和双击等事件的操作,看起来很是简捷,可是你不晓得其中的道理。VC则试图让你明白这些道理,他给出了消息函数和消息影射表这两个东西。消息函数用来处理消息,如click等,消息影射表则用来标示消息(afxmsg)从哪里(ID)来,以及该用什么函数(afxmsg fun)来处理。
上面是VC控件的基本原理,也是整个MFC框架很小的一部分,其中的技术细节浩如烟海,许多人穷经皓首,经年累月的在学习(MS还不让人家来学,狗屎,守着一堆代码发财的家伙。虽然我很是推崇MS的技术,那里面往往是最先进的理念,毕竟MS汇集了全球那么多聪明的高手),但也未必学完过。我只是刚刚开始,虽然追随技术,但不狂热,下面是对“这五部分怎样关联”的更进一步理解。
控件实物:object
属性函数:SetPropority() Getpropority()
控件ID:MYID
控件变量:objName
消息:WS_CLICK
消息函数:OnClick()
object首先关联MYID——这在建立控件的时候完成。当你画出控件实体之后,你会看到他的属性窗口中已经建立了该控件的ID。
属性函数关联objName——这个是在声明变量的时候完成的。声明一个什么类型的变量,那么该变量就具有了什么样的属性函数,这都由MFC框架类库来决定。
MYID与objName的关联——这个时候需要一个函数来完成,该函数由MFC提供,实际上是实现了控件与变量间的数据交换。
void class::DoDataExchange(CDataExchange* pDX){
CDialog::DoDataExchange(pDX);
//{{AFX_DATA_MAP(class)
DDX_Control(pDX, MYID, objName);
//}}AFX_DATA_MAP
}
WS_CLICK关联OnClick和MYID——消息影射表来了。这个表看起来的确像张表,它把消息,ID,消息函数一排列了出来。我们也就能看到这些,简单的这么一排肯定是搞不定的,到底怎么管用的,MS最为清楚,可人家不得给你说。你当然可以自己找些反汇编工具慢慢研究了(多可怜),不过有很多书好像能告诉你一部分真相。
BEGIN_MESSAGE_MAP(class, CDialog)
//{{AFX_MSG_MAP(class)
WS_CLICK(MYID, OnClick)
//}}AFX_MSG_MAP
END_MESSAGE_MAP()
这个表关联的是消息,ID,消息函数,好像并没有与控间实体相关。其实,由于ID已经与object以及objName关联过了,那么整个关联表就已经建立好了。