标签:
所以消息的获取仍然是来自主窗口,也就是MFC自己的一套消息映射,比如鼠标点击的消息,在主窗口截获,然后通过相关的处理,调用虚子窗口(DirectUI程序中的控件一般不是真正的窗口,没有m_hwnd,暂且称它为虚子窗口吧)的响应函数。所以DirectUI主要的问题是如何将主窗口的消息分派给虚子窗口,要解决这个问题,第一步如何定位虚子窗口。
首先主窗口有很多控件,主窗口有个控件容器,在窗口初始化时加入要显示的控件。加入的控件一般有一些属性,比如控件的大小,相对主窗口的位置,标题等。一般,主窗口有一个控件指针,指向那个将要收到消息的控件,称之为当前控件指针。比如,你要点击一个按钮,你如何确保当前控件指针指向该按钮?可以在主窗口的LButtonDown或者LButtonUp消息中遍历主窗口中所有的控件(遍历容器即可),当鼠标点击的坐标落在控件的区域中时,我们就可以确定当前控件。但是我们还没有考虑到鼠标盘旋在按钮上的情况,一般鼠标停留在按钮上时会引起按钮显示的改变,所以最好将获取当前控件的时间放在OnMouseMove消息中。
当前控件指针初始化时是空指针。在OnMouseMove消息中判断当前的控件是哪个,当然鼠标移出按钮区域时也会将其置为空指针。在其他诸如OnMouseLeave消息中也要进行相应的处理。当鼠标点击时肯定会生产LButtonDown和LButtonUp消息,根据获取到的当前控件指针来进行消息响应。那如何响应?首先各种控件的显示效果不一样,按钮点击时会凹下去,checkbox会有一个√来表明是否被选中等等。其次各种控件作用不一样,要做出的反应当然会不一样。可以利用C++的虚函数来定义统一的接口,然后各个控件会有不同的实现。所以各个控件都会从一个基类派生,初始化时将各个控件指向基类控件指针,主窗口的控件容器添加这些基类指针,这样不管处理什么消息什么控件,调用相同的接口即可以有不同的实现。控件在各种消息中调用其接口函数实现来相应其状态的改变,从而可以改变其外观,达到模拟真正Windows控件的目的。
如何实现控件的作用也是一个很重要的主题。点击按钮时主窗口如何得知按钮被点击的消息呢?我们知道每个主窗口有不同的各种控件,而相同的控件又有不同的消息形态。我们可以给主窗口发送一个自定义消息,然后消息参数自然要包括控件ID等附加参数来区分。什么时候来发送自定义消息呢?不同控件自然不同,拿最简单的Button控件来说,一般是在LButtonUp消息处理中给主窗口发送自定义消息,用SendMessage还是PostMessage视该功能过程而定。主窗口截获该自定义消息后自然可以处理该控件的响应了。
现在我们思考这样一个问题,能不能将主窗口截获控件发送的消息处理过程也定义为一个接口,这样只在该接口里处理控件的消息,从而免去每次响应不同控件消息时都要添加处理过程函数的麻烦。怎么去实现呢?我们让主窗口继承于一个接口,该接口包含消息处理的虚函数,同时让各控件都拥有该接口的一个指针,当主窗口加入控件时,将控件的该指针指向主窗口。这样当控件达到我们之前的理消息处理模型而触发消息要求时,我们可以调用接口函数。由于主窗口也是派生与该接口,同时接口中的消息处理函数是虚函数,主窗口当然可以处理控件消息了。我们注意到控件消息其实没有走主窗口的窗口过程函数或者消息队列,而是直接在主窗口中处理,我想其效率应该高些吧。
基于MFC的DirectUI程序的消息响应设计
标签:
原文地址:http://blog.csdn.net/zxm342698145/article/details/42676995