CSDN首页 空间 新闻 论坛 Blog 下载 读书 网摘 搜索 .NET Java 视频 接项目 求职 在线学习 买书 程序员 通知
可用分押宝游戏火热进行中... 专题改版:Java Web 专题
CSDN社区
搜索 收藏 打印 关闭
CSDN社区 >  Delphi >  数据库相关

DBGrid怎样实现自适应列宽,找过一些代码,可是都不如意

楼主558047(三个代表万睡!八荣八耻万睡!)2006-07-14 10:55:11 在 Delphi / 数据库相关 提问

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

相关问题

关键词

得分解答快速导航

  • 帖主:558047
  • daydayup234
  • BlueDeepOcean

相关链接

  • Delphi类图书
  • Delphi类源码下载
  • Delphi控件下载

广告也精彩

反馈

请通过下述方式给我们反馈
反馈
提问
网站简介|广告服务|VIP资费标准|银行汇款帐号|网站地图|帮助|联系方式|诚聘英才|English|问题报告
世纪乐知(北京)网络技术有限公司 版权所有, 京 ICP 证 020026 号
北京创新乐知广告有限公司 提供技术支持
Copyright © 2000-2007, CSDN.NET, All Rights Reserved
GongshangLogo