Click here to Skip to main content
Click here to Skip to main content

CRichEditCtrl and a popup menu

By , 15 Feb 2002
Rate this:
Please Sign up or sign in to vote.
<!-- Download Links --> <!-- Add the rest of your HTML here -->

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

About the Author

bryce
Software Developer (Senior)
Australia Australia
No Biography provided

Comments and Discussions

 
QuestionMy Vote of 1 Pinmemberllothar15-Nov-12 11:25 
AnswerRe: My Vote of 1 Pinmemberbryce15-Nov-12 11:29 
QuestionVoted for 5 Pinmemberk77725-Aug-11 12:07 
Generalthank you! Pinmemberamabelleq4-Dec-09 20:07 
GeneralRe: thank you! Pinmemberbryce5-Dec-09 0:56 
GeneralErrors during compilation Pinmembermartyix30-Mar-09 5:35 
GeneralA serious error in release executable file Pinmemberchocm15-Oct-07 2:58 
QuestionWhy not ON_COMMAND? Pinmemberchocm3-Aug-07 0:49 
AnswerRe: Why not ON_COMMAND? PinmemberKarstenK3-Aug-07 1:33 
GeneralRe: Why not ON_COMMAND? Pinmemberchocm9-Aug-07 23:55 
Generalanother implementation PinmemberMarc Hoesen7-Dec-05 3:29 
GeneralRe: another implementation PinmemberMarc Hoesen7-Dec-05 3:32 
GeneralInsert a control in a popup menu. PinmemberNegrume4-Nov-04 6:12 
GeneralRe: WM_CONTEXTMENU instead of WM_RBUTTONUP PinsussAnonymous20-May-04 11:00 
GeneralRe: WM_CONTEXTMENU instead of WM_RBUTTONUP Pinmemberhoiby31-Aug-04 8:03 
GeneralCommand Handlers Pinmemberbillgower29-Oct-03 14:20 
GeneralAuto detect if control is rich edit - also C version of the code PinmemberR. Walker2-Sep-03 14:54 
QuestionHow do use CRichEditCtrl without MFC? PinsussAnonymous4-Jul-03 16:57 
AnswerRe: CRichEditCtrl without MFC? Pinmemberbillgatest25-Aug-03 19:19 
GeneralProblem with Getting the WM_COMMAND msgs - fixed PinmemberMetX15-May-03 18:37 
GeneralOnNotify is more reliable PinsussAnonymous14-May-03 8:41 
GeneralWM_CONTEXTMENU instead of WM_RBUTTONUP Pinmemberdanmorin19-Mar-03 10:16 
GeneralRe: WM_CONTEXTMENU instead of WM_RBUTTONUP PinsussAnonymous20-May-04 5:40 
GeneralRe: WM_CONTEXTMENU instead of WM_RBUTTONUP Pinmemberdanmorin20-May-04 6:26 
GeneralShow or hide formatting marks Pinmemberwang200228-Feb-03 4:28 

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

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

| Advertise | Privacy | Mobile
Web02 | 2.8.140415.2 | Last Updated 16 Feb 2002
Article Copyright 2002 by bryce
Everything else Copyright © CodeProject, 1999-2014
Terms of Use
Layout: fixed | fluid