How to get a working context menu on a dialog bar RichEditCtrl ?
I need to get a simple edit menu popup to work on a CRichEditCtrl window in a dialog bar. (VC 2010). I cannot figure out how to 'subclass' (if that is the correct term to use) the dialog bar text window in order to get the popup menu to work. I have tried to subclass the edit window on initialization of the dialog bar using but this invariably results in an appcrash.
Code:
LONG CDialogBar1::OnInitDialog ( UINT wParam, LONG lParam)
{
BOOL bRet = HandleInitDialog(wParam, lParam);
if (!UpdateData(FALSE))
{
TRACE0("Warning: UpdateData failed during dialog init.\n");
}
// TODO: Add extra initialization here
//GetDlgItem(IDC_EDIT_QUERY)->SubclassDlgItem(IDC_EDIT_QUERY, m_pRichEditEx);
//SubclassDlgItem(IDC_EDIT_QUERY, m_pRichEditEx);
return bRet;
}
I do not understand the debug messages generated:
Unhandled exception at 0x77ad15de in XDbar.exe 0xC015000F: The activation context being deactivated is not the most recently activated one.
Re: How to get a working context menu on a dialog bar RichEditCtrl ?
Rich edit control has not a built-in context menu because it is not only designed to keep simple text like in case of the simpe edit control.
Instead, it can ask the client to provide a menu handle (which may depend on current selection contents), via IRichEditOleCallback interface.
For this purpose you have to:
derive from IRichEditOleCallback and implement its methods.
Re: How to get a working context menu on a dialog bar RichEditCtrl ?
Thanks alot Ovi. Awesome code. It's also a nice mini-tutorial on how to set up a COM interface which has always been a mystery to me. But how do I implement the menu (undo, cut, copy, paste, delete, select all, etc), assuming that I have a separate popup menu ?
Last edited by Mike Pliam; April 22nd, 2012 at 12:54 PM.
Re: How to get a working context menu on a dialog bar RichEditCtrl ?
Override OnCommand in dialog bar class and "reflect" to child controls the commands which are coming from a menu.
Code:
BOOL CTestDialogBar::OnCommand(WPARAM wParam, LPARAM lParam)
{
// if command is from a menu, "reflect" it to the child controls
if(0 == HIWORD(wParam))
{
SendMessageToDescendants(WM_COMMAND, wParam, lParam);
}
return CDialogBar::OnCommand(wParam, lParam);
}
Now, we can map (using wizard) and handle menu commands (ID_EDIT_COPY and so on) in the rich edit control class.
Code:
class CTestRichEditCtrl : public CRichEditCtrl
{
// ...
afx_msg void OnEditCopy();
// ...
};
Re: How to get a working context menu on a dialog bar RichEditCtrl ?
Ovi, your approach works beautifully. I cannot thank you enough. But I confess that I have used your code without really understanding it. I am curious as to where I might find references to the SetOLECallback(&m_xRichEditOleCallback) and other com interface code -- how do you know how to set the thing up? I have tried to read books on COM a while ago and quickly gave it up as too complicated. But your code is some of the simplest and straightforward that I have seen. And best of all -- it works!
Thanks so very much for taking the time to respond to this post. BTW, I checked the time in Bucharest -- when do you sleep?
Re: How to get a working context menu on a dialog bar RichEditCtrl ?
COM is quite easy. Basically, it's just a set of specifications for writing reusable components.
If read "Inside COM" by Dale Rogerson, may discover a lot of nice fairy tales inside.
Here is an example:
Chapter 2: The Interface
Recently, the space shuttle Atlantis docked with the Russian space station Mir.
The Americans attached a Russian docking unit to the space shuttle in order to dock to an identical androgynous unit on Mir.
Just imagine what you could do with a Russian docking unit! You could mount the unit on your house, and the space shuttle could dock there. Or you could mount the unit on a VW Beetle, the Space Needle, or your garage, and the space shuttle could attach to it.
[...] Imagine the fun!
The docking unit is an example of an interface.
// Interface? Piece of cake, who said that's complicated?
Quite difficult and scary for many people is using COM iterface libraries as well as technologies built over COM.
It may take a while to accomodate with OLE/COM programming. However, generally it's not absolutelly necessary to be an expert in what's behind, as long as Visual Studio comes with good wizards which can help. No space & time to enter in details here...
Returning to interface maps, you can have a look at MFC Interface Maps in TN038: MFC/OLE IUnknown Implementation.
However, in the particular case of this topic, it's not even necessary to dig into above technical note or in other documentation/tutorials about interface maps.
To have an idea what to do, just have a look in CRichEditView MFC class implementation. Like CRichEditCtrl it also keeps a Windows rich-edit control, but implements more, including IRichEditOleCallback methods.
Originally Posted by Mike Pliam
BTW, I checked the time in Bucharest -- when do you sleep?
I'm sleeping when not working, i.e. when browsing discussion forums.
Last edited by ovidiucucu; April 23rd, 2012 at 03:54 AM.
Re: How to get a working context menu on a dialog bar RichEditCtrl ?
Thanks for the good refs, Ovi. I checked them out and now I am inspired to try and build my own COM application -- I just cannot come up with a good reason to do so, other than the pure joy of gaining facility with a difficult area of programming. The single example you have provided is just about the only use I can think of-- but then I'm afraid I'm not very imaginative.
Re: How to get a working context menu on a dialog bar RichEditCtrl ?
Frankly, there is no need for COM, even though as Ovidiu indicated, it is not difficult.
You have stumbled across command routing issue. I am not sure why, but main frame window should route commands and commands UI update to all toolbars, including dialog bar derived toolbars.
Maybe I will investigate this later at my leisure time; I remember vaguely that it was a case in earlier versions of the VS but I could be mistaken.
Anyway, couple of points:
- You definitely do not need to introduce new menu for edit operations (copy, paste, cut e.t.c). MFC already defines all (or almost all) edit commands. You should have used standard popup menu from the main menu.
- Since main frame does not route commands and commands UI update we have to take care of it. Look at the OnCmdMsg override. It gives dialog bar first crack at message and UI updates. You can move it after call to the default implementation.
- Toolbars, including dialog bar, should route message to all children but again, this is not a case. Maybe needs further investigation as main frame issue.
Again, take a look at OnCmdMsg override. It gives rich edit view a chance to process al command messages.
One last but definitely very important change regarding handling menu context message: If you are developing MDI/SDI type of an app, always invoke TrackPopupMenu passing main frame pointer as the menu owner. Update UI mechanism will take care of routing messages to proper windows if command routing is up to requirements.
You can do the same for dialogs but this is completely different story.
See attachment for all changes i have made to make it work.
Last edited by JohnCz; May 1st, 2012 at 06:30 AM.
Reason: Spelling
There are only 10 types of people in the world: Those who understand binary and those who do not.
Re: How to get a working context menu on a dialog bar RichEditCtrl ?
I forgot to add:
I have subclassed rich edit control using standard DDX and CRichEditCtrlEx class. I had to write the code to insert member variable; class wizard is dumb handling CDialogBar derived class since it needs resource ID for a dialog template.
There are only 10 types of people in the world: Those who understand binary and those who do not.
* The Best Reasons to Target Windows 8
Learn some of the best reasons why you should seriously consider bringing your Android mobile development expertise to bear on the Windows 8 platform.