Joh*_*ica 2 delphi richedit hyperlink
我希望我的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.
Run Code Online (Sandbox Code Playgroud)
但是,我RichEditx.Lines使用对象检查器嵌入到我的超链接显示为纯文本(而不是链接)并单击它们不起作用.
我正在使用在Win32模式下在Windows 7上运行的Delphi Seattle.
我究竟做错了什么?
更新
使用发布已弃用
SendMessage(RE.Handle, EM_AUTOURLDETECT, AURL_ENABLEURL, 0);和RichEditx.Text:= 'http://www.example.com'手动设置的组合,FormCreate我可以让Richedit显示超链接和手柄.
然而,WndProc仍然没有收到WM_Notify消息.
WndProc确实收到其他消息.
UPDATE2
在我渴望简化问题,我离开了该事实RichEdit坐在的顶部Panel.面板会WM_Notify消息,因此它们无法到达下面的表格.
问题是WM_Notify消息永远不会到达主窗体.
相反,它被Richedit的父母拦截(我放置在那里的面板用于对齐目的).
我错误地在问题中忽略了这个事实,认为这无关紧要.
那说以下对我有用.
然而,我非常赞成Remy在架构上更健全的方法,而在这个问题上苦苦挣扎的人应该首先尝试这种方法.
在VCL.ComCtrls中
TCustomRichEdit = class(TCustomMemo)
private //Why private !?
procedure CNNotify(var Message: TWMNotifyRE); message CN_NOTIFY;
Run Code Online (Sandbox Code Playgroud)
解决方案是插入我们自己的TRichEdit:
uses
...., RichEdit;
type
TRichEdit = class(ComCtrls.TRichEdit)
procedure CNNotify(var Message: TWMNotifyRE); message CN_NOTIFY;
end; //never mind that its ancester is private, it will still work.
TProgCorner = class(TForm)
Run Code Online (Sandbox Code Playgroud)
我将RichRdits存储在一个数组中,所以我可以通过它们查找它们HWnd而不必循环遍历我的表单的所有子控件.
implementation
function TProgCorner.RichEditByHandle(Handle: HWnd): TRichEdit;
var
i: integer;
begin
//Keep track of the richedits in an array, initialized on creation.
for i:= Low(RichEdits) to High(RichEdits) do begin
if RichEdits[i].Handle = Handle then exit(RichEdits[i]);
end;
Result:= nil;
end;
procedure TRichEdit.CNNotify(var Message: TWMNotifyRE);
var
p: TENLink;
sURL: string;
CE: TRichEdit;
begin
if (Message.NMHdr.code = EN_LINK) then begin
p:= TENLink(Pointer(TWMNotify(Message).NMHdr)^);
if (p.Msg = WM_LBUTTONDOWN) then begin
try
//CE:= TRichEdit(ProgCorner.ActiveControl);
//SendMessage(CE.Handle, EM_EXSETSEL, 0, Longint(@(p.chrg)));
SendMessage(p.nmhdr.hwndFrom, EM_EXSETSEL, 0, Longint(@(p.chrg)));
CE:= ProgCorner.RichEditByHandle(p.nmhdr.hwndFrom);
if assigned(CE) then begin
sURL:= CE.SelText;
ShellExecute(Handle, 'open', PChar(sURL), 0, 0, SW_SHOWNORMAL);
end;
except
{ignore}
end;
end;
end;
inherited;
end;
Run Code Online (Sandbox Code Playgroud)
幸运的是,即使将原始文件声明为私有,也可以插入消息处理程序.
现在它有效.喜欢魅力.
以下是该单元的完整副本以供将来参考:
unit ProgCorn;
interface
uses
Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
StdCtrls, ExtCtrls, ComCtrls, Menus, Clipbrd, LifeConst, Tabnotbk, LifeUtil,
MyLinkLabel, RichEdit;
type
TRichEdit = class(ComCtrls.TRichEdit)
procedure CNNotify(var Message: TWMNotifyRE); message CN_NOTIFY;
end;
TProgCorner = class(TForm)
Panel1: TPanel;
Panel2: TPanel;
Label1: TLabel;
TabbedNotebook1: TTabbedNotebook;
PopupMenu1: TPopupMenu;
Copy1: TMenuItem;
Panel3: TPanel;
Button1: TButton;
RichEdit1: TRichEdit;
RichEdit2: TRichEdit;
RichEdit3: TRichEdit;
RichEdit4: TRichEdit;
Button2: TButton;
procedure Copy1Click(Sender: TObject);
procedure PopupMenu1Popup(Sender: TObject);
procedure FormCreate(Sender: TObject);
procedure Button2Click(Sender: TObject);
private
RichEdits: array[1..4] of TRichEdit;
procedure InitRichEditURLDetection(RE: TRichEdit);
function RichEditByHandle(Handle: HWnd): TRichEdit;
public
{ Public declarations }
end;
var
ProgCorner: TProgCorner;
implementation
{$R *.DFM}
uses
ShellAPI;
const
AURL_ENABLEEAURLS = 8;
AURL_ENABLEURL = 1;
procedure TProgCorner.InitRichEditURLDetection(RE: TRichEdit);
var
mask: NativeInt;
begin
mask := SendMessage(RE.Handle, EM_GETEVENTMASK, 0, 0);
SendMessage(RE.Handle, EM_SETEVENTMASK, 0, mask or ENM_LINK);
SendMessage(RE.Handle, EM_AUTOURLDETECT, {AURL_ENABLEEAURLS} AURL_ENABLEURL, 0);
end;
procedure TProgCorner.FormCreate(Sender: TObject);
begin
ProgCorner:= Self;
InitRichEditURLDetection(RichEdit1);
InitRichEditURLDetection(RichEdit2);
InitRichEditURLDetection(RichEdit3);
InitRichEditURLDetection(RichEdit4);
RichEdits[1]:= RichEdit1;
RichEdits[2]:= RichEdit2;
RichEdits[3]:= RichEdit3;
RichEdits[4]:= RichEdit4;
//WordWarp should be set during runtime only, because
//otherwise the text will not warp, but rather be cut off
//before run time.
RichEdit1.Text:= RichEdit1.Text + ' ';
RichEdit2.Text:= RichEdit2.Text + ' ';
RichEdit3.Text:= RichEdit3.Text + ' ';
RichEdit4.Text:= RichEdit4.Text + ' ';
RichEdit1.WordWrap:= true;
RichEdit2.WordWrap:= true;
RichEdit3.WordWrap:= true;
RichEdit4.WordWrap:= true;
end;
procedure TProgCorner.Copy1Click(Sender: TObject);
var
ActiveRichEdit: TRichEdit;
begin
ActiveRichEdit:= TRichEdit(Self.FindComponent('RichEdit'+
IntToStr(TabbedNotebook1.PageIndex+1)));
with ActiveRichEdit do begin
if SelText <> '' then Clipboard.AsText:= SelText
else ClipBoard.AsText:= Lines.Text;
end; {with}
end;
procedure TProgCorner.PopupMenu1Popup(Sender: TObject);
begin
Copy1.Enabled:= true;
end;
procedure TProgCorner.Button2Click(Sender: TObject);
begin
Application.HelpContext(4);
end;
{ TRichEdit }
function TProgCorner.RichEditByHandle(Handle: HWnd): TRichEdit;
var
i: integer;
begin
for i:= Low(RichEdits) to High(RichEdits) do begin
if RichEdits[i].Handle = Handle then exit(RichEdits[i]);
end;
Result:= nil;
end;
procedure TRichEdit.CNNotify(var Message: TWMNotifyRE);
var
p: TENLink;
sURL: string;
CE: TRichEdit;
begin
//if (Message.Msg = WM_NOTIFY) then begin
if (Message.NMHdr.code = EN_LINK) then begin
p:= TENLink(Pointer(TWMNotify(Message).NMHdr)^);
if (p.Msg = WM_LBUTTONDOWN) then begin
try
//CE:= TRichEdit(ProgCorner.ActiveControl);
//SendMessage(CE.Handle, EM_EXSETSEL, 0, Longint(@(p.chrg)));
SendMessage(p.nmhdr.hwndFrom, EM_EXSETSEL, 0, Longint(@(p.chrg)));
CE:= ProgCorner.RichEditByHandle(p.nmhdr.hwndFrom);
if assigned(CE) then begin
sURL:= CE.SelText;
ShellExecute(Handle, 'open', PChar(sURL), 0, 0, SW_SHOWNORMAL);
end;
except
{ignore}
end;
end;
end;
//end;
inherited;
end;
end.
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
874 次 |
| 最近记录: |