<!-- /* Font Definitions */ @font-face {font-family:宋体; panose-1:2 1 6 0 3 1 1 1 1 1; mso-font-alt:SimSun; mso-font-charset:134; mso-generic-font-family:auto; mso-font-pitch:variable; mso-font-signature:3 135135232 16 0 262145 0;} @font-face {font-family:"/@宋体"; panose-1:2 1 6 0 3 1 1 1 1 1; mso-font-charset:134; mso-generic-font-family:auto; mso-font-pitch:variable; mso-font-signature:3 135135232 16 0 262145 0;} /* Style Definitions */ p.MsoNormal, li.MsoNormal, div.MsoNormal {mso-style-parent:""; margin:0cm; margin-bottom:.0001pt; text-align:justify; text-justify:inter-ideograph; mso-pagination:none; font-size:10.5pt; mso-bidi-font-size:12.0pt; font-family:"Times New Roman"; mso-fareast-font-family:宋体; mso-font-kerning:1.0pt;} /* Page Definitions */ @page {mso-page-border-surround-header:no; mso-page-border-surround-footer:no;} @page Section1 {size:595.3pt 841.9pt; margin:72.0pt 90.0pt 72.0pt 90.0pt; mso-header-margin:42.55pt; mso-footer-margin:49.6pt; mso-paper-source:0; layout-grid:15.6pt;} div.Section1 {page:Section1;} -->
在
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;
隔
行改变
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
未能通过,颜色没有隔行变化。
在
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;
锁
定
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
处理很简单
.
例如
:
对表中某字段当其数值小于
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
种方法分别就数据网格控件的列和行的色彩进行了设
置。
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;
这
就让焦点移到第一行第一列当中
如何使
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;
在
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;
在一个
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
的帮助。
在
TDBGrid
控件中实现拖放的另外一个思路
在本
unit
中,自定义
TMyCustomDBGrid=class(TCustomDBGrid),
再如下引用
:
TMyCustomDBGrid(DBGrid1).MouseDown(...)
或
DBGrid1 as
TMyCustomDBGrid).MouseDown(...)
即可。
如何使
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
控件就出现完整的日期了。
在
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.
1575

被折叠的 条评论
为什么被折叠?



