Я имел эту ту же проблему прежде и нашел этот отрывок очень полезным:
class Tee(object):
def __init__(self, name, mode):
self.file = open(name, mode)
self.stdout = sys.stdout
sys.stdout = self
def __del__(self):
sys.stdout = self.stdout
self.file.close()
def write(self, data):
self.file.write(data)
self.stdout.write(data)
def flush(self):
self.file.flush()
от: http://mail.python.org/pipermail/python-list/2007-May/438106.html
Нат, вы почти готовы внести изменения в 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;
Оба стиля 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
. Удаление функциональности (фоновое рисование, в этом случае) трудно сделать с традиционным способом переопределения виртуальных методов, потому что вы не сможете вызвать унаследованный метод, чтобы нарисовать весь текст. Вместо этого вам, вероятно, придется скопировать и вставить реализацию базового класса, а затем добавить условные части где-нибудь посередине.
Мой совет: используйте простой 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;
Один из способов, который я могу придумать, - это создать вспомогательный класс в рамках реализации
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;
Надеюсь, что это сработает.
Обычно я ненавижу, когда люди предлагают сторонний компонент в качестве ответа, но я упомяну TMS THTMLabel как альтернативу тому, что вы хотите сделать. Он имеет свойство Transparent TLabel и позволяет использовать HTML в качестве заголовка, поэтому вы можете создавать несколько ссылок в соответствии с вашим примером.
If your text is static, then you can still do this using labels. Lay out your entire text block INCLUDING the words you want as links. Set the label as transparent. Next, drop separate label components (also set to transparent) that will be the link. Change the color to clNavy, font style to fsunderline and the cursor to crHand. Then position the label OVER the existing text. Then write a onClick handler for each "link" label to perform your hot link.
While this is not optimal, it does work as long as you don't want to bold the text and are willing to keep the text the same font size. Of course this doesn't work so well if the block is dynamic, as you would have to calculate the position of the link labels in code, which is fairly complicated if you are using wordwrap. If not, you can use the canvas.textwidth and canvas.textheight methods to determine the necessary offset positions for your link labels.