怎样在Grid中嵌入其他的组件。在线等,解决后再加200分 (100分)

T

troyliu

Unregistered / Unconfirmed
GUEST, unregistred user!
怎样在Grid中嵌入其他的组件?在线等
例如:每一列为一个操作单元。可以选择此列为CheckBox,ComboBox等。
 
先放一个需要的控件,设置VISIBLE:=FALSE
处理ONDRAWCOLUMNCELL事件,在事件里用你需要的控件的SETBOUND处理控件的大小和位置,
满足条件时设置控件的VISIBLE:=TRUE
 
//定位按扭
procedure Tform1.locaGrdBtn(Btn:TControl;Grd:TObject;flg:integer=0);
var
i:integer;
j:integer;
GetLeft,GetTop:integer;
begin
//Get Top
GetTop:= (Grd as TStringGrid).Top;
for i:=0 to (Grd as TStringGrid).Row-1 do
begin
GetTop :=GetTop+(Grd as TStringGrid).RowHeights+1;
end;
//Get Left
GetLeft:= (Grd as TStringGrid).Left;
for i:=0 to(Grd as TStringGrid).Col-1 do
begin
GetLeft :=GetLeft+(Grd as TStringGrid).ColWidths+1;
end;

Btn.top:=GetTop+2;
if flg=0 then
begin
Btn.Left:=GetLeft+(Grd as TStringGrid).ColWidths[(Grd as TStringGrid).Col]
-Btn.Width+3;
btn.Height:=(Grd as TStringGrid).RowHeights[(Grd as TStringGrid).row];
end
else begin
Btn.Top:=GetTop+(Grd as TStringGrid).RowHeights[(Grd as TStringGrid).row]+1;
Btn.Left:=GetLeft+2;
end;

btn.Visible:=true;
end;
 
满意??????????????
 
什么Grid呀!?
 
无非就是StringGrid和DBGrid了!
满意???
怎么没反应?
 
请教楼上:为什么用TstringGrid呀?
这段可以在任意Grid与Edit等中使用吗?
 
我在网上找到了一个。
例子如下。
---- 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 下调试通过。希望本文能使你可以更加方便快捷的开发数据库应用程序
主要是在事件中得到坐标的位置或得到相应的行和列。
 
这些都还要上网找,其实DFW离线论坛就有答案! 唉,现在的人什么事都先想着去问别人,
其实答案就在自己手中!
 
看看我做的怎样,在www.playicq.com软件展示厅应用软件类韩树江的时钟中,闹钟
设置和备忘提示设置中就是,2000年写的.
 
有很多好的第三方控件,譬如DX
 
静态的组件嵌入我会做。
我现在的问题是怎么做一个动态的组件嵌入。
例如,在DBGrid中的Column中可以选择此列为CheckBox,
或者其他类型。
 
难道这个问题很难吗?
我觉得很难
 
我看今天高手都回家过节去了。
 
>>难道这个问题很难吗?
>>我觉得很难
我也觉得很难。
动态嵌入必须动态创建组件。嵌入组件并不难,但“嵌入”的组件外形与Grid的外形有很大不同,
例如combobox,它的高度与Grid并不一致,无法调整。想解决这一点,就很难。
当然,你用Grid内置的类,自然可以天衣无缝,但,这真的很难 :( 至少,偶不会。
 
80. 在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环境调试通过,可以直接引用。
 
好,谢谢了。我现在就试试看。
 
非常感谢楼上,不过
DrawFrameControl是否能画别的组件能。
我的Delphi里没有此函数的帮助。
 
非常感谢各位大富翁的参加,但是都不符和我的设计
怎样在Grid中嵌入其他的组件?在线等
例如:每一列为一个操作单元。可以选择此列为CheckBox,ComboBox等。
 
我查了源码,DBGrid的一列是一个TColumn,父类是TCollection。
我想能根据程序员的选择,动态的指定TColumn的父类是什么类型。
 
顶部