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,按照我说的修改,就不会有问题了。

解决方案 »

  1.   

    procedure TCell.SetShape(value:TCellType);
    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就什么也不做。
      

  2.   

    找到问题所在:
    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之后吗?
      

  3.   

    同意 BlueTrees(蜗牛) 的看法
    其实对控件中包含子对象的赋值最好采用流的方式进行。
    procedure TCell.SetShape(value:TCellType);
    begin
      if Assigned(Value) then
           FShape.Assign(Value);
    end;
    另外Pen:=FPen;    这里有问题
        Brush:=FBrush;  同上
    你这两句简直是莫名奇妙,显得多余,本来FPen就是Pen的读方法
        
      

  4.   

    请在Create方法中显式调用一下Paint,因为它不会被控件自动调用的。