如何在Rich Edit Control中管理超链接
一、在Rich Edit Control 中显示超链接
在Rich Edit Control 中显示超链接的格式,也就是给选择的文本添加CFE_LINK属性,可以通过以下两种方法实现:
1、 自动检测超链接
Rich Edit Control本身具有URL检测功能,可以自动识别满足要求的URL文本,并自动为该文本添加CFE_LINK属性,也就显示为超链接格式,目前控件可以检测以下前缀的URL文本:
http: file: mailto: ftp: https: gopher: nntp: prospero: telnet: news: wais:
(1)打开自动检测
CWnd
*
pRE
=
GetDlgItem(IDC_RICHEDIT1);
pRE
->
SendMessage(EM_AUTOURLDETECT, TRUE,
0
);
(2)关闭自动检测
CWnd
*
pRE
=
GetDlgItem(IDC_RICHEDIT1);
pRE
->
SendMessage(EM_AUTOURLDETECT, FALSE,
0
);
(3)判断当前自动检测是否打开
BOOL bEnable
=
pRE
->
SendMessage(EM_GETAUTOURLDETECT,
0
,
0
);
2、 手动设置文本为超链接格式
如果不打开rich edit control的URL检测功能,我们可以手工对感兴趣的文本设置CFE_LINK属性,从而使其显示为超链接格式。
(1)设置CFE_LINK
CWnd
*
pRE
=
GetDlgItem(IDC_RICHEDIT1);
CHARFORMAT2 cf;
ZeroMemory(
&
cf,
sizeof
(CHARFORMAT2));
cf.cbSize
=
sizeof
(CHARFORMAT2);
cf.dwMask
=
CFM_LINK;
cf.dwEffects
|=
CFE_LINK;
pRE
->
SendMessage(EM_SETCHARFORMAT, SCF_SELECTION, (LPARAM)
&
cf);
(2)去除CFE_LINK
CWnd
*
pRE
=
GetDlgItem(IDC_RICHEDIT1);
CHARFORMAT2 cf;
ZeroMemory(
&
cf,
sizeof
(CHARFORMAT2));
cf.cbSize
=
sizeof
(CHARFORMAT2);
cf.dwMask
=
CFM_LINK;
cf.dwEffects
&=
~
CFE_LINK;
pRE
->
SendMessage(EM_SETCHARFORMAT, SCF_SELECTION, (LPARAM)
&
cf);
二、处理超链接事件(EN_LINK)
使用以上方法我们已经可以通过自动或手动显示一个超链接,接着我们需要做的是处理超链接的事件(WM_SETCURSOR、WM_MOUSEMOVE、WM_RBUTTONDOWN、WM_RBUTTONUP、WM_RBUTTONDBCLK、WM_LBUTTONDOWN、WM_LBUTTONUP、WM_LBUTTONDBCLK),所有这些都通过由Rich Edit Control 发送的EN_LINK消息通知父窗口,父窗口可以在WM_NOTIFY中接收到EN_LINK消息。具体实现如下:
1、通知Rich Edit Control 发送EN_LINK消息,默认情况下是不发送的,在初始化控件时添加:
CWnd
*
pRE
=
GetDlgItem(IDC_RICHEDIT1);
DWORD dwMask
=
pRE
->
SendMessage(EM_GETEVENTMASK,
0L
,
0L
);
dwMask
|=
ENM_LINK;
pRE
->
SendMessage(EM_SETEVENTMASK,
0L
, (LPARAM)dwMask);
2、在WM_NOTIFY消息中处理EN_LINK。
NMHDR
*
p
=
(NMHDR
*
)lParam;
if
(p
->
code
==
EN_LINK)
...
{
ENLINK *pLink = (ENLINK *)lParam;
switch(pLink->msg) ...{
case WM_LBUTTONDOWN:
//鼠标左键按下
break;
case WM_LBUTTONUP:
...{//鼠标左键松开
char strBuf[512];
CWnd *pRE = GetDlgItem(IDC_RICHEDIT1);
pRE->SendMessage(EM_EXSETSEL, 0, (LPARAM)&(pLink->chrg));
pRE->SendMessage(EM_GETSELTEXT, 0, (LPARAM)strBuf);
::ShellExecute(NULL, _T("open"), _T("iexplore"), strBuf, NULL, SW_SHOWNORMAL);
break;
}
default:
break;
}
}
三、超链接对应的操作
通过前边介绍的方法,我们可以得到两种超链接,一种是打开URL自动检测时控件自动显示的,通常只需要用iexplore打开即可,例如打开一个网页、发送一封邮件、打开一个窗口等等;另一种是手动添加的,我们可能会需要对每个超链接执行不同的操作,问题是如何区分不同的超链接呢?这是我们接下来要讨论的问题。
区分超链接首先想到的是可以根据文本来区分,不同文本对应不同操作,这就需要在超链接HyperLinkText和操作Action之间建立一个映射,我们可以在添加超链接HyperLinkText时用CMap来保存<HyperLinkText, Action>,利用这个map就可以很方便知道那个超链接进行那个操作。另外对于系统自动识别的URL,我们并没有保存映射,就可以通过iexplore进行默认操作:
Action
=
map[HyperLinkText];
if
(Action
==
Action1)
...
{
//Action1
}
else
if
(Action
==
Action2)
...
{
//Action2
}
else
...
{
//其他URL,使用iexplore打开
}
对于一些简单的操作这种方法确实可以满足要求了,但是如果出现多个相同文本的超链接,而且这些超链接对应的操作又不同,该如何区分呢?很显然仅通过文本已经无法唯一确定了,必须经过其他的特征帮助区分,在这里我使用了超链接文本的开始位置,就是CHARRANGE中的cpMin,这个位置在文本中是唯一的,在添加超文本时把<cpMin, Action>做一个映射保存在CMap中,这样当我们点击一个超链接时可以通过每个文本的开始位置cpMin找到Action,从而进行相应的操作:
Action
=
map[cpMin];
if
(Action
==
Action1)
...
{
//Action1
}
else
if
(Action
==
Action2)
...
{
//Action2
}
else
...
{
//其他URL,使用iexplore打开
}
现在我们已经可以准确控制每个超链接的操作了。如果你需要保存更多信息,可以把<cpMin, Action>中的Action用一个结构来代替<cpMin, HyperLink>,例如:
typedef
struct
_HyperLink
...
{
WORD Action;
DWORD dwId;
}
HyperLink;
下载源代码