Click here to Skip to main content
15,867,835 members
Articles / Desktop Programming / MFC
Article

How to modify a CEdit context menu

Rate me:
Please Sign up or sign in to vote.
4.58/5 (18 votes)
16 Sep 2001CPOL 201.1K   50   35
A simple way to let your CEdit derived class have a modifiable context menu

Introduction

Have you ever wanted to modify the context menu of an edit control? You would start by overriding the OnInitMenuPopup() function only to find that the edit control does not post a WM_INITMENUPOPUP message, so your function is never called. Well, here is a simple CEdit derived class that you can use.

The CMenuEdit class

The CMenuEdit class does its job with just two functions, OnContextMenu() and OnCommand().

The OnContextMenu() function gets called when a user right-clicks on the edit control. In our override, we create a new popup menu that exactly duplicates the default context menu, and we call TrackPopupMenu() on that menu. By doing this, a WM_INITMENUPOPUP message is posted, which can then be handled in a class derived from CMenuEdit.

The OnCommand() function handles commands generated when a user selects an item from the menu. If the command is not generated by our menu, it is passed onto CEdit::OnCommand().

You can either derive your edit class from CMenuEdit or include these two functions in your class.

Updates

September 17, 2001 - Now handles read-only edit controls

The Source Files

The Header file

// MenuEdit.h : header file
// Written by PJ Arends
// pja@telus.net
// http://www3.telus.net/pja/

#if !defined(AFX_MENUEDIT_H__8EA53611_FD2B_11D4_B625_D04FA07D2222__INCLUDED_)
#define AFX_MENUEDIT_H__8EA53611_FD2B_11D4_B625_D04FA07D2222__INCLUDED_

#if _MSC_VER > 1000
#pragma once
#endif 

class CMenuEdit : public CEdit
{
public:
    CMenuEdit() {};

protected:
    virtual BOOL OnCommand(WPARAM wParam, LPARAM lParam);
    afx_msg void OnContextMenu(CWnd* pWnd, CPoint point);

    DECLARE_MESSAGE_MAP()
};

#endif 

The Source file

// MenuEdit.cpp : implementation file
// Written by PJ Arends
// pja@telus.net
// http://www3.telus.net/pja/

#include "stdafx.h"
#include "MenuEdit.h"

#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif

#define MES_UNDO        _T("&Undo")
#define MES_CUT         _T("Cu&t")
#define MES_COPY        _T("&Copy")
#define MES_PASTE       _T("&Paste")
#define MES_DELETE      _T("&Delete")
#define MES_SELECTALL   _T("Select &All")
#define ME_SELECTALL    WM_USER + 0x7000

BEGIN_MESSAGE_MAP(CMenuEdit, CEdit)
    ON_WM_CONTEXTMENU()
END_MESSAGE_MAP()

void CMenuEdit::OnContextMenu(CWnd* pWnd, CPoint point)
{
    SetFocus();
    CMenu menu;
    menu.CreatePopupMenu();
    BOOL bReadOnly = GetStyle() & ES_READONLY;
    DWORD flags = CanUndo() && !bReadOnly ? 0 : MF_GRAYED;
    menu.InsertMenu(0, MF_BYPOSITION | flags, EM_UNDO,
        MES_UNDO);

    menu.InsertMenu(1, MF_BYPOSITION | MF_SEPARATOR);

    DWORD sel = GetSel();
    flags = LOWORD(sel) == HIWORD(sel) ? MF_GRAYED : 0;
    menu.InsertMenu(2, MF_BYPOSITION | flags, WM_COPY,
        MES_COPY);

    flags = (flags == MF_GRAYED || bReadOnly) ? MF_GRAYED : 0;
    menu.InsertMenu(2, MF_BYPOSITION | flags, WM_CUT,
        MES_CUT);
    menu.InsertMenu(4, MF_BYPOSITION | flags, WM_CLEAR,
        MES_DELETE);

    flags = IsClipboardFormatAvailable(CF_TEXT) &&
        !bReadOnly ? 0 : MF_GRAYED;
    menu.InsertMenu(4, MF_BYPOSITION | flags, WM_PASTE,
        MES_PASTE);

    menu.InsertMenu(6, MF_BYPOSITION | MF_SEPARATOR);

    int len = GetWindowTextLength();
    flags = (!len || (LOWORD(sel) == 0 && HIWORD(sel) ==
        len)) ? MF_GRAYED : 0;
    menu.InsertMenu(7, MF_BYPOSITION | flags, ME_SELECTALL,
        MES_SELECTALL);

    menu.TrackPopupMenu(TPM_LEFTALIGN | TPM_LEFTBUTTON |
        TPM_RIGHTBUTTON, point.x, point.y, this);
}

BOOL CMenuEdit::OnCommand(WPARAM wParam, LPARAM lParam)
{
    switch (LOWORD(wParam))
    {
    case EM_UNDO:
    case WM_CUT:
    case WM_COPY:
    case WM_CLEAR:
    case WM_PASTE:
        return SendMessage(LOWORD(wParam));
    case ME_SELECTALL:
        return SendMessage (EM_SETSEL, 0, -1);
    default:
        return CEdit::OnCommand(wParam, lParam);
    }
}

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)


Written By
President
Canada Canada
Father of two, brother of two, child of two.
Spouse to one, uncle to many, friend to lots.
Farmer, carpenter, mechanic, electrician, but definitely not a plumber.
Likes walks with the wife, board games, card games, travel, and camping in the summer.
High school graduate, college drop-out.
Hobby programmer who knows C++ with MFC and the STL.
Has dabbled with BASIC, Pascal, Fortran, COBOL, C#, SQL, ASM, and HTML.
Realized long ago that programming is fun when there is nobody pressuring you with schedules and timelines.

Comments and Discussions

 
QuestionLanguage independant version Pin
User 269427-Sep-15 1:27
professionalUser 269427-Sep-15 1:27 
AnswerRe: Language independant version Pin
PJ Arends7-Sep-15 18:13
professionalPJ Arends7-Sep-15 18:13 
GeneralMy vote of 4 Pin
Falkir26-Mar-11 8:42
Falkir26-Mar-11 8:42 
GeneralMy vote of 5 Pin
Yangyong Qin1-Mar-11 13:22
Yangyong Qin1-Mar-11 13:22 
GeneralExample program would be useful Pin
l_d_allan1-Jan-04 2:24
l_d_allan1-Jan-04 2:24 
QuestionDoes this work on CDialogBar? Pin
Steven M Hunt3-Jun-03 14:21
Steven M Hunt3-Jun-03 14:21 
AnswerRe: Does this work on CDialogBar? Pin
PJ Arends4-Jun-03 21:13
professionalPJ Arends4-Jun-03 21:13 
GeneralA small question Pin
Doan Quang Minh31-May-03 17:57
Doan Quang Minh31-May-03 17:57 
GeneralRe: A small question Pin
PJ Arends13-Jul-03 0:57
professionalPJ Arends13-Jul-03 0:57 
GeneralRe: A small question Pin
Doan Quang Minh14-Jul-03 0:21
Doan Quang Minh14-Jul-03 0:21 
GeneralRe: A small question Pin
hoc9629-Jul-03 22:11
hoc9629-Jul-03 22:11 
QuestionHow to access data Pin
Jack_pt15-Nov-02 16:55
Jack_pt15-Nov-02 16:55 
AnswerRe: How to access data Pin
PJ Arends16-Nov-02 9:10
professionalPJ Arends16-Nov-02 9:10 
GeneralRe: How to access data Pin
Jack_pt18-Nov-02 3:08
Jack_pt18-Nov-02 3:08 
GeneralWay to avoid overriding OnCommand Pin
Paul Vickery9-Aug-02 0:59
professionalPaul Vickery9-Aug-02 0:59 
GeneralRe: Way to avoid overriding OnCommand Pin
PJ Arends9-Aug-02 5:55
professionalPJ Arends9-Aug-02 5:55 
GeneralRe: Way to avoid overriding OnCommand Pin
nikster28-Jan-03 5:01
nikster28-Jan-03 5:01 
GeneralRe: Way to avoid overriding OnCommand Pin
Paul Vickery29-Jan-03 11:06
professionalPaul Vickery29-Jan-03 11:06 
GeneralRe: Way to avoid overriding OnCommand Pin
nikster30-Jan-03 0:09
nikster30-Jan-03 0:09 
GeneralRe: Way to avoid overriding OnCommand Pin
Crnjan22-Oct-04 2:30
Crnjan22-Oct-04 2:30 
GeneralRe: Way to avoid overriding OnCommand Pin
Paul Vickery22-Oct-04 2:52
professionalPaul Vickery22-Oct-04 2:52 
GeneralThere are some bits missing Pin
Paul Vickery9-Aug-02 0:28
professionalPaul Vickery9-Aug-02 0:28 
GeneralRe: There are some bits missing Pin
PJ Arends9-Aug-02 5:47
professionalPJ Arends9-Aug-02 5:47 
GeneralRe: There are some bits missing Pin
Paul Vickery9-Aug-02 6:06
professionalPaul Vickery9-Aug-02 6:06 
QuestionQuestion? Pin
Dejan Petrovic27-Sep-01 19:44
Dejan Petrovic27-Sep-01 19:44 
This solution seems to be working properly.
However it involves creating and using the derived class CMenuEdit. Is there a way to hook (intercept) the contex menu (of a CEdit) on a dialog level and then alter menu items from there?
Thanks,

Dejan

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.