TPageControl上的TLinkLabel背景

时间:2009-08-28 06:23:18

标签: delphi delphi-2009

我试图在TPageControl上使用TLinkLabel,我找不到让它使用它的父级背景的方法。

// Image removed because the website doesn't exist any more 
// and I can't find it anywhere... Sorry.

如您所见,父标签页的可爱渐变不会保留在链接文本后面。

我希望在流动的文本块中具有多个链接的功能(TLinkLabel提供的功能)具有显示在文本后面的父级背景。

TLinkLabel没有ParentBackground属性。我尝试创建一个派生类,将csParentBackground添加到控件样式,但无济于事:

TMyLinkLabel = class (TLinkLabel)
public
  constructor Create(AOwner: TComponent); override;
end;

...

constructor TMyLinkLabel.Create(AOwner: TComponent); 
begin
  inherited;
  ControlStyle := ControlStyle - [csOpaque] + [csParentBackground]
end;

有人有什么想法吗?

6 个答案:

答案 0 :(得分:7)

Nat,你差不多对ControlStyle的{​​{1}}进行了更改。此外,您还需要确保标准Windows静态控件(即TLinkLabel)的父级正确处理TLinkLabel消息。

VCL有一个很好的重定向机制,让控件可以处理作为通知发送到父窗口的消息。可以创建一个完全独立的透明链接标签:

WM_CTLCOLORSTATIC

答案 1 :(得分:4)

通常我讨厌当人们提供第三方组件作为答案时,但我会提到TMS THTMLabel作为你想要做的事情的替代方案。它具有TLabel的Transparent属性,并允许您使用HTML作为标题,因此您可以根据您的示例执行多个链接。

答案 2 :(得分:3)

csParentBackgroundcsOpaque样式都需要与控件代码的其他部分合作。仅仅设置它们不会有太大影响;如果确实如此,则控件可能已经具有公共Transparent属性。

您可以查看TCustomLabel.Paint,了解它如何尊重csOpaque风格。它在绘制背景之前通过读取Transparent属性来检查该样式:

if not Transparent then
begin
  Canvas.Brush.Color := Self.Color;
  Canvas.Brush.Style := bsSolid;
  FillRect(ClientRect);
end;

csParentBackground样式对TCustomLabel没有影响,因为该样式仅影响窗口控件; TCustomLabel来自TGraphicControl,而不是TWinControl

我没有TLinkLabel,因此我无法查看其源代码以找出需要更改的内容。如果它是TGraphicControl后代,那么它需要包含我在TCustomLabel上面显示的代码。如果它来自TWinControl,那么我会调整来自TCustomStaticText的代码。那有点复杂;它会调用DrawParentBackground来响应cn_CtlColorStatic通知消息。它也不会在Delphi代码中绘制自己。该控件是Win32“静态”控件类型的包装器。

TLinkLabel显然无条件地描绘了它的背景。要解决此问题,您需要覆盖Paint方法。 删除功能(在这种情况下为背景绘制)很难用传统的覆盖虚方法的方法,因为您将无法调用继承的方法来获取所有绘制的文本。相反,您可能必须复制并粘贴基类的实现,然后在中间的某处添加条件部分。

答案 3 :(得分:1)

我能想到的一种方法是在实现

下创建辅助类
type
  TLinkLabelHelper = class helper for TLinkLabel
  public
    procedure Add(const aBGColor: TColor; const S: string);
  end;

procedure TLinkLabelHelper.Add(const aBGColor: TColor; const S: string);
begin
  Color := aBGColor;
  Caption := S;
end;

然后,我创建一个公共

procedure AfterConstruction; override;

procedure Form_A.AfterConstruction;
begin
  inherited;
  LinkLabel1.Add(Self.Color, 'Hello World');
end;

希望这有效。

答案 4 :(得分:0)

我的建议:使用简单的TLabel。 TLabel有一个名为Transparent的属性 - 这就是你需要的。将TLabels光标设置为crHandPoint(AFAIR这是链接光标),将字体设置为蓝色下划线,并编写OnClick事件处理程序,这将打开Web浏览器以导航到指向的URL。 您甚至可以拥有一个默认事件处理程序。

procedure OnClickOnMyLinkTLabels(Sender : TObject);
var
  Address : string;
begin
  if NOT (Sender is TLabel) then Exit;
  Address := (Sender as TLabel).Caption;
  ShellExecute(self.WindowHandle,'open',PChar(Address),nil,nil, SW_SHOWNORMAL);
end;

修改

如果您不想在标题中包含地址,可以使用Tag属性检索地址并将标题设置为您想要的任何内容:

procedure OnClickOnMyLinkTLabels(Sender : TObject);
var
  Address : string;
begin
  if NOT (Sender is TLabel) then Exit;
  Address :=  GetAddresByTag( (Sender as TLabel).Tag );
  ShellExecute(self.WindowHandle,'open',PChar(Address),nil,nil, SW_SHOWNORMAL);
end;

如何实施GetAddresByTag是您的选择。最简单的是使用字符串数组:

//in your form defintion
   private
     FAddresses : array of string;

function GetAddresByTag(id : integer): string;
begin
  if (i<Low(FAddresses)) OR (I> High(FAddresses)) then
    raise EXception.Create('wrong id sent!');
  Result:= FAddresses[id];
end;

答案 5 :(得分:-1)

如果您的文字是静态的,那么您仍然可以使用标签来执行此操作。布置整个文本块包括您想要的单词作为链接。将标签设置为透明。接下来,删除将成为链接的单独标签组件(也设置为透明)。将颜色更改为clNavy,将字体样式更改为fsunderline,将光标更改为crHand。然后将标签放在现有文本上。然后为每个“链接”标签编写onClick处理程序以执行热链接。

虽然这不是最佳的,但只要您不想加粗文本并且愿意保持文本的字体大小相同,它就会起作用。当然,如果块是动态的,这不能很好地工作,因为你必须计算代码中链接标签的位置,如果你使用wordwrap,这相当复杂。如果没有,您可以使用canvas.textwidth和canvas.textheight方法来确定链接标签所需的偏移位置。