⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 映射.txt

📁 c++/vc++ 精华文章
💻 TXT
字号:
//定义一个消息映射的结构
struct AFX_MSGMAP_ENTRY
{
	UINT nMessage;   // windows message
	UINT nCode;      // control code or WM_NOTIFY code
	UINT nID;        // control ID (or 0 for windows messages)
	UINT nLastID;    // used for entries specifying a range of control id's
	UINT nSig;       // signature type (action) or pointer to message #
	AFX_PMSG pfn;    // routine to call (or special value)
};

//通过链表,把整个消息映射连起来,形成表.为了在各个类之间进行路由
struct AFX_MSGMAP
{
	const AFX_MSGMAP* pBaseMap;
	const AFX_MSGMAP_ENTRY* lpEntries;
};


When there is a message send to a application,it will follow the following orders:
	1.LRESULT CALLBACK AfxWndProc(HWND hWnd, UINT nMsg, WPARAM wParam, LPARAM lParam)
	   CWnd* pWnd = CWnd::FromHandlePermanent(hWnd);	//CWnd的指针和handle相关联
	2.LRESULT AFXAPI AfxCallWndProc(CWnd* pWnd, HWND hWnd, UINT nMsg, WPARAM wParam = 0, LPARAM lParam = 0)
	   pWnd->WindowProc(nMsg, wParam, lParam); //调用CWnd的WindowProc来进行真正意义上的消息处理.
	3.LRESULT CWnd::WindowProc(UINT message, WPARAM wParam, LPARAM lParam)
	   //窗口过程函数被CWnd类的WindowProc代替
	4.BOOL CWnd::OnWndMsg(UINT message, WPARAM wParam, LPARAM lParam, LRESULT* pResult)
	   	// special case for commands
		if (message == WM_COMMAND)
		{
			if (OnCommand(wParam, lParam))
			{
				lResult = 1;
				goto LReturnTrue;
			}
			return FALSE;
		}

		// special case for notifies
		if (message == WM_NOTIFY)
		{
			NMHDR* pNMHDR = (NMHDR*)lParam;
			if (pNMHDR->hwndFrom != NULL && OnNotify(wParam, lParam, &lResult))
				goto LReturnTrue;
			return FALSE;
		}
	. . . . . . . .
	const AFX_MSGMAP* pMessageMap; pMessageMap = GetMessageMap();

	5.const AFX_MSGMAP* theClass::GetMessageMap() const 
	  { 
		return &theClass::messageMap; 
	  }

	6.AFX_COMDAT AFX_DATADEF const AFX_MSGMAP theClass::messageMap = 
	  { 
		&baseClass::messageMap, &theClass::_messageEntries[0] 
	  }; 

	7.AFX_COMDAT const AFX_MSGMAP_ENTRY theClass::_messageEntries[] =
	  {
		{ WM_COMMAND, CN_COMMAND, (WORD)id, (WORD)id, AfxSig_vv, (AFX_PMSG)&memberFxn },
		{ WM_MOUSEMOVE, 0, 0, 0, AfxSig_vwp,(AFX_PMSG)(AFX_PMSGW)(void (AFX_MSG_CALL CWnd::*)(UINT, CPoint))&OnMouseMove },
		{0, 0, 0, 0, AfxSig_end, (AFX_PMSG)0 }
	  }; 
	//5.  6.  7.  就是相应类的BEGIN_MSG_MAP 和 END_MSG_MAP的作用.作用就是让类对象得到MessageEntries一个数组,和一个连接类的指针
	8. if((lpEntry=AfxFindMessageEntry(pMessageMap->lpEntries,message,0,0)!=NULL)
	  //搜寻关联类的MessgeEntries,头指针是lpEntries,如果搜到,关联message和function
------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
	9.上面说的是windows标准消息相应机制,下面说一下WM_COMMAND消息,上面有一个if这么写到:
		// special case for commands
		if (message == WM_COMMAND)
		{
			if (OnCommand(wParam, lParam))
			{
				lResult = 1;
				goto LReturnTrue;
			}
			return FALSE;
		}
	对于命令消息,实际上是交给OnCommand函数处理。而OnCommand是一个虚函数,即WM_COMMAND消息发生时,
	最终是发生该消息所对应的MFC对象去执行OnCommand。比如点框架窗口菜单,即向CFrameWnd发送一个WM_COMMAND,
	将会导致CFrameWnd::OnCommand(wParam,lParam)
	且看该函数原型

	BOOL CFrameWnd::OnCommand(WPARAM wParam,LPARAM lParam)
	{
       	……
       	return CWnd:: OnCommand(wParam,lParam);

	}
	可以看出,它最后把该消息交给CWnd:: OnCommand处理。再看:
	BOOL CWnd::OnCommand(WPARAM wParam,LPARAM lParam)
	{
		  ……
		return OnCmdMsg(nID,nCode,NULL,NULL);

	}
	这里包含了一个C++多态性很经典的问题。在这里,虽然是执行CWnd类的函数,但由于这个函数在CFrameWnd:: OnCmdMsg
	里执行,即当前指针是CFrameWnd类指针,再有OnCmdMsg是一个虚函数,所以如果CFrameWnd改写了OnCommand,程序会
	执行CFrameWnd::OnCmdMsg(…)。
	对CFrameWnd::OnCmdMsg(…)函数原理扼要分析如下:
	BOOL CFrameWnd:: OnCmdMsg(…)
	{
		CView pView = GetActiveView();//得到活动视指针。
		if(pView-> OnCmdMsg(…))
		return TRUE; //如果CView类对象或其派生类对象已经处理该消息,则返回。
		……//否则,同理向下执行,交给文档、框架、及应用程序执行自身的OnCmdMsg。
	}
	到此,CFrameWnd:: OnCmdMsg完成了把WM_COMMAND消息传递到视对象、文档对象及应用程序对象实现消息响应。
	注释:在这里可以看到:接受WM_COMMAND消息的几个基本类的顺序,View->Document->CFrame->App,所以如果重复定义了
	多个同样的WM_COMMAND给几个类,只会有一个类做出相应,安装上面的顺序来进行相应

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -