当前位置 博文首页 > 一位初中编程爱好者的博客:MFC 在RichEdit里创建右键菜单

    一位初中编程爱好者的博客:MFC 在RichEdit里创建右键菜单

    作者:[db:作者] 时间:2021-08-29 22:32

    一、简介

    最近做了一个程序,里面的RichEdit控件需要添加一个右键菜单,包括复制、粘贴等功能。但MFC自带的RichEdit没有右键菜单,而且无法使用主对话框的WM_RBUTTONUP消息(在控件内右击不会发送给父窗口),我又不想派生一个类。经过查阅资料和自己摸索,我发现RichEdit也给了一个接口,那就是EN_MSGFILTER事件。
    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,它就是控件发送给父窗口收到的消息。如果收到右键松开的消息,就可以创建菜单了。创建菜单的方法请大家自行搜索。

    三、程序截图

    程序截图

    cs