如何检测其他控件何时更改?

use*_*818 5 delphi delphi-xe2

我有一个习惯TLabel,原则上可以附加到表单中的任何其他可视组件.该组件具有一个属性position,告诉它将朝向附加控件(左侧,上方等)的位置.当附加相关控件时,这可以正常工作,并且组件根据position属性定位自身.

问题是当相关控件改变它的界限时我无法检测组件,因此它可以正确地重新定位自己.我想这与WMMove和有关WMResize.如何通知相关控件以通知TLabel任何边界属性已更改?

Rem*_*eau 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;
Run Code Online (Sandbox Code Playgroud)

当然,如果用户想要将自己的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;
Run Code Online (Sandbox Code Playgroud)