我们知道windows系统会预先为我们注册一些窗口类 如"button",“edit”,"Static"等等;而在MFC中如果我们关联控件变量的时候,关联的类类型与对应关联的窗口的注册窗口类名称如果不匹配会发生什么;拿CStatic与CEdit这俩个MFC为我们写好的类举例 首先我们看看这二个MFC如何封装这二个类的;【这里就不暂时这二个类的源码了】从MFC源码上我们可以看出这二个类本身并没有添加任何新的数据成员,全部都是继承CWnd类;但是里面提供的接口不同,看实现我们发现这些成员函数的实现全部都是发消息给对应的窗口; 这些消息肯定要被窗口过程处理,所以我们先看看系统定义了哪些消息 https://docs.microsoft.com/en-us/windows/win32/winmsg/about-messages-and-message-queues#system-defined-messages
从源码我们可以得知,MFC定义的类之所以能够起作用是因为向窗口发送了消息并获得响应(返回值);那么我们看向窗口发送与其注册窗口类不匹配的这些系统预定义的消息会如何就知道关联控件如果与窗口类不匹配会如何;我们以这个消息为例EM_GETLINECOUNT
设定条件断点追踪这个消息的处理;我们发现至少在EM_GETLINECOUNT这个消息上无论是向匹配的m_linkedit发送还是向不匹配的m_static发送最后都会走到DefWindowProc里面去;但是匹配的DefWindowProc调用返回结果可以返回正确的值;而不匹配的调用DefWindowProc返回的是0;【或许对不同的消息DefWindowProc的差异行为可能会不同,甚至消息路由不一定都是走DefWindowProc;但是这都对我们想说明的问题而言无关紧要】 那么从这个消息的追踪我们就可以看出;如果不匹配的会有怎么样的行为: 1.首先就是这些自定义或者MFC定义的成员函数可能没有作用了,因为这些函数的实现是向一个窗口发送不匹配的消息;可能被DefWindowProc忽略默认处理了;既然这样就那么这些自定义或者MFC定义的类就毫无意义因为在面向对象设计上的初衷就是继承接口;而现在这些接口无法发挥作用! 【这里有人会说如果先不考虑面向对象设计,完全不用类类型原来提供的接口,并且尽可能的添加自己的消息响应函数避免走默认的DefWindowProc函数处理是不是就可以了;】【还是太天真】 2.自定义或者MFC定义的类类型的消息响应函数可能永远不会被响应;因为他们关联的那个注册窗口类的窗口可能永远不会发生需要响应的那个消息! 3.与第二条相对的是无法响应注册窗口类对应的窗口本来可以响应的消息,即便是手工在不匹配的自定义类中去添加这个消息的响应函数也无法得到响应【MFC实测】
所以你认为如果抛开面向对象接口的设计,只要不使用原来提供的接口,并且自己提供消息处理函数就万事大吉是愚蠢的干法;
Effective MFC :不要发生关联类类型与窗口注册类的不匹配的行为!
测试源码:
|