方法一:修改AdvStringGird的代码: 在unit AdvGrid中找到TopLeftChanged函数,然后修改为如下procedure TAdvStringGrid.TopLeftChanged; function CellRectEx(c,r: integer): TRect;//自己新增的CellRectEx函数 var r1, r2: TRect; BC, pSpan: TPoint; begin if HasCellProperties(c,r) then if (CellProperties[c,r].CellSpanX <> -1) or (CellProperties[c,r].CellSpanY <> -1) then begin BC := BaseCell(c,r); pSpan.X := CellProperties[BC.X,BC.Y].CellSpanX; pSpan.Y := CellProperties[BC.X,BC.Y].CellSpanY; if BC.X < LeftCol then begin pSpan.X := pSpan.X - (LeftCol - BC.X); BC.X := LeftCol; end; if BC.Y < TopRow then begin pSpan.Y := pSpan.Y - (TopRow - BC.Y); BC.Y := TopRow; end; r1 := GetCellRect(BC.X,BC.Y); r2 := GetCellRect(BC.X + pSpan.X,BC.Y + pSpan.Y); UnionRect(r1, r1, r2); Result := r1; end else Result := GetCellRect(c,r) else Result := GetCellRect(c,r); end; var i,j: Integer; r: TRect; ctrl: TControl; begin inherited TopLeftChanged; if (EditMode) and (EditControl <> edNormal) then HideInplaceEdit; UpdateVScrollBar; UpdateHScrollBar; UpdateFooter; for i := FOldLeftCol to FOldLeftCol + VisibleColCount do for j := FOldTopRow to FOldTopRow + VisibleRowCount do begin if (i < LeftCol) or (i > LeftCol + VisibleColCount) or (j < TopRow) or ( j > TopRow + VisibleRowCount) then begin ctrl := CellControls[i,j]; if Assigned(ctrl) then begin r := CellRect(i,j); ctrl.SetBounds(r.Left,r.Top,0,0); end; end; end; for i := LeftCol to LeftCol + VisibleColCount do for j := TopRow to TopRow + VisibleRowCount do begin ctrl := CellControls[i,j]; if Assigned(ctrl) then begin r := CellRectEx(i,j);//修改成自己加的CellRectEx ctrl.SetBounds(r.Left,r.Top,r.Right - r.Left,r.Bottom - r.Top); end; end; FOldLeftCol := LeftCol; FOldTopRow := TopRow; end;方法二,继承TAdvStringGrid,全部代码如下,但是,不知为啥,继承后的控件就是不执行我重载的函数TopLeftChanged;有高手在的话也帮忙看下为什么,觉得继承TAdvStringGrid的方式比较好,不会修改到TAdvStringGrid的源码。unit Unit1;interfaceuses Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms, Dialogs, Grids, BaseGrid, AdvGrid, StdCtrls, ExtCtrls;type TMyAdvStringGrid = class(TAdvStringGrid) private protected procedure TopLeftChanged; reintroduce; public constructor Create(AOwner:TComponent); override; end; TForm1 = class(TForm) Button1: TButton; AdvStringGrid1: TAdvStringGrid; Panel1: TPanel; Edit1: TEdit; Panel2: TPanel; procedure FormCreate(Sender: TObject); procedure FormDestroy(Sender: TObject); private { Private declarations } MyAdvStringGrid1: TAdvStringGrid; public { Public declarations } end;var Form1: TForm1;implementation{$R *.dfm}procedure TForm1.FormCreate(Sender: TObject); var i: integer; begin MyAdvStringGrid1 := TAdvStringGrid.Create(Self); MyAdvStringGrid1.Parent := Self; MyAdvStringGrid1.SetBounds(100, 100, 680, 200); MyAdvStringGrid1.DefaultColWidth := 30; MyAdvStringGrid1.ColCount := 30; for i := 1 to AdvStringGrid1.RowCount - 1 do MyAdvStringGrid1.Cells[0, i] := IntToStr(i); for i := 1 to AdvStringGrid1.ColCount - 1 do MyAdvStringGrid1.Cells[i, 0] := IntToStr(i); Panel1.Parent := MyAdvStringGrid1; MyAdvStringGrid1.MergeCells(1, 1, 10, 1); MyAdvStringGrid1.CellControls[10, 1] := Panel1; AdvStringGrid1.MergeCells(1, 1, 10, 1); AdvStringGrid1.CellControls[10, 1] := Panel2; for i := 1 to AdvStringGrid1.ColCount - 1 do AdvStringGrid1.Cells[i, 0] := IntToStr(i); end;{ TMyAdvStringGrid }constructor TMyAdvStringGrid.Create(AOwner: TComponent); begin inherited Create(AOwner); end;procedure TMyAdvStringGrid.TopLeftChanged; function CellRectEx(c,r: integer): TRect; var r1, r2: TRect; BC, pSpan: TPoint; begin if IsMergedCell(c,r) then begin BC := BaseCell(c,r); pSpan := CellSpan(c, r); if BC.X < LeftCol then begin pSpan.X := pSpan.X - (LeftCol - BC.X); BC.X := LeftCol; end; if BC.Y < TopRow then begin pSpan.Y := pSpan.Y - (TopRow - BC.Y); BC.Y := TopRow; end; r1 := GetCellRect(BC.X,BC.Y); r2 := GetCellRect(BC.X + pSpan.X,BC.Y + pSpan.Y); UnionRect(r1, r1, r2); Result := r1; end else Result := GetCellRect(c,r); end; var i,j: Integer; r: TRect; ctrl: TControl; begin inherited TopLeftChanged; for i := LeftCol to LeftCol + VisibleColCount do for j := TopRow to TopRow + VisibleRowCount do begin ctrl := CellControls[i,j]; if Assigned(ctrl) then begin r := CellRectEx(i,j); ctrl.SetBounds(r.Left,r.Top,r.Right - r.Left,r.Bottom - r.Top); end; end; end;procedure TForm1.FormDestroy(Sender: TObject); begin if Assigned(MyAdvStringGrid1) then FreeAndNil(MyAdvStringGrid1); end;end.
方法二可以了,不用修改AdvStringGrid的源码来了,代码如下: unit Unit1;interfaceuses Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms, Dialogs, Grids, BaseGrid, AdvGrid, StdCtrls, ExtCtrls;type TMyAdvStringGrid = class(TAdvStringGrid) private protected procedure TopLeftChanged; override; public constructor Create(AOwner:TComponent); override; end; TForm1 = class(TForm) Button1: TButton; AdvStringGrid1: TAdvStringGrid; Panel1: TPanel; Edit1: TEdit; Panel2: TPanel; procedure FormCreate(Sender: TObject); procedure FormDestroy(Sender: TObject); private { Private declarations } MyAdvStringGrid1: TMyAdvStringGrid; public { Public declarations } end;var Form1: TForm1;implementation{$R *.dfm}procedure TForm1.FormCreate(Sender: TObject); var i: integer; begin MyAdvStringGrid1 := TMyAdvStringGrid.Create(Self); MyAdvStringGrid1.Parent := Self; MyAdvStringGrid1.SetBounds(100, 100, 680, 200); MyAdvStringGrid1.DefaultColWidth := 30; MyAdvStringGrid1.ColCount := 30; for i := 1 to MyAdvStringGrid1.RowCount - 1 do MyAdvStringGrid1.Cells[0, i] := IntToStr(i); for i := 1 to MyAdvStringGrid1.ColCount - 1 do MyAdvStringGrid1.Cells[i, 0] := IntToStr(i); Panel1.Parent := MyAdvStringGrid1; MyAdvStringGrid1.MergeCells(1, 1, 10, 1); MyAdvStringGrid1.CellControls[10, 1] := Panel1; AdvStringGrid1.MergeCells(1, 1, 10, 1); AdvStringGrid1.CellControls[10, 1] := Panel2; for i := 1 to AdvStringGrid1.RowCount - 1 do MyAdvStringGrid1.Cells[0, i] := IntToStr(i); for i := 1 to AdvStringGrid1.ColCount - 1 do AdvStringGrid1.Cells[i, 0] := IntToStr(i); end;{ TMyAdvStringGrid }constructor TMyAdvStringGrid.Create(AOwner: TComponent); begin inherited Create(AOwner); end;procedure TMyAdvStringGrid.TopLeftChanged; function CellRectEx(c,r: integer): TRect; var r1, r2: TRect; BC, pSpan: TPoint; begin if IsMergedCell(c,r) then begin BC := BaseCell(c,r); pSpan := CellSpan(c, r); if BC.X < LeftCol then begin pSpan.X := pSpan.X - (LeftCol - BC.X); BC.X := LeftCol; end; if BC.Y < TopRow then begin pSpan.Y := pSpan.Y - (TopRow - BC.Y); BC.Y := TopRow; end; r1 := GetCellRect(BC.X,BC.Y); r2 := GetCellRect(BC.X + pSpan.X,BC.Y + pSpan.Y); UnionRect(r1, r1, r2); Result := r1; end else Result := GetCellRect(c,r); end; var i,j: Integer; r: TRect; ctrl: TControl; begin inherited TopLeftChanged; for i := LeftCol to LeftCol + VisibleColCount do for j := TopRow to TopRow + VisibleRowCount do begin ctrl := CellControls[i,j]; if Assigned(ctrl) then begin r := CellRectEx(i,j); ctrl.SetBounds(r.Left,r.Top,r.Right - r.Left,r.Bottom - r.Top); end; end; end;procedure TForm1.FormDestroy(Sender: TObject); begin if Assigned(MyAdvStringGrid1) then FreeAndNil(MyAdvStringGrid1); end;end.
我想知道你放那个Panel的用意是什么?
AdvStringGrid1.MergeCells(1, 1, 10, 1);
AdvStringGrid1.CellControls[1, 1] := Panel1;如果不用Controls这个属性,应该有其他办法能实现你要的功能。
我想在panel1上搭载60*3=180个listbox,系统共需14个panel共2520个listbox
其实AdvStringGrid每个cell对应一个listbox是最好的,但这样会有两个问题
1.会把listbox的拖拽事件屏蔽掉,而我恰好需要拖拽功能
2.AdvStringGrid每个cell对应一个listbox系统花销太大,初始化就需要1分钟,拖动出现显示断裂现象
而先在AdvStringGrid上放置panel再在panel上放listbox则能解决这两个问题,可又出现了刚才说的panel挡住advstringgrid的问题,也是最后一个没解决的问题了~
只是需要自己处理滚动
那你可以每个Panel搭载一个ListBox是试下,不要搭载3个;不过这样真的很耗内存,严重影响性能;我是觉得可以不用Panel和ListBox,可以用AdvStringGrid的重画功能可以实现你的功能。
方法一:修改AdvStringGird的代码:
在unit AdvGrid中找到TopLeftChanged函数,然后修改为如下procedure TAdvStringGrid.TopLeftChanged;
function CellRectEx(c,r: integer): TRect;//自己新增的CellRectEx函数
var
r1, r2: TRect;
BC, pSpan: TPoint;
begin
if HasCellProperties(c,r) then
if (CellProperties[c,r].CellSpanX <> -1) or (CellProperties[c,r].CellSpanY <> -1) then
begin
BC := BaseCell(c,r);
pSpan.X := CellProperties[BC.X,BC.Y].CellSpanX;
pSpan.Y := CellProperties[BC.X,BC.Y].CellSpanY;
if BC.X < LeftCol then
begin
pSpan.X := pSpan.X - (LeftCol - BC.X);
BC.X := LeftCol;
end;
if BC.Y < TopRow then
begin
pSpan.Y := pSpan.Y - (TopRow - BC.Y);
BC.Y := TopRow;
end;
r1 := GetCellRect(BC.X,BC.Y);
r2 := GetCellRect(BC.X + pSpan.X,BC.Y + pSpan.Y); UnionRect(r1, r1, r2);
Result := r1;
end
else
Result := GetCellRect(c,r)
else
Result := GetCellRect(c,r);
end;
var
i,j: Integer;
r: TRect;
ctrl: TControl;
begin
inherited TopLeftChanged;
if (EditMode) and (EditControl <> edNormal) then
HideInplaceEdit;
UpdateVScrollBar;
UpdateHScrollBar;
UpdateFooter; for i := FOldLeftCol to FOldLeftCol + VisibleColCount do
for j := FOldTopRow to FOldTopRow + VisibleRowCount do
begin
if (i < LeftCol) or (i > LeftCol + VisibleColCount) or
(j < TopRow) or ( j > TopRow + VisibleRowCount) then
begin
ctrl := CellControls[i,j];
if Assigned(ctrl) then
begin
r := CellRect(i,j);
ctrl.SetBounds(r.Left,r.Top,0,0);
end;
end;
end; for i := LeftCol to LeftCol + VisibleColCount do
for j := TopRow to TopRow + VisibleRowCount do
begin
ctrl := CellControls[i,j];
if Assigned(ctrl) then
begin
r := CellRectEx(i,j);//修改成自己加的CellRectEx
ctrl.SetBounds(r.Left,r.Top,r.Right - r.Left,r.Bottom - r.Top);
end;
end; FOldLeftCol := LeftCol;
FOldTopRow := TopRow;
end;方法二,继承TAdvStringGrid,全部代码如下,但是,不知为啥,继承后的控件就是不执行我重载的函数TopLeftChanged;有高手在的话也帮忙看下为什么,觉得继承TAdvStringGrid的方式比较好,不会修改到TAdvStringGrid的源码。unit Unit1;interfaceuses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, Grids, BaseGrid, AdvGrid, StdCtrls, ExtCtrls;type
TMyAdvStringGrid = class(TAdvStringGrid)
private
protected
procedure TopLeftChanged; reintroduce;
public
constructor Create(AOwner:TComponent); override;
end; TForm1 = class(TForm)
Button1: TButton;
AdvStringGrid1: TAdvStringGrid;
Panel1: TPanel;
Edit1: TEdit;
Panel2: TPanel;
procedure FormCreate(Sender: TObject);
procedure FormDestroy(Sender: TObject);
private
{ Private declarations }
MyAdvStringGrid1: TAdvStringGrid;
public
{ Public declarations }
end;var
Form1: TForm1;implementation{$R *.dfm}procedure TForm1.FormCreate(Sender: TObject);
var
i: integer;
begin
MyAdvStringGrid1 := TAdvStringGrid.Create(Self);
MyAdvStringGrid1.Parent := Self;
MyAdvStringGrid1.SetBounds(100, 100, 680, 200);
MyAdvStringGrid1.DefaultColWidth := 30;
MyAdvStringGrid1.ColCount := 30;
for i := 1 to AdvStringGrid1.RowCount - 1 do
MyAdvStringGrid1.Cells[0, i] := IntToStr(i);
for i := 1 to AdvStringGrid1.ColCount - 1 do
MyAdvStringGrid1.Cells[i, 0] := IntToStr(i); Panel1.Parent := MyAdvStringGrid1;
MyAdvStringGrid1.MergeCells(1, 1, 10, 1);
MyAdvStringGrid1.CellControls[10, 1] := Panel1; AdvStringGrid1.MergeCells(1, 1, 10, 1);
AdvStringGrid1.CellControls[10, 1] := Panel2;
for i := 1 to AdvStringGrid1.ColCount - 1 do
AdvStringGrid1.Cells[i, 0] := IntToStr(i);
end;{ TMyAdvStringGrid }constructor TMyAdvStringGrid.Create(AOwner: TComponent);
begin
inherited Create(AOwner);
end;procedure TMyAdvStringGrid.TopLeftChanged;
function CellRectEx(c,r: integer): TRect;
var
r1, r2: TRect;
BC, pSpan: TPoint;
begin
if IsMergedCell(c,r) then
begin
BC := BaseCell(c,r);
pSpan := CellSpan(c, r);
if BC.X < LeftCol then
begin
pSpan.X := pSpan.X - (LeftCol - BC.X);
BC.X := LeftCol;
end;
if BC.Y < TopRow then
begin
pSpan.Y := pSpan.Y - (TopRow - BC.Y);
BC.Y := TopRow;
end;
r1 := GetCellRect(BC.X,BC.Y);
r2 := GetCellRect(BC.X + pSpan.X,BC.Y + pSpan.Y); UnionRect(r1, r1, r2);
Result := r1;
end
else
Result := GetCellRect(c,r);
end;
var
i,j: Integer;
r: TRect;
ctrl: TControl;
begin
inherited TopLeftChanged; for i := LeftCol to LeftCol + VisibleColCount do
for j := TopRow to TopRow + VisibleRowCount do
begin
ctrl := CellControls[i,j]; if Assigned(ctrl) then
begin
r := CellRectEx(i,j);
ctrl.SetBounds(r.Left,r.Top,r.Right - r.Left,r.Bottom - r.Top);
end;
end;
end;procedure TForm1.FormDestroy(Sender: TObject);
begin
if Assigned(MyAdvStringGrid1) then
FreeAndNil(MyAdvStringGrid1);
end;end.
unit Unit1;interfaceuses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, Grids, BaseGrid, AdvGrid, StdCtrls, ExtCtrls;type
TMyAdvStringGrid = class(TAdvStringGrid)
private
protected
procedure TopLeftChanged; override;
public
constructor Create(AOwner:TComponent); override;
end; TForm1 = class(TForm)
Button1: TButton;
AdvStringGrid1: TAdvStringGrid;
Panel1: TPanel;
Edit1: TEdit;
Panel2: TPanel;
procedure FormCreate(Sender: TObject);
procedure FormDestroy(Sender: TObject);
private
{ Private declarations }
MyAdvStringGrid1: TMyAdvStringGrid;
public
{ Public declarations }
end;var
Form1: TForm1;implementation{$R *.dfm}procedure TForm1.FormCreate(Sender: TObject);
var
i: integer;
begin
MyAdvStringGrid1 := TMyAdvStringGrid.Create(Self);
MyAdvStringGrid1.Parent := Self;
MyAdvStringGrid1.SetBounds(100, 100, 680, 200);
MyAdvStringGrid1.DefaultColWidth := 30;
MyAdvStringGrid1.ColCount := 30;
for i := 1 to MyAdvStringGrid1.RowCount - 1 do
MyAdvStringGrid1.Cells[0, i] := IntToStr(i);
for i := 1 to MyAdvStringGrid1.ColCount - 1 do
MyAdvStringGrid1.Cells[i, 0] := IntToStr(i); Panel1.Parent := MyAdvStringGrid1;
MyAdvStringGrid1.MergeCells(1, 1, 10, 1);
MyAdvStringGrid1.CellControls[10, 1] := Panel1; AdvStringGrid1.MergeCells(1, 1, 10, 1);
AdvStringGrid1.CellControls[10, 1] := Panel2;
for i := 1 to AdvStringGrid1.RowCount - 1 do
MyAdvStringGrid1.Cells[0, i] := IntToStr(i);
for i := 1 to AdvStringGrid1.ColCount - 1 do
AdvStringGrid1.Cells[i, 0] := IntToStr(i);
end;{ TMyAdvStringGrid }constructor TMyAdvStringGrid.Create(AOwner: TComponent);
begin
inherited Create(AOwner);
end;procedure TMyAdvStringGrid.TopLeftChanged;
function CellRectEx(c,r: integer): TRect;
var
r1, r2: TRect;
BC, pSpan: TPoint;
begin
if IsMergedCell(c,r) then
begin
BC := BaseCell(c,r);
pSpan := CellSpan(c, r);
if BC.X < LeftCol then
begin
pSpan.X := pSpan.X - (LeftCol - BC.X);
BC.X := LeftCol;
end;
if BC.Y < TopRow then
begin
pSpan.Y := pSpan.Y - (TopRow - BC.Y);
BC.Y := TopRow;
end;
r1 := GetCellRect(BC.X,BC.Y);
r2 := GetCellRect(BC.X + pSpan.X,BC.Y + pSpan.Y); UnionRect(r1, r1, r2);
Result := r1;
end
else
Result := GetCellRect(c,r);
end;
var
i,j: Integer;
r: TRect;
ctrl: TControl;
begin
inherited TopLeftChanged; for i := LeftCol to LeftCol + VisibleColCount do
for j := TopRow to TopRow + VisibleRowCount do
begin
ctrl := CellControls[i,j]; if Assigned(ctrl) then
begin
r := CellRectEx(i,j);
ctrl.SetBounds(r.Left,r.Top,r.Right - r.Left,r.Bottom - r.Top);
end;
end;
end;procedure TForm1.FormDestroy(Sender: TObject);
begin
if Assigned(MyAdvStringGrid1) then
FreeAndNil(MyAdvStringGrid1);
end;end.