unit JKFootpanel; interface uses Windows, Messages, SysUtils, Classes,Graphics, Controls, Forms, Dialogs, ExtCtrls, dbctrls, stdctrls, db, ADODB, ComCtrls; type TEditorstyle = (TsDbMemo,TsDBcombox,Tsdbedit); type TJKFootpanel = class(TPanel) private { Private declarations } FLeft: Integer; FTop: Integer; maxTextLen: Integer; maxLabelLen: Integer; FScrollBox: TScrollBox; {滚动控件} FLineHeight: Integer; FEditorstyle:Teditorstyle; FTitleVisible :Boolean; //数据数组控件,动态生成 MemoEditors :array of TDBMemo; comEditors :array of TDBCombobox; edEditors :array of TDBedit; Labels :array of TLAbel; //字段标题,动态生成 FDataSource :TDataSource; // 数据源 FColumns :Integer; //显示列数 procedure FreeEditors; //释放数据输入控件的内存 procedure AKeyDown(Sender :TObject; var Key: Word; Shift:TShiftState); procedure AKeyPress(Sender :TObject; var Key: Char); 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; procedure Setedit(Value :TEditorstyle); procedure ClearHits(ItemIndex :Integer); procedure AddHits(ItemIndex :Integer; Hits :array of string); Function CreateEditors(DS :TDataSource; ColCount :Integer) :integer; //创建各字段的数据输入控件 { 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 FEditorstyle default Tsdbedit; property EditorWidth :Integer read maxTextLen write maxTextLen default 100; property TitleWidth :Integer read maxLabelLen write maxLabelLen default 100; property LineHeight :Integer read FLineHeight write FLineHeight default 15; property TitleVisible :Boolean read FTitleVisible write FTitleVisible default True; property DataSource :TDataSource read FDataSource write FDataSource; //数据源 property Columns :Integer read FColumns write FColumns default 4;//表列数 { Published declarations } end; procedure Register; implementation constructor TJKFootpanel.Create(AOwner: TComponent); begin Inherited Create(AOWner); FLeft :=16; FTop := 10; maxTextLen := 100; maxLabelLen := 100; FLineHeight := 15; FTitleVisible := True; Editorstyle := Tsdbedit; end; procedure Register; begin RegisterComponents('Data Controls', [TJKFootpanel]); end; procedure TJKFootpanel.Setedit(Value : TEditorstyle); begin if FEditorstyle <> Value then begin FEditorstyle := Value; Invalidate; end; end; { 为第I字段增加提示信息的方法} procedure TJKFootpanel.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 TJKFootpanel.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 TJKFootpanel.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; { 创建各字段的数据输入控件的方法} Function TJKFootpanel.CreateEditors(DS: TDataSource; ColCount: Integer):Integer ; var i, n, RowCount: Integer; TextHeight: Integer; begin result := 120; if DataSource = nil then exit; if not DataSource.DataSet.Active then exit; Columns := ColCount; if Columns = 0 then exit; n := DataSource.DataSet.fieldCount; 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 Columns > n then Columns := n else Columns := ColCount; RowCount := n div Columns; if n mod Columns <> 0 then inc(RowCount); { 分配内存} FreeEditors; SetLength(Labels,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; //FScrollBox.Color := clSkyBlue; FScrollBox.OnDblClick := OnDblClick; { 创建编辑} for i := 0 to n - 1 do begin { 创建标题} Labels[i] := TLabel.Create(Owner); Labels[i].visible := TitleVisible; Labels[i].Parent := FScrollBox; Labels[i].Caption := DataSource.DataSet.Fields[i].FieldName; Labels[i].Left := FLeft + (maxLabelLen + 16) * (i div RowCount)+ 2; //+maxTextLen if FEditorstyle = TsDBMemo then begin Labels[i].Width := maxLabelLen; Labels[i].Top := FTop + (i mod RowCount) * (TextHeight*2+4) + 12; end else begin Labels[i].Width := maxLabelLen; Labels[i].Top := FTop + (i mod RowCount) * (TextHeight*1 +12) end; { 创建信息显示数据对象} 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+15; comEditors[i].DataSource := DataSource; comEditors[i].DataField := DataSource.DataSet.Fields[i].FieldName; comEditors[i].OnKeyPress := AKeyPress; comEditors[i].OnKeyDown := AKeyDown; comEditors[i].Font.Color := ClBlue; 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+15; edEditors[i].DataSource := DataSource; edEditors[i].DataField := DataSource.DataSet.Fields[i].FieldName; edEditors[i].OnKeyPress := AKeyPress; edEditors[i].OnKeyDown := AKeyDown; edEditors[i].Font.Color := ClBlue; 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+15; MemoEditors[i].DataSource := DataSource; MemoEditors[i].DataField := DataSource.DataSet.Fields[i].FieldName; MemoEditors[i].OnKeyPress := AKeyPress; MemoEditors[i].OnKeyDown := AKeyDown; MemoEditors[i].Font.Color := ClBlue; end; end; if FEditorstyle = TsDBMemo then result := RowCount*TextHeight*4 +20 else result := RowCount*TextHeight*2 +20; DataSource.DataSet.EnableControls; FScrollBox.Visible := True; end; end; destructor TJKFootpanel.Destroy; begin FreeEditors; Inherited Destroy; end; function TJKFootpanel.comEditor(Index: Integer): TDBComboBox; begin if Index< Length(comEditors) then Result := comEditors[Index] else Result := nil; end; function TJKFootpanel.edEditor(Index: Integer): TDBedit; begin if Index < Length(edEditors) then Result := edEditors[Index] else Result := nil; end; function TJKFootpanel.MemoEditor(Index: Integer): TDBMemo; begin if Index< Length(MemoEditors) then Result := MemoEditors[Index] else Result := nil; end; // 内存的释放是要有顺序的!必须以创建的相反的顺序进行!尤其是当组件之间有父子关系时 procedure TJKFootpanel.FreeEditors; begin if FScrollBox <> nil then begin comEditors := nil; edEditors := nil; MemoEditors := nil; FScrollBox.Free; FScrollBox := nil; end; end; procedure TJKFootpanel.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; end.