我有一个来自TGraphicControl的自定义Delphi组件。它的类声明如下:
TMyLabel = class(TGraphicControl)
private
...
protected
...
public
...
published
property Height;
property Width write SetWidth;
...
end;
SetWidth的实现更进一步:
procedure TMyLabel.SetWidth(const Value: Integer);
begin
if (Value >= 0) and (Value <> Width)
then begin
inherited Width := Value;
// Do some other stuff
...
end;
MessageDlg('Test', mtInformation, [mbOK], 0);
end;
当在运行时或设计时通过在对象检查器的相应字段中输入值以编程方式更改组件的宽度时,我当前调用了SetWidth。但是,当我在设计时使用鼠标调整组件大小时,对象检查器的“宽度”字段会更新,但不显示任何消息框,因此不会调用我的SetWidth过程。
我需要在鼠标调整组件大小时调用SetWidth,这样我就可以为Paint过程设置一个标志,以便知道它何时必须执行其他操作(除了重新绘制组件之外)。有没有办法实现这个目标?
答案 0 :(得分:6)
我现在无法检查,但是iirc我怀疑设计师使用SetBounds()调整控件的大小,而不是设置单独的left,top,width和height属性。
幸运的是,SetBounds()是虚拟的,因此您可以在自定义控件类中简单地覆盖它。
答案 1 :(得分:6)
虽然Mason Wheeler's answer是您问题的答案,但我想提醒您。
覆盖属性可能会产生奇怪的结果,因为您不能拥有“虚拟”属性,而SetWidth也不是虚拟的。如果有人使用您的类的后代来设置Width属性,则不会调用您的代码。因此,我建议以这种方式反对覆盖属性。
var Control: TControl;
begin
Control := MyLabel;
Control.Width := 5000; // TMyLabel.SetWidth is not called!!
此外:设置Width属性不是将控件宽度更改为Deltics explains的唯一方法。你应该覆盖TControl.SetBounds。
var MyLabel: TMyLabel;
begin
MyLabel.SetBounds(0, 0, 100, 100); // TMyLabel.SetWidth nor TControl.SetWidth is called!!
但似乎您想要限制控件的宽度。然后你最好覆盖为此目的而制作的 TControl.CanResize 。或者,如果您只想对任何类型的调整大小做出反应,最好覆盖 TControl.Resize 。
答案 2 :(得分:4)
重新声明宽度时,您需要为其指定读取和写入,否则您将无法在对象检查器中对其进行修改。如果你不打算改变阅读方式,那就给它一个虚函数:
procedure TMyLabel.GetWidth: Integer;
begin
result := inherited Width;
end;