您的位置:逆风者 VC++ 正文
 添加时间:2007-09-01 原文发表:2007-08-31 人气:89 来源:vckbase.com

本文章共5248字,分4页,当前第2页,快速翻页:
 
  可以看出DECLARE_MESSAGE_MAP宏在其类中申请了一个全局结构和获得该结构的函数,而在BEGIN_MESSAGE_MAP和END_MESSAGE_MAP之间填写刚才的全局结构,将消息和对应的处理函数联系起来,并通过AFX_MSGMAP中的pBaseMap指针,将各类按继承顺序连接起来,从而提供消息流动的道路(即消息的直流,满足标准消息流动的要求)。
逆@风@者

下面我们举个例子:
CMyWnd : public CWnd

{

   ……

   DECLARE_MESSAGE_MAP()

}

BEGIN_MESSAGE_MAP(CMyWnd,CWnd)

     ON_WM_CREATE()

     ON_WM_PAINT()

END_MESSAGE_MAP()

被展开后,代码如下:
CMyWnd:public CWnd

{

    ……

private:

    static const AFX_MSGMAP_ENTRY _messageEntries[];

protected:

    static AFX_DATA const AFX_MSGMAP messageMap;

    virtual const AFX_MSGMAP* GetMessageMap() const;

}



const AFX_MSGMAP* CMyWnd::GetMessageMap() const

{  return &CMyWnd::messageMap;}

AFX_DATADEF const AFX_MSGMAP CMyWnd::messageMap=

{&CWnd::messageMap, &CMyWnd::_messageEntries[0]};

const AFX_MSGMAP_ENTRY CMyWnd::_messageEntries[]=

{

{WM_CREATE,0,0,0,AfxSig_is,

(AFX_PMSG)(AFX_PMSGW)(int(AFX_MSG_CALL CWnd::*)(LPCREATESTRUCT))OnCreate},

{WM_PAINT,0,0,0,AfxSig_vv,

(AFX_PMSG)(AFX_PMSGW)(void (AFX_MSG_CALL CWnd::*)(void))OnPaint},

{0,0,0,0,AfxSig_end,(AFX_PMSG)0}

};

  这样 WM_CREATE,WM_PAINT 在消息网中流动,当流到CMyWnd类的 messageMap 结构时,发现有该消息的记录,则调用记录中记载的 OnCreate 和 OnPaint 函数,进行响应消息,从而完成了 Windows 消息驱动机制。

四、MFC消息的起点
  我们已经建立了一张消息流动网络,但是消息是怎样从产生到响应函数收到该消息,而且标准消息需要直流,命令消息还有许多拐弯(在标题二中可以看到)。不要紧张,我们只需要看看MFC是怎样实现的。
  不管怎么说,对 Windows 系统来说都是一样的,它都是不断地用GetMessage(或者其它)从消息队列中取出消息,然后用DispatchMessage将消息发送到窗口函数中去。在"窗口类的诞生"中知道,MFC将所有的窗口处理函数都注册成DefWndProc,那是不是MFC将所有的消息都发送到DefWndProc中去了呢?很抱歉不是,而是都发送到了AfxWndProc函数去了。你可能要问为什么,这也是我想知道的,那我们就看看MFC代码吧:
BOOL CWnd::CreateEx(……)

{

……

PreCreateWindow(cs);

AfxHookWindowCreate(this);

HWND hWnd = ::CreateWindowEx(……);

……

}

void AFXAPI AfxHookWindowCreate(CWnd *pWnd)

{

……

pThreadState->m_hHookOldCbtFilter = 

::SetWindowsHookEx(WH_CBT,_AfxCbtFilterHook,NULL,::GetCurrentThreadId());

……

}

_AfxCbtFilterHook(int code, WPARAM wParam, LPARAM lParam)

{

……

if(!afxData.bWin31)

{

_AfxStandardSubclass((HWND)wParam);

}

……

}

void AFXAPI _AfxStandardSubclass(HWND hWnd)

{

……

oldWndProc =

 (WNDPROC)SetWindowLong(hWnd,GWL_WNDPROC,(DWORD)AfxGetAfxWndProc());

}

WNDPROC AFXAPI AfxGetAfxWndProc()

{

……

return &AfxWndProc;

}

  看了上面的代码,不知你有没有了然于胸的感觉"啊,原来是这样呀!"其实MFC在PreCreateWindow注册窗口类之后,在创建窗口之前,调用了AfxHookWindowCreate函数,该函数设置了钩子(钩子用SetWinowsHook或者SetWindowsHookEx设置,这样消息有满足设置的消息时,系统就发送给你设置的函数,这里是_AfxCbtFilterHook函数),这样每次创建窗口的时候,该函数就将窗口函数修改成AfxWndProc。至于为什么这样做吗?那是为了包容新的3D控件而又同MFC2.5兼容。
 
本文章更多内容<<上一页 - 1 - 2 - 3 - 4 - 下一页>>
相关文章

PhotoShop插件开发之选区(Selection)
编写多文档应用程序
COM 组件设计与应用(五)——用 ATL 写第一
MFC程序员的WTL指南: 中文版序言
不重起Windows直接更改IP地址
类似于FlashGet的悬浮框的制作
毫秒定时器
C :使用 Visual C 2005 的现代语言特色
IP Messenger 详细分析
可设置单元格颜色的ClistCtrl类
定制调试诊断工具和实用程序——摆脱DLL“地
WMI 的一个实现
自绘按钮的实现
《系统飞狐》系列软件中的“系统监视器”开
定时显示远程计算机的桌面
一个实用的CToolBar扩展类CToolBarEx
简单实用的Xml解析类
SQL Server 索引结构及其使用(三)
图形显示特技算法
论程序设计方法

相关评论


本文章所属分类:首页 VC++

  热门关键字: