- android - 多次调用 OnPrimaryClipChangedListener
- android - 无法更新 RecyclerView 中的 TextView 字段
- android.database.CursorIndexOutOfBoundsException : Index 0 requested, 光标大小为 0
- android - 使用 AppCompat 时,我们是否需要明确指定其 UI 组件(Spinner、EditText)颜色
我需要在 TRichEdit 中支持“友好名称超链接”,我找到的所有解决方案都基于自动 URL(EM_AUTOURLDETECT),它通过检测用户输入的以 www(或 http)开头的字符串来工作。
但我想在不以 www 开头的字符串上放置链接。示例:' Download '.
最佳答案
您需要执行以下操作:
向 RichEdit 发送 EM_SETEVENTMASK
启用 ENM_LINK
标志的消息。在创建 RichEdit 后执行此操作一次,然后在每次 RichEdit 收到 CM_RECREATEWND
消息时再次执行此操作。
选择您想要变成链接的文本。您可以使用 RichEdit 的 SelStart
和 SelLength
属性,或向 RichEdit 发送 EM_SETSEL
或 EM_EXSETSEL
信息。无论哪种方式,然后向 RichEdit 发送 EM_SETCHARFORMAT
带有 CHARFORMAT2
的消息结构以对所选文本启用 CFE_LINK
效果。
继承 RichEdit 的 WindowProc
属性来处理 CN_NOTIFY(EN_LINK)
和 CM_RECREATEWND
消息。收到 EN_LINK
后,您可以使用 ShellExecute/Ex()
启动所需的 URL。
例如:
unit Unit1;
interface
uses
Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants, System.Classes, Vcl.Graphics,
Vcl.Controls, Vcl.Forms, Vcl.Dialogs, Vcl.StdCtrls, Vcl.ComCtrls;
type
TForm1 = class(TForm)
RichEdit1: TRichEdit;
Button1: TButton;
procedure FormCreate(Sender: TObject);
procedure Button1Click(Sender: TObject);
private
{ Private declarations }
PrevRichEditWndProc: TWndMethod;
procedure InsertHyperLink(const HyperlinkText: string);
procedure SetRichEditMasks;
procedure RichEditWndProc(var Message: TMessage);
public
{ Public declarations }
end;
var
Form1: TForm1;
implementation
{$R *.dfm}
uses
Winapi.RichEdit, Winapi.ShellAPI;
procedure TForm1.FormCreate(Sender: TObject);
begin
PrevRichEditWndProc := RichEdit1.WindowProc;
RichEdit1.WindowProc := RichEditWndProc;
SetRichEditMasks;
RichEdit1.Text := 'Would you like to Download Now?';
RichEdit1.SelStart := 18;
RichEdit1.SelLength := 12;
InsertHyperLink('Download Now');
end;
procedure TForm1.Button1Click(Sender: TObject);
begin
InsertHyperLink('Another Link');
end;
procedure TForm1.InsertHyperLink(const HyperlinkText: string);
var
Fmt: CHARFORMAT2;
StartPos: Integer;
begin
StartPos := RichEdit1.SelStart;
RichEdit1.SelText := HyperlinkText;
RichEdit1.SelStart := StartPos;
RichEdit1.SelLength := Length(HyperlinkText);
FillChar(Fmt, SizeOf(Fmt), 0);
Fmt.cbSize := SizeOf(Fmt);
Fmt.dwMask := CFM_LINK;
Fmt.dwEffects := CFE_LINK;
SendMessage(RichEdit1.Handle, EM_SETCHARFORMAT, SCF_SELECTION, LPARAM(@Fmt));
RichEdit1.SelStart := StartPos + Length(HyperlinkText);
RichEdit1.SelLength := 0;
end;
procedure TForm1.SetRichEditMasks;
var
Mask: DWORD;
begin
Mask := SendMessage(RichEdit1.Handle, EM_GETEVENTMASK, 0, 0);
SendMessage(RichEdit1.Handle, EM_SETEVENTMASK, 0, Mask or ENM_LINK);
SendMessage(RichEdit1.Handle, EM_AUTOURLDETECT, 1, 0);
end;
procedure TForm1.RichEditWndProc(var Message: TMessage);
type
PENLINK = ^ENLINK;
var
tr: TEXTRANGE;
str: string;
p: PENLINK;
begin
PrevRichEditWndProc(Message);
case Message.Msg of
CN_NOTIFY: begin
if TWMNotify(Message).NMHdr.code = EN_LINK then
begin
P := PENLINK(Message.LParam);
if p.msg = WM_LBUTTONUP then
begin
SetLength(str, p.chrg.cpMax - p.chrg.cpMin);
tr.chrg := p.chrg;
tr.lpstrText := PChar(str);
SendMessage(RichEdit1.Handle, EM_GETTEXTRANGE, 0, LPARAM(@tr));
if str = 'Download Now' then
begin
ShellExecute(Handle, nil, 'http://www.SomeSite.com/download', nil, nil, SW_SHOWDEFAULT);
end
else if str = 'Another Link' then
begin
// do something else
end;
end;
end;
end;
CM_RECREATEWND: begin
SetRichEditMasks;
end;
end;
end;
end.
更新:根据 MSDN:
RichEdit Friendly Name Hyperlinks
In RichEdit, the hyperlink field entity is represented by character formatting effects, as contrasted to delimiters which are used to structure math objects. As such, these hyperlinks cannot be nested, although in RichEdit 5.0 and later they can be adjacent to one another. The whole hyperlink has the character formatting effects of
CFE_LINK
andCFE_LINKPROTECTED
, while autoURLs only have theCFE_LINK
attribute. TheCFE_LINKPROTECTED
is included for the former so that the autoURL scanner skips over friendly name links. The instruction part, i.e., the URL, has theCFE_HIDDEN
attribute as well, since it’s not supposed to be displayed. The URL itself is enclosed in ASCII double quotes and preceded by the string“HYPERLINK “
. SinceCFE_HIDDEN
plays an integral role in friendly name hyperlinks, it cannot be used in the name.For example, in WordPad, which uses RichEdit, a hyperlink with the name MSN would have the plain text
HYPERLINK “http://www.msn.com”MSN
The whole link would have
CFE_LINK
andCFE_LINKPROTECTED
character formatting attributes and all but the MSN would have theCFE_HIDDEN
attribute.
这可以很容易地用代码模拟:
procedure TForm1.FormCreate(Sender: TObject);
begin
...
RichEdit1.Text := 'Would you like to Download Now?';
RichEdit1.SelStart := 18;
RichEdit1.SelLength := 12;
InsertHyperLink('Download Now', 'http://www.SomeSite.com/downloads');
end;
procedure TForm1.Button1Click(Sender: TObject);
begin
InsertHyperLink('A Text Link');
end;
procedure TForm1.InsertHyperLink(const HyperlinkText: string; const HyperlinkURL: string = '');
var
HyperlinkPrefix, FullHyperlink: string;
Fmt: CHARFORMAT2;
StartPos: Integer;
begin
if HyperlinkURL <> '' then
begin
HyperlinkPrefix := Format('HYPERLINK "%s"', [HyperlinkURL]);
FullHyperlink := HyperlinkPrefix + HyperlinkText;
end else begin
FullHyperlink := HyperlinkText;
end;
StartPos := RichEdit1.SelStart;
RichEdit1.SelText := FullHyperlink;
RichEdit1.SelStart := StartPos;
RichEdit1.SelLength := Length(FullHyperlink);
FillChar(Fmt, SizeOf(Fmt), 0);
Fmt.cbSize := SizeOf(Fmt);
Fmt.dwMask := CFM_LINK;
Fmt.dwEffects := CFE_LINK;
if HyperlinkURL <> '' then
begin
// per MSDN: "RichEdit doesn’t allow the CFE_LINKPROTECTED attribute to be
// set directly by programs. Maybe it will allow it someday after enough
// testing is completed to ensure that things cannot go awry"...
//
{
Fmt.dwMask := Fmt.dwMask or CFM_LINKPROTECTED;
Fmt.dwEffects := Fmt.dwEffects or CFE_LINKPROTECTED;
}
end;
SendMessage(RichEdit1.Handle, EM_SETCHARFORMAT, SCF_SELECTION, LPARAM(@Fmt));
if HyperlinkURL <> '' then
begin
RichEdit1.SelStart := StartPos;
RichEdit1.SelLength := Length(HyperlinkPrefix);
FillChar(Fmt, SizeOf(Fmt), 0);
Fmt.cbSize := SizeOf(Fmt);
Fmt.dwMask := CFM_HIDDEN;
Fmt.dwEffects := CFE_HIDDEN;
SendMessage(RichEdit1.Handle, EM_SETCHARFORMAT, SCF_SELECTION, LPARAM(@Fmt));
end;
RichEdit1.SelStart := StartPos + Length(FullHyperlink);
RichEdit1.SelLength := 0;
end;
然后通过解析点击的超链接文本在EN_LINK
通知中处理:
uses
..., System.StrUtils;
...
SendMessage(RichEdit1.Handle, EM_GETTEXTRANGE, 0, LPARAM(@tr));
// Per MSDN: "The ENLINK notification structure contains a CHARRANGE with
// the start and end character positions of the actual URL (IRI, file path
// name, email address, etc.) that typically appears in a browser URL
// window. This doesn’t include the “HYPERLINK ” string nor the quotes in
// the hidden part. For the MSN link above, it identifies only the
// http://www.msn.com characters in the backing store."
//
// However, without the CFM_LINKPROTECTED flag, the CHARRANGE will report
// the positions of the entire "HYPERLINK ..." string instead, so just strip
// off what is not needed...
//
if StartsText('HYPERLINK "', str) then
begin
Delete(str, 1, 11);
Delete(str, Pos('"', str), MaxInt);
end;
if (str is a URL) then begin
ShellExecute(Handle, nil, PChar(str), nil, nil, SW_SHOWDEFAULT);
end
else begin
// do something else
end;
关于html - 为 TRichEdit 添加真正的超链接支持,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/42532760/
我正在尝试找到一种在使用 RichEdit 控件打印方法时在 Delphi 中强制分页的方法。由于某些愚蠢的原因,Rich Edit 控件忽略了\page 命令。 有谁知道有什么方法可以做到这一点吗?
如何在同一行书写不同颜色的文字? (我使用richedit)。 procedure TForm1.btnEClick(sender: TObject); begin m0.SelAttribute
很难说这里问的是什么。这个问题是模棱两可的、模糊的、不完整的、过于宽泛的或修辞的,无法以目前的形式得到合理的回答。如需帮助澄清此问题以便重新打开它,visit the help center . 10
我目前在我的一个软件(在 Delphi 7 中)中使用 TRichEdit 作为“实时”事件日志查看器,我最近分析了我的软件,TRichEdit 消耗了超过 40% 的软件 cpu 时间。 我只是想测
有没有办法改变插入符号的像素位置? 我想每次移动鼠标时都移动护理点。 喜欢: 鼠标移动: MoveCaretPos(X, Y); 最佳答案 不,您不能将插入符号的位置设置在特定点,而必须将插入符号设置
我使用 TRichEdit 来显示我的应用程序中完成的最后操作。我的 TRichEdit 的第一行应该是最后一个操作。如果操作失败,我想把这条线变成红色。 我的问题是我无法在 TRichEdit 顶部
TRichEdit 控件中每行的左侧有一个不可见的空间,其中光标变为右上箭头,当您单击此处时,整行都会被选中。当 TRichEdit 的文本对齐方式为居中或右时,很容易看到它。我相信这个空间被称为选择
我需要在运行时使用 TRichEdit 来执行 rtf 到文本的转换,如所讨论的 here 。我成功地做到了这一点,但我必须设置一个虚拟表单作为父表单,否则我无法填充 TRichedit.Lines。
我想创建一个自定义控件(TRichEdit 的后代)。我只想在编辑字段上方添加一些文本。 我创建了自己的控件,并重写了构造函数来为标题创建 TLabel。它有效,但我的问题是:如何将标签移到 Rich
我有返回字符索引的函数 GetCharFromPos(Pt: TPoint): Integer; 现在我想了解该职位的特征。像 GetCharByIndex(Index: Integer): Char
我需要在 TRichEdit 中支持“友好名称超链接”,我找到的所有解决方案都基于自动 URL(EM_AUTOURLDETECT),它通过检测用户输入的以 www(或 http)开头的字符串来工作。
有没有办法暂停/恢复 TRichEdit 控件中的撤消记录?是否有要发送的消息或要设置的模式? 编辑 我已经通过使用 ITextDocument 接口(interface)解决了这个问题。请看我下面的
如何在 TRichEdit 中阻止拖放?德尔福代码我使用 Rich edit,并且很难阻止拖放功能,特别是从表单外部拖动文本,比如从 IE 拖到我的 RichEdit。 最佳答案 参见RevokeDr
我目前正在将我们的软件解决方案从 Delphi 7 迁移到 2010。大部分更改都很简单,只剩下少量障碍。 在表单上,我们使用 TRichEdit,它显示从 MSSQL 数据库中的 blob 字段
我正在使用 tRichEdit 组件,并使用 tSpinedit 来确定制表符间距,使用 trichedit.oncreate 事件来生成制表符位置数组。这工作正常,我生成的每个新段落都使用定义的制表
我在使用 TRichEdit 时遇到一些问题。 第一个问题是,如果我尝试将剪贴板中的大量文本粘贴到空的 TRichEdit 中,它会截断文本的底部。 我猜想与第一个问题相关的第二个问题是,我似乎限制了
我正在尝试围绕 TRichEdit 编写一个包装类,它可以将 RTF 编码为明文或从明文解码。 这是我到目前为止所写的内容: type TRTF = class private FRi
我正在使用当前代码在 TRichEdit 上突出显示 URL: procedure TForm1.WndProc(var Message: TMessage); var p: TENLink;
我正在尝试将 TRichEdit 组件上的富文本转换为 HTML 标签。我有一个函数用于此,但它不起作用,因为组件中的文本始终以 PlainText 发送。组件上的 PlainText 选项设置为 f
我就这个问题给你一个简短的想法。 从数据库中检索 (id,name) 字段记录到列表框中。 从列表中选择任何记录。 将备注(Blob 类型)显示到选定 ID 的丰富编辑框中。 除了两个记录都很好。 这
我是一名优秀的程序员,十分优秀!