我试了一下,并没有错误。
贴些代码上来。你是如何使用TStrignGrid1的.

解决方案 »

  1.   

    声明这个类当然没有错误,但是如果调用这个函数就会出错了。
    在StringGrid1中inherited DrawCell(ACol, ARow, ARect, AState);
    调用的并不是TDrawGrid的成员DrawCell,而是调用的TStringGrid的成员(也就是自己本身),如是形成了一个递归死循环(呵呵,不知道是不是这样说,因为是只递了却没有归^_^),则无论把堆栈设多大,都会导致堆栈溢出!我的代码如下:
    unit StrGrid;interfaceuses
      Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
      Grids, Db, DBTables, ToolWin, ComCtrls, StdCtrls, Buttons;type
      TStringGrid1 = class(TStringGrid)
      procedure DrawCell(ACol, ARow: Integer;
          Rect: TRect; State: TGridDrawState);override;
      end;  TForm1 = class(TForm)
        ToolBar1: TToolBar;
        Table1: TTable;
        BitBtn1: TBitBtn;
        Button1: TButton;
        procedure FormCreate(Sender: TObject);
        procedure BitBtn1Click(Sender: TObject);
        procedure StringGrid1DrawCell(Sender: TObject; ACol, ARow: Integer;
          Rect: TRect; State: TGridDrawState);
        procedure Button1Click(Sender: TObject);
      private
        { Private declarations }
      public
        procedure datafresh;
        { Public declarations }
      end;var
      Form1: TForm1;
      StringGrid1:TStringGrid1;
      var n:integer;implementation{$R *.DFM}procedure TStringGrid1.DrawCell(ACol, ARow: Integer;
          Rect: TRect; State: TGridDrawState);
    begin  inherited DrawCell(ACol, ARow, Rect, State);
    end;
    procedure TForm1.FormCreate(Sender: TObject);
    begin
        n:=0;
        StringGrid1:=TStringGrid1.Create(Self);
        STringGrid1.Parent:=Self;
        with STringGrid1 do
        begin
        Left := 0;
        Top := 29;
        Width := 536;
        Height := 319;
        Align := alClient;
        DefaultColWidth := 40;
        DefaultRowHeight := 18;
        FixedCols := 2;
        Font.Charset := GB2312_CHARSET;
        Font.Color := clWindowText;
        Font.Height := -13;
        Font.Name := '宋体';
        Font.Style := [];
        ParentFont := False;
        TabOrder := 1;
        OnDrawCell := StringGrid1DrawCell;
        end;    ShortDateFormat:='yyyy-m-d';
        datafresh;
    end;procedure tform1.datafresh;
    var i,j,k:integer;
    begin
       table1.open;
       table1.First;
       k:=table1.FieldCount div 2;
       stringgrid1.ColCount:=k+2;
       stringgrid1.RowCount:=table1.RecordCount*2+1;
       stringgrid1.ColWidths[0]:=130;
       stringgrid1.ColWidths[1]:=38;
       for i:= 2 to table1.FieldCount+2 do
       stringgrid1.Cells[i,0]:='设备'+inttostr(i-1);
       for i:= 0 to table1.RecordCount-1 do
       begin
         stringgrid1.Cells[0,i*2+1]:=table1.Fields[0].AsString;
         stringgrid1.cells[1,i*2+1]:='重力:';
         stringgrid1.cells[1,i*2+2]:='水平:';
         for j:=1 to k do
            stringgrid1.Cells[j+1,i*2+1]:=table1.Fields[j].AsString;
         for j:=1 to k do
            stringgrid1.Cells[j+1,i*2+2]:=table1.Fields[j+k].AsString;
         table1.Next;
       end;
       table1.Close;
    end;procedure TForm1.BitBtn1Click(Sender: TObject);
    begin
        datafresh;
    end;procedure TForm1.StringGrid1DrawCell(Sender: TObject; ACol, ARow: Integer;
      Rect: TRect; State: TGridDrawState);
    var value:real;
    begin
         n:=n+1;
         if (ACol>=2) and ((ARow mod 2)=1) then
         begin
            value:=StrToFloat(stringgrid1.Cells[ACol,ARow]);
            if (value<2.0) or (value>4.0) then
            begin
                StringGrid1.Canvas.Font.Color:=clRed;
                StringGrid1.DrawCell(ACol,ARow,Rect,State);
            end;
         end;
    end;procedure TForm1.Button1Click(Sender: TObject);
    begin
       button1.Caption:=IntToStr(n);
    end;end.
    其中设置个n是为了检测究竟产生了多少次事件响应如果但是如果把StringGrid1DrawCell中调用DrawCell那一行去掉,就不会有错误,而且n值为网格数,但是调用了DrawCell后,堆栈溢出后,n成了天文数字,所以肯定是导致了一个递归的死循环,我认为必须要能够正确的调用到TDrawGrid(也就是TString1的两重祖先)的虚函数DrawCell才行!请各位大侠指教!
      

  2.   

    不要这样干,在TStringGrid的OnDrawCell中自己画。
    虚函数是没有实体的。
    或者看看DBGrid的source, 可能有启发。
      

  3.   

    你认为必须要能够正确的调用到TDrawGrid(也就是TString1的两重祖先)的
    虚函数DrawCell才行,我想那还是不行的死循环问题就出在下面两句
    OnDrawCell := StringGrid1DrawCell;
    然后你在StringGrid1DrawCell里调用了DrawCell。看如下源代码
    procedure TDrawGrid.DrawCell(ACol, ARow: Longint; ARect: TRect;
      AState: TGridDrawState);
    var
      Hold: Integer;
    begin
      if Assigned(FOnDrawCell) then
      begin
        if UseRightToLeftAlignment then
        begin
          ARect.Left := ClientWidth - ARect.Left;
          ARect.Right := ClientWidth - ARect.Right;
          Hold := ARect.Left;
          ARect.Left := ARect.Right;
          ARect.Right := Hold;
          ChangeGridOrientation(False);
        end;
        FOnDrawCell(Self, ACol, ARow, ARect, AState);
        if UseRightToLeftAlignment then ChangeGridOrientation(True); 
      end;
    end;当你调用DrawCell是,程序最终会走到TDrawGrid.DrawCell里,然后由于你
    分配了FOnDrawCell=StringGrid1DrawCell;所以进入了死循环。你的解救办法
    只能是自己在StringGrid1DrawCell里去画,我想不会很麻烦吧。另外一个问题
    (其实我的目的是要把TStringGrid的DrawCell在TStringGrid1中声明成public)
    如果你想在一个unit中调用一个存在于另一个unit中的类的protected成员时,
    只学要从新定义一个类就可以,他的protected成员函数不用重写成public,如
    TStringGrid1 = class(TStringGrid) ;就行了。
    这样,在这个unit里,你的TStringGrid1 的实体就可以直接调用TStringGrid
    的protected成员函数了,其实这是不符合面向对象编程的,但是Delphi可以
    这样做,说不上是缺点还是优点,反正当你用的着时用上去会感到很爽,xixi!
      

  4.   

    你怎么在OnDrawCell时又去DrawCell,岂不死掉!