MFC之CToolTipCtrl按钮提示(消息捕获和消息传递)
记得以前写对话框时,按钮直接有一个tips属性,可以添加默认值,不记得是C#还是啥了,今天忽然想给几个按钮添加提示信息,就捣鼓了一下。
头文件中创建CToolTipCtrl变量,然后在初始化时激活使用:
CToolTipCtrl m_iToolTips;
BOOL CTestDXFDlg::OnInitDialog() { CDialog::OnInitDialog(); // 设置此对话框的图标。当应用程序主窗口不是对话框时,框架将自动 // 执行此操作 SetIcon(m_hIcon, TRUE); // 设置大图标 SetIcon(m_hIcon, FALSE); // 设置小图标 // TODO: 在此添加额外的初始化代码 EnableToolTips(TRUE); m_iToolTips.Create(this); m_iToolTips.Activate(TRUE); m_iToolTips.SetTipTextColor(RGB(0,255,0)); m_iToolTips.SetTipBkColor(RGB(255,0,0)); m_iToolTips.SetDelayTime(150); m_iToolTips.AddTool(GetDlgItem(IDC_BTN_ZOOM_IN), "放大"); m_iToolTips.AddTool(GetDlgItem(IDC_BTN_ZOOM_OUT), "缩小"); m_iToolTips.AddTool(GetDlgItem(IDC_BTN_ZOOM_EXTENT), "适应"); return TRUE; // 除非将焦点设置到控件,否则返回 TRUE }
重载PreTranslateMessage系统消息函数
BOOL CTestDXFDlg::PreTranslateMessage(MSG* pMsg) { switch(pMsg->message) { case WM_MOUSEMOVE: m_iToolTips.RelayEvent(pMsg); break; default: break; } return CDialog::PreTranslateMessage(pMsg); }
手动和自动添加该函数均可(vs2008自动添加PreTranslateMessage函数)
然后遇到问题:不能设置tip的背景颜色和字体颜色,查询后发现,在xp系统下是正常的,在xp之后的系统均出现这个问题,注释掉stdafx.h中相关代码又出现界面其他显示问题。(注释代码详情)
WIN32消息传递方式
- MFC消息,MFC会把所有的消息一条条放到一个AFX_MSG_MAP_ENTRY结构中,形成一个数组,该数组存放了所有的消息和与它们相关的参数。也可以说是放到消息队列里去,受PreTranslateMessage()影响。
- 采用SendMessage()或其他类似的方式向窗口直接发送的而不经过消息队列的消息。
消息处理函数
- MFC中,PreTranslateMessage()是虚函数,可以重载它来处理键盘和鼠标消息。
- SDK中,调用回调函数 LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)处理消息,它和PreTranslateMessage起的作用是类似的。
PreTranslateMessage函数表示在消息处理(TranslateMessage()和DispatchMessage()等)前所作的操作,如果函数返回值为TRUE,那么消息处理即终止,不会调用TranslateMessage()和DispatchMessage()来翻译和分发消息给相应的窗口;若返回值为FALSE,才会调用翻译和分发消息函数。
注:
- 是否调用TranslateMessage()和DispatchMessage()是由一个名称为PreTranslateMessage()函数的返回值决定的,如果该函数返回TRUE,则不会把该消息分发给窗口函数处理。
- 传给PreTranslateMessage()的消息是未经翻译过的消息,它没有经过TranslateMessage()处理。例如可以在该函数中使用(pMsg->wParam == VK_RETURN)来拦截回车键。
- 在WindowProc里不能处理WM_CHAR消息。
- SetWindowText会发送WM_CHAR给窗口。
- PeekMessage和GetMessage的区别:GetMessage在没有消息的时候等待消息,效率低。PeekMessage没有消息的时候立刻返回,所以CPU使用率高。因为游戏不能靠Windows消息驱动,所以要用PeekMessage()。
屏蔽消息
直接在函数中屏蔽回车和ESC的消息
BOOL CDemoDlg::PreTranslateMessage(MSG* pMsg) { if(pMsg->message==WM_KEYDOWN && pMsg->wParam==VK_ESCAPE)
return TRUE; if(pMsg->message==WM_KEYDOWN && pMsg->wParam==VK_RETURN)
return TRUE; else return CDialog::PreTranslateMessage(pMsg); }
屏蔽并继续传递消息
if (pMsg->message == WM_KEYDOWN && pMsg->wParam == VK_RETURN) //如果消息类型为WM_KEYDOWN并且用户按下的是回车 return FALSE; //不翻译消息,直接将消息传递下去。具体可查MSDN。注意,这里返回值不能为TRUE,TRUE的意思是翻译消息后退出消息传递,如此一来虽然也能避开对话框默认处理,但是会退出消息传递,这样EDIT控件照样得不到消息。