程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> 更多編程語言 >> Delphi >> 淺談控件(組件)制作方法一(附帶一delphi導出數據到Excel的組件實例)

淺談控件(組件)制作方法一(附帶一delphi導出數據到Excel的組件實例)

編輯:Delphi

  從99年學習delphi開始,我就被它的快速開發迷上了,那時候剛接觸編程,對可視化開發特別來勁,原因嘛,不外乎是比C更快的實現啦,這幾年來,從delphi的C/S到三層B/S,大大小小也寫過一些軟件,自認為這Delphi也就這麼些功能吧,自從最近偶得一本Com本質論,研究了一下VCL源碼,才發現它真的神通廣大(我也不知道用什麼詞來形容),最近有些許突破,就在此於大家分享,有不對之處還請指點一二。

  說白了,組件只包括二類成員:   屬性和方法(我所說的方法包括了事件)
  分屬於四個部分:
    private
    protected
    public
    published
  上面四部分的意思在一般的可視化開發書籍當中都會有介紹,這裡只相對於Delphi作簡單概述。
   private: 所有私有的成員都放在這裡,只能被類自身的方法所訪問,而不能被子類訪問,對子類透明。也可說只能被單元本身的方法訪問。
   protected:除了可以被子類繼承外,其余和private一樣。不能被外界訪問。
   public:  公有的,在此間聲明的屬性和方法能被用戶調用。
   published: 出現在Delphi開發環境屬性欄中。

  首先我們來做一個最簡單的控件,不到五分鐘,你就會明白Delphi的組件面板上的組件是如何制作的了。
    新建->New->Component 回車。
    然後在Ancestor type:中選擇你要繼承的父類,這裡我們選TComponent.表示繼承TComponent的所有屬性和方法。
    Class Name:中輸入將要制作的組件的類名。(我們輸入TShowText)
    Palette Page:組件將要安裝到Delphi的哪個面板上。(我們選擇Samples,你也可以輸入一個新的名字)
   下面的就不用我說了吧。
   點擊OK按鈕,Delphi自動生成了一個基本的繼承自TComponent的控件了,也可以這樣理解,我們已經開發了一個與TComponent功能一樣強大的控件,不過這不是我們需要的,下面我們繼續。
  下面說明一下組件本身私有變量的讀寫方法:
    比如我們寫了下面一小段:
    private
      FText : String;
      ....
    /*私有變量不是允許被外界使用的,那麼要如何才能對這個FText字符串變量進行操作呢?*/

  我們還要在Published後面添加這麼一段:
    property Text: String read FText write FText;
   這裡的意思就是指,這個Text屬性會出現在DelphiSDK的屬性欄中,用戶修改屬性欄中的Text實際上都是在修改FText這個字符串變量。read表示用戶讀取Text屬性實際上讀取FText,write當然就表示用戶為Text賦值則存在FText字符串變量中啦。
   如果在這時候保存,並在Delphi中安裝.那麼我們這個最基本的組件就制作完了。(安裝組件方法在最後有介紹)
   哈哈,是不是很簡單呢?只不過我們的這個組件沒有實現什麼具體用處罷了。
   剛才這裡我們介紹了屬性,下面我們繼續增加功能,來介紹一下方法的使用。
   我們在Public後面添加如下:
   procedure ShowText();
   然後按Ctrl + Alt +C,系統自動為你添加了些方法的實現代碼。
   接下來我們在寫:
  procedure TShowText.ShowText();
  begin
   ShowMessage(FText);  
  end;
    看到了,上面的ShowMessage顯示的就是類私有變量的值,到這裡大家應該明白了,只有在類本事的方法才能訪問私有的變量。這裡必須在uses 後面加上Dialogs單元,因為ShowMessage包含在Dialogs單元中,否則通不過。

  當然,上面的事件只能在控件中使用,去不能在屬性框中的事件欄中出現,為什麼呢?因為這裡聲名的方法只是Public的,純方法而已,並沒有聲明為事件。
  通過上面的學習,大家是不是已經知道控件的屬性和方法是如何寫的和調了的了呢?
  不過,一個真正意義上的控件是離不開事件的,而事件的調用必須通過消息來驅動,這將在我的下一篇中介紹。
   一個功能強大的控件的屬性和方法也不是這麼容易的,還需要大家多實踐,多應用。
  下面附帶了我寫的一個DBGridToExcel控件,功能是把DBGrid中的數據導出到Excel中。大家可以學習一下,做為參考。為個控件中包括了使用屬性,方法和我們將在下一篇中講到的“事件”。

  附1: 安裝自制控件的方法:
  
  (1).在Component菜單中,選擇"Install Component...".
    (2).在Unit File name 後面單擊“...",選擇"*.pas"控件的單元文件,再點擊OK。在出現的窗口中單擊"install",即安裝完畢。
  新裝的控件即出現在你的面板中。

  附2: TDBGridToExcel控件的全部源碼,把它拷貝到記事本中,存為.pas文件即可。
  unit DBGridToExcel;

  {***********************************************************************}
  {*                                                                     *}
  {*           Export Grid To Word VCL Control for D5 & D6               *}
  {*        Copyright(C) xiangding 2003.10.1 All rights reserved         *}
  {*            Bug Report: [email protected]                                *}
  {*            Author    : 小熊                                         *}
  {*                                                                     *}
  {***********************************************************************}
  {*                                                                     *}
  {*          This is a Simple Version                                   *}
  {*                                                                     *}
  {***********************************************************************}
  {*                                                                     *}
  {* Install:                                                            *}
  {*    Please Save as file GridToExcel.pas then open the file           *}
  {*    Click the menu item [Component] --> [Install Component]          *}
  {*    Click [Install] button in the Install Component dialog           *}
  {*    after install ,you can find the control at component             *}
  {*    page [sample]                                                    *}
  {*                                                                     *}
  {***********************************************************************}
  {*                                                                     *}
  {* 安裝:                                                              *}
  {*   把附件保存,然後用Delphi打開這個GridToExcel.Pas文件,             *}
  {*   選擇Delphi菜單--〉Component-->Install Component,                 *}
  {*   然後選擇Install即可。安裝之後,在控件面板的Samples頁面上面,      *}
  {*   熟悉之後,你可以試著設置一些復雜的屬性,其他的自己摸索吧,        *}
  {***********************************************************************}
  interface

  uses
    Windows, StdCtrls, ComCtrls, Messages, DBGrids, Graphics, ExtCtrls,
    Forms, DB, ComObj, Controls, SysUtils, Classes;

  ResourceString
    SPromptExport     = '請等待,正在導出數據……';
    SConnectExcel     = '正在啟動Excel,請稍候……';
    SConnectExcelError= '連接Excel失敗,可能沒有安裝Excel,無法導出.';
    SCancel           = '取消(&C)';
    SError            = '錯誤';
    SConfirm          = '真的要終止數據的導出嗎?';
    SCaption          = '確認';
    SGridError        = '沒有指定數據集,請指定數據集控件!';

  type
    TDBGridToExcel = class(TComponent)
    private
      ProgressForm: TForm;
      FShowProgress: Boolean;
      ExcelApp : Variant;
      FTitle: String;
      Quit: Boolean;
      FOnProgress: TNotifyEvent;
      FGrid: TDBGrid;   {The Source Grid}
      ProgressBar: TProgressBar;
      Prompt: TLabel;
      FAutoExit: Boolean;
      FAutoSize: Boolean;
      FDBGrid: TDBGrid;
      procedure SetShowProgress(const Value: Boolean);
      procedure CreateProgressForm;
      procedure ButtonClick(Sender: TObject);
      Function ConnectToExcel: Boolean;
      procedure ExportDBGrid;
      { Private declarations }
    protected
      { Protected declarations }
    public
      Constructor Create(AOwner: TComponent); override;
      Destructor Destroy(); override;
      Procedure ExportToExcel;   {Export Grid To Excel}
      { Public declarations }
    published
      { Published declarations }
      property DBGrid: TDBGrid read FDBGrid write FDBGrid;
      property Title: String read FTitle write FTitle;
      property ShowProgress: Boolean read FShowProgress write SetShowProgress;

      property OnProgress: TNotifyEvent read FOnProgress write FOnProgress;

    end;

  procedure Register;

  implementation

  procedure Register;
  begin
    RegisterComponents('Samples', [TDBGridToExcel]);
  end;

  { TDBGridToExcel }

  procedure TDBGridToExcel.ButtonClick(Sender: TObject);
  begin
    Quit := MessageBox(ProgressForm.Handle, pchar(SConfirm), pchar(SCaption),
      MB_OKCANCEL + MB_ICONINFORMATION) = IDOK;
  end;

  function TDBGridToExcel.ConnectToExcel: Boolean;
  begin
    Result := true;
    Try
      ExcelApp := CreateOleObject('Excel.Application');
      ExcelApp.Visible := False;
      if Title<>'' then ExcelApp.Caption := Title;
      ExcelApp.WorkBooks.Add;
    except
      MessageBox(GetActiveWindow,PChar(SConnectExcelError),PChar(SError),Mb_OK+MB_IconError);
      result := false;
    end;
  end;

  constructor TDBGridToExcel.Create(AOwner: TComponent);
  begin
    inherited;
    FShowProgress := True;          {Default value was Show the Progress}
    FAutoExit := False;
    FAutoSize := True;
  end;

  procedure TDBGridToExcel.CreateProgressForm;
  var
    Panel  : TPanel;
    Button : TButton;
  begin
    if Assigned(ProgressForm) then exit;  {Aready Create?}

    ProgressForm := TForm.Create(Owner);
    With ProgressForm do
    begin
      Font.Name := '宋體';
      Font.Size := 10;
      BorderStyle := bsNone;
      Width := 280;
      Height := 120;
      BorderWidth := 1;
      Color := clBackground;
      Position := poOwnerFormCenter;
    end;

    Panel := TPanel.Create(ProgressForm);
    with Panel do { Create Panel }
    begin
      Parent := ProgressForm;
      Align := alClIEnt;
      BevelInner := bvNone;
      BevelOuter := bvRaised;
      Caption := '';
    end;

    Prompt := TLabel.Create(Panel);
    with Prompt do { Create Label }
    begin
      Parent := Panel;
      Left := 20;
      Top := 25;
      Caption := SConnectExcel;
    end;

    ProgressBar := TProgressBar.Create(panel);
    with ProgressBar do { Create ProgressBar }
    begin
      Step := 1;
      Parent := Panel;
      Smooth := true;
      Left := 20;
      Top := 50;
      Height := 18;
      Width := 260;
    end;

    Button := TButton.Create(Panel);
    with Button do { Create Cancel Button }
    begin
      Parent := Panel;
      Left := 115;
      Top := 80;
      Caption := SCancel;
      OnClick := ButtonClick;
    end;

    ProgressForm.Show;
    ProgressForm.Update;
  end;

  destructor TDBGridToExcel.Destroy;
  begin

    inherited;
  end;

  procedure TDBGridToExcel.ExportDBGrid;
  var
    Data   : TDataSet;
    ADBGrid: TDBGrid;
    i, j   : integer;
    CurrentPoint : Pointer;
    OldBeforeScroll, OldAfterScroll: TDataSetNotifyEvent;
  begin
    Screen.Cursor := crHourGlass;
    try
      try
        TForm(Owner).Enabled := False;
        ExcelApp.DisplayAlerts := false;
        ExcelApp.ScreenUpdating := false;
        Quit := false;

        if ShowProgress then Prompt.Caption := SPromptExport;
        ADBGrid := DBGrid;
        Data := ADBGrid.DataSource.DataSet;
        with ADBGrid do { Insert Table Header }
          for i := 1 to Columns.Count do
            if Columns[i - 1].Visible then
              ExcelApp.Cells[1,i].Value :=Columns[i - 1].Title.Caption;

        CurrentPoint := Data.GetBookmark;  {Save Current Position}
        OldBeforeScroll := Data.BeforeScroll; { Save Old Before Scroll Event handle }
        OldAfterScroll := Data.AfterScroll; { Save Old After Scroll Event Handle }
        Data.DisableControls; { Disable Control }
        Data.BeforeScroll := nil;
        Data.AfterScroll := nil;
   
        if ShowProgress then ProgressBar.Max := Data.RecordCount;
        i := 2;
        Data.First;
        while not Data.Eof do  { Process All record }
        begin
          with ADBGrid do { Process one record }
            for j := 1 to Columns.Count do
              if Columns[j - 1].Visible then
                ExcelApp.Cells[i,j].Value := Columns[j - 1].FIEld.DisplayText;
          Inc(i);
          Data.Next;
          if Assigned(FOnProgress) then FOnProgress(Self);
          if ShowProgress then { Update Progress UI }
          begin
            ProgressBar.StepIt;
            Application.ProcessMessages;
            if Quit then exit;
          end;
        end;
      except
        MessageBox(GetActiveWindow,PChar(SConnectExcelError),Pchar(SError),MB_OK+MB_ICONERROR);
      end;
      ExcelApp.Visible := False;
      TForm(Owner).Enabled := True;
      Screen.Cursor := crDefault;
      if ShowProgress then FreeAndNil(ProgressForm); { Free Progress Form }
      ExcelApp.DisplayAlerts := True;
      ExcelApp.ScreenUpdating := True;
    finally
      Data.BeforeScroll := OldBeforeScroll; { Restore Old Event Handle }
      Data.AfterScroll := OldAfterScroll;
      Data.GotoBookmark(CurrentPoint);
      Data.FreeBookmark(CurrentPoint);
      Data.EnableControls;
      Screen.Cursor := crDefault;
    end;
  end;

  procedure TDBGridToExcel.ExportToExcel;
  begin
    if DBGrid= nil then raise Exception.Create(SGridError); {No DataSource, then Error}
    if ShowProgress then CreateProgressForm; {Whether or not Show the ProgressForm}
    if not ConnectToExcel then { Exit when error occer }
    begin
      if ShowProgress then  FreeAndNil(ProgressForm);   {release form}
      exit;
    end;
    ExportDBGrid;  {begin Export Data}
  end;

  procedure TDBGridToExcel.SetShowProgress(const Value: Boolean);
  begin
    FShowProgress := Value;
  end;

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved