DBGridEh大全

查看完全版本: dbgrid应用全书
帖数:23 分页:[ 1]
(作者: songwt 2005-1-30 9:32:02)  [资料] [短信] [好友] [邮箱] [只看楼主]
1
 


dbgrid应用全书

您无权查看此精华帖,请先 登录或者 注册
(作者: songwt 2005-1-30 9:32:57)  [资料] [短信] [好友] [邮箱]
2
 




DBgrid应用全书	2
问题: Delphi5 - 隔行改变DBGrid网格颜色 3
在Delphi的DBGrid中插入其他可视组件 4
锁定DBGrid左边的列 6
使dbgrid的某几笔资料变色 7
实战Delphi数据网格色彩特效 8
点击DBGrid的Title对查询结果排序 10
去掉DbGrid的自动添加功能 11
dbgrid中移动焦点到指定的行和列 12
如何使DBGRID网格的颜色随此格中的数据值的变化而变化? 13
判断Grid是否有滚动条? 15
两个Grid的同步滚动 15
在Delphi中随意控制DBGrid 每一行的颜色简易方法 18
如何在DBGrid中能支持多项记录的选择 19
另外一种可以在在Delphi中随意控制DBGrid 每一行颜色的方法 23
在一个Dbgrid中显示多数据库 25
在 DBGrid 中如何让回车变为光标右移动 26
从 DBGrid 中复制记录 26
使用 DBGrid 的复选项(请参考如何在DBGrid中能支持多项记录的选择) 27
在DBGrid上Drag & Drop(拖放) 28
如何使DBGrid的指针不移动? 29
如何动态更新DBGrid的颜色?(请同时参考“如何使DBGRID网格的颜色随此格中的数据值的变化而变化?”) 29
使用DBGrid显示日期 30
在TDBGrid控件中实现拖放的另外一个思路(请同时参考在DBGrid上Drag & Drop(拖放)) 30
在dbgrid表格中如何设置按回车键相当于单click? 30
Delphi 的 DBGrid 中的下拉列表和查找字段编程方法 31
Delphi中定制DBGrid控件 33
在DBGrid控件中显示图形 39
如何侦测DBGrid目前的记录与栏位资讯 40
用DbGrid制作edit录入时的下拉提示框 40
Delphi的dbgrid中根据数据的属性不同显示不同的颜色 44
给DBGrid加入排序功能(同时参考“点击DBGrid的Title对查询结果排序”) 44
将 DBGrid 中的内容输出至 Excel 或 ClipBoard 48
怎样获得DBGrid中的cell的坐标??? 50
多层表头的DBGrid(推荐大家学习,很有用) 52
在 dbgrid 中实现 copy、paste 功能 53
禁止在DBGrid中按delete删除记录 54
给 DBGrid 添加搜索功能 55
数据网格自动适应宽度 58
移除DBGrid的垂直滚动条(参考“判断Grid是否有滚动条?”) 59
解决dbgrid上下移动的另外一种办法 61
关于DBGrid中下拉列表的两种设计比较 63
有关双击dbgrid排序的问题(想让用户双击dbgird控件的某一个字段 67
在DBGrid中,怎样才能让我能点击一个单元格选择整行,又可以编辑单元格的内容呢?【hongxing_dl 提供代码】 68
怎样在DbGrid的左边,实现像EXCEL那样的自动编号?这些编号与表无关. 69
如何将几个DBGRID里的内容导入同一个EXCEL表中? 70
自制精美易用的DBGrid【陈大峰】 75
在DELPHI中利用API实现网格内组件的嵌入 89
Ehlib使用说明 92
如何使用 Ehlib 实现自动排序 93
以下这段文字摘自《Delphi 园地》 94
DBGridEh控件的页脚属性怎么设? 101
如何实现在DbgridEh中不同的行显示不同的颜色?或某一些条件的行显示特定的颜色? 101
在dbgrideh中允许选择多行,如何知道哪些行被选中? 102
dbgrideh 上选择多行之后,要求把所选择的记录全部添加入SQL数据库的一个固定表中。 103
在dbgrideh中直接点击title就可按点击的那个字段排序的方法 103
ehlib的颜色控制及打印 104
DBGridEH 所有欄位自動寬度的實現 106


[此贴子已经被作者于2005-1-30 10:06:00编辑过]

(作者: songwt 2005-1-30 9:33:51)  [资料] [短信] [好友] [邮箱]
3
 




DBgrid应用全书

在 Delphi 语言的数据库编程中,DBGrid 是显示数据的主要手段之一。但是 DBGrid 缺省的外观未免显得单调和缺乏创意。其实,我们完全可以在我们的程序中通过编程来达到美化DBGrid 外观的目的。通过编程,我们可以改变 DBGrid 的表头、网格、网格线的前景色和背景色,以及相关的字体的大小和风格。
以下的示例程序演示了对 DBGrid 各属性的设置,使 Delphi 显示的表格就像网页中的表格一样漂亮美观。
示例程序的运行:
在 Form1 上放置 DBGrid1、Query1、DataSource1 三个数据库组件,设置相关的属性,使 DBGrid1 能显示表中的数据。然后,在 DBGrid1 的 onDrawColumnCell 事件中键入以下代码,然后运行程序,就可以看到神奇的结果了。本代码在 Windows98、Delphi5.0 环境下调试通过。
procedure TMainForm.DBGrid1DrawColumnCell(Sender: TObject;
const Rect: TRect; DataCol: Integer; Column: TColumn;State: TGridDrawState);
var i :integer;
begin
if gdSelected in State then Exit;
//定义表头的字体和背景颜色:
for i :=0 to (Sender as TDBGrid).Columns.Count-1 do
begin
(Sender as TDBGrid).Columns[i].Title.Font.Name :=/'宋体/'; //字体
(Sender as TDBGrid).Columns[i].Title.Font.Size :=9; //字体大小
(Sender as TDBGrid).Columns[i].Title.Font.Color :=$000000ff; //字体颜色(红色)
(Sender as TDBGrid).Columns[i].Title.Color :=$0000ff00; //背景色(绿色)
end;
//隔行改变网格背景色:
if Query1.RecNo mod 2 = 0 then
(Sender as TDBGrid).Canvas.Brush.Color := clInfoBk //定义背景颜色
else
(Sender as TDBGrid).Canvas.Brush.Color := RGB(191, 255, 223); //定义背景颜色
//定义网格线的颜色:
DBGrid1.DefaultDrawColumnCell(Rect,DataCol,Column,State);
with (Sender as TDBGrid).Canvas do //画 cell 的边框
begin
Pen.Color := $00ff0000; //定义画笔颜色(蓝色)
MoveTo(Rect.Left, Rect.Bottom); //画笔定位
LineTo(Rect.Right, Rect.Bottom); //画蓝色的横线
Pen.Color := $0000ff00; //定义画笔颜色(绿色)
MoveTo(Rect.Right, Rect.Top); //画笔定位
LineTo(Rect.Right, Rect.Bottom); //画绿色的竖线
end;
end;

2003-11-5 17:30:00
查看评语»»»

2003-11-5 17:31:41
原来还有这个办法啊,在没有DevExpress之前....
我会陆续添加的

2003-11-11 17:07:42 问题: Delphi5 - 隔行改变DBGrid网格颜色
在 Form1 上放置 DBGrid1、Query1、DataSource1 三个数据库组件,设置相关的属性,使 DBGrid1 能显示表中的数据。然后,在 DBGrid1 的 onDrawColumnCell 事件中键入以下代码,然后运行程序

代码:
procedure TForm1.DBGrid1DrawColumnCell(Sender: TObject; const Rect: TRect;
DataCol: Integer; Column: TColumn; State: TGridDrawState);

var i:integer;
begin
if gdSelected in State then Exit; //隔行改变网格背景色:
if adoQuery1.RecNo mod 2 = 0 then
(Sender as TDBGrid).Canvas.Brush.Color := clinfobk //定义背景颜色
else
(Sender as TDBGrid).Canvas.Brush.Color := RGB(191, 255, 223); //定义背景颜色

//定义网格线的颜色:
DBGrid1.DefaultDrawColumnCell(Rect,DataCol,Column,State);
with (Sender as TDBGrid).Canvas do //画 cell 的边框
begin
Pen.Color := $00ff0000; //定义画笔颜色(蓝色)
MoveTo(Rect.Left, Rect.Bottom); //画笔定位
LineTo(Rect.Right, Rect.Bottom); //画蓝色的横线
Pen.Color := clbtnface; //定义画笔颜色(兰色)
MoveTo(Rect.Right, Rect.Top); //画笔定位
LineTo(Rect.Right, Rect.Bottom); //画绿色
end;
end;

用BDE中的table1未能通过,颜色没有隔行变化。

2003-11-11 17:12:09 在Delphi的DBGrid中插入其他可视组件
Delphi提供了功能强大的 DBGrid组件,以方便进行数据库应用程序设计。但是如果我们仅仅利用DBGrid组件,每一个获得焦点(Grid)只是一个简单的文本编辑框,不方便用户输入数据。Delphi也提供了一些其他数据组件来方便用户输入,比如DBComboBox,DBCheckBox等组件,但这些组件却没有DBGrid功能强大。Delphi能不能象Visual Foxpro那样让DBGrid中获得焦点网格可以是其它可视数据组件以方便用户呢?其实我们可以通过在DBGrid中插入其他可视组件来实现这一点。

Delphi对DBGrid处理的内部机制,就是在网格上浮动一个组件——DBEdit组件。你输入数据的网格其实是浮动DBEdit组件,其他未获得焦点地方不过是图像罢了。所以,在DBGrid中插入其他可视组件就是在网格上浮动一个可视组件。因此任何组件,包括从简单的DbCheckBox到复杂的对话框,都可以在DBGrid中插入。下面就是一个如何在DBGrid中插入DBComboBox组件的步骤,采用同样的办法可以插入其他组件。

1、在Delphi 4.0中新建一个项目。

2、分别拖动的Data Access组件板上DataSource、Table,Data Controls组件板上DBGrid,DBComboBox四个组件到Form1上。

3、设置各个组件的属性如下:

rcf1对象 属性 设定植
Form1 Caption /'在DBGrid中插入SpinEdit组件示例/'
DataSource1 DataSet Table1
Table1 DatabaseName DBDEMOS
TableName /'teacher.DBF/'
Active True
DBGrid1 DataSource DataSource1
DBComboBox1 DataField SEX
DataSource DataSource1
Visible False
Strings Items. /'男/'| /'女/'

注意:我在这里用了Teacher.dbf,那是反映教职工的性别,只能是“男”或者是“女”。

4、DrawDataCell事件是绘制单元格,当获得焦点网格所对应的字段与组合框所对应的字段一致时,移动组合框到获得焦点的网格上,并且使组合框可视,从而达到在DBGrid指定列上显示DBComboBox的功能。设置DBGrid1的OnDrawDataCell事件如下:

procedure TForm1.DBGrid1DrawDataCell(Sender: TObject; const Rect: TRect; Field: TField; State: TGridDrawState);
begin
if (gdFocused in State) then
begin
if (Field.FieldName = DBComboBox1.DataField ) then
begin
DBComboBox1.Left := Rect.Left + DBGrid1.Left;
DBComboBox1.Top := Rect.Top + DBGrid1.top;
DBComboBox1.Width := Rect.Right - Rect.Left;
DBComboBox1.Height := Rect.Bottom - Rect.Top;
DBComboBox1.Visible := True;
end;
end;
end;

5、DBGrid指定单元格未获得焦点时不显示DBComboBox,设置DBGrid1的OnColExit事件如下:
procedure TForm1.DBGrid1ColExit(Sender: TObject);
begin
If DBGrid1.SelectedField.FieldName = DBComboBox1.DataField then
begin
DBComboBox1.Visible := false;
end;
end;

6、当DBGrid指定列获得焦点时DrawDataCell事件只是绘制单元格,并显示DBComboBox,但是DBComboBox并没有获得焦点,数据的输入还是在单元格上进行。在DBGrid1的KeyPress事件中调用SendMessage这个 Windows API函数将数据输入传输到DBComboBox上,从而达到在DBComboBox上进行数据输入。因此还要设置KeyPress事件如下:

procedure TForm1.DBGrid1KeyPress(Sender: TObject; var Key: Char);
begin
if (key < > chr(9)) then
begin
if (DBGrid1.SelectedField.FieldName =DBComboBox1.DataField) then
begin
DBComboBox1.SetFocus;
SendMessage(DBComboBox1.Handle,WM_Char,word(Key),0);
end;
end;
end;

程序在中文Windows 98,Delphi 4.015 下调试通过。希望本文能使你可以更加方便快捷的开发数据库应用程序。

(作者: songwt 2005-1-30 10:08:40)  [资料] [短信] [好友] [邮箱]
4
 




锁定DBGrid左边的列 
我在使用 Delphi3 进行数据库编程的时候,希望 DBGRID 构件在显示数据的时候能象FoxPro 的 BROWSE 命令一样,锁定左边指定的几列不进行滚动,请问应用什么方法来实现?

我们知道 Delphi 的 TStringGrid 有一个属性 FixedCols 来指定不滚动的列。虽然TDBGrid 不能直接使用这一属性,但通过强制类型转换也可以首先这一功能,因为这两个类都来自 TCustomGrid 类。下面我们以 Delphi 3.0的 Demos//Db//CtrlGrid 为例来说明具体的用法。在这个例子的 TFmCtrlGrid.FormShow 过程中加入如下一行:

TStringGrid(DbGrid1).FixedCols := 2;

运行该程序,在左右移动各列时,Symbol 列不会移动。除了这种方法,也可以采用下面的方法:首先在 Form 声明部分加上

type TMyGrid = Class(TDBGrid) end;

然后在 TFmCtrlGrid.FormShow 过程中加入:

TMyGrid(DbGrid1).FixedCols := 2;

两者从形式上略有不同,但实质都是一样的。我们这里设置 FixedCols 为 2,这是因为在 DBGrid 构件最左侧有个指示列,如果你将 DBGrid 的 Options 属性的 dgIndicator 设为False,则应设置 FixedCols 为1。

使dbgrid的某几笔资料变色
你可在 DBGrid 元件的 DrawDataCell 事件中依资料的条件性来改变格子或文字的颜色.
如 :

OnDrawDataCell(...)
begin
with TDBGrid(Sender) do
begin
if (条件) then
Canvas.TextOut(Rect.Left + 4
Rect.Top + 2

/'要显示的文字如表格的资料/');
end;

而你会看到 DBGrid 的显示资料怎麽有重叠的情况那是因为原本DBGrid要显示的资料与 TextOut 所显示的资料重叠
解决方法 :
在 Query 元件所加入的栏位(在元件上按右键会有 Add Fields...的选单)在不要显示资料的栏位的 OnGetText 事件中有一参数设定为 False;

procedure TForm1.Query1Detail1GetText(Sender: TField; var Text: string;
DisplayText: Boolean);
begin
// 决定在 DBGrid 得知表格资料时要不要显示所得到的资料False -> 不显示
// 就可避免与 TextOut 的文字重叠了
DisplayText : = False;
end;
end;

如果用 Delphi 3 处理很简单.例如:对表中某字段当其数值小于0时为红字其他为黑字.
在 DBGrid.OnDrawColumnCell(...) 中:

begin
if TableField.AsInteger < 0 then
DBGrid.Canvas.Font.Color := clRed
else
DBGrid.Canvas.Font.Color := clBlack;
DBGrid.DefaultDrawColumnCell(...);
end;

这样对 Field 指定的格式仍旧生效不必重写.

实战Delphi数据网格色彩特效
Delphi中的数据网格控件(TDbGrid)对于显示和编辑数据库中大量的数据起着十分重要的作用;然而,在使用数据网格控件的同时,也往往因为表格中大量的数据不易区分,而令操作者眼花缭乱。如何提高网格控件的易用性,克服它的此项不足呢?本文从改变数据网格的色彩配置角度,提出了一种解决办法。

以下为数据网格控件的6种特殊效果的实现方法,至于数据网格控件与数据集如何连接的方法从略。

1. 纵向斑马线效果:实现网格的奇数列和偶数列分别以不同的颜色显示以区别相邻的数据列。
file://在DbGrid的DrawColumnCell事件中编写如下代码:

Case DataCol Mod 2 = 0 of
True: DbGrid1.Canvas.Brush.Color:= clBlue; file://偶数列用蓝色
False: DbGrid1.Canvas.Brush.Color:= clAqua; file://奇数列用浅绿色
End;
DbGrid1.Canvas.Pen.Mode:=pmMask;
DbGrid1.DefaultDrawColumnCell (Rect
DataCol
Column
State);

2. 纵向斑马线,同时以红色突出显示当前单元格效果:以突出显示当前选中的字段。

file://将上述代码修改为:
Case DataCol Mod 2 = 0 of
True: DbGrid1.Canvas.Brush.Color:= clBlue; file://偶数列用蓝色
False: DbGrid1.Canvas.Brush.Color:= clAqua; file://奇数列用浅绿色
End;
If ((State = [gdSelected]) or (State=[gdSelectedgdFocused])) then
If Not DbGrid1.SelectedRows.CurrentRowSelected then
DbGrid1.Canvas.Brush.Color:=clRed; file://当前选中单元格显示红色
DbGrid1.Canvas.Pen.Mode:=pmMask;
DbGrid1.DefaultDrawColumnCell (Rect
DataCol
Column
State);

上述两种方法突出了列的显示效果。

3.在数据网格中以红色突出显示当前选中的行。
设置DbGrid控件的Options属性中的dgRowSelect属性为真,Color属性为clAqua(背景色)
在DbGrid的DrawColumnCell事件中编写如下代码:

if ((State = [gdSelected]) or (State=[gdSelected gdFocused])) then
DbGrid1.Canvas.Brush.color:=clRed; file://当前行以红色显示,其它行使用背景的浅绿色
DbGrid1.Canvas.pen.mode:=pmmask;
DbGrid1.DefaultDrawColumnCell (Rect
DataCol
Column
State);

4.行突显的斑马线效果:既突出当前行,又区分不同的列(字段)。

file://其它属性设置同3,将上述代码修改为:
if ((State = [gdSelected]) or (State=[gdSelectedgdFocused])) then
begin
Case DataCol Mod 2 = 0 of
True : DbGrid1.Canvas.Brush.color:=clRed; file://当前选中行的偶数列显示红色
False: DbGrid1.Canvas.Brush.color:=clblue; file://当前选中行的奇数列显示蓝色
end;
DbGrid1.Canvas.pen.mode:=pmmask;
DbGrid1.DefaultDrawColumnCell (Rect
DataCol
Column
State);
end;

5.横向斑马线, 同时以红色突显当前行效果。

file://其它属性设置同3,将上述代码修改为:
Case Table1.RecNo mod 2 = 0 of file://根据数据集的记录号进行判断
True : DbGrid1.Canvas.Brush.color:=clAqua; file://偶数行用浅绿色显示
False: DbGrid1.Canvas.Brush.color:=clblue; file://奇数行用蓝色表示
end;
if ((State = [gdSelected]) or (State=[gdSelectedgdFocused])) then file://选中行用红色显示
DbGrid1.Canvas.Brush.color:=clRed;
DbGrid1.Canvas.pen.mode:=pmMask;
DbGrid1.DefaultDrawColumnCell (Rect
DataCol
Column
State);

6.双向斑马线效果:即行间用不同色区分,同时,选中行以纵向斑马线效果区分不同的列。

file://其它属性设置同3,将上述代码修改为:
Case Table1.RecNo mod 2 = 0 of file://根据数据集的记录号进行判断
True : DbGrid1.Canvas.Brush.color:=clAqua; file://偶数行用浅绿色显示
False: DbGrid1.Canvas.Brush.color:= clblue; file://奇数行用蓝色表示
end;
If ((State = [gdSelected]) or (State=[gdSelectedgdFocused])) then
Case DataCol mod 2 = 0 of
True : DbGrid1.Canvas.Brush.color:=clRed; file://当前选中行的偶数列用红色
False: DbGrid1.Canvas.Brush.color:= clGreen; file://当前选中行的奇数列用绿色表示
end;
DbGrid1.Canvas.pen.mode:=pmMask;
DbGrid1.DefaultDrawColumnCell (Rect
DataCol
Column
State);

上述6种方法分别就数据网格控件的列和行的色彩进行了设置,读者可以根据自己的需要设置特效。该程序在Delphi5中测试通过。

(作者: songwt 2005-1-30 10:09:36)  [资料] [短信] [好友] [邮箱]
5
 




点击DBGrid的Title对查询结果排序 
关键词:DBGrid 排序

欲实现点击DBGrid的Title对查询结果排序,想作一个通用程序,不是一事一议,例如不能在SQL语句中增加Order by ...,因为SQL可能原来已经包含Order by ...,而且点击另一个Title时又要另外排序,目的是想作到象资源管理器那样随心所欲。

procedure TFHkdata.SortQuery(Column:TColumn);
var
SqlStr,myFieldName,TempStr: string;
OrderPos: integer;
SavedParams: TParams;
begin
if not (Column.Field.FieldKind in [fkData,fkLookup]) then exit;
if Column.Field.FieldKind =fkData then
myFieldName := UpperCase(Column.Field.FieldName)
else
myFieldName := UpperCase(Column.Field.KeyFields);
while Pos(myFieldName,/';/')<>0 do
myFieldName := copy(myFieldName,1,Pos(myFieldName,/';/')-1)+ /',/' + copy(myFieldName,Pos(myFieldName,/';/')+1,100);
with TQuery(TDBGrid(Column.Grid).DataSource.DataSet) do
begin
SqlStr := UpperCase(Sql.Text);
// if pos(myFieldName,SqlStr)=0 then exit;
if ParamCount>0 then
begin
SavedParams := TParams.Create;
SavedParams.Assign(Params);
end;
OrderPos := pos(/'ORDER/',SqlStr);
if (OrderPos=0) or (pos(myFieldName,copy(SqlStr,OrderPos,100))=0) then
TempStr := /' Order By /' + myFieldName + /' Asc/'
else if pos(/'ASC/',SqlStr)=0 then
TempStr := /' Order By /' + myFieldName + /' Asc/'
else
TempStr := /' Order By /' + myFieldName + /' Desc/';
if OrderPos<>0 then SqlStr := Copy(SqlStr,1,OrderPos-1);
SqlStr := SqlStr + TempStr;
Active := False;
Sql.Clear;
Sql.Text := SqlStr;
if ParamCount>0 then
begin
Params.AssignValues(SavedParams);
SavedParams.Free;
end;
Prepare;
Open;
end;
end;


去掉DbGrid的自动添加功能

关键词:DbGrid

移动到最后一条记录时再按一下“下”就会追加一条记录,如果去掉这项功能
procedure TForm1.DataSource1Change(Sender: TObject; Field: TField);
begin
if TDataSource(Sender).DataSet.Eof then TDataSource(Sender).DataSet.Cancel;
end;
DBGrid不支持鼠标的上下移动的解决代码
自己捕捉WM_MOUSEWHEEL消息处理
private
OldGridWnd : TWndMethod;
procedure NewGridWnd (var Message : TMessage);
public

procedure TForm1.NewGridWnd(var Message: TMessage);
var
IsNeg : Boolean;
begin
if Message.Msg = WM_MOUSEWHEEL then
begin
IsNeg := Short(Message.WParamHi) < 0;
if IsNeg then
DBGrid1.DataSource.DataSet.MoveBy(1)
else
DBGrid1.DataSource.DataSet.MoveBy(-1)
end
else
OldGridWnd(Message);
end;

procedure TForm1.FormCreate(Sender: TObject);
begin
OldGridWnd := DBGrid1.WindowProc ;
DBGrid1.WindowProc := NewGridWnd;
end;

dbgrid中移动焦点到指定的行和列
dbgrid是从TCustomGrid继承下来的,它有col与row属性,只不过是protected的,不能直接访问,要处理一下,可以这样:

TDrawGrid(dbgrid1).row:=row;
TDrawGrid(dbgrid1).col:=col;
dbgrid1.setfocus;
就可以看到效果了。

1 这个方法是绝对有问题的,它会引起DBGrid内部的混乱,因为DBGrid无法定位当前纪录,如果DBGrid只读也就罢了(只读还是会出向一些问题,比如原本只能单选的纪录现在可以出现多选等等,你可以自己去试试),如果DBGrid可编辑那问题就可大了,因为当前纪录的关系,你更改的数据字段很可能不是你想象中的
2 我常用的解决办法是将上程序改为(随便设置col是安全的,没有一点问题)

Query1.first;
TDrawGrid(dbgrid1).col:=1;
dbgrid1.setfocus;

这就让焦点移到第一行第一列当中

(作者: songwt 2005-1-30 10:10:24)  [资料] [短信] [好友] [邮箱]
6
 




如何使DBGRID网格的颜色随此格中的数据值的变化而变化? 
在做界面的时候,有时候为了突出显示数据的各个特性(如过大或者过小等),需要通过改变字体或者颜色,本文就是针对这个情况进行的说明。

如何使DBGRID网格的颜色随此格中的数据值的变化而变化。如<60的网格为红色?
Delphi中数据控制构件DBGrid是用来反映数据表的最重要、也是最常用的构件。在应用程序中,如果以彩色的方式来显示DBGrid,将会增加其可视性,尤其在显示一些重要的或者是需要警示的数据时,可以改变这些数据所在的行或列的前景和背景的颜色。
  DBGrid属性DefaultDrawing是用来控制Cell(网格)的绘制。若DefaultDrawing的缺省设置为True,意思是Delphi使用DBGrid的缺省绘制方法来制作网格和其中所包含的数据,数据是按与特定列相连接的Tfield构件的DisplayFormat或EditFormat特性来绘制的;若将DBGrid的DefaultDrawing特性设置成False,Delphi就不绘制网格或其内容,必须自行在TDBGrid的OnDrawDataCell事件中提供自己的绘制例程(自画功能)。
  在这里将用到DBGrid的一个重要属性:画布Canvas,很多构件都有这一属性。Canvas代表了当前被显示DBGrid的表面,你如果把另行定义的显示内容和风格指定给DBGrid对象的Canvas,DBGrid对象会把Canvas属性值在屏幕上显示出来。具体应用时,涉及到Canvas的Brush属性和FillRect方法及TextOut方法。Brush属性规定了DBGrid.Canvas显示的图像、颜色、风格以及访问Windows GDI 对象句柄,FillRect方法使用当前Brush属性填充矩形区域,方法TextOut输出Canvas的文本内容。

  以下用一个例子来详细地说明如何显示彩色的DBGrid。在例子中首先要有一个DBGrid构件,其次有一个用来产生彩色筛选条件的SpinEdit构件,另外还有ColorGrid构件供自由选择数据单元的前景和背景的颜色。

  1.建立名为ColorDBGrid的Project,在其窗体Form1中依次放入所需构件,并设置属性为相应值,具体如下所列:

   Table1 DatabaseName: DBDEMOS
TableName: EMPLOYEE.DB
Active: True;
  DataSource1 DataSet: Table1
  DBGrid1 DataSource1: DataSource1
DefaultDrawing: False
  SpinEdit1 Increment:200
Value: 20000
  ColorGrid1 GridOrdering: go16*1

  2.为DBGrid1构件OnDrawDataCell事件编写响应程序:

//这里编写的程序是<60的网格为红色的情况,其他的可以照此类推
  procedure TForm1.DBGrid1DrawDataCell(Sender: TObject; const Rect: TRect;Field: TField; State: TGridDrawState);
  begin
   if Table1.Fieldbyname(′Salary′).value<=SpinEdit1.value then
   DBGrid1.Canvas.Brush.Color:=ColorGrid1.ForeGroundColor
   else
    DBGrid1.Canvas.Brush.Color:=ColorGrid1.BackGroundColor;
   DBGrid1.Canvas.FillRect(Rect);
   DBGrid1.Canvas.TextOut(Rect.left+2,Rect.top+2,Field.AsString);
  end;

  这个过程的作用是当SpinEdit1给定的条件得以满足时,如′salary′变量低于或等于SpinEdit1.Value时,DBGrid1记录以ColorGrid1的前景颜色来显示,否则以ColorGrid1的背景颜色来显示。然后调用DBGrid的Canvas的填充过程FillRect和文本输出过程重新绘制DBGrid的画面。

  3.为SpinEdit1构件的OnChange事件编写响应代码:

  procedure TForm1.SpinEdit1Change(Sender: TObject);
  begin
   DBGrid1.refresh; //刷新是必须的,一定要刷新哦
  end;

  当SpinEdit1构件的值有所改变时,重新刷新DBGrid1。

  4.为ColorGrid1的OnChange事件编写响应代码:

  procedure TForm1.ColorGrid1Change(Sender: TObject);
  begin
   DBGrid1.refresh; //刷新是必须的,一定要刷新哦
  end;

  当ColorGrid1的值有所改变时,即鼠标的右键或左键单击ColorGrid1重新刷新DBGrid1。

  5.为Form1窗体(主窗体)的OnCreate事件编写响应代码:

  procedure TForm1.FormCreate(Sender: TObject);
  begin
   ColorGrid1.ForeGroundIndex:=9;
    ColorGrid1.BackGroundIndex:=15;
 end;

  在主窗创建时,将ColorGrid1的初值设定前景为灰色,背景为白色,也即DBGrid的字体颜色为灰色,背景颜色为白色。

  6.现在,可以对ColorDBGrid程序进行编译和运行了。当用鼠标的左键或右键单击ColorGrid1时,DBGrid的字体和背景颜色将随之变化。

  在本文中,只是简单展示了以彩色方式显示DBGrid的原理,当然,还可以增加程序的复杂性,使其实用化。同样道理,也可以将这个方法扩展到其他拥有Canvas属性的构件中,让应用程序的用户界面更加友好。



判断Grid是否有滚动条?
这是一个小技巧,如果为了风格的统一的话,还是不要用了。:)

。。。

if (GetWindowlong(Stringgrid1.Handle, GWL_STYLE) and WS_VSCROLL) <> 0 then
ShowMessage(/'Vertical scrollbar is visible!/');
if (GetWindowlong(Stringgrid1.Handle, GWL_STYLE) and WS_HSCROLL) <> 0 then
ShowMessage(/'Horizontal scrollbar is visible!/');


两个Grid的同步滚动
在实际制作一个项目当中,有时候需要几个grid一起同步滚动以减少用户的操作量。希望下面那段代码对您有一定的参考价值。

{1.}

unit SyncStringGrid;

interface

uses
Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms,Dialogs, Grids;

type
TSyncKind = (skBoth, skVScroll, skHScroll);
TSyncStringGrid = class(TStringGrid)

private
FInSync: Boolean;
FsyncGrid: TSyncStringGrid;
FSyncKind: TSyncKind;
{ Private declarations }
procedure WMVScroll(var Msg: TMessage); message WM_VSCROLL;
procedure WMHScroll(var Msg: TMessage); message WM_HSCROLL;

protected
{ Protected declarations }

public
{ Public declarations }
procedure DoSync(Msg, wParam: Integer; lParam: Longint); virtual;

published
{ Published declarations }
property SyncGrid: TSyncStringGrid read FSyncGrid write FSyncGrid;
property SyncKind: TSyncKind read FSyncKind write FSyncKind default skBoth;
end;

procedure Register;

implementation

procedure Register;
begin
RegisterComponents(/'Samples/', [TSyncStringGrid]);
end;

procedure TSyncStringGrid.WMVScroll(var Msg: TMessage);
begin
if not FInSync and Assigned(FSyncGrid) and (FSyncKind in [skBoth, skVScroll]) then
FSyncGrid.DoSync(WM_VSCROLL, Msg.wParam, Msg.lParam);
inherited;
end;

procedure TSyncStringGrid.WMHScroll(var Msg: TMessage);
begin
if not FInSync and Assigned(FSyncGrid) and (FSyncKind in [skBoth, skHScroll]) then
FSyncGrid.DoSync(WM_HSCROLL, Msg.wParam, Msg.lParam);
inherited;
end;

procedure TSyncStringGrid.DoSync(Msg, wParam: Integer; lParam: Longint);
begin
FInSync := True;
Perform(Msg, wParam, lParam);
FinSync := False;
end;

end.

{****************************************}

{2.}
private
OldGridProc1, OldGridProc2: TWndMethod;
procedure Grid1WindowProc(var Message: TMessage);
procedure Grid2WindowProc(var Message: TMessage);

public
{...}

procedure TForm1.Grid1WindowProc(var Message: TMessage);

begin
OldGridProc1(Message);
if ((Message.Msg = WM_VSCROLL) or (Message.Msg = WM_HSCROLL) or Message.msg = WM_Mousewheel)) then
begin
OldGridProc2(Message);
end;
end;

procedure TForm1.Grid2WindowProc(var Message: TMessage);
begin
OldGridProc2(Message);
if ((Message.Msg = WM_VSCROLL) or (Message.Msg = WM_HSCROLL) or (Message.msg = WM_Mousewheel)) then
begin
OldGridProc1(Message);
end;
end;

procedure TForm1.FormCreate(Sender: TObject);
begin
OldGridProc1 := StringGrid1.WindowProc;
OldGridProc2 := StringGrid2.WindowProc;
StringGrid1.WindowProc := Grid1WindowProc;
StringGrid2.WindowProc := Grid2WindowProc;
end;

(作者: songwt 2005-1-30 10:11:03)  [资料] [短信] [好友] [邮箱]
7
 




在Delphi中随意控制DBGrid 每一行的颜色简易方法 
Delphi中使用 DBGrid 控件时,每一列都能按需要随意地改变颜色,但要改变每一行的颜色却很难,那么在不重新制作新控制件的情况下,有没有好的办法让DBGrid按照用户自己要求随意改变每一行颜色的?答案是有,下面介绍一种简单的方法。

要改变DBGrid每一行的颜色,只要在ONDrawColumnCell事件中设定要改变颜色的行的条件,
并指定DBGrid的Canvas.Brush.color属性并且把Canvas.pen.mode属性设成pmmask,再调用DBGrid 的DefaultDrawColumnCell方法即可。注意在改变这两个属性前要先保护好原来的
Canvas.Brush.color 属性的值,调节器用完成 DefaultDrawColumnCell 方法后要把原属性值改
回,现以 Delphi//demos//db//clientmd 目录下的演示程序 clintproj.dpr 为例子,做简单说明,下面是对程序中的栅格 MemberGrid 的合条件的整行进行变色,变成黑体背景黄色的,其它不合条件的行的颜色为正常字体,白色背景,只在 DrawColumnCelL 事件中设条件其它的不变,如下:

procedure TClientForm.MemberGridDrawColumnCell(Sender: TObject; const Rect: TRect;
DataCol: Integer; Column: TColumn; State: TGridDrawState);
var
oldcolor:tcolor;
oldpm:tpenmode;
begin
if DM.ProjectTEAM_LEADER.Value = DM.Emp_ProjEMP_NO.Value then {设定变色的行的条件}
MemberGrid.Canvas.Font.Style := [fsBold];
MemberGrid.DefaultDrawColumnCell(Rect, DataCol, Column, State);
{上面是演示程序的原内容,以下是增加部分}
if DM.ProjectTEAM_LEADER.Value =DM.Emp_ProjEMP_NO.Value then {设定变色的行的条件}
begin
oldpm:= MemberGrid.Canvas.pen.mode;
oldcolor:= MemberGrid.Canvas.Brush.color;
MemberGrid.Canvas.Brush.color:=clyellow;
MemberGrid.Canvas.pen.mode:=pmmask;
MemberGrid.DefaultDrawColumnCell(Rect, DataCol, Column, State);
MemberGrid.Canvas.Brush.color:=oldcolor;
MemberGrid.Canvas.pen.mode:=oldpm;
end;

end;

感觉上这个方法和前面的几个颜色控制方法的原理是一样的,都是通过ONDrawColumnCell事件来实现变色醒目美化的功能。:)

如何在DBGrid中能支持多项记录的选择
这份文档来自国外,粗略看了一下,很有用,推荐给大家学习使用。
【Question】: How to do multi-selecting records in TDBGrid?
When you add [dgMultiSelect] to the Options property of a DBGrid, you give yourself the ability to select multiple records within the grid.
The records you select are represented as bookmarks and are stored in the SelectedRows property.
The SelectedRows property is an object of type TBookmarkList. The properties and methods are described below.

// property SelectedRows: TBookmarkList read FBookmarks;

// TBookmarkList = class
// public
{* The Clear method will free all the selected records within the DBGrid *}
// procedure Clear;
{* The Delete method will delete all the selected rows from the dataset *}
// procedure Delete;
{* The Find method determines whether a bookmark is in the selected list. *}
// function Find(const Item: TBookmarkStr;
// var Index: Integer): Boolean;
{* The IndexOf method returns the index of the bookmark within the Items property. *}
// function IndexOf(const Item: TBookmarkStr): Integer;
{* The Refresh method returns a boolean value to notify whether any orphans were dropped (deleted) during the time the record has been selected in the grid. The refresh method can be used to update the selected list to minimize the possibility of accessing a deleted record. *}
// function Refresh: Boolean; True = orphans found
{* The Count property returns the number of currently selected items in the DBGrid *}
// property Count: Integer read GetCount;
{* The CurrentRowSelected property returns a boolean value and determines whether the current row is selected or not. *}
// property CurrentRowSelected: Boolean
// read GetCurrentRowSelected
// write SetCurrentRowSelected;
{* The Items property is a TStringList of TBookmarkStr *}
// property Items[Index: Integer]: TBookmarkStr
// read GetItem; default;
// end;

unit Unit1;

interface

uses
Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs, StdCtrls, Grids, DBGrids, DB, DBTables;

type
TForm1 = class(TForm)
Table1: TTable;
DBGrid1: TDBGrid;
Count: TButton;
Selected: TButton;
Clear: TButton;
Delete: TButton;
Select: TButton;
GetBookMark: TButton;
Find: TButton;
FreeBookmark: TButton;
DataSource1: TDataSource;
procedure CountClick(Sender: TObject);
procedure SelectedClick(Sender: TObject);
procedure ClearClick(Sender: TObject);
procedure DeleteClick(Sender: TObject);
procedure SelectClick(Sender: TObject);
procedure GetBookMarkClick(Sender: TObject);
procedure FindClick(Sender: TObject);
procedure FreeBookmarkClick(Sender: TObject);
private
{ Private declarations }
public
{ Public declarations }
end;

var
Form1: TForm1;
Bookmark1: TBookmark;
z: Integer;

implementation

{$R *.DFM}

//Example of the Count property
procedure TForm1.CountClick(Sender: TObject);
begin
if DBgrid1.SelectedRows.Count > 0 then
begin
showmessage(inttostr(DBgrid1.SelectedRows.Count));
end;
end;

//Example of the CurrentRowSelected property
procedure TForm1.SelectedClick(Sender: TObject);
begin
if DBgrid1.SelectedRows.CurrentRowSelected then
showmessage(/'Selected/');
end;

//Example of the Clear Method
procedure TForm1.ClearClick(Sender: TObject);
begin
dbgrid1.SelectedRows.Clear;
end;

//Example of the Delete Method
procedure TForm1.DeleteClick(Sender: TObject);
begin
DBgrid1.SelectedRows.Delete;
end;

{*
This example iterates through the selected rows of the grid and displays the second field of the dataset.
The Method DisableControls is used so that the DBGrid will not update when the dataset is changed. The last position of the dataset is saved as a TBookmark.
The IndexOf method is called to check whether or not the bookmark is still existent.
The decision of using the IndexOf method rather than the Refresh method should be determined by the specific application.
*}

procedure TForm1.SelectClick(Sender: TObject);
var
x: word;
TempBookmark: TBookMark;
begin
DBGrid1.Datasource.Dataset.DisableControls;
with DBgrid1.SelectedRows do
if Count > 0 then
begin
TempBookmark:= DBGrid1.Datasource.Dataset.GetBookmark;
for x:= 0 to Count - 1 do
begin
if IndexOf(Items[x]) > -1 then
begin
DBGrid1.Datasource.Dataset.Bookmark:= Items[x];
showmessage(DBGrid1.Datasource.Dataset.Fields[1].AsString);
end;
end;
end;
DBGrid1.Datasource.Dataset.GotoBookmark(TempBookmark);
DBGrid1.Datasource.Dataset.FreeBookmark(TempBookmark);
DBGrid1.Datasource.Dataset.EnableControls;
end;

{*
This example allows you to set a bookmark and and then search for the bookmarked record within selected a record(s) within the DBGrid.
*}

//Sets a bookmark
procedure TForm1.GetBookMarkClick(Sender: TObject);
begin
Bookmark1:= DBGrid1.Datasource.Dataset.GetBookmark;
end;

//Frees the bookmark
procedure TForm1.FreeBookmarkClick(Sender: TObject);
begin
if assigned(Bookmark1) then
begin
DBGrid1.Datasource.Dataset.FreeBookmark(Bookmark1);
Bookmark1:= nil;
end;
end;

//Uses the Find method to locate the position of the bookmarked record within the selected list in the DBGrid
procedure TForm1.FindClick(Sender: TObject);
begin
if assigned(Bookmark1) then
begin
if DBGrid1.SelectedRows.Find(TBookMarkStr(Bookmark1),z) then
showmessage(inttostr(z));
end;
end;

end.

另外一种可以在在Delphi中随意控制DBGrid 每一行颜色的方法
有个问题是在Delphi中使用DBGrid时,如何让DBGrid中每一行颜色按照用户自己的意愿控
制。最初看到这个问题时,我们以为非常非常简单,所以马上动手准备解决它。结果却发现不是
那么回事,传统方法根本不能发挥作用。在电脑面前一直坐到凌晨4点,不断地调试,幸运地是凭借平时积累的一点编程经验,终于找到了开门的匙钥。现将它充公,供大家享用。

1、 数据表的建立
在Delphi的工具菜单中选择Database desktop,在数据库DBDemos下建立一个名为
example.db的数据表。数据表的字段和内容如下:

Name Age Wage
张山 25 500
王武 57 1060
李市 30 520
刘牛 28 390

2、创建基于TDBGrid的TColoredDBGrid组件
在Delphi组件菜单中,选择New Component,在弹出对话框中作以下设置:

Ancestor Type = TDBGrid
Class Name = TColoredDBGrid

然后单击OK按钮,Delphi自动完成组件基本框架的定义。增添OnDRawColoredDBGrid事件并
使它出现在Object Inspector的Events中以便在应用程序中设定改变行颜色的条件。重载
DrawCell方法,只能自己绘制单元格。不能通过在OnDrawColumnCell来设置颜色,因为在
OnDrawColumnCell改变单元格的颜色会再次触发OnDrawColumnCell。
下面就是所创建组件的源程序 。

3、建立应用程序进行验证。
在Delphi文件菜单中选择New建立新的应用程序工程Project1和主窗体Form1,设置Form1的
Caption属性为“控制DBGrid行颜色的示例”。在主窗体上添加Data Source、Table、Button和
ColoredDBGrid组件。设置各组件的属性如下:

Table1.Database=’DBDemos’
Table1.Tablename=’example.db’
Datasource1.Dataset=Table1
ColoredDBGrid1.Datasource=DataSource1
Button1.Caption=’退出’

在ColoredDBGrid1的onDRawColoredDBGrid事件中输入下列代码,设定由Wage(工资)来决
定在ColoredDBGrid1各行的颜色。

procedure TForm1.ColoredDBGrid1 DRawColoredDBGrid (Sender: TObject; Field: TField; var Color: TColor; var Font: TFont);
Var
p : Integer;
begin
p := Table1.FindField(/'wage/').AsInteger;
//取得当前记录的Wage字段的值。
if (p < 500) then begin
//程序将根据wage值设置各行的颜色。
Color := clGreen;
Font.Style := [fsItalic];
//不仅可以改变颜色,还可以改变字体
end;
if(p >= 500) And (p < 800) then
Color := clRed;
if(p >=800) then begin
Color := clMaroon;
Font.Style := [fsBold];
end;
end;
//用‘退出’按钮结束程序运行。
procedure TForm1.Button1Click(Sender: TObject);
begin
Close;
end;

(作者: songwt 2005-1-30 10:11:39)  [资料] [短信] [好友] [邮箱]
8
 




在一个Dbgrid中显示多数据库 
在数据库编程中,不必要也不可能将应用程序操作的所有数据库字段放入一个数据库文件中。正确的数据库结构应是:将数据库字段放入多个数据库文件,相关的数据库都包含一个唯一
的关键字段,在多数据库结构里可以建立联系。
例如:要编制一个人事管理程序,为简化演示程序,只建立两个数据库,每个数据库都只建
立两个字段。
个人简介 jianjie.dbf,由人事处维护;工资情况 gongzi.dbf,由财务处维护。
1.数据库的建立
进入DataBase Desktop,建立数据库结构如下:

jianjie.dbf
编号 字段名:bianhao size:4 type:number
姓名 字段名:xingming size:10 type:character

gongzi.dbf
编号 字段名:bianhao size:4 type:number
工资 字段名:gongzi size:4 Dec 2 type:number

注意: 两个数据库的bianhao字段的size、type必须一致。实际上,两数据库文件可以分布
在网络的不同计算机上,为便于演示,分别存为″c: //test//jianjie.dbf″和 ″c://test
//gongzi.dbf″。

2.应用程序的编制
启动Delphi, 新建一个工程,在窗体中加入Query控件Query1,databasename属性设为c:
//test;

加入DataSource控件datasource1, DataSet属性设为Query1; 加入DbGrid控件 dbgrid1,
DataSource属性设为DataSource1,将Query1.sql属性设为

SELECT DISTINCT A.bianhao,a.xingming, b.gongzi
FROM ″jianjie.dbf″ A, ″gongzi.DBF″ b
WHERE A.bianhao=b.bianhao

再将Query1.enabled属性设为True, 不用编译, DbGrid1就会显示: bianhao,
xingming, gongzi三个字段。如果jianjie.dbf和gongzi.dbf中有记录,则记录会显示出来。因
篇幅所限,此文只介绍了Dbgrid中显示多个数据库内容的一般方法,读者可在此基础上进行完
善,使该方法更好地适应您的需要。


在 DBGrid 中如何让回车变为光标右移动

在Form.OnKeyPress事件中写如下代码:

if Key = #13 then
if ActiveControl = DBGrid1 then begin
TDBGrid(ActiveControl).SelectedIndex := TDBGrid(ActiveControl).SelectedIndex + 1;
Key := #0;
end;

有2点需要注意:
1.当光标达到DBGird最右列的时候,再按回车,光标还会停留在原地。
2.Key := #0

从 DBGrid 中复制记录
procedure TForm1.DBGrid1DblClick(Sender: TObject);
var
x : integer ;
HadToOpen : boolean ;
begin
with Sender as TDBGrid do begin
HadToOpen := not tTarget.Active ;
if HadToOpen then
tTarget.Active := True ;
tTarget.Append ;
for x := 0 to FieldCount - 1 do
case Fields[x].DataType of
ftBoolean : tTarget.FieldByName(Fields[x].FieldName).AsBoolean := Fields[x].AsBoolean
ftString : tTarget.FieldByName(Fields[x].FieldName).AsString := Fields[x].AsString
ftFloat : tTarget.FieldByName(Fields[x].FieldName).AsFloat := Fields[x].AsFloat
ftInteger : tTarget.FieldByName(Fields[x].FieldName).AsInteger := Fields[x].AsInteger
ftDate : tTarget.FieldByName(Fields[x].FieldName).AsDateTime := Fields[x].AsDateTime ;
end ;
tTarget.Post ;
if HadToOpen then
tTarget.Active := False ;
end ;
end;

使用 DBGrid 的复选项(请参考如何在DBGrid中能支持多项记录的选择)
procedure TForm1.SelectClick(Sender: TObject);
var
x: word;
TempBookmark: TBookMark;
begin
DBGrid1.Datasource.Dataset.DisableControls;
with DBgrid1.SelectedRows do
if Count <> 0 then
begin
TempBookmark:= DBGrid1.Datasource.Dataset.GetBookmark;
for x:= 0 to Count - 1 do
begin
if IndexOf(Items[x]) > -1 then
begin
DBGrid1.Datasource.Dataset.Bookmark:= Items[x];
showmessage(DBGrid1.Datasource.Dataset.Fields[1].AsString);
end;
end;
end;
DBGrid1.Datasource.Dataset.GotoBookmark(TempBookmark);
DBGrid1.Datasource.Dataset.FreeBookmark(TempBookmark);
DBGrid1.Datasource.Dataset.EnableControls;
end;



在DBGrid上Drag & Drop(拖放)
我们在做程序中发现,如果能够让用户将一个Edit的内容直接拖放到一个DBGrid里,会显得很方便,但在程序编制过程中发现,似乎拖放只能拖放到当前的记录上,那假如要拖放到其他记录又怎么办呢,总不能让用户先选择记录,然后再拖放吧。
后来,通过研究发现,当用鼠标点DBGrid时,DBGrid会自动将记录指针移动到所点击的记录上,这就给了我一个思路,让程序模拟在DBGrid上的一次点击先让光标移动到那条记录上,然后就可以将拖放的数据写入DBgrid里面了。
通过事实证明这个思路是可行的。下面,我就告诉大家我的做法:
1) 首先在Form上放一个DBGrid,并它能够显示记录,(这比较简单,就不用多说了)
2) 在Form上放一个Edit
3) 修改Edit的属性,把DragMode改为dmAutoMatic, 让用户能够拖放
4) 在Dbgrid的DragOver事件中增加如下代码: 让它能够接收 Drag & drop

procedure TForm1.DBGrid1DragOver(Sender, Source: TObject; X, Y: Integer; State: TDragState; var Accept: Boolean);
begin
accept:=true;
end;

5) 在Dbgrid的DragDrop事件中增加如下代码: 让它能够自动跳到光标所指定的记录上

procedure TForm1.DBGrid1DragDrop(Sender, Source: TObject; X, Y: Integer);
begin
if Source<>Edit1 then exit;
with Sender as TDbGrid do begin
Perform(wm_LButtonDown,0,MakeLong(x,y));
PerForm(WM_LButtonUp, 0,MakeLong(x,y));
SelectedField.Dataset.edit;
SelectedField.AsString:=Edit1.text;
end;
end;

至此,我们就实现了想要的功能,其中PerForm是TControl的一个通用方法目的是绕过Windows本身的消息循环,而将消息直接发给要发的Control,其具体使用方法请参考Delphi的帮助。

(作者: songwt 2005-1-30 10:12:20)  [资料] [短信] [好友] [邮箱]
9
 




如何使DBGrid的指针不移动? 

【问题】:我用DBGRID显示TABLE中的内容,现在我要从头到尾读一遍TABLE里的数据,用
Table1.First,Next来做会使DBGRID里面的指针也跟着跑,怎么才能使这时候DBGRID里面的指针不
动呢?

【答案】:使用如下代码即可:

  with DataSet do
  try
  DisableControls;
   Do_something;
  finally
   EnableControls;
  end;

如何动态更新DBGrid的颜色?(请同时参考“如何使DBGRID网格的颜色随此格中的数据值的变化而变化?”)
DBGrid控件是一个有许多用户接口的显示数据库的控件,以下的程序告诉您如何根据显示的内容改变字体的显示颜色。例如,如果一个城市的人口大于200万,我们就让它显示为蓝色。使用的控件事件为DBGrid.OnDrawColumeCell.

procedure TForm1.DBGrid1DrawColumnCell(Sender: TObject; const Rect:TRect;DataCol:
Integer; Column: TColumn; State: TGridDrawState);
begin
if Table1.FieldByName(/'Population/').AsInteger > 20000000 then
DBGrid1.Canvas.Font.Color := clBlue;
DBGrid1.DefaultDrawColumnCell(Rect, DataCol, Column, State);
end;

上面的例子是简单的,但是你可以根据自己的需要扩充,例如字体也变化等,甚至你可以调用画圆的函数在数字上画上一个红色的圆圈。

使用DBGrid显示日期
在使用 DBGRID 控件时显示 DATATIME 时其年份是为2位的,但我们在步入2000年后需要显示的日期是4位,如:1998、2001。在数据库中该字段只有在2000年后才会显示4位,怎么办呢? 下面我们就让该字段在DBGRID控件中也显示4位的日期格式: 双击 Table1 控件,就会出现 form1.table 窗体,击右键,选 Add Fields...,选择日期字段后按ok,窗体中就出现了数据库的日期字段名,点日期的那个字段名,属性框里就出现了该字段的信息,里面有一项 DispalyFormat,在该显示格式里输入 yyyy.mm.dd ,那么DBGRID控件就出现完整的日期了。

在TDBGrid控件中实现拖放的另外一个思路(请同时参考在DBGrid上Drag & Drop(拖放))
在本unit中,自定义TMyCustomDBGrid=class(TCustomDBGrid),再如下引用:

TMyCustomDBGrid(DBGrid1).MouseDown(...)

DBGrid1 as TMyCustomDBGrid).MouseDown(...)即可。

在dbgrid表格中如何设置按回车键相当于单click?
【例程】:
在窗体form1中放入table1,datasource1,dbgrid1,设好联连关系,使 dbgrid1 中能正确显示出table1的数据。然后:
procedure TForm1.DBGrid1KeyPress(Sender: TObject;
var Key: Char);
begin
with DBGrid1 do
if Key=#13 then
DBGrid1CellClick(Columns[SelectedIndex]);
end;

procedure TForm1.DBGrid1CellClick(Column: TColumn);
begin
with DBGrid1 do
showmessage(format(/'row=%d/',[SelectedIndex]));
end;

Delphi 的 DBGrid 中的下拉列表和查找字段编程方法
数据网格是非常流行的数据输入和显示形式,像大家熟悉的Excel、VFP 中的功能强大的BROWS 等,为广大程序员乐于采用。在用 Delphi 开发数据库应用系统时,利用数据网格DBGrid 输入数据时,有些字段只允许某几个固定的字符串,像档案案卷的保管期限,只有“永久”、“长期”和“短期”三种,可否从一个下拉列表中进行选择,从而方便输入和避免输入错误呢?还有一些字段,例如职工信息库中的单位编号(在另外的单位库中保存着单位的详细信息),在输入和显示职工数据时,能否不对单位编号进行操作,而代之于更加直观的单位库中的单位名称呢?答案是肯定的,Delphi 的数据网格控件 DBGrid,支持下拉列表和查找字段的编程,而且,编程的过程都是可视化的,不需要写一行语句。

一、DBGrid 中的下拉列表
在 DBGrid 网格中实现下拉列表,设置好 DBGrid 中该字段的 PickList 字符串列表、初始的序号值 DropDownRows 即可。以职工信息库中的籍贯字段(字符串类型)为例,具体设计步骤如下:
1、在窗体上放置Table1、DataSource1、DBGrid1、DBNavigator1 等控件对象,按下表设置各个对象的属性:

---------------------------------------
对象 属性 设定值
---------------------------------------
Table1 DataBase sy1
Table zgk.dbf //职工信息库
DataSource1 DataSet Table1
DbGrid1 DataSource DataSource1
DBNavigator1 DataSource Datasource1
-------------------------------------------
2、双击Table1, 在弹出的Form1.Table1 窗口中,用右键弹出快捷菜单,单击Add Fields 菜单项;选择所有的字段后,按OK 按钮。

3、修改第2 步新增字段的 DisplayLabel 属性。以 Table1ZGBH 字段为例,在 Object Inspector 窗口中选择 Table1ZGBH, 修改属性 DisplayLabel= 职工编号,其余字段类似。

4、双击 DBGrid1, 在弹出的 Editing DBGrid1.Columns 窗口中,单击 Add all Fields 按钮,增加Table1 的所有字段。

5、在 Editing DBGrid1.Columns 窗口,选择 jg 这一行,切换到 Object Inspector 窗口,修改它的 PickList.Strings 为“湖北枝江市(换行)北京市(换行)河南平顶山市(换行)浙江德清市”

6、在 Form1.Oncreate 事件中写入语句:

Table1.Open;

7、F9 运行,用鼠标点击某个记录的籍贯字段,右边即出现一个按钮,点击这个按钮,可出现一个下拉列表,包含第5 步中输入的四行字符串,可用鼠标进行选择。当然也可以自行输入一个并不属下拉列表中的字符串。

二、DBGrid 中的查找字段
所谓查找字段 (LookUp Field),即 DBGrid 中的某个关键字段的数值来源于另外一个数据库的相应字段。运用查找字段技术,不仅可以有效的避免输入错误,而且 DBGrid 的显示方式更为灵活,可以不显示关键字段,而显示源数据库中相对应的另外一个字段的数据。
---- 例如,我们在 DBGrid 中显示和编辑职工信息,包括职工编号、职工姓名、籍贯、所在单位编号,而单位编号来源于另一个数据库表格——单位库,称“单位编号”为关键字段。如果我们直接显示和编辑单位编号的话,将会面对1、2、3 等非常不直观的数字,编辑时极易出错。但是如果显示和编辑的是单位库中对应的单位名称话,将非常直观。这就是DBGrid 的所支持的查找字段带来的好处。

实现DBGrid 的查找字段同样不需要任何语句,具体设计步骤如下:
1、在窗体上放置 Table1、Table2、DataSource1、DBGrid1、DBNavigator1 等控件对象,按下表设置各个对象的属性:

---------------------------------------
对象 属性 设定值
---------------------------------------
Table1 DataBase sy1
Table zgk.dbf //职工信息库
Table2 DataBase sy1
Table dwk.dbf //单位信息库
DataSource1 DataSet Table1
DbGrid1 DataSource DataSource1
DBNavigator1 DataSource Datasource1
------------------------------------------
2、双击 Table1, 在弹出的 Form1.Table1 窗口中,用右键弹出快捷菜单,单击 Add Fields 菜单项;选择所有的字段后,按OK 按钮。

3、修改第2 步新增字段的 DisplayLabel 属性。以 Table1ZGBH 字段为例,在 Object Inspector 窗口中选择 Table1ZGBH, 修改属性 DisplayLabel= 职工编号,其余字段类似。

4、设置 Table1DWBH.Visible=False。

5、在 Form1.Table1 窗口,用右键弹出快捷菜单,单击 New Field 菜单项,新增一个查找字段DWMC,在弹出的窗口设置相应的属性, 按 OK 按钮确认;在 Object Inspector 窗口,设置 Table1DWMC.DisplayLabel= 单位名称。

6、在 Form1.Oncreate 事件中写入语句:

Table1.Open;

7、按 F9 运行,当光标移至某个记录的单位名称字段时,用鼠标点击该字段,即出现一个下拉列表,点击右边的下箭头,可在下拉列表中进行选择。在这里可以看出,下拉列表的内容来自于单位信息库,并且不能输入其他内容。

三、DBGrid 中的下拉列表和查找字段的区别
虽然 DBGrid 中的下拉列表和查找字段,都是以下拉列表的形式出现的,但两者有很大的差别。
1、用 PickList 属性设置的下拉列表,它的数据是手工输入的,虽然也可以在程序中修改,但动态特性显然不如直接由另外数据库表格提取数据的查找字段。

2、用 PickList 属性设置的下拉列表,允许输入不属于下拉列表中的数据,但查找字段中只能输入源数据库中关键字段中的数据,这样更能保证数据的完整性。

3、用 PickList 属性设置的下拉列表设计较为简单。

Delphi中定制DBGrid控件
  在Delphi中,DBGrid控件是一个开发数据库软件不能不使用的控件,其功能非常强大,可以配合SQL语句实现几乎所有数据报表的显示,操作也非常简单,属性、过程、事件等都非常直观,但是使用中,有时侯还是需要一些其他功能,例如打印、斑马纹显示、将DBGrid中的数据转存到Excel97中等等。这就需要我们定制DBGrid,以更好的适应我们的实际需要定制DBGrid,实现了以上列举的功能,对于打印功能则是在DBGrid的基础上联合QuickReport的功能,直接进行DBGrid的打印及预览,用户感觉不到QuickReport的存在,只需调用方法WpaperPreview即可;对于转存数据到Excel也是一样,不过这里使用的是自动化变量Excel而已。由于程序太长,不能详细列举,这里介绍一个完整的实现斑马纹显示的DBGrid,名字是NewDBGrid。根据这个小程序,读者可以添加其他更好、更多、更实用的功能。
  NewDBGrid的实现原理就是继承DBGrid的所有功能,同时添加新的属性:
Wzebra,WfirstColor ,WsecondColor。
当Wzebra的值为True时,显示斑马纹效果,其显示的效果是单数行颜色为WfirstColor,双数行颜色为WsecondColor。具体的见下面程序清单:

unit NewDBGrid;

interface

uses
Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs, DB, Grids, DBGrids, Excel97;
type
TDrawFieldCellEvent = procedure(Sender: TObject; Field: TField;
var Color: TCOlor; var Font: TFont; Row: Longint) of object;
//新的数据控件由 TDBGrid 继承而来
TNewDBGrid = class(TDBGrid)

private
//私有变量
FWZebra: Boolean; //是否显示斑马颜色
FWFirstColor: TColor; //单数行颜色
FWSecondColor: TCOlor; //双数行颜色
FDrawFieldCellEvent: TDrawFieldCellEvent;
procedure AutoInitialize; //自动初使化过程
procedure AutoDestroy;
function GetWFirstColor: TColor;
//FirstColor 的读写函数及过程
procedure SetWFirstColor(Value: TColor);
function GetWSecondColor: TCOlor;
procedure SetWSecondColor(Value: TColor);
function GetWZebra: Boolean;
procedure SetWZebra(Value: Boolean);

protected
procedure Scroll(Distance: Integer); override;
//本控件的重点过程
procedure DrawCell(Acol, ARow: Longint; ARect:
TRect; AState: TGridDrawState); override;

public
constructor Create(AOwner: TComponent); override;
destructor Destroy; override;

published
property WZebra: Boolean read GetWZebra write SetWZebra;
property OnDblClick;
property OnDragDrop;
property OnKeyUp;
property OnKeyDown;
property OnKeyPress;
property OnEnter;
property OnExit;
property OnDrawDataCell;
property WFirstColor: TColor
read GetWFirstColor write SetWFirstColor;
property WSecondColor: TColor
read GetWSecondColor write SetWSecondColor;
end;

procedure Register;

implementation

procedure Register;
begin
RegisterComponents(/'Data Controls/', [TNewDBGrid]);
end;

procedure TNewDBGrid.AutoInitialize;
begin
FWFirstColor := RGB(239, 254, 247);
FWSecondColor := RGB(249, 244, 245);
{可以在次添加需要的其它控件及初使化参数}
end;

procedure TNewDBGrid.AutoDestroy;
begin
{在这里释放自己添加参数等占用的系统资源}
end;

procedure TNewDBGrid.SetWZebra(Value: Boolean);
begin
FWZebra := Value;
Refresh;
end;

function TNewDBGrid.GetWZebra: Boolean;
begin
Result := FWZebra;
end;

function TNewDBGrid.GetWFirstColor: TColor;
begin
Result := FWFirstColor;
end;

procedure TNewDBGrid.SetWFirstColor(Value: TColor);
begin
FWFirstColor := Value;
Refresh;
end;

function TNewDBGrid.GetWSecondColor: TColor;
begin
Result := FWSecondColor;
end;

procedure TNewDBGrid.SetWSecondColor(Value: TColor);
begin
FWSecondColor := Value;
Refresh;
end;

constructor TNewDBGrid.Create(AOwner: TComponent);
begin
inherited Create(AOwner);
AutoInitialize;
end;

destructor TNewDBGrid.Destroy;
begin
AutoDestroy;
inherited Destroy;
end;
//实现斑马效果

procedure TNewDBGrid.DrawCell(ACol, ARow:
Longint; ARect: TRect; AState: TGridDrawState);
var
OldActive: Integer;
Highlight: Boolean;
Value: string;
DrawColumn: Tcolumn;
cl: TColor;
fn: TFont;
begin
{如果处于控件装载状态,则直接填充颜色后退出}
if csLoading in ComponentState then
begin
Canvas.Brush.Color := Color;
Canvas.FillRect(ARect);
Exit;
end;
if (gdFixed in AState) and (ACol - IndicatorOffset < 0) then
begin
inherited DrawCell(ACol, ARow, ARect, AState);
Exit;
end;
{对于列标题,不用任何修饰}
if (dgTitles in Options) and (ARow = 0) then
begin
inherited DrawCell(ACol, ARow, ARect, AState);
Exit;
end;
if (dgTitles in Options) then Dec(ARow);
Dec(ACol, IndicatorOffset);
if (gdFixed in AState) and ([dgRowLines, dgColLines] * Options =
[dgRowLines, dgColLines]) then
begin
{缩减ARect,以便填写数据}
InflateRect(ARect, -1, -1);
end
else
with Canvas do
begin
DrawColumn := Columns[ACol];
Font := DrawColumn.Font;
Brush.Color := DrawColumn.Color;
Font.Color := DrawColumn.Font.Color;
if FWZebra then //如果属性WZebra为True则显示斑马纹
if Odd(ARow) then
Brush.Color := FWSecondColor
else
Brush.Color := FWFirstColor;
if (DataLink = nil) or not DataLink.Active then
FillRect(ARect)
else
begin
Value := /'/';
OldActive := DataLink.ActiveRecord;
try
DataLink.ActiveRecord := ARow;
if Assigned(DrawColumn.Field) then
begin
Value := DrawColumn.Field.DisplayText;
if Assigned(FDrawFieldCellEvent) then
begin
cl := Brush.Color;
fn := Font;
FDrawFieldCellEvent(self, DrawColumn.Field, cl, fn, ARow);
Brush.Color := cl;
Font := fn;
end;
end;
Highlight := HighlightCell(ACol, ARow, Value, AState);
if Highlight and (not FWZebra) then
begin
Brush.Color := clHighlight;
Font.Color := clHighlightText;
end;
if DefaultDrawing then
DefaultDrawColumnCell(ARect, ACol, DrawColumn, AState);
if Columns.State = csDefault then
DrawDataCell(ARect, DrawColumn.Field, AState);
DrawColumnCell(ARect, ACol, DrawColumn, AState);
finally
DataLink.Activerecord := OldActive;
end;
if DefaultDrawing and (gdSelected in AState) and
((dgAlwaysShowSelection in Options) or Focused)
and not (csDesigning in Componentstate)
and not (dgRowSelect in Options)
and (ValidParentForm(self).ActiveControl = self) then
begin
//显示当前光标处为蓝底黄字,同时加粗显示
Windows.DrawFocusRect(Handle, ARect);
Canvas.Brush.COlor := clBlue;
Canvas.FillRect(ARect);
Canvas.Font.Color := clYellow;
Canvas.Font.Style := [fsBold];
DefaultDrawColumnCell(ARect, ACol, DrawColumn, AState);
end;
end;
end;
if (gdFixed in AState) and ([dgRowLines, dgColLines] * Options =
[dgRowLines, dgColLines]) then
begin
InflateRect(ARect, -2, -2);
DrawEdge(Canvas.Handle, ARect, BDR_RAISEDINNER, BF_BOTTOMRIGHT);
DrawEdge(Canvas.Handle, ARect, BDR_SUNKENINNER, BF_TOPLEFT);
end;
end;
//如果移动光标等,则需要刷新显示DBGrid

procedure TNewDBGrid.Scroll(Distance: Integer);
begin
inherited Scroll(Distance);
refresh;
end;

end.

以上程序在Win98 + Delphi 5下调试通过。
(作者: songwt 2005-1-30 10:13:07)  [资料] [短信] [好友] [邮箱]
10
 




在DBGrid控件中显示图形 
  如果在数据库中设置了一个为BLOB类型的字段用于保存图形,在使用DBGrid控件显示时,在表格中显示的是BLOB,而无法显示出图形,当然,有一些第三方控件可以显示出图形,但是要去找第三方控件不是一件容易的事,而且有些好用的都需要付费。能不能在DBGrid中显示图形呢?答案是肯定的。
  在DBGrid的OnDrawCell事件中加入如下代码即可在DBGrid控件中显示图形。
var
Bmp: TBitmap;
begin
if (Column.Field.DataTyp = ftBLOB) or (Column.Field.DataTyp = ftGraphic) then
begin
Bmp:=TBitmap.Create;
try
Bmp.Assign(Column.Field);
DBGrid1.Canvas.StretchDraw(Rect,Bmp);
Bmp.Free;
Except
Bmp.Free;
end;
end;
end;
  按照类似的方法,就可以在DBGrid中显示Memo类型的字段内容。
  另外,在往数据库中保存图形时,建议使用EMF图元文件,这样数据库文件的大小不会变的十分惊人,我试过了,同样是一幅400*300的图形,如果用位图,保存100多幅时,数据库文件大小会达到近20MB,而使用EMF矢量图形保存,保存800多幅时才260多KB,保存EMF矢量图形的方法与保存位图是差不多的,在DBGrid中显示也差不多,只不过BLOB型字段内容不能直接Assign给EMF文件,要用MemoryStream来中转。


如何侦测DBGrid目前的记录与栏位资讯
请问用什麽方式可以抓到游标或滑鼠目前所在DBGrid的Record? 我的意思是,让游标所在之record可以立即显示在另外的edit 内

如果您的问题是对应一组 Edit 元件的话, 建议采用 TDBEdit 或 TDBLabel, 可以不必再费心管记录位置;
如果是只有一个 EditBox, 内容要一直反应 DBGrid 的目前记录的目前栏位, 那可以同时在 DataSource 的 OnDataChange 与 DbGrid 的 OnColEnter 这两个事件中写更新EditBox内容的程式.
例如 DBGrid 的 OnColEnter 事件:

procedure TForm1.DBGrid1ColEnter(Sender: TObject);
begin
if DBGrid1.SelectedField <> nil then
Edit1.Text := DBGrid1.SelectedField.AsString;
end;

但只靠 OnColEnter 是不够的, 因为, 在同一个 Column(同一个栏位)上下移动反白方格时, OnColEnter 是不会被触发的, 所以, 可以再搭配 OnDataChange事件, 在 State 为 dsBrowse 时的 DataChange, 可以视同记录位置的改变,以下的程式是呼叫 DBGrid 的 OnColEnter 事件处理程序:

procedure TForm1.DataSource1DataChange(Sender: TObject; Field: TField);
begin
if DataSource1.State = dsBrowse then
DBGrid1ColEnter(Sender);
end;

用DbGrid制作edit录入时的下拉提示框
在Delphi语言中提拱了不少数据输入的方法,如可从数据库中选择或人工输入的控件有:DBListBox、DBComboBox、DBLookupListBox、DBLookupComboBox等。但对于这样一个例子:数据库名为dm.db,其中有两个字段:
代码:Code
名称:Name
要求根据用户输入的代码,去获取该代码对应的名称。

一般的用户并不知道代码和名称的对应关系,如让用户输入代码,选出对应的名称,由于上述的控件不能使操作人员看到代码和名称的对应关系,如让用户根据代码用下拉框去查找到对应的该条纪录的名称,将很难操作。

根据这种情况,我编制了下面程序,把DBGrid做为Edit的下拉列表框辅助操作,在DBGrid中直观地显示出代码和名称的对应关系,并且能够根据用户录入代码的变化情况,随时更新DBGrid中的记录指针,使用户可以直观方便地点取所需要的名字,而且DBGrid是依据用户在Edit中输入代码时才显现,跳出Edit框即消失。这种方法既为用户录入提供了方便,又不影响界面的整体美观,效果不错。现把该程序提供给大家,你们可根据自己的需要,对程序进行加工处理,应用于程序开发中,希望起到抛砖引玉的作用。

【问题】:做这样一个小程序:让用户输入代码,然后将名称显示在窗体上。

1、首先我们可以建立一个Form,在此Form中增加控件:

Table : Table1,设置其属性对应代码库dm.db,并将Active置为True
DataSource : DataSource1, 设置其属性DataSet为Table1
Edit : CodeEdit,NameEdit分别对应代码输入框和名称显示框
DBGrid : DBGrid1, 设置其属性DataSource为DataSource1
并把CodeEdit的属性Text的值置空,NameEdit的属性Text的值置空。

2、对照以下语句,修改CodeEdit的OnEnter、OnExit、OnKeyDown、OnKeyUp事件:

在CodeEdit的OnEnter事件如下:
procedure TForm1.CodeEditEnter(Sender: TObject);
begin
if CodeEdit.text<>/'/' then
begin
CodeEdit.SelStart:=length(CodeEdit.text);
Table1.locate(/'code/', CodeEdit.text,[lopartialkey]);
End;
end;

CodeEdit的OnExit事件如下:
procedure TForm1.CodeEditExit(Sender: TObject);
begin
if activecontrol<>dbgrid1 then
begin
dbgrid1.Visible:=false;
Table1.Locate(/'code/',codeedit.text,[lopartialkey]);
if Table1.Eof then
begin
dbgrid1.Visible:=true;
exit;
end;
if not Table1.Eof then
begin
codeedit.Text:=Table1.fieldbyname(/'code/').asstring;
NameEdit.Text := Table1.fieldbyname(/'name/').asstring;
end;
end;
end;

CodeEdit的OnKeyDown事件如下:
Procedure Tform1.CodeEditKeyDown(Sender: TObject;var Key: Word;Shift: TShiftState);
var
i:integer;
begin
if (Table1.RecordCount>0) then
begin
case key of 48..57:
begin
dbgrid1.Visible:=true;
Table1.Locate(/'code/',CodeEdit.text,[lopartialkey]);
end;
vk_next:
if dbgrid1.Visible then
begin
i:=0;
while (not Table1.Eof) and (i<11) do
begin
Table1.Next;
i:=i+1;
end;
CodeEdit.Text:=Table1.fieldbyname(/'code/').asstring;
End;
vk_prior:
if dbgrid1.Visible then
begin
i:=0;
while (not Table1.Bof) and (i<11) do
begin
Table1.prior;
i:=i+1;
end;
CodeEdit.Text:=Table1.fieldbyname(/'code/').asstring;
end;
vk_down:
if dbgrid1.Visible then
begin
if not Table1.Eof then
begin
Table1.Next;
CodeEdit.Text:=Table1.fieldbyname(/'code/').asstring;
end;
end;
vk_up:
if dbgrid1.Visible then
begin
if not Table1.Bof then
begin
Table1.Prior;
CodeEdit.Text:=Table1.fieldbyname(/'code/').asstring;
end;
end;
end;
end
else
dbgrid1.Visible:=false;
CodeEdit.SelStart:=length(CodeEdit.text);
end;

CodeEdit的OnKeyUp事件如下:
procedure Tform1.CodeEditKeyUp(Sender: TObject; var Key: Word; Shift: TShiftState);
begin
if (Table1.RecordCount>0) then
begin
if ((key>=48) and (key<=57)) then
Table1.Locate(/'code/',codeedit.text,[lopartialkey]);
if (key=VK_back) and (codeedit.text<>/'/') then
Table1.Locate(/'code/',codeedit.text,[lopartialkey]);
if (key=VK_BACK) and (codeedit.text=/'/') then
Table1.First;
if (key=vk_down) or (key=vk_up) or (key=vk_prior) or (key=vk_next) then
if dbgrid1.Visible then
codeedit.Text:=Table1.fieldbyname(/'code/').asstring;
end
else
dbgrid1.Visible:=false;
codeedit.SelStart:=length(codeedit.text);
end;

本程序在Windows98+Delphi4.0、5.0下均调试通过。

Delphi的dbgrid中根据数据的属性不同显示不同的颜色
(请同时参考如何动态更新DBGrid的颜色?/如何使DBGRID网格的颜色随此格中的数据值的变化而变化?)

在应用系统中,用户常常要求把数据按不同的颜色显示出来,只要你在 Dbgrid 的 DrawColumnCell 事件中加入以下代码就可以了:
If Query.fieldbyname(/'字段名/').values 满足条件 then
Begin
Dbgrid.Canvas.Brush.Color := 颜色(如:clInfoBk) ;
Dbgrid.DefaultDrawColumnCell( Rect, DataCol, Column, [gdFixed,gdFocused,gdSelected] );
End ;

给DBGrid加入排序功能(同时参考“点击DBGrid的Title对查询结果排序”)

在实际数据库管理系统中,用户对表中数据的操作,最频繁的莫过于浏览查询了,而查询中若能提供为某字段建立的排序功能,则非常有利于用户对“关键数据”的了解。

Windows的用户都知道,在“我的电脑”或“资源管理器”中打开任一文件夹,若以“详细资料”方式查看,系统会显示出该文件夹下的子文件夹和文件相关信息,如:名称、类型 、大小、修改时间,用户只需要单击标题栏中的相应项,则系统自动按该项进行“升序”(或“降序”)的排列显示,这样用户便能轻松查看相应的文件夹或文件对象的内容。

受此启发,考虑能不能在显示数据的Grid表格中完成如此功能呢?答案是肯定的。下面以在Delphi中的实现方法为例,通过具体内容,介绍该功能的实现。
步骤如下:

一、先建立一数据表
该表以Delphi 中最常用的Paradox为类型,取名为Student,反映(在职)学生的基本情况。该表各字段定义如下:
--------------------------------------------
字段名    类型      大小
序号     Short型     / (Key*)
学号     Alpha型     6
出生日期   Date型      /
性别     Alpha型     2
婚否     Logical型    /
英语     Number型     /
高数     Number型     /
PASCAL    Number型     /
备注     Memo型      20
-------------------------------------------
保存后,随意往表中输入3至5条记录内容。

注:①表中必须建立关键索引(为首字段建立)。此处为“序号”字段;
②该表中使用了Paradox常用的几种字段类型,但尚未全部包含。

二、建立项目,实现功能
1.新建一项目,并为表单添加相关控件,各控件主要属性如下表:

2.建立各Click的事件代码

Button1(打开表)的Click事件代码如下:
procedure TForm1.Button1Click(Sender: TObject);
begin
Table1.Open; // 打开Table1关联的表Student
end;

Button2(关闭表单)的Click事件代码如下:
procedure TForm1.Button2Click(Sender: TObject);
begin
Application.Terminate;
end;

DBGrid1的TitleClick事件代码如下:
procedure TForm1.DBGrid1TitleClick(Column: TColumn);
//注:本过程参数Column包含的信息量非常多
begin
MySort(DBGrid1,Column);
end; //调用字段排序
其中,MySort(DBGrid1,Column)为自定义的排序过程,具体代码见下述。

3.建立通用处理模块
为使该功能具有“通用性”,将其定义为一过程。
首先,预声明过程及建立两个全局私有变量:

...
Type
...

procedure MySort(DBGrid0:TDBGrid; Column: TColumn);//预声明过程

private

{ Private declarations }
psIndexName:string; //记录当前索引名称
plAscend:boolean; //记录当前索引名称的索引状态

public
{ Public declarations }

end;

...

其次,该过程完整代码如下:

procedure TForm1.MySort(DBGrid0:TDBGrid; Column: TColumn);
var
//本模块使用到的psIndexName, plAscend两个变量见上定义
mode:char; //记录是“升序”还是“降序”
ColName:string; //记录当前字段名
iCol:Integer; //记录当前列号

begin
with DBGrid0.DataSource.DataSet as TTable do //Table0
begin
//检测当前工作表是否已打开
if not Active
then begin
MessageBeep(0);
Application.MessageBox(/'工作表尚未打开!/',/'停止/',MB_OK+MB_ICONSTOP);
Abort
end;

//检测当前字段是否“能排序”。以下字段类型不能排序
case Column.Field.DataType of
ftBoolean,
ftBytes,
ftBlob, //Binary
ftMemo,
ftGraphic,
ftFmtMemo, //Formatted memo
ftParadoxOle: //OLE
begin
MessageBeep(0);
Application.MessageBox(Pchar(/'项目"/'+Column.FieldName+/'"/'+/'不能排序!/'),/'停止/',MB_OK+MB_ICONSTOP);
Abort
end;
end; //case
mode:=/'0/';
iCol:=Column.Field.FieldNo-1;
try
ColName:=Column.fieldname;
if psIndexName=Column.fieldname
then begin //与原来同列
if plAscend //升序
then begin
mode:=/'2/';
IndexName:=ColName+/'2/'; //应“降序”
end
else begin
mode:=/'1/';
IndexName:=ColName+/'1/'; //应“升序”
end;
plAscend:=not plAscend;
end
else begin //新列
IndexName:=ColName+/'2/';
plAscend:=false;
psIndexName:=ColName;
end;
except
on EDatabaseError do //若未有索引,则重新建立
begin
Messagebeep(0);
//以下新建索引
IndexName:=/'/';
Close;
Exclusive:=true;
if mode=/'1/'
then AddIndex(ColName+/'1/',ColName,[ixCaseInsensitive],/'/')//
else //包括/'0/'
AddIndex(ColName+/'2/',ColName,[ixDescending,ixCaseInsensitive],/'/');
Exclusive:=false;
Open;
try //try 1
if mode<>/'1/'
then begin
mode:=/'2/';//转换
plAscend:=false;
end
else plAscend:=true;
IndexName:=ColName+mode;
psIndexName:=ColName;
except
on EDBEngineError do
IndexName:=/'/';
end //try 2
end
end;
First;
end; //with
DBGrid0.SelectedIndex:=iCol;
end;//End of MySort

本过程已对所有可能的错误进行了相应的检测及处理,代码是比较完整的。因此,把该过程放入你相应的单元中,对每一个DBGrid,只要传递不同的DBGrid及Column参数,就能实现对应数据表的自动排序处理,而事先只为某字段建立一关键索引即可,其它Secondery Indexes的建立均在程序中自动完成,但会为每一个建立了索引的字段生成了一些附加文件(如*.XG?,*YG?等)。当然若有必要,可以在表单关闭前将所有的附加文件删除。


(作者: songwt 2005-1-30 10:13:39)  [资料] [短信] [好友] [邮箱]
11
 




将 DBGrid 中的内容输出至 Excel 或 ClipBoard 

//注意:下面的方法必须包含 ComObj, Excel97 单元
//-----------------------------------------------------------
// if toExcel = false, export dbgrid contents to the Clipboard
// if toExcel = true, export dbgrid to Microsoft Excel
procedure ExportDBGrid(toExcel: Boolean);
var
bm: TBookmark;
col, row: Integer;
sline: String;
mem: TMemo;
ExcelApp: Variant;
begin
Screen.Cursor := crHourglass;
DBGrid1.DataSource.DataSet.DisableControls;
bm := DBGrid1.DataSource.DataSet.GetBookmark;
DBGrid1.DataSource.DataSet.First;

// create the Excel object
if toExcel then
begin
ExcelApp := CreateOleObject(/'Excel.Application/');
ExcelApp.WorkBooks.Add(xlWBatWorkSheet);
ExcelApp.WorkBooks[1].WorkSheets[1].Name := /'Grid Data/';
end;

// First we send the data to a memo
// works faster than doing it directly to Excel
mem := TMemo.Create(Self);
mem.Visible := false;
mem.Parent := MainForm;
mem.Clear;
sline := /'/';

// add the info for the column names
for col := 0 to DBGrid1.FieldCount-1 do
sline := sline + DBGrid1.Fields[col].DisplayLabel + #9;
mem.Lines.Add(sline);

// get the data into the memo
for row := 0 to DBGrid1.DataSource.DataSet.RecordCount-1 do
begin
sline := /'/';
for col := 0 to DBGrid1.FieldCount-1 do
sline := sline + DBGrid1.Fields[col].AsString + #9;
mem.Lines.Add(sline);
DBGrid1.DataSource.DataSet.Next;
end;

// we copy the data to the clipboard
mem.SelectAll;
mem.CopyToClipboard;

// if needed, send it to Excel
// if not, we already have it in the clipboard
if toExcel then
begin
ExcelApp.Workbooks[1].WorkSheets[/'Grid Data/'].Paste;
ExcelApp.Visible := true;
end;

FreeAndNil(mem);
// FreeAndNil(ExcelApp);
DBGrid1.DataSource.DataSet.GotoBookmark(bm);
DBGrid1.DataSource.DataSet.FreeBookmark(bm);
DBGrid1.DataSource.DataSet.EnableControls;
Screen.Cursor := crDefault;
end;

怎样获得DBGrid中的cell的坐标???
//新建一个工程,在窗体上加一个StringGrid

//下面是unit1.pas

unit Unit1;

interface

uses
Windows Messages SysUtils Classes Graphics Controls Forms Dia

logs
Grids;

type
TForm1 = class(TForm)
StringGrid1: TStringGrid;
procedure FormCreate(Sender: TObject);
procedure StringGrid1DblClick(Sender: TObject);
procedure StringGrid1MouseDown(Sender: TObject; Button: TMouseButton; Shift: TShiftState; X Y: Integer);
procedure StringGrid1Click(Sender: TObject);

private
{ Private declarations }

public
{ Public declarations }
end;

var
Form1: TForm1;

implementation

const
WeekDayName :Array[1..7] of String=(/'星期一/' /'星期二/' /'星期三/' /'星期四
/' /'星期五/' /'星期六/' /'星期日/');

var
X_Pos Y_Pos:integer;//鼠标在窗体的位置
Col_Pos Row_Pos:integer;//单元位置

{$R *.DFM}

procedure TForm1.FormCreate(Sender: TObject);
var
i:integer;
begin
Application.HintPause:=100;
Font.Size :=10;
Caption:=/'STring岩石程序/';
StringGrid1.ShowHint :=True;
StringGrid1.ColCount :=8;
StringGrid1.RowCount :=12;
StringGrid1.Cells[0 0]:=/'第18周/';
for i:=1 to StringGrid1.ColCount -1 do
StringGrid1.Cells[i 0]:=WeekDayName[i];
for i:=1 to StringGrid1.RowCount -1 do
StringGrid1.Cells[0 i]:=InttoStr(i+7)+/':00/';
StringGrid1.Options :=StringGrid1.Options+[goTabs goROwSizing goColSizing]-[goEditing];
end;

procedure TForm1.StringGrid1DblClick(Sender: TObject);
var
SchemeItem:String;
begin
StringGrid1.MouseToCell(X_Pos Y_Pos Col_Pos Row_Pos) ; //转换到单位位置
if (Col_Pos<0 )or (Row_Pos<0 ) then
Exit;
if (StringGrid1.Cells[Col_Pos Row_Pos]<>/'/' ) then //取消计划概要
begin
StringGrid1.Cells[Col_Pos Row_Pos]:=/'/';
Exit;
end;
SchemeItem:=InputBox(/'提示/' /'请输入计划概要:/' /'会议/');
StringGrid1.Cells[Col_Pos Row_Pos]:=SchemeItem;
End;

procedure TForm1.StringGrid1MouseDown(Sender: TObject; Button: TMouseButton; Shift: TShiftState; X Y: Integer);
begin
X_Pos:=x;
Y_Pos:=y;
end;

procedure TForm1.StringGrid1Click(Sender: TObject);
begin
StringGrid1.MouseToCell(X_Pos Y_Pos Col_Pos Row_Pos);//转化到单元位置
StringGrid1.Hint :=StringGrid1.Cells[Col_Pos Row_Pos];//暂时借用该特性显示工作计划
end;

end.

多层表头的DBGrid(推荐大家学习,很有用)
TclientDataSet控件是在Delphi中设计多层分布式数据库程序的核心控件,在Delphi3中它最早出现,在Delphi4和Delphi5中得到了进一步加强。TclientDataSet控件具有强大的功能,无论是单层、两层C/S和多层结构都可以使用TclientDataSet控件。从borland公司的公布的资料看,它的功能还将得到不断增强,本文主要介绍利用TclientDataSet控件的特色功能——抽象字段类型配合TDBGRID控件实现复杂题头。

在设计数据库录入界面时,经常需要实现一些复杂题头,这通常需要利用第三方控件或进行特殊处理才能实现。而在Delphi中利用TClientDataSe的ADT(抽象字段类型)配合TDbgrid控件,可以非常容易地实现这种题头。

下面就以一个员工的工资信息表来说明具体步骤。
假设某单位的工资信息表的结构如图所示。
-----------------
基本信息
-----------------

性别 | 年龄 | 籍贯 | 职称

首先生成一个新的 Application,在窗体上添加一个 TClientDataSet 构件和 TDataSource 构件,其 name 属性分别为 ClientDataSet1 和 DataSource1 ,并把 DataSource1 的 DataSource 属性设置为 ClientDataSet1 上;添加一个 TDBGRID 和 TdbNavigator 控件,命名为 DBGRID1 和 DbNavigator1,其 Datasource1 属性设置为 ClientDataSet1。

然后建立 TclientDataSet 的字段定义。这里只介绍如何定义抽象字段:将基本信息和工资作为两个抽象字段,如图3所示,将两个字段分别命名为 INFO 和 Salary。

然后依次建立 INFO 字段和 SALARY 的子字段,单击对象观察器的 ChildDefs,进入子字段编辑器,依次输入该字段的子字段。然后调用 TclientDataSet 的快捷菜单(鼠标点击 TclientDataSet 控件,然后右击鼠标) CreateDataSet 建立 CDS 数据表,并保存文件。最后建立 TClientDataSet 的永久字段,TclientDataSet 的快捷菜单,选择ADD All Fields。

至此有关 ClientDataSet 的设置完毕。
在设置完 ClientDataSet 之后,需要设置DBGRID的显示属性。主要就是设置 Colums 的有关属性(略)。编译运行即可出现如图2所示的运行界面。然后添加一个 Tdbnavigator 控件,将其 DataSource 属性设置为 Datasource1。这些与普通的基于BDE的数据库应用是一样的,不多叙述。

在 dbgrid 中实现 copy、paste 功能
  工具条上的Cut、Copy和Paste加速按钮,对于使用Windows下编辑器的人来说,恐怕都是非常熟悉而且不可缺少的。Delphi中的有些控件,如:TDBEdit、TDBImage、TDBMemo、TEdit等,具有CutToClipboard、CopyToClipboard和PasteFromClipboard方法,在这些控件上,利用这几个方法,只要通过简单的编程,就可以实现上述加速按钮。但TDBGrid控件却不提供上述方法,无法直接实现这几种功能。而在单机的数据库应用程序中,TDBGrid却经常被用来进行数据(包括数字和文字)的输入,没有Copy和Paste功能,使用起来深感不便。笔者在编程过程中,利用中间控件进行“过渡”,间接地实现了这几种功能。

  【主要思路】:既然TDBGrid控件无法直接实现Copy和Paste编辑功能,则可以将TDBGrid控件中需要进行这几种编辑的字段(Field)的内容,转移到具备这几种功能的控件(以TDBEdit为例)中去,编辑完毕后,再传回到TDBGrid中。

  【具体方法】:在已设计好的包含有TDBGrid控件(设名为DBGrid1)的窗体中,增加一个TDBEdit(设名为DBEdit1)控件,其DataSources属性设为与DBGrid1的DataSources属性相同,对DBGrid1控件的OnColEnter事件编程,使DBEdit1的DataField属性值等于DBGrid1控件的被选择字段的字段名。再在窗体中增加两个快速按钮:Copy和Paste,图形可选Delphi子目录下ImagesιButtons子目录里的Copy.bmp和Paste.bmp。
对Copy快速按钮的OnClick事件编程:
  DBEdit1.CopyToClipboard;

  对Paste快速按钮的OnClick事件编程:
  DBEdit1.PasteFromClipboard;
  DBGrid1.SelectedField.AsString:=DBEdit1.Text;

  此时,如果DBGrid1中的某一单元Cell数字需要粘贴另一单元Cell2的部分或全部内容,用鼠标单击选择Cell2,此时DBEdit1所显示的内容与Cell2的内容相同。在DBEdit1中用鼠标拖曳选择部分或全部内容,单击Copy快速按钮;再用鼠标单击选择Cell,此时DBEdit1所显示的内容与Cell相同,在DBEdit中欲粘贴刚才所选内容的位置插入光标,单击Paste快速按钮,则刚才所选内容插入到光标位置,Cell的内容也随之改变成插入后的内容,由此完成了一次Copy—Paste操作。

  用这种方法实现Copy—Paste操作,比正常的操作多了一次鼠标的键击、两次鼠标的移动。在重复输入的内容不多,且操作者键盘输入很快很熟练的情况下,这种实现Copy—Paste的方法,意义似乎不大。但如果应用程序的使用者是那些并没有掌握某种快速文字输入技巧、很有可能还在使用拼音输入法的人,如果使用者对正常的Copy—Paste方法本来就不熟练(则感觉不到这种方法的不合常规),且又非常地善于在一长串的同音字里翻来翻去地寻找的话,这还是一种不错的方法。如果哪位读者有能在TDBGrid中实现常规Copy—Paste操作的方法,请不吝赐教。

  以下是有关的程序代码:
  procedure TUnitDetail.DBGrid1ColEnter(Sender:TObject);
  begin
  case DBGrid1.SelectedIndex of
  0:DBEdit1.DataField:=/'UnitNum/';
 1:DBEdit1.DataField:=/'UnitName/';
  2:DBEdit1.DataField:=/'Header/';
  3:DBEdit1.DataField:=/'Address/';
  4:DBEdit1.DataField:=/'Tel/';
  end;
  end;

  
  procedure TUnitDetail.SBCopyClick(Sender:TObject);
  begin
  DBEdit1.CopyToClipboard;
  end;

  procedureTUnitDetail.SBPasteClick(Sender:TObject);
  begin
  DBEdit1.PasteFromClipboard;
  DBGrid1.SelectedField.AsString:=DBEdit1.text;
  end;
(作者: songwt 2005-1-30 10:14:25)  [资料] [短信] [好友] [邮箱]
12
 




禁止在DBGrid中按delete删除记录 
procedure TForm1.DBGrid1KeyDown(Sender: TObject; var Key: Word; Shift: TShiftState);
begin
if (ssctrl in shift) and (key=vk_delete) then key:=0;
end;

给 DBGrid 添加搜索功能
下面给出一个完整的例子,要注意的是:一开始需要将查询的字段全部加入TDBGrid中,否则会有访问冲突的。

unit Unit1;

interface

uses
Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs, Db, DBTables, Grids, DBGrids, StdCtrls, ExtCtrls, DBCtrls;

type
TTFm_Main = class(TForm)
qry_Data: TQuery;
Ds_Data: TDataSource;
Ed_Search: TEdit; //附加一个TEdit框.
dbg_Data: TDBGrid;
Database1: TDatabase; //数据库构件,试验时可任意设定。
DBNavigator1: TDBNavigator;
procedure dbg_DataTitleClick(Column: TColumn);
procedure FormCreate(Sender: TObject);
procedure Ed_SearchChange(Sender: TObject);

private
{ Private declarations }
FQueryStatement: string; // SQL 查询语句。
FALphaNumericKeyPress: TKeyPressEvent;

public
{ Public declarations }
property QueryStatement: string read FQueryStatement;
procedure FloatOnKeyPress(Sender: TObject; var Key: Char);
end;

var
TFm_Main: TTFm_Main;

implementation

{$R *.DFM}

procedure TTFm_Main.dbg_DataTitleClick(Column: TColumn);
var
vi_Counter: Integer;
vs_Field: string;
begin
with dbg_Data do
begin

//First, deselect all the Grid Columns
for vi_Counter := 0 to Columns.Count - 1 do
Columns[vi_Counter].Color := clWindow;

//Next "Select" the column the user has Clicked on
Column.Color := clTeal;

//Get the FieldName of the Selected Column
vs_Field := Column.FieldName;

//Order the Grid Data by the Selected column
with qry_Data do
begin
DisableControls;
Close;
SQL.Clear;
SQL.Text := QueryStatement + /' ORDER BY /' + vs_Field;
Open;
EnableControls;
end;
//Get the DataType of the selected Field and change the Edit event

//OnKeyPress to the proper method Pointer
case Column.Field.DataType of
ftFloat: Ed_Search.OnKeyPress := FloatOnKeyPress;
else
Ed_Search.OnKeyPress := FALphaNumericKeyPress;
end;
end;
end;

procedure TTFm_Main.FloatOnKeyPress(Sender: TObject; var Key: Char);
begin
if not (Key in [/'0/'../'9/', #13, #8, #10, #46]) then
Key := #0;
end;

procedure TTFm_Main.FormCreate(Sender: TObject);
begin

//Keep a pointer for the default event Handler
FALphaNumericKeyPress := Ed_Search.OnKeyPress;

//Set the original Query SQL Statement
FQueryStatement := /'SELECT * FROM your_table_name/';

//Select the first Grid Column
dbg_DataTitleClick(dbg_Data.Columns[0]);
end;

procedure TTFm_Main.Ed_SearchChange(Sender: TObject);
var
vi_counter: Integer;
vs_Field: string;
begin
try
with dbg_Data do
begin

//First determine wich is the Selected Column
for vi_Counter := 0 to Columns.Count - 1 do
if Columns[vi_Counter].Color = clTeal then
begin
vs_Field := Columns[vi_Counter].FieldName;
Break;
end;

//Locate the Value in the Query
with qry_Data do
case Columns[vi_Counter].Field.DataType of
ftFloat: Locate(vs_Field, StrToFloat(Ed_Search.Text),
[loCaseInsensitive, loPartialKey]);
else
Locate(vs_Field, Ed_Search.Text, [loCaseInsensitive, loPartialKey]);
end;
end;
except
end;
end;

end.

数据网格自动适应宽度
///源代码开始
uses
Math;

function DBGridRecordSize(mColumn: TColumn): Boolean;
{ 返回记录数据网格列显示最大宽度是否成功 }
begin
Result := False;
if not Assigned(mColumn.Field) then Exit;
mColumn.Field.Tag := Max(mColumn.Field.Tag,
TDBGrid(mColumn.Grid).Canvas.TextWidth(mColumn.Field.DisplayText));
Result := True;
end; { DBGridRecordSize }

function DBGridAutoSize(mDBGrid: TDBGrid; mOffset: Integer = 5): Boolean;
{ 返回数据网格自动适应宽度是否成功 }
var
I: Integer;
begin
Result := False;
if not Assigned(mDBGrid) then Exit;
if not Assigned(mDBGrid.DataSource) then Exit;
if not Assigned(mDBGrid.DataSource.DataSet) then Exit;
if not mDBGrid.DataSource.DataSet.Active then Exit;
for I := 0 to mDBGrid.Columns.Count - 1 do begin
if not mDBGrid.Columns[I].Visible then Continue;
if Assigned(mDBGrid.Columns[I].Field) then
mDBGrid.Columns[I].Width := Max(mDBGrid.Columns[I].Field.Tag,
mDBGrid.Canvas.TextWidth(mDBGrid.Columns[I].Title.Caption)) + mOffset
else mDBGrid.Columns[I].Width :=
mDBGrid.Canvas.TextWidth(mDBGrid.Columns[I].Title.Caption) + mOffset;
mDBGrid.Refresh;
end;
Result := True;
end; { DBGridAutoSize }
///源代码结束

///使用示例开始
procedure TForm1.DBGrid1DrawColumnCell(Sender: TObject; const Rect: TRect;
DataCol: Integer; Column: TColumn; State: TGridDrawState);
begin
DBGridRecordSize(Column);
end;

procedure TForm1.Button1Click(Sender: TObject);
begin
DBGridAutoSize(DBGrid1);
end;
///使用示例结束

移除DBGrid的垂直滚动条(参考“判断Grid是否有滚动条?”)
type
TNoVertScrollDBGrid = class(TDBGrid)
protected
procedure Paint; override;
end;

procedure Register;

implementation

procedure TNoVertScrollDBGrid.Paint;

begin
SetScrollRange(Self.Handle, SB_VERT, 0, 0, False);
inherited Paint;
end;

procedure Register;
begin
RegisterComponents(/'Data Controls/', [TNoVertScrollDBGrid]);
end;

end.

2003-11-19 14:00:48 DBGrid拖放的例子(请同时参考“在TDBGrid控件中实现拖放的另外一个思路/在DBGrid上Drag & Drop(拖放)”)
unit GridU1;

interface

uses
Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms,
Dialogs, Db, DBTables, Grids, DBGrids, StdCtrls;

type
TForm1 = class(TForm)
MyDBGrid1: TDBGrid;
Table1: TTable;
DataSource1: TDataSource;
Table2: TTable;
DataSource2: TDataSource;
MyDBGrid2: TDBGrid;
procedure MyDBGrid1MouseDown(Sender: TObject;
Button: TMouseButton; Shift: TShiftState; X, Y: Integer);
procedure MyDBGrid1DragOver(Sender, Source: TObject;
X, Y: Integer; State: TDragState; var Accept: Boolean);
procedure MyDBGrid1DragDrop(Sender, Source: TObject;
X, Y: Integer);
private
{ Private declarations }
public
{ Public declarations }
end;

var
Form1: TForm1;

implementation

{$R *.DFM}

var
SGC : TGridCoord;

procedure TForm1.MyDBGrid1MouseDown(Sender: TObject;
Button: TMouseButton; Shift: TShiftState; X, Y: Integer);
var
DG : TDBGrid;
begin
DG := Sender as TDBGrid;
SGC := DG.MouseCoord(X,Y);
if (SGC.X > 0) and (SGC.Y > 0) then
(Sender as TDBGrid).BeginDrag(False);
end;

procedure TForm1.MyDBGrid1DragOver(Sender, Source: TObject;
X, Y: Integer; State: TDragState; var Accept: Boolean);
var
GC : TGridCoord;
begin
GC := (Sender as TDBGrid).MouseCoord(X,Y);
Accept := Source is TDBGrid and (GC.X > 0) and (GC.Y > 0);
end;

procedure TForm1.MyDBGrid1DragDrop(Sender, Source: TObject;
X, Y: Integer);
var
DG : TDBGrid;
GC : TGridCoord;
CurRow : Integer;
begin
DG := Sender as TDBGrid;
GC := DG.MouseCoord(X,Y);
with DG.DataSource.DataSet do begin
with (Source as TDBGrid).DataSource.DataSet do
Caption := /'You dragged "/'+Fields[SGC.X-1].AsString+/'"/';
DisableControls;
CurRow := DG.Row;
MoveBy(GC.Y-CurRow);
Caption := Caption+/' to "/'+Fields[GC.X-1].AsString+/'"/';
MoveBy(CurRow-GC.Y);
EnableControls;
end;
end;

end.

解决dbgrid上下移动的另外一种办法
不用重新寫控件,也不用改控件!直接將光色代碼部分加到你的窗體單無中就行.
type
【 TDBGrid = class(DBGrids.TDBGrid)
private
FOldGridWnd : TWndMethod;
procedure NewGridWnd (var Message : TMessage);
public
constructor Create(AOwner: TComponent); override;
end;】
TXXXForm = class(TForm)
......
end;
{ TDBGrid }


【constructor TDBGrid.Create(AOwner: TComponent);
begin
inherited;
Self.FOldGridWnd := Self.WindowProc;
Self.WindowProc := NewGridWnd;
end;

procedure TDBGrid.NewGridWnd(var Message: TMessage);
var
IsNeg : Boolean;
begin

if Message.Msg = WM_MOUSEWHEEL then
begin
IsNeg := Short(Message.WParamHi) < 0;
if IsNeg then
self.DataSource.DataSet.MoveBy(1)
else
self.DataSource.DataSet.MoveBy(-1)
end
else Self.FOldGridWnd(Message);

end;



TDBGrid = class(DBGrids.TDBGrid)
....
end;
一定要放在最前面,也可以將【】紅色部分代碼寫一共用單無中,
然後uses publicunit;
再加上這一句:
TDBGrid = Class(publicunit.TDBGrid);
TXXFrom =Class(TForm)

2003-11-25 17:29:59 修改过的Grids,可以支持鼠标滚轮翻页的功能。
拷贝到/delphi/source/vcl目录下就能使用。不过我用的是D7,低版本的朋友还是先看看再使用,以防不测。
修改过的Grids,可以支持鼠标滚轮翻页的功能。

2003-12-1 10:29:21 可以支持鼠标滚轮翻页的功能的Grids
详细说明见内。
可以支持鼠标滚轮翻页的功能的Grids

关于DBGrid中下拉列表的两种设计比较
一、DBGrid 中 的 下 拉 列 表
在 DBGrid 网格中实现下拉列表,设置好 DBGrid 中该字段的 PickList 字符串列表、初始的序号值 DropDownRows 即可。以职工信息库中的籍贯字段(字符串类型)为例,具体设计步骤如下:
1、在窗体上放置 Table1、DataSource1、DBGrid1、DBNavigator1 等控件对象,按下表设置各个对象的属性:

---------------------------------------
对象 属性 设定值
---------------------------------------
Table1 DataBase sy1
TableName zgk.dbf //职工信息库
DataSource1 DataSet Table1
DbGrid1 DataSource DataSource1
DBNavigator1 DataSource Datasource1
-------------------------------------------

2、双击 Table1,在弹出的 Form1.Table1 窗口中,用右键弹出快捷菜单,单击 Add Fields 菜单项;选择所有的字段后,按 OK 按钮。

3、修改第 2 步新增字段的 DisplayLabel 属性。以 Table1ZGBH 字段为例, 在 Object Inspector 窗口中选择 Table1ZGBH,修改属性 DisplayLabel= 职工编号,其余字段类似。

4、双击 DBGrid1,在弹出的 Editing DBGrid1.Columns 窗口中, 单击 Add all Fields 按钮,增加 Table1 的所有字段。

5、在 Editing DBGrid1.Columns 窗口,选择 jg 这一行,切换到 Object Inspector 窗口,修改它的 PickList.Strings 为
“湖北枝江市
北京市
河南平顶山市
浙江德清市”

6、在 Form1.Oncreate 事件中写入语句:

Table1.Open;

7、F9 运行,用鼠标点击某个记录的籍贯字段,右边即出现一个按钮,点击这个按钮,可出现一个下拉列表,包含第 5 步中输入的四行字符串,可用鼠标进行选择。当然也可以自行输入一个并不属下拉列表中的字符串。


二、DBGrid 中 的 查 找 字 段
所谓查找字段(LookUp Field),即 DBGrid中的某个关键字段的数值来源于另外一个数据库的相应字段。运用查找字段技术,不仅可以有效的避免输入错误,而且 DBGrid 的显示方式更为灵活,可以不显示关键字段,而显示源数据库中相对应的另外一个字段的数据。

例如,我们在 DBGrid 中显示和编辑职工信息,包括职工编号、职工姓名、籍贯、所在单位编号,而单位编号来源于另一个数据库表格——单位库,称“单位编号”为关键字段。如果我们直接显示和编辑单位编号的话,将会面对 1、2、3 等非常不直观的数字,编辑时极易出错。但是如果显示和编辑的是单位库中对应的单位名称话,将非常直观。这就是 DBGrid 的所支持的查找字段带来的好处。

实现 DBGrid 的查找字段同样不需要任何语句,具体设计步骤如下:
1、在窗体上放置 Table1、Table2、DataSource1、DBGrid1、DBNavigator1 等控件对象,按下表设置各个对象的属性:
---------------------------------------
对象 属性 设定值
---------------------------------------
Table1 DataBase sy1
TableName zgk.dbf //职工信息库
Table2 DataBase sy1
TablenAME dwk.dbf //单位信息库
DataSource1 DataSet Table1
DbGrid1 DataSource DataSource1
DBNavigator1 DataSource Datasource1
------------------------------------------

2、双 击Table1,在弹出的 Form1.Table1 窗口中,用右键弹出快捷菜单,单击 Add Fields 菜单项;选择所有的字段后,按 OK 按钮。

3、修改第 2 步新增字段的 DisplayLabel 属性。以 Table1ZGBH 字段为例,在 Object Inspector 窗口中选择 Table1ZGBH,修改属性 DisplayLabel= 职工编号,其余字段类似。

4、设置 Table1DWBH.Visible=False。

5、在 Form1.Table1 窗口,用右键弹出快捷菜单,单击 New Field 菜单项,新增一个查找字段 DWMC,在弹出的窗口设置相应的属性,按 OK 按钮确认;在 Object Inspector 窗口,设置 Table1DWMC.DisplayLabel= 单位名称。

6、在 Form1.Oncreate 事件中写入语句:
Table1.Open;

7、按 F9 运行,当光标移至某个记录的单位名称字段时,用鼠标点击该字段,即出现一个下拉列表,点击右边的下箭头,可在下拉列表中进行选择。在这里可以看出,下拉列表的内容来自于单位信息库,并且不能输入其他内容。


三、DBGrid 中的下拉列表和查找字段的区别
虽然 DBGrid 中的下拉列表和查找字段,都是以下拉列表的形式出现的,但两者有很大的差别。

1、用 PickList 属性设置的下拉列表,它的数据是手工输入的,虽然也可以在程序中修改,但动态特性显然不如直接由另外数据库表格提取数据的查找字段。

2、用 PickList 属性设置的下拉列表,允许输入不属于下拉列表中的数据,但查找字段中只能输入源数据库中关键字段中的数据,这样更能保证数据的完整性。

3、用 PickList 属性设置的下拉列表设计较为简单。

2003-12-10 14:44:11 用 dbgrid 或 dbgrideh 如何让所显示数据自动滚动?
procedure TForm1.Timer1Timer(Sender: TObject);
var
m:tmessage;
begin
m.Msg:=WM_VSCROLL;
m.WParamLo:=SB_LINEDOWN;
m.WParamHi:=1 ;
m.LParam:=0;
postmessage(self.DBGrid1.Handle,m.Msg,m.WParam,m.LParam);

end;

procedure TForm1.Button1Click(Sender: TObject);
begin
self.Timer1.Enabled:=true;
end;

如果需要让他自动不断地从头到尾滚动,添加如下代码
if table1.Eof then table1.First;

2003-12-10 14:58:31 DBGrid 对非布尔字段的栏中如何出现 CheckBox 选择输入
可将dbgrid关联的dataset中需显示特殊内容字段设为显式字段,并在OnGetText事件中写如下代码:
以table举例:
procedure TForm1.Table1Myfield1GetText(Sender: TField;
var Text: String; DisplayText: Boolean);
var Pd:string;
begin
inherited;
pd:=table1.fieldbyname(/'myfield1/').asstring;
if pd=/'1/' then
Text:=/'□/'
else
if pd=/'2/' then
text:=/'▲/'
else
Text:=/'√/';
end;

2003-12-15 9:22:15 DbGrid控件隐藏或显示标题栏
DbGrid控件隐藏或显示标题栏

1、 新建一个带两个参数的过程(第1个参数是菜单对象,第2 个是DbGrid控件):
Procedure ViewTitle(Sender:TObject;DbgColumns:TDBGrid);
//隐藏或显示DbGrid标题栏

2、 然后按Ctrl+Shift+C组合键,定义的过程会在实现部分出现。
Procedure FrmStock.ViewTitle(Sender:TObject;DbgColumns:TDBGrid);
begin
With (Sender as TMenuItem) do
begin
Checked:=not Checked;
DbgColumns.Columns[Tag].Visible:=Checked;
end;
end;

3、 把菜单子项的Tag设置成跟DbGrid的Columns值相对应,比如:
DbGrid有一个标题栏是‘日期‘在第0列,然后把要触法该列的菜单的Tag设置成0。

4、 把菜单的OnClick事件选择ViewTitle该过程。

(作者: songwt 2005-1-30 10:15:01)  [资料] [短信] [好友] [邮箱]
13
 




有关双击dbgrid排序的问题(想让用户双击dbgird控件的某一个字段
时就升序,再双击就降序....?)【DFW:DouZheng】
procedure TForm1.DBGrid1TitleClick(Column: TColumn);
var
temp, title: string;
begin
temp := Column.FieldName;
qusp.Close;
if Column.Index <> lastcolumn then
begin
if (Pos(/'↑/', DBGrid1.Columns[LastColumn].Title.Caption) > 0) or (Pos(/'↓/', DBGrid1.Columns[LastColumn].Title.Caption) > 0) then
DBGrid1.Columns[LastColumn].Title.Caption := Copy(DBGrid1.Columns[LastColumn].Title.Caption, 3, Length(DBGrid1.Columns[LastColumn].Title.Caption) - 2);
qusp.Sql[icount] := /'order by /' + temp + /' asc/';
DBGrid1.Columns[Column.Index].Title.Caption := /'↑/' + DBGrid1.Columns[Column.Index].Title.Caption;
lastcolumn := column.Index;
end
else
begin
LastColumn := Column.Index;
title := DBGrid1.Columns[LastColumn].Title.Caption;
if Pos(/'↑/', title) > 0 then
begin
qusp.Sql[icount] := /'order by /' + temp + /' desc/';
Delete(title, 1, 2);
DBGrid1.Columns[LastColumn].Title.Caption := /'↓/' + title;
end
else if Pos(/'↓/', title) > 0 then
begin
qusp.Sql[icount] := /'order by /' + temp + /' asc/';
Delete(title, 1, 2);
DBGrid1.Columns[LastColumn].Title.Caption := /'↑/' + title;
end
else
begin
qusp.Sql[icount] := /'order by /' + temp + /' asc/';
DBGrid1.Columns[LastColumn].Title.Caption := /'↑/' + title;
end;
end;
qusp.Open;
end;

在DBGrid中,怎样才能让我能点击一个单元格选择整行,又可以编辑单元格的内容呢?【hongxing_dl 提供代码】
在设计过程中,有时候数据较大量,field 较多的时候,只是点击单元格可能会对某个field的数据误操作(如数据错行),为此才会想到这个问题,解决办法如下:
点击单元格就改当前行颜色。这个办法也算是没办法的办法吧!

type
TMyDBGrid=class(TDBGrid);
//
//DBGrid1.Options->dgEditing=True
//DBGrid1.Options->dgRowSelect=False
procedure TForm1.DBGrid1DrawColumnCell(Sender: TObject; const Rect: TRect;
DataCol: Integer; Column: TColumn; State: TGridDrawState);
begin
with TMyDBGrid(Sender) do
begin
if DataLink.ActiveRecord=Row-1 then
begin
Canvas.Font.Color:=clWhite;
Canvas.Brush.Color:=$00800040;
end
else
begin
Canvas.Brush.Color:=Color;
Canvas.Font.Color:=Font.Color;
end;
DefaultDrawColumnCell(Rect,DataCol,Column,State);
end;
end;

测试通过(d7)!

怎样在DbGrid的左边,实现像EXCEL那样的自动编号?这些编号与表无关.
呵呵,很厉害的 Grid 控件强人 hongxing_dl,以下是他的代码(可以解决问题)

unit Unit1;

interface

uses
Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
Grids, DBGrids, StdCtrls, Buttons, Db, DBTables, ExtCtrls, jpeg;
const ROWCNT=20;

type
tmygrid=class(tdbgrid)
protected
procedure Paint;override;
procedure DrawCell(ACol:Integer;ARow:Integer;ARect:TRect;AState:TGridDrawState);override;
public
constructor create(AOwner:TComponent);override;
destructor destroy;override;
end;

TForm1 = class(TForm)
BitBtn1: TBitBtn;
DataSource1: TDataSource;
Table1: TTable;
procedure BitBtn1Click(Sender: TObject);
private
{ Private declarations }
public
{ Public declarations }
end;

var
Form1: TForm1;
mygrid:tmygrid;
implementation

{$R *.DFM}

{tmygrid}
constructor tmygrid.create(AOwner:TComponent);
begin
inherited create(Owner);
RowCount:=ROWCNT;
end;

destructor tmygrid.destroy;
begin
inherited;
end;

procedure tmygrid.Paint;
begin
RowCount:=ROWCNT;
if dgIndicator in options then
ColWidths[0]:=30;
inherited;
end;

procedure tmygrid.DrawCell(ACol:Integer;ARow:Integer;ARect:TRect;AState:TGridDrawState);
begin
inherited;
if (ARow>=1) and (ACol=0) then
Canvas.TextRect(ARect,ARect.Left,ARect.Top,IntToSTr(ARow));
end;

procedure TForm1.BitBtn1Click(Sender: TObject);
begin
mygrid:=tmygrid.create(Self);
mygrid.parent:=self;
mygrid.left:=0;
mygrid.top:=0;
mygrid.Height:=300;
mygrid.DataSource:=DataSource1;
end;

end.

如何将几个DBGRID里的内容导入同一个EXCEL表中?
前言:

  在软件实际制作中,为节省开发成本和开发周期,一些软件人员通常会吧DBGrid中的数据直接导出到Excel表中,而先前能看到的函数仅仅只能在WorkBook的一个Sheet中导入数据,不支持多Sheet!。

单元应用:

Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, StdCtrls, DB, DBTables, Grids, DBGrids, ActiveX, ComObj,
Excel2000, OleServer;

测试环境:

  OS:Win2k Pro;Excel2k;Delphi6.0

源程序:  

{
功能描述:把DBGrid输出到Excel表格(支持多Sheet)
设计:CoolSlob
日期:2002-10-23
支持:CoolSlob@163.com
调用格式:CopyDbDataToExcel([DBGrid1, DBGrid2]);
}

procedure CopyDbDataToExcel(Args: array of const);
var
iCount, jCount: Integer;
XLApp: Variant;
Sheet: Variant;
I: Integer;
begin
Screen.Cursor := crHourGlass;
if not VarIsEmpty(XLApp) then
begin
XLApp.DisplayAlerts := False;
XLApp.Quit;
VarClear(XLApp);
end;

try
XLApp := CreateOleObject(‘Excel.Application‘);
except
Screen.Cursor := crDefault;
Exit;
end;

XLApp.WorkBooks.Add;
XLApp.SheetsInNewWorkbook := High(Args) + 1;

for I := Low(Args) to High(Args) do
begin
XLApp.WorkBooks[1].WorkSheets[I+1].Name := TDBGrid(Args[I].VObject).Name;
Sheet := XLApp.Workbooks[1].WorkSheets[TDBGrid(Args[I].VObject).Name];

if not TDBGrid(Args[I].VObject).DataSource.DataSet.Active then
begin
Screen.Cursor := crDefault;
Exit;
end;

TDBGrid(Args[I].VObject).DataSource.DataSet.first;
for iCount := 0 to TDBGrid(Args[I].VObject).Columns.Count - 1 do
Sheet.Cells[1, iCount + 1] := TDBGrid(Args[I].VObject).Columns.Items[iCount].Title.Caption;

jCount := 1;
while not TDBGrid(Args[I].VObject).DataSource.DataSet.Eof do
begin
for iCount := 0 to TDBGrid(Args[I].VObject).Columns.Count - 1 do
Sheet.Cells[jCount + 1, iCount + 1] := TDBGrid(Args[I].VObject).Columns.Items[iCount].Field.AsString;

Inc(jCount);
TDBGrid(Args[I].VObject).DataSource.DataSet.Next;
end;
end;

XlApp.Visible := True;
Screen.Cursor := crDefault;
end;

2003-12-22 9:25:32 DbGrid控件的标题栏弹出菜单
DbGrid控件的标题栏弹出菜单

procedure TFrmOrderPost.DbgOrderPostMouseDown(Sender: TObject; Button: TMouseButton; Shift: TShiftState; X, Y: Integer);
var
CurPost:TPoint;
begin
GetCursorPos(CurPost);//获得鼠标当前坐标
if (y<=17) and (x<=vCurRect.Right) then
begin
if button=mbright then
begin
PmTitle.Popup(CurPost.x,CurPost.y);
end;
end;
end;
//vCurRect该变量在DbGrid的DrawColumnCell事件中获得
{procedure TFrmOrderPost.DbgOrderPostDrawColumnCell(Sender: TObject;const Rect: TRect; DataCol: Integer; Column: TColumn; State: TGridDrawState);
begin
vCurRect:=Rect;//vCurRect在实现部分定义
end;}

2003-12-22 10:12:55 DbGrid控件的标题栏弹出菜单
DbGrid控件的标题栏弹出菜单

procedure TFrmOrderPost.DbgOrderPostMouseDown(Sender: TObject; Button: TMouseButton; Shift: TShiftState; X, Y: Integer);
var
CurPost:TPoint;
begin
GetCursorPos(CurPost);//获得鼠标当前坐标
if (y<=17) and (x<=vCurRect.Right) then
begin
if button=mbright then
begin
PmTitle.Popup(CurPost.x,CurPost.y);
end;
end;
end;
//vCurRect该变量在DbGrid的DrawColumnCell事件中获得
{procedure TFrmOrderPost.DbgOrderPostDrawColumnCell(Sender: TObject;const Rect: TRect; DataCol: Integer; Column: TColumn; State: TGridDrawState);
begin
vCurRect:=Rect;//vCurRect在实现部分定义
end;}

2003-12-22 10:14:26 把DBGrid输出到Excel表格(支持多Sheet)
{
功能描述:把DBGrid输出到Excel表格(支持多Sheet)
调用格式:CopyDbDataToExcel([DBGrid1, DBGrid2]);
}
procedure CopyDbDataToExcel(Args: array of const);
var
iCount, jCount: Integer;
XLApp: Variant;
Sheet: Variant;
I: Integer;
begin
Screen.Cursor := crHourGlass;
if not VarIsEmpty(XLApp) then
begin
XLApp.DisplayAlerts := False;
XLApp.Quit;
VarClear(XLApp);
end;

try
XLApp := CreateOleObject(‘Excel.Application‘);
except
Screen.Cursor := crDefault;
Exit;
end;

XLApp.WorkBooks.Add;
XLApp.SheetsInNewWorkbook := High(Args) + 1;

for I := Low(Args) to High(Args) do
begin
XLApp.WorkBooks[1].WorkSheets[I+1].Name := TDBGrid(Args[I].VObject).Name;
Sheet := XLApp.Workbooks[1].WorkSheets[TDBGrid(Args[I].VObject).Name];

if not TDBGrid(Args[I].VObject).DataSource.DataSet.Active then
begin
Screen.Cursor := crDefault;
Exit;
end;

TDBGrid(Args[I].VObject).DataSource.DataSet.first;
for iCount := 0 to TDBGrid(Args[I].VObject).Columns.Count - 1 do
Sheet.Cells[1, iCount + 1] :=
TDBGrid(Args[I].VObject).Columns.Items[iCount].Title.Caption;

jCount := 1;
while not TDBGrid(Args[I].VObject).DataSource.DataSet.Eof do
begin
for iCount := 0 to TDBGrid(Args[I].VObject).Columns.Count - 1 do
Sheet.Cells[jCount + 1, iCount + 1] :=
TDBGrid(Args[I].VObject).Columns.Items[iCount].Field.AsString;

Inc(jCount);
TDBGrid(Args[I].VObject).DataSource.DataSet.Next;
end;
XlApp.Visible := True;
end;
Screen.Cursor := crDefault;
end;
(作者: songwt 2005-1-30 10:15:40)  [资料] [短信] [好友] [邮箱]
14
 




    
以下内容含脚本,或可能导致页面不正常的代码
说明:上面显示的是代码内容。您可以先检查过代码没问题,或修改之后再运行.
(作者: songwt 2005-1-30 10:16:19)  [资料] [短信] [好友] [邮箱]
15
 




在DELPHI中利用API实现网格内组件的嵌入 
--------------------------------------------------------------------------------

  Delphi中向TDBGrid添加组件是一件十分麻烦的事情。笔者在这里向大家介绍一种利用WIN32 API函数在TDBGRID中嵌入CHECKBOX组件的方法。

  TDBGrid部件是用于显示和编辑数据库表中记录信息的重要部件,它是我们在程序设计过程中要经常使用的一个强有力的工具。TDBGrid具有很多重要的属性,我们可以在程序设计阶段和程序运行过程中进行设置。TDBGrid部件中有很多重要的属性,我们在这里重点介绍Option属性和DefaultDrawing属性,其他属性及其设置方法请参看联机帮助文件。

  Options属性:它是TDBGrid部件的一个扩展属性,在程序设计阶段设置Options属性可以控制TDBGrid部件的显示特性和对事件的响应特性。

  DefalultDrawing属性:该属性是布尔型属性,它用于控制网格中各网格单元的绘制方式。在缺省情况下,该属性的值为True,也就是说Delphi使用网格本身缺省的方法绘制网格中各网格单元,并填充各网格单元中的内容,各网格单元中的数据根据其对应的字段部件的DisplayFormat属性和EidtFormat属性进行显示和绘制。如果DefaulDrawing属性被设置为False,Delphi不会自动地绘制网格中各网格单元和网格单元中的数据,用户必须自己为TDBGrid部件的OnDrawDataCell事件编写相应的程序以用于绘制各网格单元和其中的数据。

  需要注意的是,当一个布尔字段得到焦点时,TDBGrid.Options中的 gdEditing属性不能被设置成为可编辑模式。另外,TDBGrid.DefaultDrawing属性不要设置为FALSE,否则,就不能得到网格中画布属性的句柄。

  程序设计开始时就应考虑:需要设定一变量来存储原始的 TDBGrid.Options的所有属性值。这样,当一boolean字段所在栏得到焦点时将要关闭TDBGrid.Options中gdEditing的可编辑模式。与此相对应,若该栏失去焦点时,就要重新恢复原始的 TDBGrid.Options的所有属性值。

  在实例中可以通过鼠标点击或敲打空格键改变布尔值,这样就需要触发TDBGrid.OnCellClick事件和TDBGrid.OnKeyDown事件。因为这两个事件都是改变单元格中逻辑字段的布尔值,所以为了减少代码的重复最好创建一个私有过程(SaveBoolean;)来完成逻辑值的输入,以后,在不同的事件中调用此过程即可。

  对 TDBGrid.OnDrawColumnCell事件的处理是整个程序的关键。处理嵌入组件的显示的传统方法是:在表单上实际添加组件对象,然后对组件的位置属性与网格中单元格的位置属性进行调整,以达到嵌入的视觉效果。这种方法虽然可行但代码量大,实际运行时控制性很差。笔者采用的方法是充分利用WIN32 API函数:DrawFrameControl(),由于此函数可以直接画出Checkbox组件,所以就无须在表单中实际添加组件。如何使用API函数:DrawFrameControl()是本程序技巧所在。

  在TDBGrid.OnDrawColumnCell事件中,我想大家会注意到:设定一个整型数组常数,而这个返回的整数值是与布尔值相一致的,如果字段是逻辑字段,则只将其布尔值放入数组中,提供给DrawFrameControl()函数中的状态参数进行调用,从而实现了Checkbox组件在网格中的嵌入效果。

  源代码如下:

  type

   TForm1 = class(TForm)
    DataSource1: TDataSource;
    Table1: TTable;
    DBGrid1: TDBGrid;
    procedure DBGrid1DrawColumnCell(Sender: TObject;
          const Rect: TRect; DataCol: Integer;
          Column: TColumn; State: TGridDrawState);
    procedure DBGrid1ColEnter(Sender: TObject);
    procedure DBGrid1ColExit(Sender: TObject);
    procedure DBGrid1CellClick(Column: TColumn);
    procedure DBGrid1KeyDown(Sender: TObject; var Key: Word;
          Shift: TShiftState);
   private
    { Private declarations }
    OriginalOptions : TDBGridOptions;
    procedure SaveBoolean;
   public
    { Public declarations }
   end;

  {...}

  procedure TForm1.DBGrid1DrawColumnCell(Sender: TObject;
           const Rect: TRect; DataCol: Integer;
           Column: TColumn; State: TGridDrawState);
  const
   // 这个整数值将按照布尔值返回,并送入数组
   CtrlState : array[Boolean] of Integer = (DFCS_BUTTONCHECK,DFCS_BUTTONCHECK or DFCS_CHECKED);
  begin
   //确保只有在逻辑字段才能插入组件
   if Column.Field.DataType = ftBoolean then
   begin
    DBGrid1.Canvas.FillRect(Rect);
    DrawFrameControl(DBGrid1.Canvas.Handle,
             Rect,
             DFC_BUTTON,
             CtrlState[Column.Field.AsBoolean]);
   end;
  end;

  procedure TForm1.DBGrid1ColEnter(Sender: TObject);
  begin
   // 确保该栏是逻辑字段
   if DBGrid1.SelectedField.DataType = ftBoolean then
   begin
    OriginalOptions := DBGrid1.Options;
    DBGrid1.Options := DBGrid1.Options - [dgEditing];
   end;
  end;

  procedure TForm1.DBGrid1ColExit(Sender: TObject);
  begin
   //确保该栏是逻辑字段
   if DBGrid1.SelectedField.DataType = ftBoolean then
    DBGrid1.Options := OriginalOptions;
  end;

  procedure TForm1.DBGrid1CellClick(Column: TColumn);
  begin
   //确保该栏是逻辑字段
   if DBGrid1.SelectedField.DataType = ftBoolean then
    SaveBoolean();
  end;

  procedure TForm1.DBGrid1KeyDown(Sender: TObject;
             var Key: Word; Shift: TShiftState);
  begin
   //确保该栏是逻辑字段和空格键在键盘中被敲击
   if ( Key = VK_SPACE ) and
     ( DBGrid1.SelectedField.DataType = ftBoolean ) then
    SaveBoolean();
  end;

  procedure TForm1.SaveBoolean;
  begin
   DBGrid1.SelectedField.Dataset.Edit;
   DBGrid1.SelectedField.AsBoolean :=not DBGrid1.SelectedField.AsBoolean;
   DBGrid1.SelectedField.Dataset.Post;
  end;

  以上源程序在PWIN+DELPHI5.0环境调试通过,可以直接引用。



Ehlib使用说明

使用 TDBSumList 组件
还记得以前有朋友问过这样一个问题:在 DBGrid 下如何像 Excel 一样能够做统计计算,实话说,使用 DBGrid 来做的话着实不易,不过现在有了这个咚咚,相信会简单些。以下是摘录的一些使用上的说明:

【TDBSumList说明】
你可以使用TDBSumList在可视动态变化数据集中进行记录统计。在你想查看的数据集中设置相关的数据字段,然后写 SumListChanged 事件来指定在TDBSumList发生改变后所要做的操作。TDBSumList 的 SumCollection 属性上一个 TDBSum 对象容器。每个 TDBSum 对象是一个可以指定集合值的元件。 FieldName 和 GroupOperation 决定了集合值的类型,SumValue 控制当前的集合值。

TDBSumList 被埋藏于 DBGridEh 组件中,因此所的下面有关TDBGridEh.SumList 的说明与TDBGirdEh的TDBGridEh.SumList 属性的说明是一样的。

【如何工作以及为什么有时SumList的集合值计算不正确?】
你知道 data-aware 控件与数据集是通过 TDataLink 对象相连接的。 TDataLink 不允许快速重新计算集合值。例如,当从数据集中删除记录时,数据集发送deDataSetChange事件给所有的TDataLink对象,在当前局部过滤发生改变时,同样的事件也被发送了。因此当 TDataLink 接收到该事件时,它不得不在所有的数据集中重新计算集合值,甚至于仅从数据集中删除一条记录。在激活后, TDBSumList 重载了数据集的下列事件: OnAfterEdit, OnAfterInsert, OnAfterOpen, OnAfterPost, OnAfterScroll, OnBeforeDelete, OnAfterClose。这种方法避免了在所有的数据集中它。在不需要它时,又会出现其它的问题,比如: T 运行时指定这些事件。在指定上述事件之一以前,关闭 SumList。
在下面的情形下,SumList 发出存取错误信息。 SumList 试着向数据集返回事件,但数据集数据并未被删除。在SumList(或网格)以及数据集放置在不同的窗体(数据模块)这种情况下,可以显示数据。在这种情况下,试着在从数据集或数据模块中数据集数据被删除时关闭SumList。
如果你使用SetRange或ApplyRange事件,SumList 将不能跟踪数据集中发生的变化。但可以调用 SumList.RecalAll 方法。
在非BDE数据集的主/明细表中,SumList 不能跟踪数据变化。在主数据集激活状态数据集发生变化后,调用 SumList.RecalAll 方法。
在任何其它情况下,如果你发现了其它SumList的计算值不正确,你都可以调用 RecalAll 方法。

如何使用 Ehlib 实现自动排序
在 Ehlib 的 DataService 文件夹下提供了一些可以使数据集实现自动排序的文件。TDBGridEh 使用这些文件中的相关对象可以实现当排序标记发生变化时实现自动排序。

如果你改变了数据网格及标题的排序标记而没有书写 OnSortMarkingChanged 事件,数据网格将尝试自动进行数据排序。DBGridEhDataService 尝试通过 GetDatasetFeaturesForDataSet 查找 TDataSet 中可以排序的特定的对象。正如你所知道的,TDataSet 不支持数据排序,但它的派生对象 TQuery 或 TClientDataSet 却允许实现数据排序。使用过程 RegisterDatasetFeaturesEh ,你可以注册 TDatasetFeaturesEhClass 类,该类可以实现对 TQuery, TADOQuery 以及 TClientDataSet 对象进行排序。简单地通过 uses 子句添加 Ehlib...(EhlibBDE,EhlibADO,EhlibCDS)的单元之一到你的工程的任意单元中,与它们相连的数据网格将自动对该数据集进行排序。 EhLibBDE, EhLibADO, EhLibCDS 通过在单元数据集中调用 RegisterDatasetFeaturesEh 过程来实现初始化。对于其它数据集类型,你必须编写、并注册可以实现该数据集排序的新对象。书写过程 T[你的数据集]DatasetFeaturesEh.ApplySorting ,你可以存取那些使用了 SortMarkedColumns 属性的列以实现直接排序。你可以查看 DbUtilsEh 单元中的示例以明白如何编写T[你的数据集]DatasetFeaturesEh 类及查看 EhLibBDE 单元以明白如何注册 T[你的数据集]DatasetFeaturesEh 类。

引擎 数据集 单元文件

BDE TQuery EhLibBDE
ADO TADOQuery EhLibADO
ClientDataSet TClientDataSet EhLibCDS
DBExpress TSQLQuery EhLibDBX
InterBase Express TIBQuery EhLibIBX

【译【者注】:
实际上,实现该功能非常简单(以下我以BDE为例说明如何实现自动排序):
1.在窗体上放置一个 DBGridEh 组件,并将其连接到相应的 BDE 数据集;
2.将该组件的[OptionsEn]中的 dgAutoSortMarking 属性设置为 True;
3.双击该组件,在其弹出的属性编辑器中添加相关字段;
4.将要排序的字段的属性列表的 [Title]的 TitleButton 属性设置为 True;
5.最后,千万不要忘了在 uses 子句中加上 EhlibBDE单元。

好了,使用上面的方法,你会发现原来通过 Ehlib 实现数据的自动排序居然如些简单!

以下这段文字摘自《Delphi 园地》
【定制网格标题 】--
-【复杂标题】
TDBGridEh 允许在多列上创建标题,设置 DBGridEh.UseMultiTitle 属性为 True 并且填充字段的标签或列标题的标题,可以使用下面的规则:字段标签中的文本部分或列标题必须由几部分组成,并且用 "|" 分割,几个列的每一个通用部分都设置为相同。其它字段或标题必须在相应的部分包含同样的文本。

例如:
Field1.DisplayLabel := /'Title1|SubTitle1/';
Field2.DisplayLabel := /'Title1|SubTitle2/';

DBGridEh.Columns[0].Title.Caption := /'Title1|SubTitle1/';
DBGridEh.Columns[1].Title.Caption := /'Title1|SubTitle2/';

-【按钮式标题】
设置Column.Title.TitleButton 为 True可以强制标题单元为按钮式。写 OnTitleBtnClick事件来控制用户单击标题单元时的操作。

-【在标题中显示位图】
To show bitmap in titles instead of caption use TitleImages property of TDBGridEh and ImageIndex property of TColumnTitleEh.

-【自动用位置标识排序标题】.
TDBGridEh allows to show special sortmarking bitmaps (small triangles) in the right part of title cell. In order to automatically marking title by sortmarking bitmaps add dghAutoSortMarking to OptionsEh property. Add dghMultiSortMarking too in order to allow sortmarking several columns simultaneously. Set Column.Title.TitleButton to true for titles which will have possibility to change sortmarkers at run time. At runtime clicking on title will change sortmarking. Holding Ctrl key allows to mark several columns simultaneously. After user change sormarking grid call OnSortMarkingChanged event. You can write this event to change sorting and reopen in dataset. Use SortMarkedColumns property to access to sortmarked columns.

-【标题属性的默认值】
使用TDBGridEh.ColumnDefValues.Title来设置标题属性的默认值。

【定制网格页脚】--
-【页脚以及统计值】
TDBGridEh allows to show special row (footer) or rows at bottom part. Use FooterRowCount property to specify the number of footer rows in the grid. Use Footer or Footers property of TColumnEh object to specify information which need to show in footer cells. Footers property useful then you have more then one footer rows. Footers is a collection of TColumnFooterEh objects where information from i-th aliment of collection will be show in i-th cell of footer column. In footer cell, it is possible to show: Sum value for specified field, record count, value of a specified field or static text. Use property Footer.ValueType or Footers[i].ValueType to specify which type of value will be show in footer cell. If ValueType = fvtStaticText, then set the property Value to specify text which need to show. If ValueType = fvtFieldValue, then you need to set property FieldName to specify field, value of which need to show. To force grid to calculate total values need to activate SumList (DBGridEh.SumList.Active := True). Set ValueType to fvtSum and grid must to show sum value of the column field in the footer cell, you can also specify Column.Footer.FieldName to calculate total value of the other field. Set ValueType to fvtCount to force grid to show count of records in the footer cell.

-【定制网格数据单元】
在数据单元中显示字段值为图形。
TDBGridEh allows to show bitmaps from TImageList component depending on field values. To show bitmaps depending on field values need: Fill list of field values to Column.KeyList property (every value in separate line) and set Column.ImageList property to ImageList control that has the bitmap in according index. Set Column.NotInKeyListIndex to index of bitmap that will be shown if field/'s value does not correspond to any value in KeyList (for instance you can set index of image for Null field value). At run time you are not allowed to edit bitmap in column cell. Use blank key and mouse click to set next value from Column.KeyList to the field; Shift-blank key and Shift-Mouse click to set previous value from Column.KeyList. Set Column.DblClickNextval to True have allows to change value on mouse double click.

【检查框式的逻辑及非逻辑值】
Grid automatically shows checkboxes for boolean field. To show checkboxes for non boolean fields fill first line of Column.KeyList property that corresponds to the checked state of the checkbox, second line - non checked state, and set Column.Checkboxes ptoperty to True. Line of KeyList can represent more than one value in a semicolon-delimited list of items.

【数据行高度】
使用 RowHeight 和 RowLines 属性来指定数据行高。完整的数据行高 = 行线高度+行高。设置 RowSizingAllowed 为 True 以允许可以在运行是使用鼠标来改变行高。
设置Column.WordWrap为True可以使数据行中文本多行显示。如果行高>文本行,它就换行。

【显示备注字段】
设置 DrawMemoText to True来显示文本式的备注字段。.

【定制单元格字体及颜色】
TDBGridEh 中的 Font 和 Color 属性描述了数据网格中绘制单元格的字体和颜色。
TColumnEh 中的 Font 和 Color 属性描述了指定列中绘制单元格的字体和颜色。

【事件定制单元格字体及颜色】
有几个事件可以让你能够在绘制单元格前定制单元格字体和颜色。你可以写TDBGridEh的OnDrawColumnCellEvent事件句柄来在控制在网格单元中绘制数据。你可以使用Canvas属性的方法来绘制单元格。但是如果你只想改变字体或颜色的属性,我建议你使用下面的事件。你可以写TDBGridEh的OnGetCellParams事件来控制在绘制数据单元以前所指定的操作。你可以改变绘制字体及背景色。这个事件适合你在想改变整行的字体或颜色时使用。如果你想改变指定列中单元格的属性,你可以使用TColumnEh.OnGetCellParams。写这个事件用来控制在一列数据单元被重绘或编辑时的操作。在一列数据单元被重绘以前,你可以改变绘制字体,背景色,对齐方式,图像索引,文本或检查框。在编辑一列数据单元以前,你可以改变编辑字体,背景色,文本或只读状态。

【列属性的默认值】
使用ColumnDefValues属性来设置列属性的默认值。新创建的列将从ColumnDefValues属性中获得属性值,并且直到第一次为其指定值为止。

【在网格的适当位置放置编辑器】--
-【在下拉列表中显示几个字段】
在下拉列表中显示几个下拉字段,需要设置列的LookupDisplayFields属性到字段的Semicolons属性来分割多个字段名。命名为Column.Field.LookupResultField的属性必须位于LookupDisplayFields列表中。多字段的下拉列表只能应用于下拉字段。

-【显示下拉方式的列】
你可以通过KeyList 和 PickList 属性在相关的的字段中显示其它文本。KeyList显示包含在字段的值而非PickList索引所包含的值。 Column.NotInKeyListIndex to index of text from PickList that will be shown if field value do not contain in KeyList (for instance you can set index of text for Null field value). Set Column.DblClickNextval to True to change value on mouse double click.

-【下拉式计算器】
对于 TDateField 和 TDateTimeField 字段,inplace 编辑器将显示下拉按钮以显示显示下拉计算器。设置 Column.ButtonStyle 为 cbsNone 以禁止显示下拉按钮。

【设置编辑器颜色和字体】
Inplace编辑器可以设置数据单元的颜色和字体。数据单元使用OnGetCellParams 事件来控制列的颜色和字体。 Inplace 编辑器在行高>一行的高度时自动设置为多行模式并且将列的属性 WordWrap 设置为True.

【自动填充网格列宽到网格客户区】
设置AutoFitColWidths为True以自动重置列宽来设置网格的宽度等于客户区宽度。 MinAutoFitWidth 属性决定网格的最小宽度,列宽将会被重新计算。

【3D或平面外观】
使用 OptionsEh 属性来显示/隐藏固定的3D框架,冷区,页脚以及数据行。
使用 Flat 属性来设置用平面方式显示数据网格。

【从多种格式导入/导出数据到TDBGridEh】
EhLib 的函数集可以从DBGridEh导出数据到Text, Csv, HTML, RTF, XLS以及其内部格式。它可以保存数据到流(TStream对象)或文件。

例子
Pascal: SaveDBGridEhToExportFile(TDBGridEhExportAsText,DBGridEh1,/'c://temp//file1.txt/',False);
C++: SaveDBGridEhToExportFile(__classid(TDBGridEhExportAsText),DBGridEh1,"c:tempfile1.txt",false);

EhLib 的函数集可以从 Text以及其内部格式的数据导入到DBGridEh的数据集中。它可以从文件中读取数据或读取数据到流(TStream对象)。

【其它特性】--
用lookup 编辑器,你可以在运行时清空(设置为Null) LookupKeyField 值。比如选择整个文本然后按Delete键。

-【冷区】
冷区是数据网格列集左边显示的不可滚动的区域。与固定列不同的是,冷区的列可以获得编辑焦点。可以通过设置FrozenCols属性来设置右边不可滚动的列集。

-【增量搜索】
TDBGridEh 允许用户在网格列中实现特定的“增量”搜索。当用户进入增量搜索时他可以显示字符以及网格,并且在当前的列中查找文本。使用 dghIncSearch 和 dghPreferIncSearch的值(在OptionsEh 选项中) 在数据网格中操作增量搜索。 dghIncSearch 值允许在数据网格中进行增量搜索。运行时你能够使用下面的键进行增量搜索:

Ctrl+F - 开始增量搜索。
Ctrl+Enter - 查找下一个匹配记录。
Ctrl+Shift+Enter - 查找前一个匹配记录。

如果OptionsEh选项中的 dghIncSearch 是只读的,那么网络将自动设置增量模式在第一次按键以及1.5秒后返回普通模式。 dghPreferIncSearch 值决定网格设置自动增量搜索模式在第一次按键时替代单元编辑。

【水平或垂直滚动条】
使用 VertSctollbar, HorzSctollbar 属性来显示/隐藏以及跟踪水平或垂直滚动条。

【多选】
TDBGridEh 允许在选定的区域上进行选择记录,列以及矩形区域等操作:

×允许多选会影响下面这些属性:
Options 选项中的 dgMultiSelect 属性 - 设置是否允许多选。
Options 选项中的 dghClearSelection 属性- 设置在用户移到下一个单元时是否清除已选记录。
Options 选项中的 EditActions 属性 -设置用户可以在已选记录上执行哪些操作(比如,拷贝,剪切,删除,粘贴,全选等)。
Options 选项中的 AllowedSelections 属性-设置允许选定记录的类型(比如,行,列,矩形区域等)。
Options 选项中的 Selection 属性-设置一个当前的多选状态,已选记录,列或矩形区域以及存取它们的属性和函数。

【从注册表或ini文件中保存或恢复网格和列的层次】
TDBGridEh 有一个常规设置来从注册表或ini文件中保存和恢复网络以及列的层次:
RestoreColumnsLayout - 从注册表中恢复列的次序,宽度,排序标志。
RestoreColumnsLayoutIni - 从ini文件中恢复列的次序,宽度,排序标志。
RestoreGridLayout - 从注册表中恢复列的次序,宽度,可视,排序标志,排序索引或行高。
RestoreGridLayoutIni - 从ini文件中恢复列的次序,宽度,可视,排序标志,排序索引或行高。
SaveColumnsLayout - 保存列的次序,宽度,排序标志到注册表中。
SaveColumnsLayoutIni - 保存列的次序,宽度,排序标志到ini文件中。
SaveGridLayout - 保存列的次序,宽度,可视,排序标志,排序索引或行高到注册表中。
SaveGridLayoutIni - 保存列的次序,宽度,可视,排序标志,排序索引或行高到ini文件中。

『以下内容仅供参考了,因为不知道它那个版本是多少,目前最新的版本是3.2吧,俺正在用,感觉很不错啊~~』
当前版本的TDBGridEh不支持的特性:
TDBGridEh 不能设置每一个数据窗口中单独行的行高。
TDBGridEh 不能象TreeView那样工作。它不能拥有节点和枝叶。
TDBGridEh 不能横向或纵向合并数据单元。

【将已存在的TDBGrid组件转换为TDBGridEh组件】:
尽管TDBGridEh并不是从TCustomDBGrid组件继承而来的,但是在TDBGridEh和TDBGrid中还是有一些相似的属性。
它允许仅用一点点代价来转换已存在的TDBGrid组件到TDBGridEh。

【注意】:可以按照下面的提示来转转换已存在的TDBGrid组件到TDBGridEh:
在Delphi的IDE中打开包含有TDBGrid组件的应用程序。
设置视图方式为文本方式(Alt-F12)。
if key=VK_RETURN then //Key:回车
begin
if (grdDetailData.SelectedIndex=grdDetailData.Columns.Count-1) and not (dgRowSelect in grdDetailData.Options) then
BEGIN
if (dgEditing in grdDetailData.Options) and (grdDetailData.Row=grdDetailData.RowCount-1) then //从表GRID能进行编辑和当前光标焦点在最后一行时
acAddDetailExecute(self)
else
begin
grdDetailData.Row:=grdDetailData.Row+1; //改变光标焦点行到下一行(当为新增加时,这句不用运行
grdDetailData.SelectedIndex:=0 //改变光标焦点列到第一列
end;
END ELSE
BEGIN
grdDetailData.SelectedIndex:=grdDetailData.SelectedIndex+1;
while grdDetailData.Columns[grdDetailData.SelectedIndex].ReadOnly do
grdDetailData.SelectedIndex:=grdDetailData.SelectedIndex+1;
END;
key:=0;
end;
if key=VK_INSERT then //Insert键:新增一条记录
begin
acAddDetailExecute(self);
key:=0;
end;
if key=VK_DELETE then //Delte: 删除一条记录
begin
acDeleteDetailExecute(self);
key:=0;
end;

【页脚合计】
1、设置DBGRIDEH属性的FooterRowCount值为1;
2、设置DBGRIDEH属性的SumList的Active值为true;
3、设置你要求和的该列的Footer的ValueType类型为fvtSum;
4、运行OK!
在DataSet打开时写:
DBGridEh1.Columns[0].Footer.Value := IntToStr DBGridEh1.DataSource.DataSet.RecordCount);

2003-12-5 16:56:13 Ehlib 的 DBGridEh 控件怎样才能像 dxDBGrid 控件那样输出文件到 EXCEL
以下是EHLIB的导出代码:(其实EHLIB的DEMO1中已有)

procedure TInvoiceManager.ppmSaveSelectionClick(Sender: TObject);
var ExpClass:TDBGridEhExportClass;
Ext:String;
begin
SaveDialog1.FileName := /'file1/';
if (ActiveControl is TDBGridEh) then
if SaveDialog1.Execute then
begin
case SaveDialog1.FilterIndex of
1: begin ExpClass := TDBGridEhExportAsText; Ext := /'txt/'; end;
2: begin ExpClass := TDBGridEhExportAsCSV; Ext := /'csv/'; end;
3: begin ExpClass := TDBGridEhExportAsHTML; Ext := /'htm/'; end;
4: begin ExpClass := TDBGridEhExportAsRTF; Ext := /'rtf/'; end;
5: begin ExpClass := TDBGridEhExportAsXLS; Ext := /'xls/'; end;
else
ExpClass := nil; Ext := /'/';
end;
if ExpClass <> nil then
begin
if UpperCase(Copy(SaveDialog1.FileName,Length(SaveDialog1.FileName)-2,3)) <>
UpperCase(Ext) then
SaveDialog1.FileName := SaveDialog1.FileName + /'./' + Ext;
SaveDBGridEhToExportFile(ExpClass,TDBGridEh(ActiveControl),
SaveDialog1.FileName,False);
end;
end;
end;
(作者: songwt 2005-1-30 10:16:46)  [资料] [短信] [好友] [邮箱]
16
 




Ehlib 在 Delphi 7 中的安装(我可是花了半天的力气才搞定的哦) 
Delphi 7中的安装方法

1. 把 EhLib 中的 common 和 DataService 文件拷贝到 Delphi7 目录中.
2.在 TOOLS->Environment Options->Library->Library Path 中添入EHLIB路径。
3.打开新建文件夹中的 EHLIB70.DPK ,编译一下,但不要安装。
4.打开Ehlib中的DclEhLib70.DPK,编译,安装
5. 在Delphi 7中打开DclEhLib70.dpk,编译并安装。
6. 组件面板中出现一个EhLib的组件页。
7. 打开附带的DEMOS,编译并运行,测试安装成功。


DBGridEh控件的页脚属性怎么设?
0、将dBGridEh.FooterRowCount := 1
1、将DBGridEh.SumList.Active := True;
2、将Columns[要求和的字段].Footer.ValueType := vtSum;
就行了

最后要注意,在FormCloseQuery事件中,一定要将SumList.Active := False,因为在数据集中的数据多了以后,FormClose会让DBGridEh释放所有EhLib资源,会使得退出很慢,所以将SumList.Active := False不会引起退出很慢

如何实现在DbgridEh中不同的行显示不同的颜色?或某一些条件的行显示特定的颜色?
【实现 DBGridEh 隔行分色显示】
procedure TForm1.DBGridEh1GetCellParams(Sender: TObject; Column: TColumnEh;
AFont: TFont; var Background: TColor; State: TGridDrawState);
begin
if DBGridEh1.SumList.RecNo mod 2 = 1 then
Background := $00FFC4C4
else
Background := $00FFDDDD;
end;


【DBGridEh 在某些条件下某行显示特定颜色】
procedure TForm1.DBGridEh1GetCellParams(Sender: TObject; Column: TColumnEh; AFont: TFont; var Background: TColor; State: TGridDrawState);
begin

//在 name 字段值为 aaa 的行设置行背景色(ado 设置情况下)
if ADOQuery1.FieldByName(/'name/').AsString = /'aaa/' then
Background := $00FFC4C4

//在 xm 字段值为 Li ming 的行设置行背景色(bde 设置情况下)
else if DBGridEh1.DataSource.DataSet.FieldByName(/'xm/').AsString = /'Li ming/' then
Background := $00FFC4C4
else
Background := $00FFDDDD;

end;

DBGridEh 控件导出文件到 EXCEL 的补充说明(关于多表头导出的设计思路)
如果表头是着样的:
|Mergetitle|
------------
Col1|Col2
分析表头几层,然后根据其表头的/'|/' 将,其还原成
|Mergetitle|Mergetitle
----------------------
Col1 |Col2
再导入到Excel里合并单元格即可!

在dbgrideh中允许选择多行,如何知道哪些行被选中?
是个BOOKMARK类型的属性。
SelectedRows: TBookmarkList
procedure TForm1.Button1Click(Sender: TObject);
var
i, j: Integer;
s: string;
begin
if DBGrid1.SelectedRows.Count>0 then
with DBGrid1.DataSource.DataSet do
for i:=0 to DBGrid1.SelectedRows.Count-1 do
begin
GotoBookmark(pointer(DBGrid1.SelectedRows.Items[i]));
for j := 0 to FieldCount-1 do
begin
if (j>0) then s:=s+/', /';
s:=s+Fields[j].AsString;
end;
Listbox1.Items.Add(s);
s:= /'/';
end;
end;

dbgrideh 上选择多行之后,要求把所选择的记录全部添加入SQL数据库的一个固定表中。
dbgrideh.selectedrows记载了所有被选择行的bookmark;利用SelectedRows和GotoBookmark完成。代码如下:

procedure TForm1.Button1Click(Sender: TObject);
var
i, j: Integer;
s: string;
begin
if DBGrid1.SelectedRows.Count>0 then
with DBGrid1.DataSource.DataSet do
for i:=0 to DBGrid1.SelectedRows.Count-1 do
begin
GotoBookmark(pointer(DBGrid1.SelectedRows.Items[i]));
for j := 0 to FieldCount-1 do
begin

if (j>0) then s:=s+/', /';
s:=s+Fields[j].AsString;
end;
Listbox1.Items.Add(s);
s:= /'/';
end;
end;

(作者: songwt 2005-1-30 10:17:17)  [资料] [短信] [好友] [邮箱]
17
 




在dbgrideh中直接点击title就可按点击的那个字段排序的方法 
第一种方法(未测试)
procedure TForm1.DBGridEh1TitleClick(Column: TColumnEh);
begin
//点击GridEh标题排序
if (Column.Title.SortMarker = smNoneEh) or (Column.Title.SortMarker = smDownEh) then
begin
ADOQuery1.SORT := COLUMN.FIELDNAME;
Column.Title.SortMarker := smUpEh
end
else
begin
ADOQuery1.SORT := COLUMN.FIELDNAME + /' DESC/';
Column.Title.SortMarker := smDownEh
end;
end;

第二种方法(未测试)
procedure TPrintMai_frm.DBGridEh1TitleClick(Column: TColumnEh);
var
sortstring: string;
begin //进行排序
with Column do
begin
if FieldName = /'/' then
Exit;
case Title.SortMarker of
smNoneEh:
begin
Title.SortMarker := smDownEh;
sortstring := Column.FieldName + /' ASC/';
end;
smDownEh: sortstring := Column.FieldName + /' ASC/';
smUpEh: sortstring := Column.FieldName + /' DESC/';
end; //数据集排序。
try
DM.DataModule1.qry2.Sort := sortstring //dataset为实际数据集变量名
except
end;
end;
end;

ehlib的颜色控制及打印
From:
http://www.delphibbs.com/keylife/iblog_show.asp?xid=191

很多说根据条件在数据网格中显示不同颜色的说法都是在DrawColumnCell事件里,这样显示没有问题,但在ehlib中如果想打印出来可就不行了。
ehlib提供了GetCellParams事件,可以显示和打印
//只能显示,不能打印
procedure TfrmQueryContractInfo.DBGrid1DrawColumnCell(Sender: TObject;
const Rect: TRect; DataCol: Integer; Column: TColumnEh;
State: TGridDrawState);
var
OldColor,OldColumnColor:TColor;
v:TColCellParamsEh;
begin
{ OldColor:=DBGrid1.Canvas.Font.Color ;
if (Column.Field.FieldName = /'填制调单时间/') then
if (DBGrid1.DataSource.DataSet.FieldByName(/'填制调单时间/').AsDateTime >DBGrid1.DataSource.DataSet.FieldByName(/'应发货时间/').AsDateTime) then
begin
//v:=TColCellParamsEh.Create ;
//Column.GetColCellParams(true,v);
//v.Font.Color :=clRed;
//Column.FillColCellParams(v);
//v.Free;
DBGrid1.Canvas.font.Color := clRed;
end;

//Column.GetColCellParams .FillColCellParams()

if (Column.Field.FieldName = /'移交时间/') then
if (DBGrid1.DataSource.DataSet.FieldByName(/'移交时间/').AsDateTime >DBGrid1.DataSource.DataSet.FieldByName(/'应移交时间/').AsDateTime) then
DBGrid1.Canvas.Font.Color := clRed;

if (Column.Field.FieldName = /'填制运输单时间/') then
if (DBGrid1.DataSource.DataSet.FieldByName(/'填制运输单时间/').AsDateTime >DBGrid1.DataSource.DataSet.FieldByName(/'填制调单时间/').AsDateTime) then
DBGrid1.Canvas.Font.Color := clRed;

DBGrid1.DefaultDrawColumnCell(Rect, DataCol, Column, State);
DBGrid1.Canvas.Font.Color:=OldColor;
}
end;
//可以显示,可以打印
procedure TfrmQueryContractInfo.DBGrid1GetCellParams(Sender: TObject;
Column: TColumnEh; AFont: TFont; var Background: TColor;
State: TGridDrawState);
var
OldColor,OldColumnColor:TColor;
v:TColCellParamsEh;
begin
//OldColor:=DBGrid1.Canvas.Font.Color ;
if (Column.Field.FieldName = /'填制调单时间/') then
if (DBGrid1.DataSource.DataSet.FieldByName(/'填制调单时间/').AsDateTime >DBGrid1.DataSource.DataSet.FieldByName(/'应发货时间/').AsDateTime) then
AFont.Color := clRed;

if (Column.Field.FieldName = /'移交时间/') then
if (DBGrid1.DataSource.DataSet.FieldByName(/'移交时间/').AsDateTime >DBGrid1.DataSource.DataSet.FieldByName(/'应移交时间/').AsDateTime) then
AFont.Color := clRed;

if (Column.Field.FieldName = /'填制运输单时间/') then
if (DBGrid1.DataSource.DataSet.FieldByName(/'填制运输单时间/').AsDateTime >DBGrid1.DataSource.DataSet.FieldByName(/'填制调单时间/').AsDateTime) then
AFont.Color := clRed;

if (Column.Field.FieldName = /'实际到货时间/') then
if (DBGrid1.DataSource.DataSet.FieldByName(/'实际到货时间/').AsDateTime >DBGrid1.DataSource.DataSet.FieldByName(/'要求到货时间/').AsDateTime) then
AFont.Color := clRed;
//DBGrid1.DefaultDrawColumnCell(Rect, DataCol, Column, State);
//DBGrid1.Canvas.Font.Color:=OldColor;
end;

DBGridEH 所有欄位自動寬度的實現
interface
THackDBGridEH = class(TCustomdbgrideh)
end;

procedure OptimizeGrid(AGrid: TCustomDbGridEh);

implementation
procedure OptimizeGrid(AGrid: TCustomDbGridEh);
var
i: integer;
begin
// 優化GRID的寬度
for i := 0 to TDBGridEh(AGrid).Columns.count - 1 do
THackDBGridEH(AGrid).OptimizeSelectedColsWidth(TDBGridEh(AGrid).Columns[i]);
end;


從ehlib 3.0開始,DBGridEH的OptionEh中就多了一個dbgDblClickOptimizeColWidth選項,設為true,就可以雙擊一個標題的右邊線,自動此列的寬度.
但是我想一次性實現整個grid的自動寬度,卻沒有找到相就的方法(真的有可能是我沒有找到,如果本身就有的話請一定要用郵件通知我喔),所以就自已寫了一個,用起來還可以,數據量大的時候就會有些慢呢!


(作者: ci7 2005-2-1 8:39:34)  [资料] [短信] [好友] [邮箱]
18
 




大家好像对此不太感冒呀.

这可是真材实料呀.
每个都做通了就是这方面的专家了.
(作者: songwt 2005-2-1 8:58:43)  [资料] [短信] [好友] [邮箱]
19
 




这个资料太乱,有空整理一下,做成doc文档或者是chm文件,再放上来,其它的资料正在整理中......
(作者: 刘万红 2005-2-1 17:01:54)  [资料] [短信] [好友] [邮箱]
20
 




好得很! 待我慢慢消化.
(作者: 光记 2005-2-5 7:52:50)  [资料] [短信] [好友] [邮箱]
21
 




    
以下是引用songwt在2005-2-1 8:58:43的发言:
这个资料太乱,有空整理一下,做成doc文档或者是chm文件,再放上来,其它的资料正在整理中......


如还有请继续
(作者: 刘万红 2005-2-6 1:13:28)  [资料] [短信] [好友] [邮箱]
22
 




我正准备动手改造一下 DBGridEh ,直接去它的 DBgridEH.pas 中修改,大家觉得可行吗?
主要想改造的是: Enter键,方向键的控制;
(作者: VF爱好者 2005-2-19 19:07:55)  [资料] [短信] [好友] [邮箱]
23
 




好东东啦,先收藏起,慢慢消化
回复内容: 当前 HTML代码: 可用 UBB代码可用 贴图标签: 可用

请限定在1624000字节以内!
帖数:23 分页:[ 1]
 
  • 0
    点赞
  • 0
    评论
  • 0
    收藏
  • 打赏
    打赏
  • 扫一扫,分享海报

参与评论 您还未登录,请先 登录 后发表或查看评论
一、 DBGridEh(增强型表格组件)功能详解.....................................................................4 二、应用实例..........................................................................................................................5 1. 定制标题行......................................................................................................................5 1) 制作复杂标题行.......................................................................................................5 2) 按钮式标题..............................................................................................................5 3) 标题行显示图片.......................................................................................................5 4) 如根据不同状态在数据单元格中显示相应图片...................................................5 5) 自动显示标题行的升降排序标志符(▽降序△升序)并做相应排序...............6 6) 点dbgrideh 标题排序..............................................................................................7 7) 在DBGridEH 中怎样实现多重排序(标题出现0123等排列序号)? ................ 11 8) 让dbgrid显示序号................................................................................................ 11 2. 外观布局........................................................................................................................12 1) 根据不同字段值显示相应的小图片.....................................................................12 2) 显示检查框(checkbox)外观.............................................................................12 3) 显示单、多列下拉列表.........................................................................................12 4) 显示日历下拉列表.................................................................................................13 5) 3D或平面外观效果...............................................................................................13 6) 行头和列头的启用关闭.........................................................................................13 7) DBGrid如何实现透明效果?.................................................................................13 8) 滚动条的各种应用.................................................................................................16 9) 数据行高................................................................................................................19 10) DBGrid设置Rowheight后如何将单元格内容纵向和垂直都居中?..............19 11) 设置DBGridEH 自适应列宽的最好方法.........................................................20 12) Ehlib 的DBGridEh首列加序号........................................................................21 13) 分行分列、单元格的颜色设置.........................................................................23 14) 点击不同单元格列,执行不同的动作.............................................................27 15) 下拉式计算器.....................................................................................................28 16) 鼠标移到某个单元格,指针形状改变.............................................................28 17) 自动填充网格列宽到网格客户区.....................................................................29 18) 从注册表或ini文件中保存或恢复网格和列的层次。...................................29 3. 编辑功能........................................................................................................................29 1) 多选........................................................................................................................29 2) 文本多行显示.........................................................................................................30 3) 显示备注字段.........................................................................................................30 4) 如何让dbgrideh1 显示数据时只显示两位小数...................................................30 5) 获得当前DBGridEh表中单元格的序号.............................................................30 6) 怎样在dbgridEh和Edit中显示金额的千分号...................................................30 7) end;请问怎么才能使DBGridEh不滚动就能提交数据?...................................32 8) 我怎么把dbgrid 里的数据一次插入到数据库呢................................................32 9) 在DBGrid中可选中行而又可进入编辑状态......................................................32 10) 修正DBGrideh 丢失焦点时自动关闭输入法的问题......................................35 11) DBGRIDEH选定多行删除怎么实现...............................................................36 12) DBGrid 滚动表格的代码...................................................................................37 4. 统计功能........................................................................................................................37 白波九道整理自用版 第 3 页 1) 页脚合计................................................................................................................37 2) 定制表格底部(footer)区域的汇总统计行.......................................................38 3) TDBSumList说明..................................................................................................38 4) 如何工作以及为什么有时SumList的集合值计算不正确?.............................39 5) dbgrideh列求和.....................................................................................................39 5. 数据功能........................................................................................................................40 1) 查找字段点击某列值的下拉按纽弹出一个从数据库取值下拉列表...............40 2) 使用DBGridEh自动过滤实现方法.....................................................................40 3) 使用DBGridEh自动过滤实现方法2 ..................................................................41 4) DBGridEh 控件中使用过滤功能 (适用ehlib 5.2 ehlib 5.3)................................42 5) 支持模糊查询.........................................................................................................43 6) ehlib4.4.50中支持模糊匹配的修改方法..............................................................44 7) EhLib 5.0 Build 5.0.13的过滤字串都是模糊过滤修改.......................................45 8) 滚动条滚动时选择不变,还有自动过滤功能的实现.........................................45 9) 增量搜索................................................................................................................46 10) ehlib总是按两次ctrl+f才出来查找框,怎么办?.........................................46 11) 如何改良dbgrideh的文字过滤........................................................................46 12) 改进DBGrideh 表头点击自动排序,实现双击状态轮流.................................47 13) 改良Ehlib 的排序功能,加快排序速度.............................................................49 14) 在DbGridEh中显示TreeView效果................................................................50 15) DBGridEh-KeyList、PickList............................................................................51 16) 主从表设置........................................................................................................53 17) 在DbGridEh中显示表中表..............................................................................55 6. 输入/输出.......................................................................................................................56 1) 导入导出数据.........................................................................................................56 2) 从多种格式导入/导出数据到TDBGridEh...........................................................57 3) DBGRID 生成EXCEL报表.................................................................................57 4) 使用TPrintDBGridEh 组件.................................................................................61 5) 打印时确定Ehlib定义的报表表头颜色? ............................................................61 6) Ehlib 中的PrintDBGridEh如何印页码,即第几页共几页...................................62 7) 怎么让PrintDBGridEh只打印DbGridEh 中指定的列.......................................62 8) 怎样进行横向打印/ 打印预览?........................................................................62 7. 将存在的DBGrid组件转换为DBGridEh组件...........................................................62 三、EhLib安装问题.............................................................................................................64 1. EhLib 安装步骤.............................................................................................................64 2. EhLib 安装问题(dbsumlst.dcu出错) ..........................................................................64 3. 安装提示找不到.BPL文件...........................................................................................65 四、Delphi 下的优秀表格(Grid)显示控件........................................................................65 1. NextGrid .........................................................................................................................65 2. TopGrid 3.01...................................................................................................................65 3. XLGrid............................................................................................................................66 4. DevExpress ExpressQuantumGrid .................................................................................66 5. TMS Grid Pack...............................................................................................................68 6. EhLib ..............................................................................................................................71 白波九道整理自用版 第 4 页 7. ProfGrid..........................................................................................................................71 8. EasyGrid .........................................................................................................................71 五、delphi 中配置文件的使用(*.ini).........................................................................71 六、窗口动画效果Animatewindow应用...........................................................................72 七、Delphi Excel to Sql Server..............................................................................................73 八、Delphi控制Excel的经验如下:..................................................................................76
©️2022 CSDN 皮肤主题:大白 设计师:CSDN官方博客 返回首页

打赏作者

jian704

你的鼓励将是我创作的最大动力

¥2 ¥4 ¥6 ¥10 ¥20
输入1-500的整数
余额支付 (余额:-- )
扫码支付
扫码支付:¥2
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、C币套餐、付费专栏及课程。

余额充值