unit DBPanel;
interface
uses
windows, messages, sysutils, classes,graphics, controls, forms, dialogs,
extctrls, dbctrls, stdctrls, db;
type
TDBPanel = class(tpanel)
private
{ private declarations }
fleft: integer;
ftop: integer;
maxtextlen: integer;
maxlabellen: integer;
fscrollbox: tscrollbox; {滚动控件}
flineheight: integer;
fclick: tnotifyevent;
editors: array of tdbcombobox;
file://- >具体进行编辑所用的数据控件数组,动态生成
labels: array of tlabel;
file://- >各字段的标题,动态生成
okbutton: tbutton;
file://- >最后增加的确定按钮,用于实现提交动作。
{ 数据源}
fdatasource: tdatasource;
fcolumns: integer;
file://- >输入表格的列数
protected
{ protected declarations }
procedure freeeditors;
file://- >释放数据输入控件的内存
public
procedure createeditors(ds: tdatasource; colcount: integer);
file://- >创建各字段的数据输入控件
constructor create(aowner:
tcomponent); override;
destructor destroy; override;
procedure akeypress(sender:
tobject; var key: char);
procedure akeydown(sender:
tobject; var key: word; shift:
tshiftstate);
procedure clearhits(itemindex: integer);
procedure addhits(itemindex:
integer; hits: array of string);
function editor(index: integer):
tdbcombobox;
{ public declarations }
published
property leftlimit: integer read
fleft write fleft default 10;
property toplimit: integer read
ftop write ftop default 10;
property editorlen: integer read
maxtextlen write maxtextlen;
property labellen: integer read
maxlabellen write maxlabellen default 100;
property lineheight: integer read
flineheight write flineheight default 15;
property onokclick: tnotifyevent
read fclick write fclick;
property datasource: tdatasource
read fdatasource write fdatasource;
file://数据源
property columns: integer read
fcolumns write fcolumns;//- >表列数
{ published declarations }
end;
procedure Register;
implementation
{ 为第i字段增加提示信息的方法}
procedure tdbpanel.addhits(itemindex:
integer; hits: array of string);
var
m,n,i: integer;
begin
n := length(editors);
m := length(hits);
if itemindex< n then begin
for i:=0 to m-1 do editors[itemindex].items.add(hits[i]);
end;
end;
procedure tdbpanel.akeydown
(sender: tobject; var key: word;
shift: tshiftstate);
begin
if (sender is tdbcombobox) then begin
case key of
vk_next: (sender as tdbcombobox)
.datasource.dataset.next;
vk_prior: (sender as tdbcombobox)
.datasource.dataset.prior;
end;
end;
end;
procedure tdbpanel.akeypress(sender: tobject; var key: char);
begin
if (sender is tdbcombobox) then begin
if key=#13 then (owner as tform).perform(wm_nextdlgctl, 0, 0);
end;
end;
procedure tdbpanel.clearhits(itemindex: integer);
var
n: integer;
begin
n := length(editors);
if itemindex< n then editors[itemindex].items.clear;
end;
constructor tdbpanel.create(aowner: tcomponent);
begin
inherited create(aowner);
fleft :=10;
ftop := 10;
maxtextlen := 100;
maxlabellen := 100;
flineheight := 15;
end;
{ 创建各字段的数据输入控件的方法}
procedure tdbpanel.createeditors(ds: tdatasource; colcount: integer);
var
i, n, rowcount: integer;
textheight: integer;
begin
if datasource.dataset.active then begin
n := datasource.dataset.fieldcount;
{ 计算最大的标题长度及显示长度}
datasource.dataset.first;
{ 计算高度}
textheight := canvas.textheight(datasource
.dataset.fields[0].displaylabel) + flineheight; file://10;
{ 计算行列数}
rowcount := n div columns;
if n mod columns <> 0 then inc(rowcount);
{ 分配内存}
freeeditors;
setlength(editors, n);
setlength(labels, n);
{ 创建滚动盒}
fscrollbox := tscrollbox.create(owner);
fscrollbox.parent := self;
fscrollbox.align := alclient;
{ 创建编辑}
for i:=0 to n-1 do begin
{ 创建标题}
labels[i] := tlabel.create(owner);
labels[i].parent := fscrollbox; file://self;
labels[i].caption := datasource.dataset.fields[i].displaylabel;
labels[i].left := fleft + (maxlabellen +
maxtextlen + 10) * (i div rowcount);
labels[i].width := maxlabellen;
labels[i].top := ftop + (i mod rowcount) * textheight + 5;
{ 创建编辑对象}
editors[i] := tdbcombobox.create(owner);
editors[i].parent := fscrollbox; file://self;
editors[i].left := labels[i].left + labels[i].width;
editors[i].width := maxtextlen;
editors[i].top := ftop + (i mod rowcount) * textheight;
editors[i].datasource := datasource;
editors[i].datafield := datasource.dataset.fields[i].fieldname;
editors[i].onkeypress := akeypress;
editors[i].onkeydown := akeydown;
end;
{ 创建ok按钮}
okbutton := tbutton.create(owner);
okbutton.parent := fscrollbox;
okbutton.left := editors[n-1].left;
okbutton.top := editors[n-1].top + textheight;
okbutton.caption := '确定';
okbutton.onclick := fclick;
end;
end;
destructor tdbpanel.destroy;
begin
freeeditors;
inherited destroy;
end;
function tdbpanel.editor(index: integer): tdbcombobox;
begin
if index< length(editors) then result := editors[index]
else result := nil;
end;
procedure tdbpanel.freeeditors;
var
i,n: integer;
begin
{ 内存的释放是要有顺序的!必须以创建的相反的顺序进行!
尤其是当组件之间有父子关系时}
if okbutton<>nil then okbutton.free;
if editors<>nil then begin
n := length(editors);
for i:=0 to n-1 do editors[i].free;
editors := nil;
n := length(labels);
for i:=0 to n-1 do labels[i].free;
labels := nil;
end;
if fscrollbox<>nil then begin
fscrollbox.free;
fscrollbox := nil;
end;
end;
procedure Register;
begin
RegisterComponents('OK', [TDBPanel]);
end;
end.