我有一个定制的TLabel,原则上可以附加到表单中的任何其他可视组件。该组件具有一个属性position,它指示它将定位到附加控件的位置(左、上等)。当附加了相关控件,并且组件根据position属性定位自己时,这是很好的。
问题是,我无法让组件检测到相关控件何时改变了它的界限,这样它就可以正确地重新定位自己。我想这与WMMove和WMResize有关。如何使相关控件通知TLabel任何边界属性都已更改?
发布于 2013-12-15 21:53:12
每当控件的位置和/或维度发生更改时,都会触发控件的OnResize事件。因此,一个简单的解决方案是在将标签附加到控件时为该事件分配一个处理程序,例如:
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;发布于 2013-12-24 22:11:42
基于@RemyLebeau的答案和ExtCtrls.TLabeledEdit的一些概念想法,我编写了自己的TStickyLabel控件。(工作正在进行中)。雷米的回答应该被接受-当然:)
https://stackoverflow.com/questions/20597649
复制相似问题