Click here to Skip to main content
15,868,349 members
Articles / Desktop Programming / MFC
Article

CRichEditCtrl and a popup menu

Rate me:
Please Sign up or sign in to vote.
3.83/5 (27 votes)
15 Feb 20023 min read 221.4K   2.9K   46   35
Providing a popup menu for the CRichEditCtrl

Introduction

Welcome Gentle reader. The purpose of this article is to demonstrate the method with which to display a popup menu from a CRicheditCtrl after the user has right clicked the mouse, but first a little history

Yea verily...in the beginning there was the magic of Windows 3.1 and lo it was good(ish). And so it came to pass that years went by seemingly without incident but lo behind the scenes hoards of Microsoft(tm) minions worked feverishly for an on time release of new magic...Windows 95.

As part of the common controls to extend the much revered CEdit class, CRicheditCtrl was introduced. And CEdit class had some good magic for when you right clicked on it, a wee context menu popped up so one could cut, paste and so on. Programmers looked on this and saw it was good (ish). But alas CRicheditCtrl had no direct method for displaying a context menu...and so it is not good, it is in fact a darn pain!

So gentle reader I thought it was about time to provide a quick article on how to display a context menu from a CRicheditCtrl after a right click of the mouse.

Alas though there seemed to be a hitch dear reader as, for reasons best known to themselves, MS decided it wasn't going to make it totally easy (i.e. a simple override) to catch the WM_RBUTTONDOWN event from a CRichEditCtrl. They chose instead to make it a a bit more complicated (and I'm sure there's a very good reason which I just haven't researched.)

To begin with create a simple dialog based application, we'll call ours PopupDemo. Add a menu resource ( let's call ours IDR_MENU1) also, in the main dialog add a CRichEditCtrl member,

m_RichEdit
with IDC_RICHEDIT. Don't Forget to add

AfxInitRichEdit();

in the application's Initinstance or the application will not work...

Next, use the class wizard to generate an OnInitDialog member function for PopupDemoDlg. Inside this put the following

BOOL CPopupDemoDlg::OnInitDialog() 
{ 
   m_RichEdit.SetEventMask(ENM_MOUSEEVENTS);
...

This tells the RichEditCtrl that we want all mouse events reflected to the main window. We do this so we can catch them in a WM_NOTIFY handler.

To catch these mouse events which are being reflected to CPopupDemoDlg, we need to trap the event on OnNotify to do this...

The RichEditCtrl sends the message "EN_MSGFILTER" to the parent, now to get at which message has been reflected (because it could be a left click or a mouse move) we need to examine the message filter, so we cast lParam to MSGFILTER *

//
MSGFILTER * lpMsgFilter = (MSGFILTER *)lParam;
//

instead of the usual;

//
NMHDR * pnmh = (LPNMHDR)lParam;
//

Then we examine the result and test for which actual windows message and which window we're dealing with.

if ((wParam == IDC_RICHEDIT) && (lpMsgFilter->nmhdr.code == EN_MSGFILTER)
    & (lpMsgFilter->msg == WM_RBUTTONDOWN))
So the final OnNotify handler looks something like...
BOOL CPopupDemoDlg::OnNotify(WPARAM wParam, LPARAM lParam, LRESULT* pResult) 
{
MSGFILTER * lpMsgFilter = (MSGFILTER *)lParam; 
if ((wParam == IDC_RICHEDIT) && (lpMsgFilter->nmhdr.code == EN_MSGFILTER)   
    && (lpMsgFilter->msg == WM_RBUTTONDOWN))                                       
  
    {//if we get through here, we have trapped the right click event of the richeditctrl! 
     CPoint point;                                            
     ::GetCursorPos(&point); //where is the mouse?
     CMenu menu; //lets display out context menu :) 
     DWORD dwSelectionMade;                                       
     VERIFY(menu.LoadMenu(IDR_MENU1) );  
     CMenu *pmenuPopup = menu.GetSubMenu(0);
     ASSERT(pmenuPopup != NULL);                                       
     dwSelectionMade = pmenuPopup->TrackPopupMenu( (TPM_LEFTALIGN|TPM_LEFTBUTTON|
                                                       TPM_NONOTIFY|TPM_RETURNCMD),
                                                       point.x, point.y, this
                                );                                
  
     pmenuPopup->DestroyMenu(); 
     // Exercise for the reader...deal with the user's choice here :)                                      
     }
 return CDialog::OnNotify(wParam, lParam, pResult);
}

However... dear reader - there is a sneaker, faster way to code a method for dealing with the same event. Just override PreTranslateMessage(MSG* pMsg) (again use the class wizard). Do something similar to the following (this is not in the download files)

//
BOOL CPopupDemoDlg::PreTranslateMessage(MSG* pMsg)
{ 
    if (pMsg->message ==WM_RBUTTONDOWN)
    {
        CWnd * pWnd = (CWnd*) GetDlgItem(IDC_RICHEDIT); 
        if (pWnd ==GetFocus())
        {
              CMenu menu;
              DWORD dwSelectionMade; VERIFY(menu.LoadMenu(IDR_MENU1));
              CMenu *pmenuPopup = menu.GetSubMenu(0);
              ASSERT(pmenuPopup != NULL);                                    
              dwSelectionMade = pmenuPopup->TrackPopupMenu( (TPM_LEFTALIGN|
                                                                TPM_LEFTBUTTON|
                                                                TPM_NONOTIFY|
                                                                TPM_RETURNCMD),
                                                                 pMsg->pt.x, 
                                                                 pMsg->pt.y, this
                                                          );  
              pmenuPopup->DestroyMenu();
             //excercise for the reader...deal with the selection the user has made here
             return TRUE;
               }
    }
    return CDialog::PreTranslateMessage(pMsg);
}
//

Yea - though there are probably other ways of doing this these, gentle reader, are what I have found to be two of the easiest ways of achieving the aim. And lo, it is good.

Here-in ends the lesson.

License

This article has no explicit license attached to it but may contain usage terms in the article text or the download files themselves. If in doubt please contact the author via the discussion board below.

A list of licenses authors might use can be found here


Written By
Software Developer (Senior) TMR
Australia Australia
This member has not yet provided a Biography. Assume it's interesting and varied, and probably something to do with programming.

Comments and Discussions

 
QuestionMy Vote of 1 Pin
llothar15-Nov-12 11:25
llothar15-Nov-12 11:25 
AnswerRe: My Vote of 1 Pin
bryce15-Nov-12 11:29
bryce15-Nov-12 11:29 
QuestionVoted for 5 Pin
k77725-Aug-11 12:07
k77725-Aug-11 12:07 
Generalthank you! Pin
amabelleq4-Dec-09 20:07
amabelleq4-Dec-09 20:07 
GeneralRe: thank you! Pin
bryce5-Dec-09 0:56
bryce5-Dec-09 0:56 
GeneralErrors during compilation Pin
martyix30-Mar-09 5:35
martyix30-Mar-09 5:35 
GeneralA serious error in release executable file Pin
chocm15-Oct-07 2:58
chocm15-Oct-07 2:58 
QuestionWhy not ON_COMMAND? Pin
chocm3-Aug-07 0:49
chocm3-Aug-07 0:49 
AnswerRe: Why not ON_COMMAND? Pin
KarstenK3-Aug-07 1:33
mveKarstenK3-Aug-07 1:33 
GeneralRe: Why not ON_COMMAND? Pin
chocm9-Aug-07 23:55
chocm9-Aug-07 23:55 
Generalanother implementation Pin
MarcH757-Dec-05 3:29
MarcH757-Dec-05 3:29 
GeneralRe: another implementation Pin
MarcH757-Dec-05 3:32
MarcH757-Dec-05 3:32 
GeneralInsert a control in a popup menu. Pin
Negrume4-Nov-04 6:12
Negrume4-Nov-04 6:12 
GeneralRe: WM_CONTEXTMENU instead of WM_RBUTTONUP Pin
Anonymous20-May-04 11:00
Anonymous20-May-04 11:00 
Thanks againWink | ;-)
GeneralRe: WM_CONTEXTMENU instead of WM_RBUTTONUP Pin
hoiby31-Aug-04 8:03
hoiby31-Aug-04 8:03 
GeneralCommand Handlers Pin
billgower29-Oct-03 14:20
billgower29-Oct-03 14:20 
GeneralAuto detect if control is rich edit - also C version of the code Pin
Robert Inventor2-Sep-03 14:54
Robert Inventor2-Sep-03 14:54 
QuestionHow do use CRichEditCtrl without MFC? Pin
Anonymous4-Jul-03 16:57
Anonymous4-Jul-03 16:57 
AnswerRe: CRichEditCtrl without MFC? Pin
billgatest25-Aug-03 19:19
billgatest25-Aug-03 19:19 
GeneralProblem with Getting the WM_COMMAND msgs - fixed Pin
harningt15-May-03 18:37
harningt15-May-03 18:37 
GeneralOnNotify is more reliable Pin
Anonymous14-May-03 8:41
Anonymous14-May-03 8:41 
GeneralWM_CONTEXTMENU instead of WM_RBUTTONUP Pin
danmorin19-Mar-03 10:16
danmorin19-Mar-03 10:16 
GeneralRe: WM_CONTEXTMENU instead of WM_RBUTTONUP Pin
Anonymous20-May-04 5:40
Anonymous20-May-04 5:40 
GeneralRe: WM_CONTEXTMENU instead of WM_RBUTTONUP Pin
danmorin20-May-04 6:26
danmorin20-May-04 6:26 
GeneralShow or hide formatting marks Pin
wang200228-Feb-03 4:28
wang200228-Feb-03 4:28 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.