我有一个自定义TLabel
原则上可以附加到表单中的任何其他可视组件。该组件具有属性position
,该属性告知它将朝向附加控件(左侧,上方等)定位。附加相关控件时,此工作正常,并且组件根据position
属性定位自身。
问题是当相关控件改变它的界限时我无法检测组件,因此它可以正确地重新定位自己。我想这与WMMove
和WMResize
有关。如何让相关控件通知TLabel
任何边界属性已更改?
答案 0 :(得分:7)
只要控件的位置和/或尺寸发生变化,就会触发控件的OnResize
事件。因此,一个简单的解决方案是在将Label附加到控件时为该事件分配处理程序,例如:
private
FControl: TControl;
// OnResize is protected in TControl so use an accessor class to reach it...
type
TControlAccess = class(TControl)
end;
procedure TMyLabel.Destroy;
begin
SetControl(nil);
inherited;
end;
procedure TMyLabel.SetControl(AControl: TControl);
begin
if FControl <> AControl then
begin
if FControl <> nil then
begin
TControlAccess(FControl).OnResize := nil;
FControl.RemoveFreeNotification(Self);
end;
FControl := AControl;
if FControl <> nil then
begin
FControl.FreeNotification(Self);
TControlAccess(FControl).OnResize := ControlResized;
end;
...
end;
end;
procedure TMyLabel.Notification(AComponent: TComponent; Operation: TOperation);
begin
inherited;
if (Operation = opRemove) and (AComponent = FControl) then
FControl := nil;
end;
procedure TMyLabel.ControlResized(Sender: TObject);
begin
// reposition as needed...
end;
当然,如果用户想要将自己的OnResize
处理程序分配给控件,这将导致问题。
另一种方法是改为控制WindowProc
属性的子类:
private
FControl: TControl;
FControlWndProc: TWndMethod;
procedure TMyLabel.Destroy;
begin
SetControl(nil);
inherited;
end;
procedure TMyLabel.SetControl(AControl: TControl);
begin
if FControl <> AControl then
begin
if FControl <> nil then
begin
FControl.WindowProc := FControlWndProc;
FControl.RemoveFreeNotification(Self);
end;
FControl := AControl;
if FControl <> nil then
begin
FControlWndProc := FControl.WindowProc;
FControl.WindowProc := ControlWndProc;
FControl.FreeNotification(Self);
end else
FControlWndProc := nil;
...
end;
end;
procedure TMyLabel.Notification(AComponent: TComponent; Operation: TOperation);
begin
inherited;
if (Operation = opRemove) and (AComponent = FControl) then
begin
FControl := nil;
FControlWndProc := nil;
end;
end;
procedure TMyLabel.ControlWndProc(var Message: TMessage);
begin
FControlWndProc(Message);
// now check for position/size messages and reposition as needed...
end;
答案 1 :(得分:4)
基于@RemyLebeau的回答以及来自ExtCtrls.TLabeledEdit
的一些概念想法,我编写了自己的TStickyLabel
控件。 (工作正在进行中)。雷米的回答应该被接受当然:)