来自: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

浅谈控件(组件)制作方法一(附带一delphi导出数据到Excel的组件实例)(原创)的更多相关文章

  1. Delphi 导出数据至Excel的7种方法【转】

    一; delphi 快速导出excel   uses ComObj,clipbrd;   function ToExcel(sfilename:string; ADOQuery:TADOQuery): ...

  2. Delphi 导出数据至Excel的7种方法

    一; delphi 快速导出excel uses ComObj,clipbrd; function ToExcel(sfilename:string; ADOQuery:TADOQuery):bool ...

  3. django django中的HTML控件及参数传递方法 以及 HTML form 里的数据是怎么被包成http request 的?如何在浏览器里查看到这些数据?

    https://www.jb51.net/article/136738.htm django中的HTML控件及参数传递方法 下面小编就为大家分享一篇django中的HTML控件及参数传递方法,具有很好 ...

  4. silverlight visifire控件图表制作——silverlight 后台方法页面事件

    1.返回事件 (1.返回silverlight页面,2.返回web页面) private void button_ClickBack(object sender, RoutedEventArgs e) ...

  5. silverlight visifire控件图表制作——silverlight 后台方法ControlChart.xaml.cs

    一.构造方法ControlChart 1.前台页面控件赋值 //时间下拉框赋值,下拉框赋选定值                for (int ii = DateTime.Today.Year; ii ...

  6. [Swift通天遁地]二、表格表单-(4)使用系统自带的下拉刷新控件,制作表格的下拉刷新效果

    ★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★➤微信公众号:山青咏芝(shanqingyongzhi)➤博客园地址:山青咏芝(https://www.cnblogs. ...

  7. winform利用ImageList控件和ListView控件组合制作图片文件浏览器

    winform利用ImageList控件和ListView控件组合制作图片文件浏览器,见图,比较简单,实现LISTVIEW显示文件夹图片功能. 1.选择文件夹功能代码: folderBrowserDi ...

  8. [原创]浅谈H5页面性能优化方法

    [原创]浅谈H5页面性能优化方法 前阶段公司H5页面性能测试,其中测试时也发现了一些性能瓶颈问题,接下来我们在来谈谈H5页面性能优化,仅仅是一些常用H5页面性能优化措施,其实和Web页面性能优化思路大 ...

  9. monkeyrunner之坐标或控件ID获取方法(六)

    Monkeyrunner的环境已经搭建完成,现在对Monkeyrunner做一个简介. Monkeyrunner工具提供了一套API让用户/测试人员来调用,调用这些api可以控制一个Android设备 ...

随机推荐

  1. win7在某个盘或文件夹中出现右键只能新建文件夹的情况 (2012-12-28-bd 写的日志迁移

    至于只能新建文件夹的情况如图: 解决方法是在运行中输入msconfig进入如图: 在系统设置选工具项在选中更改UAC设置点击启动如图: 如图: 直接把通知栏拉到最低确定即可(如果已经是最低了那就随便改 ...

  2. 库函数的使用:sscanf的使用方法

    先贴代码,可以看懂代码的直接看代码: /***************************************************** ** Name : sscanf.c ** Auth ...

  3. HDU 3966 Aragorn's Story 树链拋分

    一.写在前面 终于开始开坑link-cut-tree这个了,对于网上找到的大佬的前进路线,进行了一番研发,发现实际上可以实现对于树链拋分的制作.经历了若干长时间之后终于打了出来(为什么每次学什么东西都 ...

  4. Java模拟音乐播放器 暂停与重新播放——线程如何控制另外一个线程的状态

    package com.example.Thread; import javax.swing.*; import java.awt.*; import java.awt.event.ActionEve ...

  5. Java基础知识回顾(一):字符串小结

    Java的基础知识回顾之字符串 一.引言 很多人喜欢在前面加入赘述,事实上去技术网站找相关的内容的一般都应当已经对相应知识有一定了解,因此我不再过多赘述字符串到底是什么东西,在官网中已经写得很明确了, ...

  6. Not a git repository (or any of the parent directories): .git解决

    首先git init .然后在执行就行了.意思应该是当前目录不是git.

  7. Error:Execution failed for task ':myapplication:processDebugResources'. > com.android.ide.common.pro

    Error:Execution failed for task ':myapplication:processDebugResources'. > com.android.ide.common. ...

  8. va_list

    void Log( const TCHAR *pszFormat, ... ) { TCHAR buf[] ; va_list arglist ; try { _tcscpy_s ( buf, , _ ...

  9. 【Reverse Integer】cpp

    题目: Reverse digits of an integer. Example1: x = 123, return 321Example2: x = -123, return -321 click ...

  10. DWR搭建以及使用教程

    DWR搭建以及使用教程   DWR(Direct Web Remoting)是一个Ajax的开源框架,用于改善web页面与Java类交互的远程服务器端的交互体验,可以帮助开发人员开发包含AJAX技术的 ...