我用了一个类来表示StringGrid的额外信息比如这样这样:
  TCellInfo = Class(TObject)
    CellName: Tstring;
    CellColor: TColor;
    CellFont : TFont;
  end;
   
   利用StringGrid的Objects属性指向他,然后就可以用
TCellInfo(StringGrid1.Objects[Col,Row]).CellName来访问额外属性了.
    但是绝大多数单元格的属性都是一样的,因此没必要为每个单元格都Create一个CellInfo;当没创建时,我希望能用缺省值来替代.
   当想要给某个单元格起个名字时就要这样做:
   if not assigned(StringGrid1.Objects[col,row]) then 
   begin
      CellInfo := TCellInfo.Create;
      StringGrid1.Objects[Col,Row] := CellInfo;
   end;
   TCellInfo(StringGrid1.objects[Col,Row]).CellName := 'abc';  真的很麻烦,我希望不管他是不是nil,都能直接用
  TCellInfo(StringGrid1.objects[Col,Row]).CellName := 'abc' ;
  TCellInfo(StringGrid1.objects[Col,Row]).CellColor := clWhite;
赋值;也就是把上面的Create包装起来,怎么才能做到?
   我想来想去都想不到有什么办法,只好都Create了,这样才能随意赋值而不出错,太浪费了。

解决方案 »

  1.   

    首先,你这种判断不会浪费什么cpu时间的!!如果你想做, 
    可以用个函数
     function SetCell(Col, Row: integer; val: string): boolean;
    ..
    将代码移到里面
    来操作,然后,你就可调用这个函数来设置!如果你想追求完美,你考虑用设计模式
     Flyweight
      

  2.   

    我是怕别人麻烦,我做的是控件。function SetCell(Col, Row: integer; val: string): boolean;我不能这样用,因为我是用指针的啊,这样就必须为Name,Color,Font分别写函数,我写起来麻烦没什么,就怕用起来麻烦。
      

  3.   

    interface
    uses Grids;
    type
      TCellInfo=class
      end;
      TMyGrid=class(TStringGrid)
      public
        procedure SetInfo(const Col,Row:integer;const Val:TCellInfo);
        function GetInfo(const Col,Row:integer):TCellInfo;
        property CellInfo[const Col,Row :integer]:TCellInfo read GetInfo write SetInfo;
      end;
    implementation{ TGrid }function TMyGrid.GetInfo(const Col, Row: integer): TCellInfo;
    begin
      if Objects[Col,Row]=nil then
         Objects[Col,Row]:=TCellInfo.Create;
      result:=TCellInfo(Objects[Col,Row]);
    end;procedure TMyGrid.SetInfo(const Col, Row: integer; const Val: TCellInfo);
    begin
      if  Objects[Col,Row]<>nil then
          Objects[Col,Row].Free;
      Objects[Col,Row]:=Val;
    end;
      

  4.   

    这样就可以以CellInfo属性直接访问TCellInfo对象了
      

  5.   

    这样无论你用
       CellInfo.Name := abc;
    还是
      AName := CellInfo.Name;
    调用的都是GetInfo,也就是都Create了.
      

  6.   

    可以考虑这样:
    Objects中的数组元素全部指向同一个缺省的TCellInfo对象.
    当修改TCellInfo的属性时,如果它是缺省对象,需要新建一个对象,再操作它.
      

  7.   

    这样无论你用
       CellInfo.Name := abc;
    还是
      AName := CellInfo.Name;
    调用的都是GetInfo那么我如何知道用户是读还是写呢?
    关键就是解决判断是读还是写的问题。
      

  8.   

    我个人的习惯是用一个动态数组(元素类型只是record,不用class)存储这些信息,在表格行列数改变时就全部创建好。这样比较省事。如果表格行列变动不频繁或者行数永远不会太多,甚至都用不到指针,直接用行列号做数组下标。
      

  9.   

    对了,在我上面说的个人做法中,如果不直接用行列号做数组下标,就用Objects属性记录下标,不能记录数组元素的地址,因为数组的地址在重新分配内存时会改变,
      

  10.   

    》我个人的习惯是用一个动态数组(元素类型只是record,不用class)存储这些信息,在表格行
    》列数改变时就全部创建好。这样比较省事。如果表格行列变动不频繁或者行数永远不会太
    》多,甚至都用不到指针,直接用行列号做数组下标。不同意你的说法。Record不可以加方法(成员函数)不加的话,直接对内存地址赋值,在Grid上看不到的,要刷新!》对了,在我上面说的个人做法中,如果不直接用行列号做数组下标,就用Objects属性记录
    》下标,不能记录数组元素的地址,因为数组的地址在重新分配内存时会改变,什么意思啊?我不明白,那岂不是不能用指针了?再说,如果用了数组,我记录下标来干什么?
      

  11.   

    miky(miky) :
    "在Grid上看不到的,要刷新!"
    当然是每次改动之后都要调用一下Invalidate,或者像你说的,再将需要显示的内容填入表格。(我觉得这是多余的浪费资源,实际上我根本不用StringGrid,用的是TDrawGrid)。“用了数组,我记录下标来干什么?”把数组的下标看作一种指针不行么? 为什么需要,因为视具体应用、程序写法,表格的行列不一定跟数组的元素顺序对应。我本来就声明这是“个人习惯”(这也说明当然是可行的。),仅供参考。不管如何,不该说什么“不同意”。
      

  12.   

    ImFool(搞技术的都是傻瓜)
    我说不同意,并没有贬低你的意思,也仅仅是我个人的看法,开了帖子,当然希望大家多来讨论,我一直都是尊敬回答问题的人的。
    之所以不同意你的看法,也只限于这个个例,因为我做的是控件,不希望把刷新的事情让给用户做。