如何在Rich Edit Control中管理超链接

出处:http://blog.csdn.net/zhymax/article/details/2280091

一、在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;

你可能感兴趣的:(struct,File,null,url,action,Hyperlink)