调节阀计算软件:DBGrid的应用举例 --逆水行舟

来源:百度文库 编辑:九乡新闻网 时间:2024/05/05 07:24:34




首先声明一下,本人是初学者,内容摘自《delphi source By killghost》
 
2006-01-18 19:58:12 云中霹雳
新建一个Application,在Form1上放Table1,DataSource1,DBGrid1,属性设置如下:
Table1 DatabaseName: DBDEMOS
TableName: EMPLOYEE.DB
Active: True;
DataSource1 DataSet: Table1
DBGrid1 DataSource1: DataSource1
 
2006-01-18 19:58:39 云中霹雳
以上是做下面功能的前奏
 
2006-01-18 19:58:50 fox
先介绍一下今天的主题吧。
一开门就是建工程[:L]
 
2006-01-18 19:59:12 云中霹雳
主题:DBGrid的应用举例
 
2006-01-18 19:59:29 云中霹雳
回车让光标右移动:
 
2006-01-18 19:59:48 云中霹雳
procedure TForm1.DBGrid1KeyPress(Sender: TObject; var Key: Char);
begin
   if key=#13 then                          //如果按下回车
      DBGrid1.SelectedIndex:=DBGrid1.SelectedIndex+1;  
end;
 
2006-01-18 19:59:59 云中霹雳
这个是代码,应该容易理解吧
 
2006-01-18 20:00:15 小龙南翔/mg
OK
 
2006-01-18 20:00:15 云中霹雳
但是当光标到达一行的末尾的时候就下不去了,一直处于行末状态。我们需要当光标到达行末的时候光标会到达下一行的开始。于是代码修改为下面:
 
2006-01-18 20:00:36 云中霹雳
procedure TForm1.DBGrid1KeyPress(Sender: TObject; var Key: Char);
begin
   if key=#13 then
   begin
      if DBGrid1.SelectedIndex<>5 then
         DBGrid1.SelectedIndex:=DBGrid1.SelectedIndex+1
      else
      begin
         table1.RecNo:=Table1.RecNo+1;
         DBGrid1.SelectedIndex:=0;
      end;
   end;
 
2006-01-18 20:00:56 云中霹雳
跟上面比较增加了recNO的设置
 
2006-01-18 20:00:57 Canny岑灿坤
谁有点击标题排序的图表阿姨
 
2006-01-18 20:01:25 Canny岑灿坤
就是三角箭头
 
2006-01-18 20:01:28 杭州-Tommy
先听讲,然后再提出疑问
 
2006-01-18 20:01:36 云中霹雳
要实现这个功能就得了解Selectedindex和RecNo的概念,可以通过delphi帮助了解selectedindex表示当前光标所在的位置,光标在grid中第一数据的话selectedindex的值为0,第二个的话为1,……   RecNo表示一个记录的号码,即Grid中行号,第一行的话表示1,第二行的话表示2,……。
 
2006-01-18 20:02:30 佛山-sislcb
if DBGrid1.SelectedIndex<>5 什么意思?
 
2006-01-18 20:02:40 佛山-sislcb
这里知道是五吗?
 
2006-01-18 20:02:55 云中霹雳
就是当还没到达一行的末尾的
 
2006-01-18 20:03:13 佛山-sislcb
是不是固定就是不等于五/
 
2006-01-18 20:03:15 云中霹雳
这个表就6列
 
2006-01-18 20:03:12 云中霹雳

2006-01-18 20:03:23 云中霹雳
所以我写了5
 
2006-01-18 20:03:37 云中霹雳
根据具体情况来
 
2006-01-18 20:03:52 云中霹雳
这个好了吗
 
2006-01-18 20:04:12 云中霹雳
隔行改变DBGrid网格颜色
云中霹雳 20:04:12
隔行改变DBGrid网格颜色
云中霹雳 20:04:27
 效果图:

云中霹雳 20:04:37

云中霹雳 20:05:22
用DBGrid1的DrawColumnCell方法
云中霹雳 20:05:46
这个方法在设置颜色等方面比较长用
云中霹雳 20:06:10
代码:procedure TForm1.DBGrid1DrawColumnCell(Sender: TObject; const Rect: TRect;
  DataCol: Integer; Column: TColumn; State: TGridDrawState);
begin
 if gdSelected in State then Exit;  // 如果所在区域被选中
   if table1.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);//定义网格线的颜色:
云中霹雳 20:06:18
还没完。。。
云中霹雳 20:06:35
这个部分是设置行的颜色的代码
云中霹雳 20:06:44
有什么问题?
Canny岑灿坤 20:07:06
单击标题排序的图表有吗?

Canny岑灿坤 20:07:18
单击标题排序的图表有吗?
小箭头的
云中霹雳 20:07:19
没有

云中霹雳 20:08:00
with (Sender as TDBGrid).Canvas do //画 cell 的边框
 begin
   Pen.Color := $00ff0000; //定义画笔颜色(蓝色)
   MoveTo(Rect.Left, Rect.Bottom); //画笔定位
   LineTo(Rect.Right, Rect.Bottom); //画蓝色的横线
   Pen.Color := clGreen; //定义画笔颜色(绿)
   MoveTo(Rect.Right, Rect.Top); //画笔定位
   LineTo(Rect.Right, Rect.Bottom); //画绿色的纵线
 end;
end;
云中霹雳 20:08:30
这段是画线的

佛山-sislcb 20:09:42
不要只给代码,讲点原理
云中霹雳 20:10:24
怎么讲原理
佛山-sislcb 20:10:49
为什么要这样做?
云中霹雳 20:11:21
procedure TForm1.DBGrid1DrawColumnCell(Sender: TObject; const Rect: TRect;
  DataCol: Integer; Column: TColumn; State: TGridDrawState);
云中霹雳 20:11:24
先看这个
云中霹雳 20:11:37
sender就是所选的DBGrid
  佛山-sislcb 20:11:52
知道
云中霹雳 20:12:01
Rect就是选定的一个网格的区域
云中霹雳 20:12:26
具体就是在这个区域里面画颜色
  佛山-sislcb 20:12:56
ok
云中霹雳 20:12:58
if table1.RecNo mod 2 = 0 then
云中霹雳 20:13:37
这个就是控制当行的号码为偶数的时候,颜色设置成(Sender as TDBGrid).Canvas.Brush.Color := clinfobk 
云中霹雳 20:13:59
反之是奇数行设置
云中霹雳 20:14:45
隔列改变DBGrid的网格颜色
云中霹雳 20:15:15
 

云中霹雳 20:15:21
这个跟上面的隔行应该很相似
云中霹雳 20:15:33
procedure TForm1.DBGrid1DrawColumnCell(Sender: TObject; const Rect: TRect;
  DataCol: Integer; Column: TColumn; State: TGridDrawState);
begin
  if gdSelected in state then exit;   
  with DBGrid1.Canvas do
  begin
     if datacol mod 2=0 then   
        brush.Color:=clBlue
     else
        Brush.Color:=clAqua;
  end;
  DbGrid1.Canvas.pen.mode:=pmmask;
  DBGrid1.DefaultDrawColumnCell(Rect,Datacol,Column,state);
end;
云中霹雳 20:15:57
这里主要是根据datacol(列号)来控制


云中霹雳 20:17:08
在Delphi的DBGrid中插入其他可视组件
云中霹雳 20:17:26
Delphi提供了功能强大的 DBGrid组件,以方便进行数据库应用程序设计。但是如果我们仅仅利用DBGrid组件,每一个获得焦点(Grid)只是一个简单的文本编辑框,不方便用户输入数据。Delphi也提供了一些其他数据组件来方便用户输入,比如DBComboBox,DBCheckBox等组件,但这些组件却没有DBGrid功能强大。其实我们可以通过在DBGrid中插入其他可视组件来实现这一点。
云中霹雳 20:18:09
 例:分别拖动的Data Access组件板上DataSource、Table,Data Controls组件板上DBGrid,DBComboBox四个组件到Form1上。
云中霹雳 20:18:25
  Form1 Caption '在DBGrid中插入SpinEdit组件示例'
DataSource1 DataSet Table1
Table1  DatabaseName DBDEMOS
      TableName 'employee.db'
      Active True
DBGrid1      DataSource DataSource1
DBComboBox1 DataField  Firstname
              DataSource DataSource1
              Visible False
              Strings Items:'Kim'|'Bruce'|'Ann'|'Pete' 
云中霹雳 20:18:29
前奏

云中霹雳 20:24:15
 
云中霹雳 20:24:22
上面是效果图
云中霹雳 20:25:10
procedure TForm1.DBGrid1DrawDataCell(Sender: TObject; const Rect: TRect;
  Field: TField; State: TGridDrawState);
begin
     if (gdFocused in State) then
     begin
         if Field.FieldName=DBEdit1.DataField then
         begin
             DBEdit1.Left:=Rect.Left+DBGrid1.Left;
             DBEdit1.Top:=Rect.Top+DBGrid1.Top;
             DBEdit1.Width:=Rect.right-Rect.left;
             DBEdit1.Height:=Rect.Bottom-Rect.Top;
             DBEdit1.Visible:=True;
         end;

     end;
end;
云中霹雳 20:25:27
错了
云中霹雳 20:25:37
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;

云中霹雳 20:25:55
这个功能好象跟直接在DBGrid1.column[2]上的picklist中添加'Kim'|'Bruce'|'Ann'|'Pete'一样的功能,不知道后者是不是在以前的版本中没有的?

云中霹雳 20:28:10
 if (gdFocused in State) then   //如果state=gdfocused就是当cell处于焦点的时候,然后把DBComboBox1画到rect区域中
云中霹雳 20:28:30
上面这个例子中DBGrid指定单元格未获得焦点时不显示DBComboBox,设置DBGrid1的OnColExit事件如下:
procedure TForm1.DBGrid1ColExit(Sender: TObject);
begin
 If DBGrid1.SelectedField.FieldName = DBComboBox1.DataField then
   begin
     DBComboBox1.Visible := false;
   end;
end;
云中霹雳 20:29:55
当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;
云中霹雳 20:30:36
LRESULT SendMessage(

    HWND hWnd,       // handle of destination window
    UINT Msg,     // message to send
    WPARAM wParam,       // first message parameter
    LPARAM lParam   // second message parameter
   );
云中霹雳 20:31:47
SendMessage(DBComboBox1.Handle,WM_Char,word(Key),0); 其中 DBComboBox1.handle是操作的实体
云中霹雳 20:32:04
WM_Char是消息类型
云中霹雳 20:32:24
WParam,LParam是传递的信息参数
云中霹雳 20:34:50
使dbgrid的某几笔资料变色 
 曾经拥有 20:35:53
这是干吗的?
云中霹雳 20:36:04
procedure TForm1.DBGrid1DrawDataCell(Sender: TObject; const Rect: TRect;
  Field: TField; State: TGridDrawState);
begin
 with TDBGrid(Sender) do
 begin
   if (条件) then
     Canvas.TextOut(Rect.Left + 4, Rect.Top + 2,'要显示的文字如表格的资料');
end;
云中霹雳 20:36:07
哪个?
 曾经拥有 20:36:10
这是干吗的?

云中霹雳 20:36:42
这个是在DBGrid里面自己输入文字

 曾经拥有 20:36:55
这些是干吗的?

云中霹雳 20:37:08
哪些?
 曾经拥有 20:37:30

这些是干吗的? 
云中霹雳 20:37:47
然后再
在 DBGrid.OnDrawColumnCell(...) 中:

begin
 if TableField.AsInteger < 0 then
   DBGrid.Canvas.Font.Color := clRed
 else
   DBGrid.Canvas.Font.Color := clBlack;
 DBGrid.DefaultDrawColumnCell(...);
end;
iamy 20:38:16
晕~

云中霹雳 20:38:16
上面那个没用
云中霹雳 20:38:52
什么
 曾经拥有 20:38:59

那这个呢?是干吗的?
云中霹雳 20:39:42
是在网格里面显示ComboBox

 曾经拥有 20:39:53
能用吗?
云中霹雳 20:39:59
   
云中霹雳 20:40:34
相当于直接在DBGRid1.column[index]里面设置picklist一样
 曾经拥有 20:40:51
ComboBox里面的数据是从哪里来的?
能动态改变吗?

云中霹雳 20:41:15
是在ComboBox的stringitem里面写好的
 曾经拥有 20:41:29
我试一下/。。。
云中霹雳 20:41:43
你可以对DBComboBox1进行操作来改变
 曾经拥有 20:42:14

云中霹雳 20:42:38
DBComboBox1.items.add()
 曾经拥有 20:42:53
 谢谢。
云中霹雳 20:43:42
点击DBGrid的Title对查询结果排序

云中霹雳 20:44:16
这个我还没弄怎么懂,大家一起来讨论一下
云中霹雳 20:44:26
欲实现点击DBGrid的Title对查询结果排序,想作一个通用程序,不是一事一议,例如不能在SQL语句中增加Order by ...,因为SQL可能原来已经包含Order by ...,而且点击另一个Title时又要另外排序,目的是想作到象资源管理器那样随心所欲。
云中霹雳 20:44:55
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;   // FieldKind to determine if a 
field is a data field, a calculated field, a lookup field, or an aggregate field.


 if Column.Field.FieldKind =fkData then
   myFieldName := UpperCase(Column.Field.FieldName)     
else
   myFieldName := UpperCase(Column.Field.KeyFields);   // Set KeyFields only on      
lookup fields
 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;
 曾经拥有 20:45:24
那怎么在DBGrid的Title显示三角和倒三角?
云中霹雳 20:45:25
好象被我弄的太乱了,原版发一下
云中霹雳 20:45:39
什么三角,倒三角?
 曾经拥有 20:45:41
那怎么在DBGrid的Title排序时显示三角和倒三角?

云中霹雳 20:46:09
就是用图表表示出来?
云中霹雳 20:46:15
图标?
 曾经拥有 20:46:16
不是。
云中霹雳 20:46:31
还是按从小到大还是从大到小?
 曾经拥有 20:46:54
你等等。。。
云中霹雳 20:47:06
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;

 曾经拥有 20:47:31
显示倒三角 
云中霹雳 20:48:06
哦,那不知道了
杭州-Tommy 20:48:52
只是用个flag来判断下不就可以了?
深圳-♂沙子 20:49:05
有这个特殊符号,画上去的
 曾经拥有 20:49:18
那这个 是怎么显示出来的?
云中霹雳 20:49:39
procedure TForm1.DBGrid1TitleClick(Column: TColumn);
begin
     TFHkdata.SortQuery(Column);
end;
结束!
杭州-Tommy 20:50:00
不是可以设置它的title吗?后面再加上个三角形啊

云中霹雳 20:50:28
好象有道理可能就是这么弄的

曾经拥有 20:51:08
后面再加上个三角形啊

不是这样做的。。。