He escrito un componente que pinta una imagen centrada en x, y. En tiempo de ejecución, el componente se mueve con un procedimiento SetXY(X,Y: integer).

Para lograr esto, calculo lo que los valores Left y Top deben estar en la rutina de pintura y establecerlos en consecuencia. Y todo lo que funciona bien.

Pero cuando intento hacer el posicionamiento inicial en el horario de diseño, no puedo posicionar el componente arrastrándolo a la ubicación deseada.

Cuando configuré la propiedad Left o Top a través del inspector de objetos, funciona.

procedure MyCustomComponent.SetTop(const Value: integer);
begin
  if Top = (Value) then
    exit;
    
  inherited Top := Value;
  if csDesigning in ComponentState then
    FY := Value + FBmp.Width div 2;
  Invalidate;
end;
    
procedure MyCustomComponent.SetLeft(const Value: integer);
begin
  if Left = (Value) then
    exit;
    
  inherited Left := Value;
  if csDesigning in ComponentState then
    FX := Value + FBmp.Width div 2;
  Invalidate;
end;

Sospecho que cuando el componente se arrastra y se caiga en el tiempo de diseño en el formulario, en realidad no establece las propiedades públicas Left y Top, pero en su lugar llama alguna otra función que establece los miembros del campo privado. del control subyacente que heredé el componente de ({TGraphicControl).

1
Jeppe Clausen 24 may. 2021 a las 10:00

1 respuesta

La mejor respuesta

Cuando FPIETTE y REMY señaló, anulando el SetBounds. Cuando se coloca un componente en el tiempo de diseño a través de arrastrar y soltar el componente, no establece individualmente las propiedades públicas Left y Top. Pero en su lugar hace una llamada al procedimiento SetBounds.

procedure MyComponent.SetBounds(ALeft, ATop, AWidth, AHeight: Integer);
begin
  inherited;
  if csDesigning in ComponentState then begin
    FX := ALeft + FBmp.Width div 2;
    FY := ATop + FBmp.Height div 2;
  end;
end;

Editar:

Después de las pruebas, descubrí que para que el componente se coloque correctamente en el formulario en tiempo de ejecución, también debe verificar el estado de componentes de {{x0}.

Así que una solución más completa sería así:

procedure MyComponent.SetBounds(ALeft, ATop, AWidth, AHeight: Integer);
begin
  inherited;
  if (csDesigning in ComponentState) or (csLoading in ComponentState ) then begin
    FX := ALeft + FBmp.Width div 2;
    FY := ATop + FBmp.Height div 2;
  end;
end;
1
Jeppe Clausen 28 may. 2021 a las 20:48