代码之家  ›  专栏  ›  技术社区  ›  Nat

TpageControl上的TlinkLabel背景

  •  12
  • Nat  · 技术社区  · 15 年前

    我试图在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 回复  |  直到 10 年前
        1
  •  7
  •   mghie    15 年前

    纳特,你快到了 ControlStyle TLinkLabel . 此外,还需要确保标准windows静态控件的父控件(即 标签标签 is)处理 WM_CTLCOLORSTATIC 信息正确。

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

    type
      TTransparentLinkLabel = class(TLinkLabel)
      private
        procedure CNCtlColorStatic(var AMsg: TWMCtlColorStatic);
          message CN_CTLCOLORSTATIC;
      public
        constructor Create(AOwner: TComponent); override;
      end;
    
    constructor TTransparentLinkLabel.Create(AOwner: TComponent);
    begin
      inherited;
      ControlStyle := ControlStyle - [csOpaque] + [csParentBackground];
    end;
    
    procedure TTransparentLinkLabel.CNCtlColorStatic(var AMsg: TWMCtlColorStatic);
    begin
      SetBkMode(AMsg.ChildDC, TRANSPARENT);
      AMsg.Result := GetStockObject(NULL_BRUSH);
    end;
    
        2
  •  4
  •   J__    15 年前

    通常我讨厌人们提供第三方组件作为答案,但我会提到tms thtmlabel作为您想要做的事情的替代品。它具有tlabel的透明属性,并允许您使用html作为标题,因此您可以根据示例执行多个链接。

        3
  •  3
  •   Rob Kennedy    15 年前

    这个 csParentBackground csOpaque 样式都需要控件代码的其他部分的协作。仅仅设置它们不会有太大的效果;如果设置了,那么控件可能会公开 Transparent 属性已存在。

    你可以看看 TCustomLabel.Paint 看看它是如何尊重 克索不克 风格。它通过阅读 透明的 属性在绘制其背景之前:

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

    这个 CSparentbackground公司 风格对 TCustomLabel 因为这种样式只影响窗口控件; 标签标签 TGraphicControl 不是 TWinControl .

    我没有 TLinkLabel ,所以我无法查看它的源代码来找出需要更改的内容。如果是 t图像控制 子代,然后它需要包含我在上面显示的代码 标签标签 . 如果它从 孪生控制 ,然后我将改编 TCustomStaticText 相反。那有点复杂,它叫 DrawParentBackground 作为对 cn_CtlColorStatic 通知消息。它也没有在delphi代码中绘制自己。控件是win32“静态”控件类型的包装器。

    标签标签 显然是无条件地描绘它的背景。要解决这个问题,您需要覆盖 Paint 方法。 去除 功能(在本例中为背景绘制)很难使用传统的重写虚拟方法的方法,因为您将无法调用继承的方法来绘制所有文本。相反,您可能需要复制并粘贴基类的实现,然后在中间的某个位置添加条件部分。

        4
  •  1
  •   KS.    15 年前

    我可以想到的一种方法是在实现下创建helper类

    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;
    

    希望这行得通。

        5
  •  0
  •   smok1    15 年前

    我的建议是:使用简单的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;
    
        6
  •  -1
  •   skamradt    15 年前

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

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