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;