没有改太多的东西啊,但总不能不写代码就实现这些功能吧?我把我的代码拷贝给你吧。1>先新建一个单元UDbgridSet.pas,里面放置一个TCheckListBox和一个Panel,名称你可以看看下面,Panel上面放置2个按钮。unit UDbgridSet;interfaceuses Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms, Dialogs, StdCtrls, CheckLst, ExtCtrls, Buttons, Menus, DB, DBGrids, DBClient;Const Const_FieldList='DispInfo';type _FieldInfo=Record FieldName:String; FieldWidth:Integer; FieldVis:String; //VT,VF end; ArrayFieldInfo=Array of _FieldInfo; TFrmDbgridSet = class(TForm) CkListEh: TCheckListBox; Panel1: TPanel; BtnUp: TBitBtn; BtnDown: TBitBtn; procedure FormCreate(Sender: TObject); procedure BitBtn1Click(Sender: TObject); procedure BtnUpClick(Sender: TObject); procedure BtnDownClick(Sender: TObject); procedure CkListEhClick(Sender: TObject); procedure CkListEhKeyUp(Sender: TObject; var Key: Word; Shift: TShiftState); procedure CkListEhKeyDown(Sender: TObject; var Key: Word; Shift: TShiftState); procedure FormKeyUp(Sender: TObject; var Key: Word; Shift: TShiftState); private FChanged:Boolean; FSaved:Boolean; // FFieldNames: ArrayFieldInfo; Fgrid:TDBGrid; { Private declarations } Procedure CreateColumns; Procedure UpColumn; Procedure DownColumn; Procedure SetColumnVisible; Protected Procedure SaveDbgrid; Function CanSave:Boolean; public { Public declarations } Class Procedure Execute(Agrid:TDBGrid); end; TMYDBGrid=Class(TDBGrid) private FPopMenu:TPopupMenu; Procedure SetColumnMenuClick(Sender: TObject); procedure SaveCustomDisplayMode(Sender: TObject); Procedure LoadDefaultDisplayMode(Sender: TObject);//恢复默认显示模式 protected procedure MouseDown(Button: TMouseButton; Shift: TShiftState; X, Y: Integer); override; public constructor Create(AOwner: TComponent); override; end;Procedure SaveColumnEhWidthToIni(Agrid:TDBGrid);//窗体释放的时候,保存宽度信息Procedure LoadColumnCustomInfo(Agrid:TDBGrid); //控件装载后,设置其显示信息Procedure ClearCustomDispInfo(Agrid:TDBGrid);//恢复默认显示设置implementation{$R *.dfm}Function GetIniFileName:String;Begin Result:= ExtractFilePath(Application.ExeName)+'DBgrid.INI'End;Procedure StrToFieldInfoArr( AFieldStr:String; Var FieldArr:ArrayFieldInfo);var sTmp,sFields:String; t:_FieldInfo; H,iPos:Integer;Begin sFields:= AFieldStr; SetLength(FieldArr,0); While sFields<>'' Do Begin iPos:=Pos(';',sFields); If iPos=0 then begin sTmp:= sFields; sFields:=''; end else begin sTmp:=Copy(sFields,1,iPos-1); System.Delete(sFields,1,iPos); end; sTmp:=Trim(UpperCase(sTmp)); if sTmp<>'' then //FieldName:Width:Visible begin iPos:=Pos(':',sTmp); if iPos=0 then Continue; t.FieldName := Copy(sTmp,1,iPos-1); System.Delete(sTmp,1,iPos); iPos:=Pos(':',sTmp); if iPos=0 then Continue; Try t.FieldWidth :=StrToInt( Copy(sTmp,1,iPos-1) ); Except t.FieldWidth:=0; End; System.Delete(sTmp,1,iPos); t.FieldVis:=sTmp; SetLength(FieldArr,Length(FieldArr)+1); H:=High(FieldArr); FieldArr[H] := t; End; End;End;Procedure SaveColumnEhWidthToIni(Agrid:TDBGrid);VAR sIniFile:String; sHead:String; sField:String; sVis:String; i,iWidth:Integer;begin If Agrid=nil then Exit; if Agrid.Owner=nil then Exit; if csDesigning in Agrid.ComponentState then Exit; //设计期间不掉用本函数 sIniFile:= GetIniFileName; sHead:= Agrid.Owner.Name+'_'+Agrid.Name; sField:=';'; For i:=0 to Agrid.Columns.Count-1 do Begin iWidth:=Agrid.Columns
.Width; if iWidth=64 then iWidth:=65; if Agrid.Columns.Visible then sVis:='VT' Else sVis:='VF'; sField:=sField+Format('%S:%D:%S;', [Agrid.Columns.FieldName, iWidth, sVis ]); End; //保存显示顺序 WritePrivateProfileString( PChar(sHead), Const_FieldList, PChar(sField), PChar(sIniFile) ); Application.MessageBox('自定义显示模式保存成功!','提示信息',MB_OK);End;Procedure LoadColumnCustomInfo(Agrid:TDBGrid);var ReturnStrChar; sIniFile:String; sFields,sHead:String; I,iOLDIndex:Integer; LFiles:ArrayFieldInfo; Function GetIndexByFieldName(sName:String):Integer; var iLoop:Integer; Begin Result:=-1; For iLoop:=0 to Agrid.Columns.Count-1 do Begin if AnsiCompareText( Agrid.Columns[iLoop].FieldName, sName )=0 then Begin Result:= iLoop; Break; End; End; End;begin If Agrid=nil then Exit; if Agrid.Owner=nil then Exit; if csDesigning in Agrid.ComponentState then Exit; //设计期间不掉用本函数 //获得控件信息 sIniFile:= GetIniFileName; sHead:= Agrid.Owner.Name+'_'+Agrid.Name; ReturnStr:=StrAlloc(1500); //获得字段显示顺序 GetPrivateProfileString( PChar(sHead), PChar(Const_FieldList) ,'',ReturnStr,1000, PChar(sIniFile)); sFields := StrPas(ReturnStr); Try Try StrToFieldInfoArr( sFields, LFiles ); For i:=Low(LFiles) to High(LFiles) do begin if i>= Agrid.Columns.Count then Break; iOLDIndex:= GetIndexByFieldName( LFiles.FieldName ); IF iOLDIndex>=0 then Begin if LFiles.FieldWidth<>0 then Agrid.Columns[iOLDIndex].Width:=LFiles.FieldWidth; Agrid.Columns[iOLDIndex].Visible := (LFiles.FieldVis='VT'); Agrid.Columns[iOLDIndex].Index := I; End; end; Except On E:Exception Do Application.MessageBox( PChar('LoadColumnCustomInfo函数异常'+#13#10+E.Message), '提示信息', MB_OK); End; Finally //释放 StrDispose(ReturnStr); End;end;Procedure ClearCustomDispInfo(Agrid:TDBGrid);//恢复默认显示设置VAR sIniFile:String; sHead:String;begin If Agrid=nil then Exit; if Agrid.Owner=nil then Exit; if csDesigning in Agrid.ComponentState then Exit; //设计期间不掉用本函数 sIniFile:=GetIniFileName; sHead:= Agrid.Owner.Name+'_'+Agrid.Name; //保存显示顺序 WritePrivateProfileString( PChar(sHead), Const_FieldList, PChar('NULL'), PChar(sIniFile) ); Application.MessageBox('当前默认信息必须要在下次打开界面才能发生作用!','提示信息',MB_OK);End;{ TFrmDbgridSet }procedure TFrmDbgridSet.CreateColumns;Var i:Integer; S:String;begin If Fgrid=nil then Exit; if Fgrid.Owner=nil then Exit; if Fgrid.Owner.Name='' then Exit; CkListEh.Items.Clear; For i:=0 to Fgrid.Columns.Count-1 do begin S:=Fgrid.Columns.FieldName; SetLength(FFieldNames,Length(FFieldNames)+1); FFieldNames[High(FFieldNames)].FieldName :=UpperCase(S); CkListEh.Items.Add ( Fgrid.Columns.Title.Caption ); S:=UpperCase(';'+S+';'); CkListEh.Checked:= Fgrid.Columns.Visible ; end;end;class procedure TFrmDbgridSet.Execute(Agrid: TDBGrid);begin If Agrid=nil then Exit; if Agrid.Owner=nil then Exit; With TFrmDbgridSet.Create(Agrid) Do Begin Fgrid:=Agrid; CreateColumns; ShowModal; Free; End;end;procedure TFrmDbgridSet.FormCreate(Sender: TObject);begin Self.KeyPreview:=True; FChanged:=False; FSaved:=False; SetLength(FFieldNames,0);end;procedure TFrmDbgridSet.BitBtn1Click(Sender: TObject);begin{ if Not CanSave then Exit; FSaved:=True; Close;}end;procedure TFrmDbgridSet.BtnUpClick(Sender: TObject);begin UpColumn;end;procedure TFrmDbgridSet.BtnDownClick(Sender: TObject);begin DownColumn;end;procedure TFrmDbgridSet.CkListEhClick(Sender: TObject);begin SetColumnVisible;end;procedure TFrmDbgridSet.DownColumn;var iIndex:Integer;begin iIndex:= CkListEh.ItemIndex; If iIndex>=(CkListEh.Count-1) then Exit;//最高一列无法再设置向上了 if iIndex<0 then Exit; FChanged:=True; CkListEh.Items.Exchange( iIndex, iIndex+1); Fgrid.Columns.Items[iIndex].Index:=iIndex+1;end;procedure TFrmDbgridSet.UpColumn;var iIndex:Integer;begin iIndex:= CkListEh.ItemIndex; If iIndex<=0 then Exit;//最高一列无法再设置向上了 FChanged:=True; CkListEh.Items.Exchange( iIndex, iIndex-1); Fgrid.Columns.Items[iIndex].Index:=iIndex-1;end;function TFrmDbgridSet.CanSave: Boolean;var iChkCount,i:Integer;begin Result:=False; iChkCount:=0; for i:=0 to CkListEh.Count-1 do Begin if CkListEh.Checked=True then Inc(iChkCount); End; if iChkCount=0 then Begin Application.MessageBox('不可以所有列都不可见,请检查!','提示信息',MB_OK); Exit; End; Result:=True;end;procedure TFrmDbgridSet.SaveDbgrid;begin SaveColumnEhWidthToIni(Fgrid);end;procedure TFrmDbgridSet.SetColumnVisible;var iIndex:Integer;begin For iIndex:=0 to CkListEh.Count-1 do Fgrid.Columns[iIndex].Visible := CkListEh.Checked[iIndex]; FChanged:=True;end;procedure TFrmDbgridSet.CkListEhKeyUp(Sender: TObject; var Key: Word; Shift: TShiftState);begin Case Key Of VK_SPACE:Begin SetColumnVisible; End; End;end;procedure TFrmDbgridSet.CkListEhKeyDown(Sender: TObject; var Key: Word; Shift: TShiftState);begin If Not(ssCtrl in Shift) then Exit; Case Key Of VK_UP : Begin UpColumn; Key:=0; End; VK_DOWN: Begin DownColumn; Key:=0; End; End;end;procedure TFrmDbgridSet.FormKeyUp(Sender: TObject; var Key: Word; Shift: TShiftState);begin if Key= VK_ESCAPE Then Close;end;{ TMYDBGrid }constructor TMYDBGrid.Create(AOwner: TComponent);var t:TMenuItem;begin inherited; FPopMenu:=TPopupMenu.Create(Application); t:=TMenuItem.Create(FPopMenu); t.Caption:='自定义显示列'; t.OnClick:= SetColumnMenuClick; FPopMenu.Items.Add(t); t:=TMenuItem.Create(FPopMenu); t.Caption:='保存当前设置'; t.OnClick:= SaveCustomDisplayMode; FPopMenu.Items.Add(t); t:=TMenuItem.Create(FPopMenu); t.Caption:='恢复默认设置'; t.OnClick:= LoadDefaultDisplayMode; FPopMenu.Items.Add(t);end;procedure TMYDBGrid.LoadDefaultDisplayMode(Sender: TObject);begin ClearCustomDispInfo(TDBGrid(Self));end;procedure TMYDBGrid.MouseDown(Button: TMouseButton; Shift: TShiftState; X, Y: Integer);begin inherited; if Not (csDesigning in ComponentState) then Begin if (Button in [mbLeft,mbRight]) and (X<=10) AND (Y<= Self.RowHeights[0] ) Then Begin FPopMenu.Popup( Mouse.CursorPos.X, Mouse.CursorPos.Y);; Exit; End; End;end;procedure TMYDBGrid.SaveCustomDisplayMode(Sender: TObject);begin SaveColumnEhWidthToIni(TDBGrid(Self));end;procedure TMYDBGrid.SetColumnMenuClick(Sender: TObject);begin TFrmDbGridSet.Execute( TDBGrid(Self) );end;end.2>使用案例(每个单元只需要增加2行代码就可以了,再简单一些的方法就没有了):unit Unit1;interfaceuses Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms, Dialogs, Grids, DBGrids, UDbgridEhSet; //增加的type TDBGrid = Class(UDbgridEhSet.TMYDBGrid); //增加的 TForm1 = class(TForm) DBGrid1: TDBGrid; private { Private declarations } public { Public declarations } end;