我想设计这样一个类:当接受一个控件的句柄时,更改该控件的默认消息处理函数,即在默认消息处理函数前加一个自定的函数先行处理消息。这个自定函数处理一些特定消息,余下的还是传给默认消息处理函数。
这个类可以有多个实例,即程序能同时子类化多个控件。我按着这个要求试着写了下代码,结果发现这个设计我根本无法办到……下面我逐步说明:1. 获取默认消息处理函数、并用自定函数替换是用的SetWindowLong或者SetWindowLongPtr。由于该自定函数是非静态的类成员函数,它隐含一个this指针参数,而SetWindowLong要求传入的窗口过程函数是不带this指针的,所以编译器不让通过;(具体讨论: http://topic.csdn.net/t/20050129/17/3762958.html)2. 如果把该自定函数定义为静态的或者拿到类外面,它就不带this指针参数了。可它又无法访问类的非静态成员——传入的控件的默认消息处理函数地址了。该自定函数必须访问这个非静态成员,因为还有很多消息要让默认消息处理函数处理;3. 要让静态成员函数访问非静态成员:1. 可以用实例化的类成员代替未实例化的在函数中使用;2. 可以把类成员都改成静态的;3. 可以在该函数的参数中加上一个位置,接受该非静态成员。(具体方法:http://www.builder.com.cn/2003/1110/101002.shtml)
经分析以上三个办法对这个设计都无效:1. 这样做就要为每个该类的实例创建一个函数,相当于把子类化功能拿到了类外,那这个类也就没有任何意义了;2. 这样该类就只能有一个实例了,不符合要求;3. 这个静态成员函数是消息处理函数,其参数是固定的,不能更改。4. 把“传入的控件的默认消息处理函数地址”改成静态成员。可以在类中定义N个静态的“默认消息处理函数地址”以及与之对应的N个静态的“自定消息处理函数”(每个函数内部使用一个静态“默认消息处理函数地址”)。再加一个非静态成员,指示当前实例的序号。最后规定该类最多只能有N个实例。
在运行时,每实例化一次,就根据当前的“默认消息处理函数地址”组的状态确定当前实例的序号,用SetWindowLong设置对应的“自定消息处理函数”,用返回的“默认消息处理函数地址”给对应的“默认消息处理函数地址”赋值。
这样表面问题是解决了,可由于多了N个静态的“默认消息处理函数地址”成员和N个静态的“自定消息处理函数”,类变得非常庞大,几乎没有实用价值。
我的问题是:是否有更好的解决方法?或者我的设计思路本身就错了,只要纠正了思路,就不会遇到这么变态的问题了?

解决方案 »

  1.   

    OWL VCL ATL
    都是用了同一种方法来完成这个效果
    就是将成员函数 做成回调函数.
      

  2.   

    消息处理过程有hwnd的,你可以使用一个表格
    将hwnd和具体对象的this指针对应起来
    MFC是这样做的
      

  3.   

    > akirya原来如此,这样就不用多出N个“自定消息处理函数”了,但N个“默认消息处理函数地址”及其对应的控件句柄还是不能少,是这样吧?> "就是将成员函数做成回调函数"
    这个有些不解,“自定消息处理函数”本身就是CALLBACK类型
      

  4.   

    > shakaqrj 友元的作用点是类的公有/私有方面吧,和静态/非静态没有关系。
      

  5.   

    因为成员函数有this指针嘛,他们就内嵌汇编来做,如果有条件的话看一下深入解析atl,
    关于窗口那一章有详细解释,这种方法怎么做.