DBGrid怎样实现自适应列宽,找过一些代码,可是都不如意
DBGrid怎样实现自适应列宽,找过一些代码,可是都不如意 问题点数:100、回复次数:42Top
1 楼daydayup234(关中刀客)回复于 2006-07-14 10:59:20 得分 50
void __fastcall Tdo_plan_::FormShow(TObject *Sender)
//让好几个Show和OnResize事件“定位”到这个
{
int I;
TComponent *Temp;
for(I=ComponentCount-1;I>=0;I--)
{
Temp=Components[I];
if(dynamic_cast<TDBGrid *>(Temp)!=NULL)
{
TDBGrid* dgrid=(TDBGrid *)(Temp);
TADOQuery *dset=(TADOQuery *)dgrid->DataSource->DataSet;
int count,fontSize,k;
count=dgrid->Columns->Count;
fontSize=dgrid->Font->Size;
k=count;
while(k-->0)
dset->Fields->Fields[k]->DisplayWidth=(dgrid->ClientWidth)/(count+1)/fontSize;
//因为取整的缘故,让 “列”数多1个
}
}
}Top
2 楼558047(三个代表万睡!八荣八耻万睡!)回复于 2006-07-14 11:02:35 得分 0
//让好几个Show和OnResize事件“定位”到这个
这句话是什么意思?Top
3 楼daydayup234(关中刀客)回复于 2006-07-14 11:14:33 得分 0
这个注释别介意
代码采自我的一个应用
那个释别自己看的与本贴无关
你先试代码Top
4 楼558047(三个代表万睡!八荣八耻万睡!)回复于 2006-07-14 11:20:15 得分 0
这段代码是要放在FormShow中么?我怎么编译通过,运行却出错呢?
我的意思是:DBGrid的某一列的宽度随着它内容长度的增减而相应增减
假设这个列目前最长的内容是5个汉字时,那么就让它有5个汉字那么宽Top
5 楼daydayup234(关中刀客)回复于 2006-07-14 11:45:36 得分 0
我的代码运行正常
你编译出错信息贴出来看看Top
6 楼558047(三个代表万睡!八荣八耻万睡!)回复于 2006-07-14 11:51:27 得分 0
执行到TADOQuery *dset=(TADOQuery *)dgrid->DataSource->DataSet;时出错
提示:Access violation at address 00401D74 in module 'Project1.exe'Top
7 楼daydayup234(关中刀客)回复于 2006-07-14 11:56:31 得分 0
你的所有dbgrid事先要连接好数据,而且要是TADOQuery的数据集
因为我的应用数据集合全用了TADOQuery,没有用TADOtable
也没有用BDE数据集合连dbgrid.
要完全用我的代码,适当得改改Top
8 楼558047(三个代表万睡!八荣八耻万睡!)回复于 2006-07-14 12:40:46 得分 0
刀客
我有这样几个疑问,探讨一下:
int I;
TComponent *Temp;
for(I=ComponentCount-1;I>=0;I--)
{
Temp=Components[I];
这段代码是遍历Form上的所有控件的吧,我发现它把所有的控件都遍历了一遍。能不能筛选只遍历DBGrid?
还有,dbgrid事先要连接好数据,是必须要在设计期连接还是也可以在这段代码执行之前用代码连接?Top
9 楼558047(三个代表万睡!八荣八耻万睡!)回复于 2006-07-14 13:13:34 得分 0
AnsiString strSql;
strSql="select * from MouldInfoH";
frmDm->qryDbgm->Close();
frmDm->qryDbgm->SQL->Clear();
frmDm->qryDbgm->SQL->Add(strSql);
frmDm->qryDbgm->Open();
//DBGrid自适应列宽
TADOQuery *dset=(TADOQuery *)dbgMouldH->DataSource->DataSet;
int count,fontSize,k;
count=dbgMouldH->Columns->Count;
fontSize=dbgMouldH->Font->Size;
k=count;
while(k-->0)
dset->Fields->Fields[k]->DisplayWidth=(dbgMouldH->ClientWidth)/(count+1)/fontSize;Top
10 楼558047(三个代表万睡!八荣八耻万睡!)回复于 2006-07-14 13:14:06 得分 0
上面这段代码顺利执行,可是就是没有效果,列宽还是不变Top
11 楼daydayup234(关中刀客)回复于 2006-07-14 13:29:26 得分 0
回答你短消息:
1 遍历:只有这办法遍历所有TDBGrid,是得针对TComponent判别。
2 关于连接:是事先连好。
3 效果:我从新看了,还得
OnResize事件“定位”到这个事件上
如果这个“定位”你不熟:
代码复制一份进入窗得OnResize事件Top
12 楼BlueDeepOcean(蓝色·深海)回复于 2006-07-14 13:38:36 得分 0
搅和一哈!Top
13 楼daydayup234(关中刀客)回复于 2006-07-14 13:42:36 得分 0
//---------------------------------------------------------------------------
void __fastcall TForm1::Button1Click(TObject *Sender)
{
ADOTable1->Open();
int count,fontSize,k;
count=DBGrid1->Columns->Count;
fontSize=DBGrid1->Font->Size;
k=count;
while(k-->0)
DBGrid1->DataSource->DataSet->Fields->Fields[k]->DisplayWidth=
(DBGrid1->ClientWidth)/(count+1)/fontSize;
}
//---------------------------------------------------------------------------
干脆不遍历了,专门重新写代码给你
__published: // IDE-managed Components
TADOConnection *ADOConnection1;
TADOTable *ADOTable1;
TDataSource *DataSource1;
TDBGrid *DBGrid1;
TButton *Button1;
void __fastcall Button1Click(TObject *Sender);
这下一点没问题,刚实验Top
14 楼BlueDeepOcean(蓝色·深海)回复于 2006-07-14 14:15:56 得分 50
出于人道主义救援的原则,我也给你一个,虽然不比楼上精简,但直观易懂。
//---------------------------------------------------------------------------
#include <vcl.h>
#pragma hdrstop
#include "Unit1.h"
//---------------------------------------------------------------------------
#pragma package(smart_init)
#pragma resource "*.dfm"
TForm1 *Form1;
//---------------------------------------------------------------------------
__fastcall TForm1::TForm1(TComponent* Owner)
: TForm(Owner)
{
int mWth = 0;
for (int c = 0;c < DBGrid1->Columns->Count;c ++)
{
ADOTable1->First();
while(!ADOTable1->Eof)
{
switch(DBGrid1->Columns->Items[c]->Index)
{
case 0:
if (mWth <= AnsiString(DBGrid1->Fields[DBGrid1->Columns->Items[c]->Index]->AsString).Length() * 6)
mWth = AnsiString(DBGrid1->Fields[DBGrid1->Columns->Items[c]->Index]->AsString).Length() * 6;
DBGrid1->Columns->Items[DBGrid1->Columns->Items[c]->Index]->Width = mWth;
break;
case 1:
if (mWth <= AnsiString(DBGrid1->Fields[DBGrid1->Columns->Items[c]->Index]->AsInteger).Length() * 6)
mWth = AnsiString(DBGrid1->Fields[DBGrid1->Columns->Items[c]->Index]->AsInteger).Length() * 6;
DBGrid1->Columns->Items[DBGrid1->Columns->Items[c]->Index]->Width = mWth;
break;
case 2:
if (mWth <= AnsiString(DBGrid1->Fields[DBGrid1->Columns->Items[c]->Index]->AsFloat).Length() * 6)
mWth = AnsiString(DBGrid1->Fields[DBGrid1->Columns->Items[c]->Index]->AsFloat).Length() * 6;
DBGrid1->Columns->Items[DBGrid1->Columns->Items[c]->Index]->Width = mWth;
break;
}
ADOTable1->Next();
}
}
}
//---------------------------------------------------------------------------Top
15 楼558047(三个代表万睡!八荣八耻万睡!)回复于 2006-07-14 14:27:18 得分 0
目前我的这个窗体上有几个DBGrid,目前要求DBGrid和数据库连接,必须要用代码动态实现,不能在设计期作静态连接。而且每个DBGrid都对应一个查询按钮,当每次查询结果不同时,它的列宽要随之而变化。
而这时Form的ReSize事件并没有发生
如果是这种情况,我觉得你的这段代码肯定就不适应了Top
16 楼daydayup234(关中刀客)回复于 2006-07-14 14:33:41 得分 0
我早前地代码放进ReSize事件,
最小化最大化切换一下看效果Top
17 楼558047(三个代表万睡!八荣八耻万睡!)回复于 2006-07-14 15:23:12 得分 0
我新建了一个工程,窗体上只放了一个ADOConnection,ADOQuery,DataSoure,Button
void __fastcall TForm1::Button1Click(TObject *Sender)
{
ADOQuery1->Close();
ADOQuery1->SQL->Clear();
ADOQuery1->SQL->Add("select * from MouldInfoH");
ADOQuery1->Open();
TADOQuery *dset=(TADOQuery *)DBGrid1->DataSource->DataSet;
int count,fontSize,k;
count=DBGrid1->Columns->Count;
fontSize=DBGrid1->Font->Size;
k=count;
while(k-->0)
dset->Fields->Fields[k]->DisplayWidth=(DBGrid1->ClientWidth)/(count+1)/fontSize;
}
//---------------------------------------------------------------------------
Top
18 楼daydayup234(关中刀客)回复于 2006-07-14 15:26:58 得分 0
你 ShowMessage看看,
应该没问题吧Top
19 楼558047(三个代表万睡!八荣八耻万睡!)回复于 2006-07-14 15:30:24 得分 0
while(k-->0)
{
dset->Fields->Fields[k]->DisplayWidth=(DBGrid1->ClientWidth)/(count+1)/fontSize;
ShowMessage(dset->Fields->Fields[k]->DisplayWidth);
}
每次ShowMessage都是1Top
20 楼daydayup234(关中刀客)回复于 2006-07-14 15:32:24 得分 0
void __fastcall TForm1::Button1Click(TObject *Sender)
{
ADOQuery1->Close();
ADOQuery1->SQL->Clear();
ADOQuery1->SQL->Add("select * from myTable");
ADOQuery1->Open();
TADOQuery *dset=(TADOQuery *)DBGrid1->DataSource->DataSet;
int count,fontSize,k;
count=DBGrid1->Columns->Count;
fontSize=DBGrid1->Font->Size;
k=count;
while(k-->0)
dset->Fields->Fields[k]->DisplayWidth=
(DBGrid1->ClientWidth)/(count+1)/fontSize;
}
好着,
你将窗题大小改改,再按button可看出效果Top
21 楼558047(三个代表万睡!八荣八耻万睡!)回复于 2006-07-14 15:35:08 得分 0
还是老样子,一点都没有变Top
22 楼daydayup234(关中刀客)回复于 2006-07-14 15:36:31 得分 0
你库里加几条记录看看Top
23 楼558047(三个代表万睡!八荣八耻万睡!)回复于 2006-07-14 15:43:08 得分 0
哥们,还是不行啊,我估计根数据库不应该有关系阿Top
24 楼daydayup234(关中刀客)回复于 2006-07-14 15:47:25 得分 0
要不
TADOQuery *dset=(TADOQuery *)DBGrid1->DataSource->DataSet;
加括号
TADOQuery *dset=(TADOQuery *)(DBGrid1->DataSource->DataSet);
看看Top
25 楼558047(三个代表万睡!八荣八耻万睡!)回复于 2006-07-14 15:52:54 得分 0
涛声依旧,还是不行Top
26 楼BlueDeepOcean(蓝色·深海)回复于 2006-07-14 16:01:52 得分 0
怎么这么麻烦呢?Top
27 楼keiy()回复于 2006-07-14 16:23:28 得分 0
EHLIB控件的DBGridEH就有这个功能,你可以直接用它,也可参考它的源码
Top
28 楼wxch(wxch)回复于 2006-07-14 21:23:36 得分 0
看看Top
29 楼558047(三个代表万睡!八荣八耻万睡!)回复于 2006-07-19 14:26:05 得分 0
EHLIB控件的DBGridEH就有这个功能,你可以直接用它,也可参考它的源码
除了这个,没有别的办法了么?Top
30 楼zhanghui6868_ln()回复于 2006-07-19 18:37:24 得分 0
procedure SetDBGridColumnsWidth(DBGridName:TDBGrid);
var
jsq,maxWidth:integer;
begin
DBGridName.DataSource.Dataset.DisableControls;
for jsq:=0 to DBGridName.Columns.Count-1 do
begin
DBGridName.DataSource.Dataset.First;
maxWidth:=DBGridName.Canvas.TextWidth(trim(DBGridName.Columns[jsq].Title.Caption));
while not DBGridName.DataSource.Dataset.Eof do
begin
if maxWidth<DBGridName.Canvas.TextWidth(trim(DBGridName.DataSource.Dataset.fieldbyname(DBGridName.Columns[jsq].FieldName).AsString)) then
maxWidth:=DBGridName.Canvas.TextWidth(trim(DBGridName.DataSource.Dataset.fieldbyname(DBGridName.Columns[jsq].FieldName).AsString))
else
DBGridName.DataSource.Dataset.Next;
end;
DBGridName.Columns[jsq].Width:=maxWidth+5;
end;
DBGridName.DataSource.Dataset.EnableControls;
end;
Top
31 楼SmallMaker(小人物)回复于 2006-07-19 18:47:04 得分 0
建议使用dbgridehTop
32 楼erhan(二憨)回复于 2006-07-19 19:39:18 得分 0
整个label,visible设为false,autoresize设为true;字体设成跟dbgrid的字体一样(包括大小)
dbgrid一列从头扫到尾,扫的过程中不断从当前行的这一列取出值赋给label.caption,并记录一列扫描过程的label.width的最大值
把最大值赋给dbgrid该列的width属性。Top
33 楼jjwwang((空园歌独酌,春日赋闲居))回复于 2006-07-19 19:59:47 得分 0
晕.移到这来了.Top
34 楼yjbnew(伟大的光荣的正确的ASP千岁千岁千千岁)回复于 2006-07-19 20:38:38 得分 0
DBGridEH 有这个功能吗,我怎么没有发现?Top
35 楼photo2000(死胖子)回复于 2006-07-19 23:27:36 得分 0
我也没有发现啊,在那里设置Top
36 楼keiy()回复于 2006-07-20 11:08:11 得分 0
DBGridEH有两种方式自适应宽度
1.设AutoFitColWidths=true;
它的列宽会跟据整个Grid的宽度自动调整
且每一列(TColumnEh)都有AutoFitColWidth属性,设为true,该列宽度自动调整
2.OptionsEh中有dghDblClickOptimizeColWidth,当双击表缝时,前一列按当前数据宽度自动调整宽度(与Excel中功能相同)
你可以参看它的源码,看它如何实现的
Top
37 楼whbo(王红波(年轻人,要有所作为))回复于 2006-07-21 10:03:30 得分 0
procedure FixDBGridColumnsWidth(const DBGrid: TDBGrid);
var
i: integer;
TotWidth: integer; //定义整个宽度
VarWidth: integer; //定义变化的宽度
ResizableColumnCount: integer; //定义变化宽度列的总数
AColumn: TColumn;
begin
//在重新调整前所有列的宽度
TotWidth := 0;
VarWidth := 0;
//有多少列需要自动调整
ResizableColumnCount := 0;
for i := 0 to -1 + DBGrid.Columns.Count do
begin
TotWidth := TotWidth + DBGrid.Columns[i].Width;
if DBGrid.Columns[i].Field.Tag <> 0 then
Inc(ResizableColumnCount);
end;
//为每个列分隔线增加1PX
if dgColLines in DBGrid.Options then
TotWidth := TotWidth + DBGrid.Columns.Count;
if dgIndicator in DBGrid.Options then
VarWidth := DBGrid.ClientWidth - TotWidth;
//平均分配变化宽度的值
//给所有需要自动调整的列
if ResizableColumnCount > 0 then
VarWidth := varWidth div ResizableColumnCount;
for i := 0 to -1 + DBGrid.Columns.Count do
begin
AColumn := DBGrid.Columns[i];
if AColumn.Field.Tag <> 0 then
begin
AColumn.Width := AColumn.Width + VarWidth;
if AColumn.Width < AColumn.Field.Tag then
AColumn.Width := AColumn.Field.Tag;
end;
end;
end;Top
38 楼tiaozhan2005()回复于 2006-07-23 20:33:16 得分 0
强烈要求你用CXGRID 代替DBGRID!这样你就会发现很多惊喜!!Top
39 楼fjx99(fjx99)回复于 2006-07-24 08:57:10 得分 0
试试onDrawDataCell事件
procedure TForm1.DBGrid1DrawDataCell(Sender: TObject; const Rect: TRect;
Field: TField; State: TGridDrawState);
var
nDisplayWidth : integer;
begin
nDisplayWidth := TDBGrid(Sender).Canvas.TextWidth(Field.AsString) + 4;
if nDisplayWidth > TDBGrid(Sender).Columns.Items[Field.Index].Width then
TDBGrid(Sender).Columns.Items[Field.Index].Width := nDisplayWidth;
end;Top
40 楼maxtool(≮From NingBoo≯)回复于 2006-07-24 14:50:41 得分 0
好像
DBGridEH
挺好用的说,哪里有该控件下载?Top
41 楼songyafeng(sanmo)回复于 2007-03-05 17:29:16 得分 0
for i:=0 to Dbgrideh1.Columns.Count -1 do
Dbgrideh1.Columns[i].OptimizeWidth;
//可以搞定打开后列宽为最小值,不必担心空白区域较大问题Top
42 楼m54772091(aaaa)回复于 2007-03-24 10:45:23 得分 0
用dxDbgridTop




