我有一个习惯TLabel,原则上可以附加到表单中的任何其他可视组件.该组件具有一个属性position,告诉它将朝向附加控件(左侧,上方等)的位置.当附加相关控件时,这可以正常工作,并且组件根据position属性定位自身.
问题是当相关控件改变它的界限时我无法检测组件,因此它可以正确地重新定位自己.我想这与WMMove和有关WMResize.如何通知相关控件以通知TLabel任何边界属性已更改?
只要控件的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)
| 归档时间: |
|
| 查看次数: |
1001 次 |
| 最近记录: |