zoukankan      html  css  js  c++  java
  • 浅谈控件(组件)制作方法一(附带一delphi导出数据到Excel的组件实例)(原创)

    来自:http://blog.csdn.net/zhdwjie/article/details/1490741

    -------------------------------------------------------------------

    从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: boyxd@163.net                                *}
    {*            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;
    end.

    以上为作者写的一个小控件,有兴趣的朋友可以来信一起学习。
    作者Email: boyxd@163.net

  • 相关阅读:
    如何使用Orchard搭建敏捷个人的网站(1)
    英语:敏捷英语学习开始了
    英语:普特三步听写法(转载)
    色拉英语第一集第五幕:好胖的一只鸟
    介绍一个基于ASP.NET MVC的框架Catharsis
    色拉英语第2集第3幕:He’s my favorite
    Orchard:如何生成Hello World模块
    如何使用Orchard搭建敏捷个人的网站(2)
    色拉英语第一集第四幕:我不喜欢北京烤鸭
    色拉英语第一集第二幕:请问南京路怎么走?
  • 原文地址:https://www.cnblogs.com/del88/p/3897396.html
Copyright © 2011-2022 走看看