一、简介
最近做了一个程序,里面的RichEdit控件需要添加一个右键菜单,包括复制、粘贴等功能。但MFC自带的RichEdit没有右键菜单,而且无法使用主对话框的WM_RBUTTONUP消息(在控件内右击不会发送给父窗口),我又不想派生一个类。经过查阅资料和自己摸索,我发现RichEdit也给了一个接口,那就是EN_MSGFILTER事件。
vs上的说明很清楚,允许筛选控件中的鼠标和键盘消息,也就是说,控件接收到鼠标和键盘消息后,会通知父窗口,我们创建一个响应函数。VS自动生成的代码如下:
MSGFILTER* pMsgFilter = reinterpret_cast<MSGFILTER*>(pNMHDR);
// TODO: 控件将不发送此通知,除非您重写
// CDialogEx::OnInitDialog() 函数,以将 EM_SETEVENTMASK 消息发送
// 到该控件,同时将 ENM_KEYEVENTS 或 ENM_MOUSEEVENTS 标志
//“或”运算到 lParam 掩码中。
// TODO: 在此添加控件通知处理程序代码
*pResult = 0;
这里要注意里面的注释,提示我们要在OnInitDialog中添加代码发送消息。代码如下:
m_RichEdit.SetEventMask(m_RichEdit.GetEventMask() | ENM_MOUSEEVENTS);
这样,我们就可以在OnEnMsgfilterText函数里创建菜单了。代码如下:
void CXXXDlg::OnEnMsgfilterText(NMHDR* pNMHDR, LRESULT* pResult)
{
MSGFILTER* pMsgFilter = reinterpret_cast<MSGFILTER*>(pNMHDR);
// TODO: 控件将不发送此通知,除非您重写
// CDialogEx::OnInitDialog() 函数,以将 EM_SETEVENTMASK 消息发送
// 到该控件,同时将 ENM_KEYEVENTS 或 ENM_MOUSEEVENTS 标志
//“或”运算到 lParam 掩码中。
if (pMsgFilter->msg == WM_RBUTTONUP)
{
CPoint point(LOWORD(pMsgFilter->lParam), HIWORD(pMsgFilter->lParam));
ClientToScreen(&point);
CMenu popMenu;
popMenu.LoadMenu(IDR_MENU2);
CMenu* pPopup;
pPopup = popMenu.GetSubMenu(0);
pPopup->TrackPopupMenu(TPM_LEFTALIGN | TPM_RIGHTBUTTON, point.x, point.y, this);
pPopup->Detach();
popMenu.DestroyMenu();
}
*pResult = 0;
}
这个函数第一个参数的具体说明,可以点击此处查看,也谢谢这位博主的分享。
VS自动生成的代码中有一句MSGFILTER* pMsgFilter = reinterpret_cast<MSGFILTER*>(pNMHDR);
无非是告诉我们用这个结构体指针。其中最重要的成员是msg,它就是控件发送给父窗口收到的消息。如果收到右键松开的消息,就可以创建菜单了。创建菜单的方法请大家自行搜索。