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

解决方案 »

  1.   

    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个
            }
          }
        }
      

  2.   

    //让好几个Show和OnResize事件“定位”到这个
    这句话是什么意思?
      

  3.   

    这段代码是要放在FormShow中么?我怎么编译通过,运行却出错呢?
    我的意思是:DBGrid的某一列的宽度随着它内容长度的增减而相应增减
    假设这个列目前最长的内容是5个汉字时,那么就让它有5个汉字那么宽
      

  4.   

    执行到TADOQuery *dset=(TADOQuery *)dgrid->DataSource->DataSet;时出错
    提示:Access violation at address 00401D74 in module 'Project1.exe'
      

  5.   

    你的所有dbgrid事先要连接好数据,而且要是TADOQuery的数据集因为我的应用数据集合全用了TADOQuery,没有用TADOtable
    也没有用BDE数据集合连dbgrid.要完全用我的代码,适当得改改
      

  6.   

    刀客
    我有这样几个疑问,探讨一下:
    int I;
    TComponent *Temp;
    for(I=ComponentCount-1;I>=0;I--)
    {
    Temp=Components[I];
    这段代码是遍历Form上的所有控件的吧,我发现它把所有的控件都遍历了一遍。能不能筛选只遍历DBGrid?
    还有,dbgrid事先要连接好数据,是必须要在设计期连接还是也可以在这段代码执行之前用代码连接?
      

  7.   

    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;
      

  8.   

    回答你短消息:
    1 遍历:只有这办法遍历所有TDBGrid,是得针对TComponent判别。
    2 关于连接:是事先连好。
    3 效果:我从新看了,还得
      OnResize事件“定位”到这个事件上
      如果这个“定位”你不熟:
      代码复制一份进入窗得OnResize事件
      

  9.   

    //---------------------------------------------------------------------------
        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);这下一点没问题,刚实验
      

  10.   

    出于人道主义救援的原则,我也给你一个,虽然不比楼上精简,但直观易懂。//---------------------------------------------------------------------------#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();
                    }
            }
    }
    //---------------------------------------------------------------------------
      

  11.   

    目前我的这个窗体上有几个DBGrid,目前要求DBGrid和数据库连接,必须要用代码动态实现,不能在设计期作静态连接。而且每个DBGrid都对应一个查询按钮,当每次查询结果不同时,它的列宽要随之而变化。
    而这时Form的ReSize事件并没有发生
    如果是这种情况,我觉得你的这段代码肯定就不适应了
      

  12.   

    我早前地代码放进ReSize事件,
    最小化最大化切换一下看效果
      

  13.   

    我新建了一个工程,窗体上只放了一个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;
    }
    //---------------------------------------------------------------------------
      

  14.   

    你 ShowMessage看看,
    应该没问题吧
      

  15.   

    while(k-->0)
    {
         dset->Fields->Fields[k]->DisplayWidth=(DBGrid1->ClientWidth)/(count+1)/fontSize;
         ShowMessage(dset->Fields->Fields[k]->DisplayWidth);
    }
    每次ShowMessage都是1
      

  16.   

    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可看出效果
      

  17.   

    要不
    TADOQuery *dset=(TADOQuery *)DBGrid1->DataSource->DataSet;
    加括号
    TADOQuery *dset=(TADOQuery *)(DBGrid1->DataSource->DataSet);
    看看
      

  18.   

    EHLIB控件的DBGridEH就有这个功能,你可以直接用它,也可参考它的源码
      

  19.   

    EHLIB控件的DBGridEH就有这个功能,你可以直接用它,也可参考它的源码
    除了这个,没有别的办法了么?
      

  20.   

    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;
      

  21.   

    整个label,visible设为false,autoresize设为true;字体设成跟dbgrid的字体一样(包括大小)
    dbgrid一列从头扫到尾,扫的过程中不断从当前行的这一列取出值赋给label.caption,并记录一列扫描过程的label.width的最大值
    把最大值赋给dbgrid该列的width属性。
      

  22.   

    DBGridEH 有这个功能吗,我怎么没有发现?
      

  23.   

    DBGridEH有两种方式自适应宽度
    1.设AutoFitColWidths=true;
    它的列宽会跟据整个Grid的宽度自动调整
    且每一列(TColumnEh)都有AutoFitColWidth属性,设为true,该列宽度自动调整
    2.OptionsEh中有dghDblClickOptimizeColWidth,当双击表缝时,前一列按当前数据宽度自动调整宽度(与Excel中功能相同)
    你可以参看它的源码,看它如何实现的
      

  24.   

    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;
      

  25.   

    强烈要求你用CXGRID 代替DBGRID!这样你就会发现很多惊喜!!
      

  26.   

    试试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;
      

  27.   

    好像
    DBGridEH
    挺好用的说,哪里有该控件下载?
      

  28.   

    for i:=0 to Dbgrideh1.Columns.Count -1 do
      Dbgrideh1.Columns[i].OptimizeWidth;
    //可以搞定打开后列宽为最小值,不必担心空白区域较大问题