MFC消息映射机制的理解

当窗体,控件,点击标题栏等时,会产生消息,然后发给消息处理函数进行处理,而消息与消息映射表是一一对应的关系,这个关系就是消息映射表,根据根据消息通过消息映射表来查找对应的消息处理函数,这就称为消息映射机制。
而Windows有自己的消息队列,通过消息循环,采用GetMessage来获取消息,对于不调用加速键时就要派发消息,让目标窗口函数进行处理,消息是通过窗口过程函数来处理的。

MFC中消息分为:系统消息和用户自定义消息。
系统消息分为三类:
a.标准消息:除了WM_COMMANd,以WM开头的都是标准消息。
b.命令消息:WM_COMMAND,点击菜单栏啊,工具栏之类产生的消息
c.通知消息:在b的基础上进行的扩展,不过也是WM_COMMAND消息,不过会带对应控件的ID

用户消息:用户自己定义的消息,WM_USER +100

消息的实现方式:
1.在.h中用DECLARE_MESSAGE_MAP()用这个宏进行申明消息映射,注意afx开头的
2.在cpp,在BEGIN_MESSAGE_MAP和END_MESSAGE_MAP()实现消息映射,也就是添加消息处理函数。

PreTranslateMessage函数的理解:
是一个虚函数,可以通过函数重载来处理键盘,鼠标等消息,从GetMessage中获得消息,然后发送给Pretranslate,而且发送的消息是没有进行翻译的,先进行过滤一下下,预处理。
该函数是表示在消息处理(TranslateMessge()和DispatchMessage()等)前所作的操作。如果此函数返回为true,则不调用 translate和dispatch函数,返回false才会调用这两个函数,才会翻译和分发派送消息,交由消息处理函数(进入WindowProc)进行处理。只对通过消息队列的消息处理才有用,而对sendMessage处理消息没有任何作用。
SendMessage是将消息直接分发到对应的窗口去处理,交由消息直接交到WindowProc处理直接处理。
PostMessage是进入消息队列的,发送到后就会立马返回,而SendMessage是消息处理完毕才会返回。。。
在对消息进行分发和派送。消息的分发派送是从最顶层窗口开始的,依次传递给它的下一级窗口,如果想要某个编辑框控件在相应enter键时,如果在编辑框的上层有窗口,则窗口函数执行默认的OK消息处理函数,所以,为了让目标窗口执行这个enter,可以在编辑框控件之前的窗口,重载pretranslate函数,如果有enter时,则返回false。

BOOL CAutoCutDlg::PreTranslateMessage(MSG* pMsg) 
{
	if (WM_KEYDOWN==pMsg->message)
	{
		if ((VK_RETURN==pMsg->wParam) || (VK_SPACE==pMsg->wParam) || (VK_ESCAPE==pMsg->wParam))
		{
			return false;//
		}
	}
	return CDialog::PreTranslateMessage(pMsg);
}

对于WM_KEYDOWN消息,即使添加了消息处理函数OnkeyDown(),但因为先被pretranslate函数捕获,所以会执行其中的内容 ,而后面自定义的消息处理函数则不会被执行到了。(???待解释)

GetSafeHwnd()

AfxGetApp():AfxGetApp( )这个函数可以得到当前引用的指针CWinApp*,通过这个指针可以访问到这个进程中的对象
CTestApp theApp;(工程名为Test)
//Test.cpp文件中
CTestApp theApp;(工程名为Test)
的语句。它是指向工程对象的一个指针,你可以用它方向Test工程的成员函数和变量。

是DLL程序的话,情况会稍有不同。你会发现在DLL中调用AfxGetApp这个函数会得到DLL的应用对象。原因出现在DLL的模块状态上。应用程序在调用DLL时为了保证资源不出问题,往往会调用一句:

AFX_MANAGE_STATE(AfxGetStaticModuleState())
注意这是一个宏。他的作用是切换模块的全局变量范围,即把应用程序的那些全局变量拷贝切换到这个DLL的全局变量拷贝,自然用AfxGetApp得到就是DLL里面的这个APP了。如果向访问应用程序的App对象,那么只要把模块状态切换回去就可以了,记着执行完后一定要把状态再切换回来啊,否则就要出问题了。

好了,现在我们就在CConfig类中调用str吧!
//Config.cpp文件
CTestApp *pApp=(CTestApp *)AfxGetApp( );
AfxMessageBox(pApp->str);

GetSafeHwnd()
  当我们想得到一个窗口对象(CWnd的派生对象)指针的句柄(HWND)时,最安全的方法是使用GetSafeHwnd()函数,你看有很多函数的参数要求HWND,它就可以派上用场了.
  HWND hwnd;
  CWnd* pWnd;
  pWnd=((CFrameWnd*)(AfxGetApp()->m_pMainWnd))->GetActiveView();
  hwnd=pWnd->GetDlgItem(IDC_EDIT2)->GetSafeHwnd();
  ::SetWindowText(hwnd,m_strResult);

参考:
1.https://blog.csdn.net/yiziweiyang/article/details/52470683
2.https://blog.csdn.net/yiziweiyang/article/details/52470683
3.https://blog.csdn.net/very_2/article/details/6535505
4.https://baike.so.com/doc/6744089-6958626.html

猜你喜欢

转载自blog.csdn.net/u012719076/article/details/83479802