国产探花免费观看_亚洲丰满少妇自慰呻吟_97日韩有码在线_资源在线日韩欧美_一区二区精品毛片,辰东完美世界有声小说,欢乐颂第一季,yy玄幻小说排行榜完本

首頁 > 編程 > Delphi > 正文

通用Delphi數(shù)據(jù)庫輸入控件DBPanel的實(shí)現(xiàn)

2019-11-18 19:00:35
字體:
供稿:網(wǎng)友
李曉平/河北固安華北石油職工大學(xué)

---- 無論是開發(fā)什么樣的程序,數(shù)據(jù)輸入是不可缺少的??焖俚厣梢粋€(gè)美觀的輸入界面無疑會(huì)大大提高程序開發(fā)的效率。系統(tǒng)原有的控件,往往不盡人意。在delphi中,如果針對(duì)某字段,可選的控件有DBLabel, DBEdit等;如果針對(duì)全表的輸入,有DBGrid。使用Dbedit等控件時(shí),用戶必須全面安排各字段的位置,雖然能夠達(dá)到美觀的效果,但是,如果字段數(shù)多,無疑是很麻煩的。如果采用DBGrid,無論多少個(gè)字段,只用一個(gè)控件就夠了,簡單倒是簡單,但是各字段是一字排列的,使用起來有點(diǎn)不方便。對(duì)于一般的用戶來說,采用表格形式的錄入,既方便,又美觀。這就是本文所要解決的問題。

---- 技術(shù)關(guān)鍵

---- 本控件的主要功能是實(shí)現(xiàn)對(duì)數(shù)據(jù)庫字段的編輯。按照一般的規(guī)律,控件中應(yīng)包含TdataLink對(duì)象,還應(yīng)該實(shí)現(xiàn)與TdataLink相關(guān)得一系列方法;但是,那樣會(huì)耗費(fèi)大量的代碼。代碼量越大,系統(tǒng)就越復(fù)雜,出錯(cuò)的可能性就越大。本控件的開發(fā)思路是以最少的代碼實(shí)現(xiàn)最多的功能。所以,對(duì)數(shù)據(jù)字段的編輯直接使用TDBComboBox控件。

---- 為了實(shí)現(xiàn)通用性,在控件內(nèi)部維護(hù)了一個(gè)字段編輯控件數(shù)組和字段標(biāo)題數(shù)組。如下:

Editors: array of TDBComboBox;    
- >具體進(jìn)行編輯所用的數(shù)據(jù)控件數(shù)組,動(dòng)態(tài)生成
Labels: array of TLabel;        
- >各字段的標(biāo)題,動(dòng)態(tài)生成

---- 采用TDBComboBox優(yōu)點(diǎn)是它不僅能具有一般的編輯功能,還能為各字段添加相應(yīng)的提示信息。代碼如下:
{ 為第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;

---- 具體的應(yīng)用是千差萬別的,所以,控件還需要給程序員留有足夠的事件處理接口,以實(shí)現(xiàn)具體應(yīng)用時(shí)的特殊功能。這就需要在控件中定義一定的事件處理方法供用戶實(shí)現(xiàn)。這里提供的是一個(gè)OnOkClick事件,即當(dāng)所有字段編輯完成后所執(zhí)行的處理。代碼如下:
   
OkButton: TButton;                
- >最后增加的確定按鈕,用于實(shí)現(xiàn)提交動(dòng)作。
property OnOkClick: TNotifyEvent read FClick write FClick;

---- 通過實(shí)現(xiàn)OnOKClick方法,用戶可以完成提交、數(shù)據(jù)合理性檢驗(yàn)等各種處理工作。另外一個(gè)需要特殊處理的是控制在各個(gè)字段間的轉(zhuǎn)換。缺省的情況是用鼠標(biāo)點(diǎn)擊。但是,用戶的習(xí)慣往往是用鍵盤中的"上、下、左、右"四個(gè)箭頭鍵。要實(shí)現(xiàn)這一功能需定義以下兩個(gè)方法:
   
procedure AKeyPress(Sender: TObject; var Key: Char);
procedure AKeyDown(Sender: TObject;
var Key: Word; Shift: TShiftState);

---- 將以上兩個(gè)方法賦值給動(dòng)態(tài)生成的Editors,從而實(shí)現(xiàn)對(duì)箭頭鍵的響應(yīng)。
---- 不同的表字段數(shù)不同,有可能出現(xiàn)顯示不下的情況,這就需要有滾動(dòng)的功能。所以,在控件中插入了一個(gè)TscrollBox控件。最后一個(gè)需要注意的是動(dòng)態(tài)控件的撤消及內(nèi)存的釋放??丶?shù)組的撤消及內(nèi)存的釋放是有順序的--與創(chuàng)建完全相反的順序。否則會(huì)出錯(cuò)。

----控件的使用

---- 先將DBPanel控件放在窗體上,然后設(shè)置數(shù)據(jù)源屬性、數(shù)據(jù)輸入表格的列數(shù)等屬性。在程序中,打開數(shù)據(jù)源后,調(diào)用創(chuàng)建數(shù)據(jù)編輯控件的方法即可。即:

Query1.Open;- >打開數(shù)據(jù)源
DBPanel1.CreateEditors; - >創(chuàng)建各字段的編輯控件
DBPanel1.AddHits(0,['1111','11222','eeee']);    
- >為某字段設(shè)置提示信息
DBPanel1.AddHits(1,['1111','11222','eeee']); 
- >為某字段設(shè)置提示信息
該控件及示例程序在Win98+Delphi 5.0環(huán)境下調(diào)試通過。


---- 附件:TDBPanel的源代碼

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;        {滾動(dòng)控件}
    FLineHeight: Integer;
    FClick: TNotifyEvent;
    Editors: array of TDBComboBox;    
- >具體進(jìn)行編輯所用的數(shù)據(jù)控件數(shù)組,動(dòng)態(tài)生成
    Labels: array of TLabel;        
- >各字段的標(biāo)題,動(dòng)態(tài)生成
    OkButton: TButton;                
- >最后增加的確定按鈕,用于實(shí)現(xiàn)提交動(dòng)作。
    { 數(shù)據(jù)源}
    FDataSource: TDataSource;
    FColumns: Integer;                
- >輸入表格的列數(shù)
    protected
    { Protected declarations }
    procedure FreeEditors;            
- >釋放數(shù)據(jù)輸入控件的內(nèi)存
    public
    procedure CreateEditors;//
    (DS: TDataSource; ColCount: Integer);
- >創(chuàng)建各字段的數(shù)據(jù)輸入控件
    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;
- >數(shù)據(jù)源
    property Columns: Integer read
    FColumns write FColumns;- >表列數(shù)
    { Published declarations }
  end;

procedure Register;

implementation

procedure Register;
begin
  RegisterComponents('Additional', [TDBPanel]);
end;

{ 為第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;

{ 創(chuàng)建各字段的數(shù)據(jù)輸入控件的方法}
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;
    { 計(jì)算最大的標(biāo)題長度及顯示長度}
    DataSource.DataSet.First;
    { 計(jì)算高度}
    TextHeight := Canvas.TextHeight(DataSource
    .DataSet.Fields[0].DisplayLabel) + FLineHeight; //10;
    { 計(jì)算行列數(shù)}
    RowCount := n div Columns;
    if n mod Columns <  > 0 then inc(RowCount);
    { 分配內(nèi)存}
    FreeEditors;
    SetLength(Editors, n);
    SetLength(Labels, n);
    { 創(chuàng)建滾動(dòng)盒}
    FScrollBox := TScrollBox.Create(Owner);
    FScrollBox.Parent := Self;
    FScrollBox.Align := alClient;
    { 創(chuàng)建編輯}
    for i:=0 to n-1 do begin
      { 創(chuàng)建標(biāo)題}
      Labels[i] := TLabel.Create(Owner);
      Labels[i].Parent := FScrollBox; //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;
      { 創(chuàng)建編輯對(duì)象}
      Editors[i] := TDBComboBox.Create(Owner);
      Editors[i].Parent := FScrollBox; //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;
    { 創(chuàng)建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
  { 內(nèi)存的釋放是要有順序的!必須以創(chuàng)建的相反的順序進(jìn)行!
  尤其是當(dāng)組件之間有父子關(guān)系時(shí)}
  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;

end.

上一篇:用Delphi開發(fā)屏幕保護(hù)預(yù)覽程序

下一篇:Delphi編程實(shí)現(xiàn)Ping操作

發(fā)表評(píng)論 共有條評(píng)論
用戶名: 密碼:
驗(yàn)證碼: 匿名發(fā)表
學(xué)習(xí)交流
熱門圖片

新聞熱點(diǎn)

疑難解答

圖片精選

網(wǎng)友關(guān)注

主站蜘蛛池模板: 天长市| 开封县| 井陉县| 新民市| 深水埗区| 太湖县| 东明县| 读书| 潢川县| 漳州市| 东乌珠穆沁旗| 隆子县| 普陀区| 济源市| 肥城市| 龙泉市| 射阳县| 安远县| 平和县| 墨玉县| 屯门区| 黄山市| 绥德县| 许昌市| 巴里| 泸水县| 樟树市| 罗江县| 淮安市| 工布江达县| 岢岚县| 赤城县| 嵊泗县| 凤山县| 丘北县| 商水县| 冕宁县| 绩溪县| 紫金县| 抚远县| 宜宾市|