【发布时间】:2016-10-13 22:28:37
【问题描述】:
我希望我的 RichEdit 处理超链接,所以我按照以下说明操作:http://delphi.about.com/od/vclusing/l/aa111803a.htm
以下是我对代码所做的更改:
interface
type
TProgCorner = class(TForm)
RichEdit2: TRichEdit;
RichEdit1: TRichEdit;
RichEdit3: TRichEdit;
RichEdit4: TRichEdit;
procedure FormCreate(Sender: TObject);
private
procedure InitRichEditURLDetection(RE: TRichEdit);
protected
procedure WndProc(var Msg: TMessage); override;
end;
implementation
{$R *.DFM}
uses
ShellAPI, RichEdit;
const
AURL_ENABLEURL = 1;
AURL_ENABLEEAURLS = 8;
procedure TProgCorner.InitRichEditURLDetection(RE: TRichEdit);
var
mask: LResult;
begin
mask := SendMessage(RE.Handle, EM_GETEVENTMASK, 0, 0);
//In the debugger mask is always 1, for all 4 Richedits.
SendMessage(RE.Handle, EM_SETEVENTMASK, 0, mask or ENM_LINK);
//returns 67108865
SendMessage(RE.Handle, EM_AUTOURLDETECT, AURL_ENABLEURL, 0);
//Returns 0 = success (according to MSDN), but no joy.
//SendMessage(RE.Handle, EM_AUTOURLDETECT, AURL_ENABLEEAURLS, 0);
//When uncommented returns -2147024809
//I don't think the registration works, but don't know how to fix this.
end;
procedure TProgCorner.WndProc(var Msg: TMessage);
var
p: TENLink;
sURL: string;
CE: TRichEdit;
begin
//'normal' messages do get through here, but...
if (Msg.Msg = WM_NOTIFY) then begin
//...the following line is never reached.
if (PNMHDR(Msg.lParam).code = EN_LINK) then begin
p:= TENLink(Pointer(TWMNotify(Msg).NMHdr)^);
if (p.Msg = WM_LBUTTONDOWN) then begin
try
CE:= TRichEdit(ProgCorner.ActiveControl);
SendMessage(CE.Handle, EM_EXSETSEL, 0, LPARAM(@(p.chrg)));
sURL:= CE.SelText;
ShellExecute(Handle, 'open', PChar(sURL), 0, 0, SW_SHOWNORMAL);
except
{ignore}
end;
end;
end;
end;
inherited;
end;
procedure TProgCorner.FormCreate(Sender: TObject);
begin
InitRichEditURLDetection(RichEdit1);
InitRichEditURLDetection(RichEdit2);
InitRichEditURLDetection(RichEdit3);
InitRichEditURLDetection(RichEdit4);
//If I set the text here (and not in the object inspector)
//the richedit shows a hyperlink with the 'hand' cursor.
//but still no WM_notify message gets received in WndProc.
RichEdit1.Text:= 'http://www.example.com';
end;
end.
但是,我使用对象检查器嵌入到我的RichEditx.Lines 中的超链接显示为纯文本(不是链接)并且单击它们不起作用。
我正在使用在 Win32 模式下在 Windows 7 上运行的 Delphi Seattle。
我做错了什么?
更新
结合使用已弃用的SendMessage(RE.Handle, EM_AUTOURLDETECT, AURL_ENABLEURL, 0); 和在 FormCreate 中手动设置 RichEditx.Text:= 'http://www.example.com',我可以让 Richedit 显示超链接和手形光标。
但是,WndProc 仍然没有收到 WM_Notify 消息。
WndProc 确实接收其他消息。
更新2
为了简化问题,我忽略了RichEdit 位于Panel 之上的事实。面板吃掉WM_Notify 消息,因此它们不会到达下方的表单。
【问题讨论】:
-
mask应声明为LResult。 -
SendMessage(CE.Handle, EM_EXSETSEL, 0, Longint(@(p.chrg)));应该是SendMessage(CE.Handle, EM_EXSETSEL, 0, LPARAM(@(p.chrg))); -
@LURD,已更新,但这是 win32,所以这不是问题,反正我认为 WM_Notify 被拦截了,确实是这样。
-
@Johan:你的分析是错误的。如果表单是 RichEdit 的直接
Parent,则使用 RichEdit 的WM_NOTIFY消息调用表单的WndProc()DOES。您没有考虑到的是,VCL 有时可能必须重新创建 RichEdit 的HWND,从而丢失您的EM_SETEVENTMASK和EM_AUTOURLDETECT设置。每次重新创建 RichEdit 的HWND时,您都必须再次发出这些消息。覆盖 RichEdit 的CreateWnd()方法来处理它。是的,在TRichEdit内拦截CN_NOTIFY是最好的,但这不是唯一的选择。