这篇文章从函数指针的角度理解MFC的消息映射。
首先了解下类的成员方法指针。类的静态成员方法指针和普通指针没什么区别,略过。主要了解一下类的非静态成员指针的用法
1.类的非静态成员指针的用法
c++将类的非静态成员编译成有this指针参数的方法。c++提供了"->*"和".*"运算符,来调用指针成员方法。
以代码说明问题
SunLight * lightPtr = & light;
Func f2 = &SunLight::WaveLength;
(lightPtr->*f2)();
return 0;
}
结果为
white
60nm
2.非静态成员函数指针数组
MFC中用AFX_MSGMAP_ENTRY* lpEntries储存了静态成员的指针。
下面代码实现了储存其指针的功能。
return 0;
}
这里便出现了调用的问题。通用的函数指针Func是没有参数的,PowerValue是有参数有返回值的。这应该如何调用了。
3.强转调用有参数的函数指针
只要强转一下就可以了
代码如下
FuncType2 f1 = (FuncType2)static_cast<void (SunLight::*)( )>(funcArr[2]);
cout << (light.*f1)(26) << endl;
return 0;
}
结果如下
white
60nm
260
MFC用枚举处理了这个问题。
4.MFC处理方法
代码如下
int main()
{
Func funcArr[4];
funcArr[0]= &SunLight::Color;
funcArr[1] = &SunLight::WaveLength;
funcArr[2] = (Func)(&SunLight::PowerValue);
funcArr[3] = (Func)(&SunLight::Blend);
SunLight light;
union GenerateFunctionPointers gfs;
gfs.pfn = funcArr[0];//少了强转
(light.*gfs.FuncType1)();
gfs.pfn = funcArr[2];
cout << (light.*gfs.FuncType2)(26) << endl;//少了强转
return 0;
}
结果如下
white
260
有了这些基础,我们可以模仿MFC的消息映射了。下面代码说明了MFC消息映射的主要机制。
4.简明MFC消息映射代码
#define BEGIN_MESSAGE_MAP(theClass, baseClass) /
const AFX_MSGMAP* theClass::GetMessageMap() const /
{ return GetThisMessageMap(); } /
const AFX_MSGMAP* theClass::GetThisMessageMap() /
{ /
typedef theClass ThisClass; /
typedef baseClass TheBaseClass; /
static const AFX_MSGMAP_ENTRY _messageEntries[] = /
{
#define END_MESSAGE_MAP() /
{0, 0, 0, 0, AfxSig_end, (AFX_PMSG)0 } /
}; /
static const AFX_MSGMAP messageMap = /
{ &TheBaseClass::GetThisMessageMap, &_messageEntries[0] }; /
return &messageMap; /
}
#define ON_DRAW()/
{ 100, 0, 0, 0, AfxSig_b_b_v, /
(AFX_PMSG)/
(static_cast< bool ( CCmdTarget::*)(bool) > ( &ThisClass::HasReDraw)) },
#define ON_COMMAND(id, memberFxn) /
{ 101, 101, 101, 101, AfxSigCmd_v, /
static_cast<AFX_PMSG> (memberFxn) },
#define ON_MYCOMMAND(memberFxn) /
{ 101, 101, 101, 101, AfxSig_i_ii_v, /
(AFX_PMSG)/
static_cast<int (CCmdTarget::*)(int, int) >(memberFxn) },
class CCmdTarget
{
public:
protected:
static const AFX_MSGMAP* GetThisMessageMap();
};
const AFX_MSGMAP* CCmdTarget::GetThisMessageMap()
{
return 0;
}
class DrawView : public CCmdTarget
{
public:
bool HasReDraw(bool b);
void Print();
int Add(int a, int b);
int Subtract(int a, int b);
public:
const AFX_MSGMAP * Test();
DECLARE_MESSAGE_MAP()
};
const AFX_MSGMAP * DrawView::Test()
{
return GetMessageMap(); //为虚函数
}
bool DrawView::HasReDraw(bool b)
{
cout << "Boolean" << endl;
return b;
}
void DrawView::Print()
{
cout << "drawer" << endl;
}
int DrawView::Add(int a, int b)
{
int result = a + b;
cout << result << endl;
return result;
}
int DrawView::Subtract(int a, int b)
{
int result = a - b;
cout << result << endl;
return result;
}
BEGIN_MESSAGE_MAP(DrawView,CCmdTarget)
ON_DRAW()
ON_COMMAND(101,&Print)
ON_MYCOMMAND(&Add)
ON_MYCOMMAND(&Subtract)
END_MESSAGE_MAP()
union MessageMapFunctions
{
AFX_PMSG pfn; // generic member function pointer
bool ( CCmdTarget::*pfn_b_b)(bool); //bool bool
void ( CCmdTarget::*pfn_v_v)(); // void void
int ( CCmdTarget::*pfn_i_i_i)(int, int);
};
int main()
{
DrawView view;
const AFX_MSGMAP * ite = view.Test();
const AFX_MSGMAP_ENTRY * ent = ite->lpEntries;
while(ent->nSig != AfxSig_end)
{
union MessageMapFunctions mmf;
mmf.pfn = ent->pfn;
switch(ent->nSig)
{
case AfxSig_b_b_v: // BOOL (BOOL)
(view.*mmf.pfn_b_b)(true);
break;
case AfxSigCmd_v: // void ()
(view.*mmf.pfn_v_v)();
break;
case AfxSig_i_ii_v:
(view.*mmf.pfn_i_i_i)(6,12);
break;
}
++ent;
}
return 0;
}
结果如下
Boolean
drawer
18
-6
over