反复碰到这个问题,查资料很困难,索性整理一下放在这里,供朋友们借鉴。
===========================================================================
微软很恶心,竟然无法很方便的为FormView或者Dialog上的RicheditCtrl添加右键菜单功能项.经过搜索资料和实际使用,需要用这样的方式才能实现:
注意事项
1.右键菜单中,不能出现系统命令,例如,ID_EDIT_UNDO/ID_EDIT_COPY/ID_EDIT_PASTE/ID_EDIT_CUT/ID_EDIT_SELALL等,否则,无法响应消息.
2.菜单项目,不能用OnCommand的方式进行消息处理,必须在Message Map中用ON_MESSAGE的方式,并且在头文件中实现定义好消息函数如OnMenuUndo.
BEGIN_MESSAGE_MAP(CReferenceFormView, CFormView)
//{{AFX_MSG_MAP(CReferenceFormView)
ON_MESSAGE(ID_MENU_UNDO, OnMenuUndo)
ON_MESSAGE(ID_MENU_CUT, OnMenuCut)
ON_MESSAGE(ID_MENU_COPY, OnMenuCopy)
ON_MESSAGE(ID_MENU_PASTE, OnMenuPaste)
ON_MESSAGE(ID_MENU_CLEAR, OnMenuClear)
ON_MESSAGE(ID_MENU_SELECT_ALL, OnMenuSelectAll)
//}}AFX_MSG_MAP
END_MESSAGE_MAP()
3.需要在FormView的OnInitialUpdate()函数或者Dialog的OnInitialDialog()函数中调用
m_ctrlRichEditReference.SetEventMask(ENM_MOUSEEVENTS);
表示RicheditCtrl的鼠标事件交由父窗体进行处理.
4.在父窗体(FormView或者Dialog)的OnNotify消息中做如下处理:
BOOL CReferenceFormView::OnNotify(WPARAM wParam, LPARAM lParam, LRESULT* pResult)
{
// TODO: Add your specialized code here and/or call the base class
要点1:
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;
要点2:
if ((wParam == IDC_RICHEDIT_REFERENCE) && (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 :)
UINT dwSelectionMade;
VERIFY(menu.LoadMenu(IDR_MNU_REFERENCE4RE) );
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();
PostMessage(dwSelectionMade,0,0);
}
return CFormView::OnNotify(wParam, lParam, pResult);
}
参考资料:
http://lib.training.ru/Lib/ArticleDetail.aspx?ar=468&l=n&mi=17&mic=344
---------------------------------------------------------------
楼上的也仅仅是支持右键菜单的响应,补充,如何响应快捷键,把消息往下传递:
BOOL CFormViewRecordEditor::PreTranslateMessage(MSG* pMsg)
{
// TODO: Add your specialized code here and/or call the base class
if ( pMsg->message == WM_KEYDOWN )
{
switch( pMsg->wParam )
{
case 0x41: //selete all
case 0x46: //ctrl+f
case 0x56: //Ctrl + V:
case 0x58: // cut
case 0x43: // copy
case 0x5A: //undo
case 0x59: //redo
if ( ( GetKeyState( VK_CONTROL ) & 0x80 ) )
{
m_ctlRichEditFullText.SendMessage(pMsg->message, pMsg->wParam, pMsg->lParam);
return TRUE;
}
break;
}
}//End: if ( pMsg->message );
return CFormView::PreTranslateMessage(pMsg);
}
上面所有的代码,只能对Formview或者PropertyPage上的RicheditCtrl起到效果,对于出现在上述父窗体中的Edit,要想响应快捷键,则需要使用如下代码处理:
BOOL CPPFieldEditNormal::PreTranslateMessage(MSG* pMsg)
{
// TODO: Add your specialized code here and/or call the base class
if ( pMsg->message == WM_KEYDOWN )
{
switch( pMsg->wParam )
{
case 0x41: //selete all
case 0x46: //ctrl+f
case 0x56: //Ctrl + V:
case 0x58: // cut
case 0x43: // copy
case 0x5A: //undo
case 0x59: //redo
if ( ( GetKeyState( VK_CONTROL ) & 0x80 ) && (m_ctlEditFieldValue.m_hWnd == GetFocus()->m_hWnd))
{
//m_ctlEditFieldValue.SendMessage(pMsg->message, pMsg->wParam, pMsg->lParam);//这种方式不能正确响应
//::PostMessage(m_ctlEditFieldValue.m_hWnd, pMsg->message, pMsg->wParam, pMsg->lParam);//这种方式不能正确响应
//m_ctlEditFieldValue.SendMessage(WM_COMMAND,(WPARAM)ID_EDIT_PASTE,(LPARAM)0);//这种方式不能正确响应
::PostMessage(m_ctlEditFieldValue.m_hWnd, WM_PASTE,(WPARAM)0,(LPARAM)0);//这种方式可以正确响应!!
}
return TRUE;
}
break;
}
}//End: if ( pMsg->message );
return CPropertyPage::PreTranslateMessage(pMsg);
}