2009-08-28 5 views
12

Ich versuche, ein TLinkLabel auf einem TPageControl zu verwenden, und ich finde keine Möglichkeit, es den Hintergrund der Eltern zu verwenden.TLinkLabel Hintergrund auf einem TPageControl

Wie Sie sehen können, ist der schöne Verlauf des übergeordneten Registerblattes hinter dem Linktext nicht erhalten.

Ich möchte die Funktionalität von mehreren Links in einem fließenden Textblock (die Funktionalität, die TLinkLabel bietet) und haben den Hintergrund der Elternteil zeigt hinter dem Text.

TLinkLabel hat keine ParentBackground-Eigenschaft. Ich habe versucht, eine abgeleitete Klasse erstellen, die mit dem Steuer Stil csParentBackground fügt, ohne Erfolg:

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

... 

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

Wer irgendwelche Ideen?

+0

Ist der Text statisch oder ändert er sich nach der Kompilierzeit? – skamradt

+0

Die Bild-URL ist beschädigt. –

+0

@Andreas Danke, dass du mich informiert hast ... Ich wünschte, ich könnte das Bild finden, und ich würde es irgendwo dauerhafter hochladen. – Nat

Antwort

7

Nat, Sie sind fast mit Ihren Änderungen an der ControlStyle der TLinkLabel. Was Sie zusätzlich tun müssen, ist sicherzustellen, dass das übergeordnete Element des standardmäßigen statischen Windows-Steuerelements (das ist, was das TLinkLabel ist) die WM_CTLCOLORSTATIC Nachricht korrekt behandelt.

Die VCL hat einen netten Umleitungsmechanismus, damit Steuerelemente Nachrichten verarbeiten können, die als Benachrichtigungen an ihre übergeordneten Fenster gesendet werden. Damit kann ein vollständig eigenständiges transparentes Link-Label erstellt werden:

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; 
+0

+1 sieht aus wie eine großartige Lösung, ich sehe keine Probleme, kann aber nicht testen, da ich nur D2006 auf der Maschine habe, mit der ich reise. Haben Sie das in RAD2009 oder 2010 getestet? Ein Screenshot zum Vergleich mit Nat's? – Argalatyr

+0

Getestet mit Delphi 2009, Screenshot (Windows XP, olivfarbenes Schema) unter http://img340.imageshack.us/img340/5849/tranparentlinklabel2.png - zur Veranschaulichung ist nur jedes zweite Label ein 'TTransparentLinkLabel'. – mghie

+0

Das ist die Antwort! :) Ich hatte es geschafft, dort am Freitag etwa 80% zu bekommen (siehe Kommentar zu Rob Kennedys Post, in dem ich "Forschung" erwähnte). Vielen Dank! – Nat

1

Ein Weg, ich denken kann, ist unter

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; 

Dann Implementierung Helfer-Klasse zu erstellen, erstelle ich eine öffentliche

procedure AfterConstruction; override; 

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

Hoffnung das funktioniert.

+2

Nein, es wird nicht funktionieren, da ein thematischer Hintergrund etwas anderes sein kann als ein einzelner farbiger Bereich. Die Seitensteuerung in der Frage hat beispielsweise einen Hintergrund mit Farbverlauf. Die richtige Lösung muss sein, dass das Link-Label seinen eigenen Hintergrund nicht malt/transparent macht, so dass der Elternhintergrund durchscheint. – mghie

+0

mghie ist richtig. Ich möchte nicht den Hintergrund * color * ändern, ich möchte das Hintergrundthema * des Elternsteuerelements hinter dem Etikettentext. – Nat

0

Mein Tipp: Verwenden Sie einfach TLabel. TLabel hat eine Eigenschaft namens Transparent - das brauchen Sie. Setzen Sie Ihren TLabels-Cursor auf crHandPoint (AFAIR ist der Link-Cursor), setzen Sie die Schriftart auf die blaue Unterstreichung und schreiben Sie den OnClick-Event-Handler, der den Webbrowser öffnet, um zur angegebenen URL zu navigieren. Sie können sogar einen Standard-Event-Handler haben.

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; 

bearbeiten:

Wenn Sie Adresse in Ihrer Beschriftung nicht haben möchten, können Sie Tag-Eigenschaft Adresse und setzen Beschriftung abrufen können, was Sie wollen:

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; 

Wie Sie GetAddresByTag implementieren, ist Ihre Wahl. Die einfachste ist ein Array von Strings verwenden:

//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; 
+0

:) Tolle Idee.Aber ich hätte gerne den Link in der Mitte des Textes. Ich werde mein Beispiel ein wenig verdeutlichen, um zu zeigen, was ich meine. – Nat

+0

@Nat: Antwort erweitert – smok1

+0

@ Smok1: ähm ... also schlagen Sie vor, dass ich die Etiketten zum Designzeitpunkt manuell zwischen den Text positionieren? Ich setze den Text zur Laufzeit und könnte eine Verity von verschiedenen Strings mit Links darin sein (nicht Web-Adressen, nicht dass es darauf ankommt). – Nat

4

Normalerweise hasse ich es, wenn die Leute ein Drittanbieter-Komponente als Antwort anbieten, aber ich werde das TMS THTMLabel als Alternative zu erwähnen, was Sie wollen machen. Es verfügt über die Transparent-Eigenschaft von TLabel und ermöglicht die Verwendung von HTML als Beschriftung, sodass Sie mehrere Links gemäß Ihrem Beispiel verwenden können.

+0

Danke dafür. Hatte diese Komponente schon einmal gesehen, aber im Moment keine Dollars ausgeben. Das Budget wurde durch den Kauf von Delphi 2010 aufgebraucht. :) – Nat

3

Die Modelle csParentBackground und csOpaque erfordern beide die Zusammenarbeit mit anderen Teilen des Steuercodes. Lediglich die Einstellung würde nicht viel bewirken; Wenn dies der Fall wäre, hätte das Steuerelement wahrscheinlich bereits eine öffentliche Transparent Eigenschaft.

Sie können TCustomLabel.Paint betrachten, um zu sehen, wie es den csOpaque Stil respektiert.Es prüft, für diesen Stil durch seine Transparent Eigenschaft zu lesen, bevor es seinen Hintergrund malt:

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

Der csParentBackground Stil hat keine Auswirkung auf TCustomLabel weil dieser Stil wirkt sich nur auf Fenstersteuerelementen; TCustomLabel stammt von TGraphicControl, nicht TWinControl.

Ich habe keine TLinkLabel, so kann ich nicht auf seinen Quellcode schauen, um herauszufinden, was es ändern müsste. Wenn es ein TGraphicControl Nachkomme ist, dann würde es Code einschließen müssen, wie ich oben von TCustomLabel gezeigt habe. Wenn es von TWinControl stammt, dann würde ich stattdessen Code von TCustomStaticText anpassen. Das ist ein bisschen komplizierter; es ruft DrawParentBackground in Reaktion auf die cn_CtlColorStatic Benachrichtigung Nachricht. Es zeichnet sich auch nicht in Delphi-Code. Das Steuerelement ist ein Wrapper für den Steuerelementtyp "statisch" von Win32.

TLinkLabel malt offensichtlich seinen Hintergrund bedingungslos. Um dies zu beheben, müssen Sie die Methode Paint überschreiben. Entfernen von Funktionalität (Hintergrund-Malerei, in diesem Fall) ist schwer mit der traditionellen Art des Überschreibens virtueller Methoden zu tun, weil Sie nicht in der Lage sein wird, die geerbte Methode aufrufen, um den gesamten Text zu malen. Stattdessen müssen Sie wahrscheinlich die Implementierung der Basisklasse kopieren und einfügen und dann die bedingten Teile irgendwo in der Mitte hinzufügen.

+0

Ich habe über Nacht eine Menge Nachforschungen darüber angestellt ... Standardmäßig macht das Setzen von csParentBackground * tatsächlich etwas. Es ruft die Themen-Services auf, um den Backgrounnd als Reaktion auf WM_ERASEBACKGND zu zeichnen (abhängig von bestimmten Einstellungen). Das wird tatsächlich gemacht ... Ich denke, die Kontrolle überstreicht es dann, aber ich muss mehr recherchieren. Ich werde die Frage am Montag aktualisieren (es ist das Wochenende hier unten in OZ, und ich habe Shows zu beleuchten!). – Nat

+0

Rechts. Das meinte ich mit der Zusammenarbeit der Steuerung - auch wenn 'csParentBackground' gesetzt ist, muss die Steuerung kooperieren, indem * nicht * übermalt wird. –

-1

Wenn Ihr Text statisch ist, können Sie dies weiterhin mithilfe von Beschriftungen tun. Legen Sie Ihren gesamten Textblock mit den gewünschten Wörtern als Links an. Legen Sie das Label als transparent fest. Als nächstes lassen Sie separate Label-Komponenten (auch auf transparent gesetzt), die den Link bilden. Ändern Sie die Farbe in clNavy, den Schriftschnitt in fsunderline und den Cursor in crHand. Dann positionieren Sie die Beschriftung ÜBER den vorhandenen Text. Schreiben Sie dann einen onClick-Handler für jede "Link" -Etikette, um Ihre direkte Verbindung herzustellen.

Obwohl dies nicht optimal ist, funktioniert es, solange Sie den Text nicht fett formatieren und den Text in der gleichen Schriftgröße halten möchten. Natürlich funktioniert das nicht so gut, wenn der Block dynamisch ist, da Sie die Position der Link-Labels im Code berechnen müssten, was ziemlich kompliziert ist, wenn Sie Wordwrap verwenden. Wenn nicht, können Sie die Methoden canvas.textwidth und canvas.textheight verwenden, um die erforderlichen Offset-Positionen für Ihre Link-Labels festzulegen.

+0

Vorsicht: Wenn ClearType oder normales Antialiasing aktiviert ist, wird das Etikett nicht vollständig vom Text des unteren Labels abgedeckt. Die untere Beschriftung "blutet" durch und beeinflusst die Farbe des oberen Texts. –

+0

Leider, in meinem realen Code, ist der Text umhüllt, und es ist in einer veränderbaren Form, so dass es fließen muss ... Danke für Ihren Vorschlag. – Nat

+0

-1 das ist wirklich ein hoffnungsloser Vorschlag! –

Verwandte Themen