Фон TLinkLabel на TPageControl
Я пытаюсь использовать TLinkLabel на TPageControl, и я не могу найти способ заставить его использовать фон своего родителя.
// 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 ответов
Нат, ты почти со своими изменениями в ControlStyle
из TLinkLabel
, Кроме того, необходимо убедиться, что родительский элемент стандартного статического элемента управления Windows (это то, что TLinkLabel
есть) обрабатывает 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;
Обычно я ненавижу, когда люди предлагают сторонний компонент в качестве ответа, но я упомяну TMS THTMLabel как альтернативу тому, что вы хотите сделать. Он имеет свойство Transparent TLabel и позволяет вам использовать HTML в качестве заголовка, и поэтому вы можете делать несколько ссылок в соответствии с вашим примером.
csParentBackground
а также csOpaque
оба стиля требуют взаимодействия с другими частями кода элемента управления. Простая установка их не будет иметь большого эффекта; если это так, то контроль, вероятно, будет иметь общественное 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
метод. Удаление функциональности (в данном случае рисование фона) трудно сделать традиционным способом переопределения виртуальных методов, потому что вы не сможете вызвать унаследованный метод для рисования всего текста. Вместо этого Вам, вероятно, придется скопировать и вставить реализацию базового класса, а затем добавить где-то условные части в середину.
Один из способов, который я могу придумать, - создать вспомогательный класс в процессе реализации.
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;
Надеюсь, это работает.
Мой совет: используйте простой TLabel. У TLabel есть свойство с именем Transparent - это то, что вам нужно. Установите курсор TLabels на crHandPoint (AFAIR это курсор ссылки), установите шрифт с синим подчеркиванием и напишите обработчик события OnClick, который откроет веб-браузер для перехода к указанному 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;
Если ваш текст статичен, вы все равно можете сделать это с помощью меток. Выложите весь текстовый блок, включая слова, которые вы хотите в качестве ссылок. Установите метку как прозрачную. Затем удалите отдельные компоненты метки (также прозрачные), которые будут ссылками. Измените цвет на clNavy, стиль шрифта на fsunderline и курсор на crHand. Затем поместите метку над существующим текстом. Затем напишите обработчик onClick для каждой метки "ссылка", чтобы выполнить горячую ссылку.
Хотя это не является оптимальным, оно работает, если вы не хотите выделять текст жирным шрифтом и хотите, чтобы размер шрифта был одинаковым. Конечно, это не так хорошо работает, если блок динамический, так как вам придется вычислять положение меток ссылок в коде, что довольно сложно, если вы используете перенос слов. Если нет, вы можете использовать методы canvas.textwidth и canvas.textheight, чтобы определить необходимые позиции смещения для меток ссылок.