Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How I can detect when other control changes it bounds?

I have a custom TLabel that in principle can be attached to any other visual component in the form. The component has a property position which tells where it will be positioned towards the attached control (left, above, etc.). This works fine when the related control is attached, and the component positions itself according to the position property.

Problem is that I can't make the component detect when the related control changes it bounds so it can properly reposition itself. I guess that has to do with WMMove and WMResize. How can I do for the related control to notify the TLabel that any of the bounds properties has changed?

like image 765
user2383818 Avatar asked Dec 15 '13 17:12

user2383818


People also ask

Which of the following is enables the synchronization of data bound controls on a Windows form that are bound to the same data source?

Binding managers provide a central repository of information for data-bound controls on a Windows Form that are bound to the same data source. In doing so, binding managers enable the synchronization of related controls.

How do you add a control?

To create a control that is bound to a field (meaning that the control will display and let you edit data from a table), open the Field List (Alt+F8) and drag the field from the list to the form, view, or report. Access adds a control that is appropriate for the type of data stored in the field.


2 Answers

A control's OnResize event is triggered whenever its position and/or dimension changes. So one simply solution is to assign a handler to that event when you attach your Label to a control, eg:

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;

Of course, this will cause issues if the user wants to assign their own OnResize handler to the control.

The alternative is to subclass the control's WindowProc property instead:

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;
like image 127
Remy Lebeau Avatar answered Oct 28 '22 01:10

Remy Lebeau


Based on @RemyLebeau answer and some concept ideas from ExtCtrls.TLabeledEdit I have wrote my own TStickyLabel control. (Work in progress). Remy's answer should be accepted of-course :)

like image 36
kobik Avatar answered Oct 28 '22 02:10

kobik