unit Dbpanel; interface uses Windows, Messages, SysUtils, Classes,Graphics, Controls, Forms, Dialogs, ExtCtrls, dbctrls, stdctrls, db, ADODB, ComCtrls; type TEditorstyle = (TsDbMemo,TsDBcombox,Tsdbedit); type TDBPanel = class(TPanel) private { Private declarations } FEditorstyle:Teditorstyle; FLeft: Integer; FTop: Integer; maxTextLen: Integer; maxLabelLen: Integer; FTitleVisible :Boolean; FScrollBox: TScrollBox; {滚动控件} FLineHeight: Integer; //数据数组控件,动态生成 MemoEditors: array of TDBMemo; comEditors: array of TDBCombobox; edEditors: array of TDBedit; ProgressEditor :array of TDBedit; Labels: array of TDBText; //字段标题,动态生成 ProgressBars: array of TProgressBar; FDataSource: TDataSource; // 数据源 FDataField_A: String; // DataField FDataField_B: String; // DataField FDataField_C: String; // DataField FColumns: Integer; //显示列数 procedure FreeEditors; //释放数据输入控件的内存 procedure AKeyDown(Sender:TObject; var Key: Word; Shift:TShiftState); procedure AKeyPress(Sender:TObject; var Key: Char); procedure AProgressEditorChange(Sender: TObject); function comEditor(Index: Integer):TDBComboBox; function edEditor(Index: Integer):TDBedit; function MemoEditor(Index: Integer): TDBMemo; protected { Protected declarations } public constructor Create(AOwner:TComponent); override; destructor Destroy; override; function Get_TitleVisible() :Boolean; procedure Set_TitleVisible(Value : Boolean); procedure Setedit(Value : TEditorstyle); procedure CreateEditors(DS: TDataSource; ColCount: Integer); //创建各字段的数据输入控件 procedure ClearHits(ItemIndex: Integer); procedure AddHits(ItemIndex:Integer; Hits: array of string); { Public declarations } published property LimitLeft: Integer read FLeft write FLeft default 10; property LimitTop: Integer read FTop write FTop default 10; property Editorstyle : TEditorstyle read FEditorstyle write Setedit default tsdbMemo; property EditorWidth: Integer read maxTextLen write maxTextLen default 100; property TitleWidth: Integer read maxLabelLen write maxLabelLen default 100; property TitleVisible : Boolean read Get_TitleVisible write Set_TitleVisible default True; property LineHeight: Integer read FLineHeight write FLineHeight default 15; //property OnOkClick: TNotifyEvent read FClick write FClick; property DataSource: TDataSource read FDataSource write FDataSource; //数据源 property DataField_Editor: String read FDataField_A write FDataField_A; property DataField_Title: String read FDataField_B write FDataField_B; property DataField_Progress: String read FDataField_C write FDataField_C; property Columns: Integer read FColumns write FColumns default 4;//表列数 { Published declarations } end; procedure Register; implementation procedure Register; begin RegisterComponents('Data Controls', [TDBPanel]); end; function TDBPanel.Get_TitleVisible() :Boolean; begin Result := FTitleVisible; end; procedure TDBPanel.Set_TitleVisible(Value : Boolean); begin FTitleVisible := Value; end; procedure TDBPanel.Setedit(Value : TEditorstyle); begin if FEditorstyle <> Value then begin FEditorstyle := Value; Invalidate; end; end; { 为第I字段增加提示信息的方法} procedure TDBPanel.AddHits(ItemIndex: Integer; Hits: array of string); var m,n,i: Integer; begin if FEditorstyle = TsDBcombox then begin n := Length(comEditors); m := Length(Hits); if ItemIndex< n then for i:=0 to m-1 do comEditors[ItemIndex].Items.Add(Hits[i]); end else if FEditorstyle = TsDBEdit then begin n := Length(edEditors); m := Length(Hits); if ItemIndex< n then for i:=0 to m-1 do edEditors[ItemIndex].Hint:= Hits[i]; end else if FEditorstyle = TsDBMemo then begin n := Length(memoEditors); m := Length(Hits); if ItemIndex< n then for i:=0 to m-1 do memoEditors[ItemIndex].Hint:= 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 else if (Sender is TDBedit) then begin case Key of VK_Next: (Sender as TDBedit).DataSource.DataSet.Next; VK_PRIOR: (Sender as TDBedit).DataSource.DataSet.Prior; end; end else if (Sender is TDBMemo) then begin case Key of VK_Next: (Sender as TDBMemo).DataSource.DataSet.Next; VK_PRIOR: (Sender as TDBMemo).DataSource.DataSet.Prior; end; end; end; procedure TDBPanel.AProgressEditorChange(Sender: TObject); begin // end; procedure TDBPanel.AKeyPress(Sender: TObject; var Key: Char); begin if (Sender is TDBComboBox) or (Sender is TDBedit) or (Sender is TDBMemo) then if Key=#13 then (Owner as TForm).Perform(WM_NEXTDLGCTL, 0, 0); end; procedure TDBPanel.ClearHits(ItemIndex: Integer); var n: Integer; begin if FEditorstyle = TsDBcombox then begin n := Length(comEditors); if ItemIndex< n then comEditors[ItemIndex].Items.Clear; end else if FEditorstyle = TsDBEdit then begin n := Length(edEditors); if ItemIndex< n then edEditors[ItemIndex].Hint:='';; end else if FEditorstyle = TsDBMemo then begin n := Length(MemoEditors); if ItemIndex< n then MemoEditors[ItemIndex].Hint:='';; end; 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 = nil then exit; if not DataSource.DataSet.Active then exit; n := DataSource.DataSet.RecordCount; if n > 0 then begin DataSource.DataSet.DisableControls; if maxLabelLen < maxTextLen then maxTextLen := maxLabelLen; { 计算最大的标题长度及显示长度} DataSource.DataSet.First; { 计算高度} TextHeight := Canvas.TextHeight(DataSource.DataSet.Fields[0].DisplayLabel) + FLineHeight; //10; { 计算行列数} if (FColumns = 0) or (FColumns <> ColCount) then FColumns := ColCount; RowCount := n div Columns; if n mod Columns <> 0 then inc(RowCount); { 分配内存} FreeEditors; SetLength(Labels,n); SetLength(ProgressBars,n); SetLength(ProgressEditor,n); if FEditorstyle = TsDBcombox then SetLength(comEditors,n) else if FEditorstyle = TsDBEdit then SetLength(edEditors,n) else SetLength(MemoEditors,n); { 创建滚动盒} FScrollBox := TScrollBox.Create(Owner); FScrollBox.Visible := False; FScrollBox.Parent := Self; FScrollBox.Align := alClient; { 创建编辑} for i := 0 to n - 1 do begin { 创建标题} Labels[i] := TDBText.Create(Owner); Labels[i].visible := FTitleVisible; Labels[i].Parent := FScrollBox; Labels[i].DataField := DataField_Title; Labels[i].DataSource := DataSource; Labels[i].Left := FLeft + (maxLabelLen + 36) * (i div RowCount)+16; //+maxTextLen if FEditorstyle = TsDBMemo then begin Labels[i].Width := maxLabelLen; Labels[i].Top := FTop + (i mod RowCount) * (TextHeight*4+10) + 2; end else begin Labels[i].Top := FTop + (i mod RowCount) * (TextHeight*2+10) + 2; Labels[i].Width := maxLabelLen; end; { 创建进度条数据对象} ProgressEditor[i] := TDBedit.Create(Owner); ProgressEditor[i].visible := False; ProgressEditor[i].Parent := FScrollBox; ProgressEditor[i].DataField := DataField_Progress; ProgressEditor[i].DataSource := DataSource; ProgressEditor[i].OnChange := AProgressEditorChange; { 创建信息显示数据对象} if FEditorstyle = TsDBcombox then begin comEditors[i] := TDBComboBox.Create(Owner); comEditors[i].Parent := FScrollBox; //Self; comEditors[i].Left := Labels[i].Left; //+ Labels[i].Width; comEditors[i].Width := maxTextLen; comEditors[i].Top := Labels[i].Top+20; comEditors[i].DataSource := DataSource; comEditors[i].DataField := DataField_Editor; comEditors[i].OnKeyPress := AKeyPress; comEditors[i].OnKeyDown := AKeyDown; ProgressBars[i] := TProgressBar.Create(Owner); ProgressBars[i].Parent := FScrollBox; ProgressBars[i].Orientation := pbHorizontal; ProgressBars[i].Left := comEditors[i].Left; ProgressBars[i].Width := comEditors[i].Width; ProgressBars[i].Height := 10; ProgressBars[i].Top := comEditors[i].Top+comEditors[i].height+2; ProgressBars[i].Position := i*4 end else if FEditorstyle = TsDBEdit then begin edEditors[i] := TDBedit.Create(Owner); edEditors[i].Parent := FScrollBox; edEditors[i].Left := Labels[i].Left; //+ Labels[i].Width; edEditors[i].Width := maxTextLen; edEditors[i].Top := Labels[i].Top+20; edEditors[i].DataSource := DataSource; edEditors[i].DataField := DataField_Editor; edEditors[i].OnKeyPress := AKeyPress; edEditors[i].OnKeyDown := AKeyDown; ProgressBars[i] := TProgressBar.Create(Owner); ProgressBars[i].Parent := FScrollBox; ProgressBars[i].Orientation := pbHorizontal; ProgressBars[i].Left := edEditors[i].Left; ProgressBars[i].Width := edEditors[i].Width; ProgressBars[i].Height := 10; ProgressBars[i].Top := edEditors[i].Top+edEditors[i].height+2;; ProgressBars[i].Position := i*4 end else begin MemoEditors[i] := TDBmemo.Create(Owner); MemoEditors[i].Parent := FScrollBox; MemoEditors[i].Left := Labels[i].Left; MemoEditors[i].Width := maxTextLen; MemoEditors[i].Top := Labels[i].Top+20; MemoEditors[i].DataSource := DataSource; MemoEditors[i].DataField := DataField_Editor; MemoEditors[i].OnKeyPress := AKeyPress; MemoEditors[i].OnKeyDown := AKeyDown; ProgressBars[i] := TProgressBar.Create(Owner); ProgressBars[i].Parent := FScrollBox; ProgressBars[i].Orientation := pbVertical; ProgressBars[i].Left := MemoEditors[i].Left + MemoEditors[i].Width +1; ProgressBars[i].Width := 10; ProgressBars[i].Height := MemoEditors[i].Height; ProgressBars[i].Top := MemoEditors[i].Top; ProgressBars[i].Position := i*4 end; if not DataSource.DataSet.Eof then DataSource.DataSet.next; end; DataSource.DataSet.EnableControls; FScrollBox.Visible := True; end; end; destructor TDBPanel.Destroy; begin FreeEditors; Inherited Destroy; end; function TDBPanel.comEditor(Index: Integer): TDBComboBox; begin if Index< Length(comEditors) then Result := comEditors[Index] else Result := nil; end; function TDBPanel.edEditor(Index: Integer): TDBedit; begin if Index < Length(edEditors) then Result := edEditors[Index] else Result := nil; end; function TDBPanel.MemoEditor(Index: Integer): TDBMemo; begin if Index< Length(MemoEditors) then Result := MemoEditors[Index] else Result := nil; end; // 内存的释放是要有顺序的!必须以创建的相反的顺序进行!尤其是当组件之间有父子关系时 procedure TDBPanel.FreeEditors; begin if FScrollBox <> nil then begin comEditors := nil; edEditors := nil; MemoEditors := nil; FScrollBox.Free; FScrollBox := nil; end; end; end.