VC 2005 RichEdit右键菜单复制、粘贴功能
开发平台:VS 2005
一.建立工具及控件
1.MFC新建对话框项目,选择资源视图,打开Dialog界面编辑,在工具箱对话框编辑器中拉取控件“Rich Edit2.0 Control”
2.Rich Edit2.0 Control属性设置:
3.右键Rich Edit2.0 Control控件,选择“添加变量”,变量类型--CRichEditCtrl,类别--Control,变量名:m_rEditOut
4.右键Rich Edit2.0 Control控件,选择“属性”,选择“控件事件”,找到"EN_MSGFILTER",右边下拉框选择“<添加>OnEnMsgfilterReditOut”,对应项目主文件CXXDlg.cpp下生成
void CXXDlg::OnEnMsgfilterReditOut(NMHDR *pNMHDR, LRESULT *pResult)
{
MSGFILTER *pMsgFilter = reinterpret_cast<MSGFILTER *>(pNMHDR);
// TODO: 控件将不发送该通知,除非您重写
// CDialog::OnInitDialog() 函数以发送 EM_SETEVENTMASK 消息
// 至具有 ENM_KEYEVENTS 或 ENM_MOUSEEVENTS 标志的控件
// “或”运算到 lParam 掩码中。
// TODO: 在此添加控件通知处理程序代码,下面会在此处添加右键菜单相关代码
*pResult = 0;
}
二.定义宏及消息响应接口
1.打开头文件中Resource.h文件,添加自定义右键菜单项IDR
#define IDR_MENU_CONTEXT 104 (选择未使用的ID及序号)
然后根据功能自定义菜单细项ID
#define ID_RICH_COPY 1200
#define ID_RICH_PASTE 1201
#define ID_RICH_CUT 1202
#define ID_RICH_SELECTALL 1203
2.在项目解决方案中选择资源文件,右键xx.rc,选择查看代码,找到MENU的位置,如下
/
//
// Menu
//
IDR_MAIN_MENU MENU
BEGIN
…………
END
在这个下面添加如下代码:(最好是自己手动敲,复制粘贴容易带入很多异常数据引起编译错误,且在IDR_MAIN_MENU MENU最后一个END后面添加)
IDR_MENU_CONTEXT MENU
BEGIN
POPUP ""
BEGIN
MENUITEM "复制" ID_RICH_COPY
MENUITEM "粘贴" ID_RICH_PASTE
MENUITEM "剪切" ID_RICH_CUT
MENUITEM "全选" ID_RICH_SELECTALL
END
END
保存关闭xx.rc
3.在CxxDlg.h中类中添加响应函数声明
protected:
afx_msg void OnCopy();//拷贝
afx_msg void OnCut();//剪切
afx_msg void OnPaste();//粘贴
afx_msg void OnSelectall();//全选
4.消息映射添加
在CxxDlg.cpp代码中找到BEGIN_MESSAGE_MAP(CXXDlg, CDialog),添加消息映射关系
ON_COMMAND(ID_RICH_COPY, &CXXDlg::OnCopy)
ON_COMMAND(ID_RICH_CUT, &CXXDlg::OnCut)
ON_COMMAND(ID_RICH_PASTE, &CXXDlg::OnPaste)
ON_COMMAND(ID_RICH_SELECTALL, &CXXDlg::OnSelectall)
注:ID_RICH_COPY、ID_RICH_CUT、ID_RICH_PASTE、ID_RICH_SELECTALL为头文件Resource.h中定义
OnCopy、OnCut、OnPaste、OnSelectall为CxxDlg.h中类添加的响应函数声明,以下也会在CxxDlg.cpp中添加对应响应函数代码
三:主要编码
1.菜单项显示:
CxxDlg.cpp代码中,找到OnEnMsgfilterReditOut消息响应接口,编写代码在“// TODO: 在此添加控件通知处理程序代码”位置
void CXXDlg::OnEnMsgfilterReditOut(NMHDR *pNMHDR, LRESULT *pResult)
{
MSGFILTER *pMsgFilter = reinterpret_cast<MSGFILTER *>(pNMHDR);
// TODO: 控件将不发送该通知,除非您重写
// CDialog::OnInitDialog() 函数以发送 EM_SETEVENTMASK 消息
// 至具有 ENM_KEYEVENTS 或 ENM_MOUSEEVENTS 标志的控件
// “或”运算到 lParam 掩码中。
// TODO: 在此添加控件通知处理程序代码
if (pMsgFilter->msg == WM_RBUTTONUP)
{
CPoint point(LOWORD(pMsgFilter->lParam), HIWORD(pMsgFilter->lParam));//传入的是在RichEdit控件中的位置,如在RichEdit控件最左边顶端,x=0,y=0
CMenu popMenu;
popMenu.LoadMenu(IDR_MENU_CONTEXT);//载入菜单
//------------------------------以下代码块主要是用于判断弹出菜单框时什么菜单项可用的简单判断-----------------------------------------------------------
//根据是否有选中区域来决定是否允许拷贝菜单项使用
long nStart, nEnd;
m_rEditOut.GetSel(nStart,nEnd);
if (nStart == nEnd)
{
//选中位置相同表示没有选中内容,拷贝菜单项不能使用
popMenu.EnableMenuItem(ID_RICH_COPY,MF_BYCOMMAND|MF_DISABLED|MF_GRAYED);//不允许菜单项使用
}
else
{
//选中位置不相同表示有选中内容,拷贝菜单项可以使用
popMenu.EnableMenuItem(ID_RICH_COPY,MF_BYCOMMAND|MF_ENABLED);//允许菜单项使用
}
//根据剪切板是否有内容决定粘贴菜单是否使用
//打开剪贴板
char * buffer = NULL;
if ( OpenClipboard() )
{
HANDLE hData = GetClipboardData(CF_TEXT);
buffer = (char*)GlobalLock(hData);
GlobalUnlock(hData);
CloseClipboard();
}
if (buffer == NULL)
{
popMenu.EnableMenuItem(ID_RICH_PASTE,MF_BYCOMMAND|MF_DISABLED|MF_GRAYED);//不允许菜单项使用
}
else
{
popMenu.EnableMenuItem(ID_RICH_PASTE,MF_BYCOMMAND|MF_ENABLED);//允许菜单项使用
}
//剪切功能暂时不允许使用
popMenu.EnableMenuItem(ID_RICH_CUT,MF_BYCOMMAND|MF_DISABLED|MF_GRAYED);//不允许菜单项使用
//--------------------------------以上代码块主要是用于判断弹出菜单框时什么菜单项可用的简单判断----------------------------------------------------------
ClientToScreen(&point);//将客户区坐标转换成屏幕坐标
popMenu.GetSubMenu(0)->TrackPopupMenu(TPM_LEFTALIGN | TPM_RIGHTBUTTON, (point.x +180), (point.y+55), this); //显示弹出菜单,参数依次为(鼠标在菜单左边|跟踪右键,x,y,this),此处+180和+55是调整弹出框在鼠标右侧位置,主要是懒得再找其他方法
popMenu.Detach();
popMenu.DestroyMenu();
}
//
*pResult = 0;
}
2.增加拷贝、粘贴、全选等响应函数
1)//拷贝
void CXXDlg::OnCopy()
{
//拷贝
long nStart, nEnd;
CString strTemp;
m_rEditOut.GetSel(nStart,nEnd);
intstart = (int)nStart;
intend = (int)nEnd;
if(nStart == nEnd)
{
//此处两行代码仅为了显示,使用时可根据个人功能做代码修改
strTemp.Format(_T(" 光标[guang biao]在%d" ), nStart);
AfxMessageBox(strTemp);
}
else
{
//得到RichEdit 选中的内容
strTemp = m_rEditOut.GetSelText();
//拷贝数据到剪切板
if( OpenClipboard() )//打开剪切板
{
HGLOBAL clipbuffer;//内存句柄
char * buffer;
EmptyClipboard();//函数清空剪切板并释放剪切板内数据的句柄
clipbuffer = GlobalAlloc(GMEM_DDESHARE, strTemp.GetLength()+1);//分配内存
buffer = (char*)GlobalLock(clipbuffer);//指定一个内存块并返回内存块的首地址
strcpy(buffer, strTemp.GetBuffer());
GlobalUnlock(clipbuffer);
SetClipboardData(CF_TEXT,clipbuffer);
CloseClipboard();
}
}
return;
}
2)//粘贴
void CXXDlg::OnPaste()
{
//粘贴
char * buffer = NULL;
CString szTemp;
//打开剪贴板
if (OpenClipboard() )
{
HANDLE hData = GetClipboardData(CF_TEXT);
buffer = (char*)GlobalLock(hData);
//用需要的方式显示粘贴的内容
//m_rEditOut.SetSel(-1,-1);//增加这行,在粘贴时直接粘贴在控件末尾,不用这行时,会粘贴在控件当前鼠标光标所在位置,是光标点击后的位置
szTemp.Format("%s",buffer);
m_rEditOut.ReplaceSel(szTemp);
GlobalUnlock(hData);
CloseClipboard();
}
return;
}
3)全选
void CXXDlg::OnSelectall()
{
//全选
m_rEditOut.SetSel(0,-1);//nStartChar 选择中的第一个字符的从零开始的索引。nEndChar 选择中的最后一个字符的从零开始的索引。可以用一个为0的开始索引和一个为-1的结束索引来调用SetSel
return;
}
OK,完结