在Delphi中一个派生类如何调用前两重祖先的虚函数? 我试了一下,并没有错误。贴些代码上来。你是如何使用TStrignGrid1的. 解决方案 » 免费领取超大流量手机卡,每月29元包185G流量+100分钟通话, 中国电信官方发货 声明这个类当然没有错误,但是如果调用这个函数就会出错了。在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才行!请各位大侠指教! 不要这样干,在TStringGrid的OnDrawCell中自己画。虚函数是没有实体的。或者看看DBGrid的source, 可能有启发。 你认为必须要能够正确的调用到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! 你怎么在OnDrawCell时又去DrawCell,岂不死掉! 把SQL连接到delphi TreeView关于复选框 请解释一个这个函数定义. 請問如何得到鍵盤按下的動作? 档案传输要怎么做? 请教快速搜索数组的字符串的方法 安装新控件的疑问,在线求救!!!!! 请教怎样读取数据库服务器的主机名称?100分! 急!!!提示“服务器URL错误”是怎么回事? 蔡鸟问题 如何实现WINDOWS风格的文件拷贝功能?(显示拷贝进度) 请问:进行MIDAS开发时,数据处理最好在那边写最好?
在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才行!请各位大侠指教!
虚函数是没有实体的。
或者看看DBGrid的source, 可能有启发。
虚函数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!