关于如何为FormView中的Richedit/Edit添加右键菜单,并响应CTRL+C等快捷键

反复碰到这个问题,查资料很困难,索性整理一下放在这里,供朋友们借鉴。  
faq-it.org/apache/===========================================================================  
微软很恶心,竟然无法很方便的为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);  
}  
 

posted on 2006-10-18 23:33  cy163  阅读(2710)  评论(1编辑  收藏  举报

导航