Pen:=FPen;
这一句,不要这么使用,请这样使用,Pen.Assign(FPen)如果你一定坚持原先的用法,请这样处理
TempPen:=Pen;
Pen:=FPen;
....
Pen:=TempPen;
SetPen中也不能这样写
应当这样
FPen.Assign(value);
也不需要比较两个对象,只要判断是不是Value为空就可以了,要知道,TPen在程序加载的时候,会生成一个临时的Pen然后调用SetPen传递给你的Pen属性,很快这个临时对象就会释放。原因是TPen是一个Published属性,他会把这个对象(Pen)的属性保存到.dfm文件,编译完成后加载,是先按照pen属性生成临时pen并赋值给Pen属性,然后就会调用SetPen。
以上讨论也适用Brush,按照我说的修改,就不会有问题了。
这一句,不要这么使用,请这样使用,Pen.Assign(FPen)如果你一定坚持原先的用法,请这样处理
TempPen:=Pen;
Pen:=FPen;
....
Pen:=TempPen;
SetPen中也不能这样写
应当这样
FPen.Assign(value);
也不需要比较两个对象,只要判断是不是Value为空就可以了,要知道,TPen在程序加载的时候,会生成一个临时的Pen然后调用SetPen传递给你的Pen属性,很快这个临时对象就会释放。原因是TPen是一个Published属性,他会把这个对象(Pen)的属性保存到.dfm文件,编译完成后加载,是先按照pen属性生成临时pen并赋值给Pen属性,然后就会调用SetPen。
以上讨论也适用Brush,按照我说的修改,就不会有问题了。
begin
if FShape<>value then
begin
FShape:=value;
Invalidate; //强制新形状的重画
end;
end;
这一段也有问题,问题是,这个属性会比Pen属性或者Brush属性更早的赋值,这时候调用了Invalidate就会产生问题,因为Pen和Brush可能还没有建立,但是你在Create中已经建立了FPen应该不会有问题,Brush倒是有问题,怀疑,在inherited Create(Aowner);中可能调用了会产生Paint的过程,解决这个方法只有一个办法,就是在Panit的时候判断FBrush和FPen是不是nil如果不是就按照正常程序过去,如果有一个nil就什么也不做。
procedure TCell.Paint;
begin
with Canvas do
begin
//Pen:=FPen; 这里有问题
//Brush:=FBrush; 同上
case FShape of
sstRectangle,sstSquare:
Rectangle(0,0,Width,Height);
sstRoundRect,sstRoundSquare:
RoundRect(0,0,Width,Height,Width div 4,Height div 4);
sstCircle,sstEllipse:
Ellipse(0,0,width,Height);
end;
end;
end;可是我只能注释掉它,怎么能够实现我想要的功能?
难道我在constructor中创建了还不行?
这个paint在什么时候执行的?不在constructor之后吗?
其实对控件中包含子对象的赋值最好采用流的方式进行。
procedure TCell.SetShape(value:TCellType);
begin
if Assigned(Value) then
FShape.Assign(Value);
end;
另外Pen:=FPen; 这里有问题
Brush:=FBrush; 同上
你这两句简直是莫名奇妙,显得多余,本来FPen就是Pen的读方法