C++Builder 2009 ファーストガイド 第九回「コンポーネントの作成」

By: Chikako Yonezawa

Abstract: C++Builder 2009 で既存のコンポーネントをベースに新たなコンポーネントを作成し、使用する方法について説明します。

このファーストガイドは、これから C++Builder 2009 を使い始める初心者の方を対象に 10回に分けて基本的な事項を説明していきます。第八回では、コンポーネントの概要とその操作ついて説明しました。第九回は、既存のコンポーネントを継承(ベースに)して新たなコンポーネントを作成し、その作成したコンポーネントを使用する方法について説明します。

    コンポーネントの作成

C++Builderには、フォーム、ボタン、データベース等、さまざまなコンポーネントが付属していますが、既存のコンポーネントを継承して、機能を追加し新しいコンポーネントを作成したり、一から新しいコンポーネントを作成することが可能です。ここでは、既存のコンポーネント TEditを継承して新しいコンポーネント TEditExを作成し、そのコンポーネントに機能を追加する方法について説明します。

    コンポーネントの作成手順

  1. C++Builder 2009のメニューより [コンポーネント|新規 VCLコンポーネント]を実行します。

Hide image
bcb9_01

  1. 「VCLコンポーネントの新規作成」のウィザードが表示されます。

Hide image
bcb9_02

  1. 今回は TEditを継承して新しいコンポーネントを作成しますので、コンポーネントのリストをスクロール、または右上の検索ボックスに TEditと入力し、TEditを選択して、[次へ]のボタンをクリックします。

Hide image
bcb9_03

  1. コンポーネントのクラス名等を設定する画面が表示されますので、クラス名を TEditEx、ユニット名を EditEx.cppに修正し、その他はそのままで [次へ]のボタンをクリックします。

Hide image
bcb9_04

  1. ユニットの作成の画面が表示されます。コンポーネントを作成するにはクラスを定義する新しいユニットが必要となります。また、コンポーネントを作成し使用するためにはパッケージが必要となります。ここでは新規にユニットを作成し、またそのユニットを保存するための新規のパッケージも合わせて生成するので「新規パッケージへインストール」を選択して[次へ]のボタンをクリックします。

Hide image
bcb9_05

  1. 新規パッケージの画面が表示されますので、パッケージ名を入力します。ここでは EditExPackageと入力し、[完了]のボタンをクリックします。

Hide image
bcb9_06

  1. ユニットの保存ダイアログが表示されますので、適切な場所に保存してください。

Hide image
bcb9_07

  1. ユニットを保存すると、コードが生成、コンパイルが行われ、作成したコンポーネントのインストールまで行われます。

Hide image
bcb9_08

実は、この段階で TEditから派生した(といっても何も機能追加していないので TEditを別の名前に変えただけの)コンポーネントが作成され、C++Builder IDE上にインストールされています。

    作成したコンポーネントを使用する

単純に派生しただけのコンポーネントですが、上記手順によって Samplesカテゴリ内にインストールされています。(コンポーネントを作成する際、パレットページ名はデフォルトの Samplesのままにしたので、作成されたコンポーネントは Samplesカテゴリに登録されます)

以下の手順にて作成したコンポーネントを確認します。

  1. メニューより [ファイル|すべて閉じる]で現在開いているファイルを一度すべて閉じ、[ファイル|新規作成|VCLフォームアプリケーション – C++Builder]を選択して、デザイン画面を表示します。
  2. ツールパレットの Samplesカテゴリを開きます。作成した TEditExコンポーネントが一番下に追加されているのが確認できます。

Hide image
bcb9_09

  1. 他のコンポーネント同様、ダブルクリック、またはドラックアンドドロップでフォーム上にコンポーネントを追加できます。

Hide image
bcb9_10

    コンポーネントに機能を追加する

TEditを継承した TEditExコンポーネントを作成しましたが、現時点では TEditを別の名前に変更しただけのコンポーネントとなっています。このコンポーネントに独自のプロパティやイベント等を追加していきます。

    コンストラクタとデストラクタ

コンストラクタとは、オブジェクトが生成される際に呼び出されるメソッドです。デストラクタは、オブジェクトが破棄されるタイミングで呼び出されるメソッドとなります。

コンストラクタ内には、主にコンポーネントが作成されるときに実行したいコード(初期化処理など)を追加します。デストラクタ内には破棄されるタイミングで実行したいコード(開放処理など)を追加します。

まず、作業を行うために、[ファイル|プロジェクトを開く]で、作成した EditExpackage.cbprojを選びプロジェクトを開きます。

既存のコンポーネントから継承して、新しいコンポーネントを作成した際に生成されるコード内には、コンストラクタがクラス名と同じ名前で自動生成されています。今回の例の場合は、EditEx.cppファイル内の以下の部分がコンストラクタのコードとなります。

__fastcall TEditEx::TEditEx(TComponent* Owner)
    : TEdit(Owner)
{
}

デストラクタは、コンストラクタと異なり自動生成は行われません。デストラクタの名称は、コンストラクタと同様にクラス名と同じ名称になりますが、先頭に~が付きます。(例 ~TEditEx)

TEditExの初期化処理として、このコンポーネントが作成された(ロードされた)際のコンポーネントの色を継承し、元の TEditと異なる色になるようコードを追加します。色を変えるには Colorプロパティに値を代入します。

__fastcall TEditEx::TEditEx(TComponent* Owner)
    : TEdit(Owner)
{
    Color = clSkyBlue;
}

メニューの [ファイル|すべて保存]を実行してコードを保存し、メニューの[プロジェクト|EditExPackageを再構築]を選び、パッケージの再コンパイル・再構築を行います。

これで TEditExに初期化処理が追加されました。コンポーネントの動作を確認するために、このパッケージを再インストールします。

再インストールは、プロジェクトマネージャー上に表示されている EditExPackage.bplの部分を選択し、マウスの右ボタンを押して表示されるポップアップメニューより「インストール」を選択します。

Hide image
bcb9_11

メモ :

パッケージの再インストールや再構築を行った際に、エラーが発生することがあります。これは作業中のコンポーネントが格納されているパッケージファイルが IDEに既にインストールされてしまっているために更新することができないためです。再インストールや再構築の際にエラーになった場合は、メニューの[コンポーネント|パッケージのインストール]を実行し、設計時パッケージに追加されてしまっている EditExPackageの横のチェックボックスを Offにしてから、再インストールや再構築を実行します。

Hide image
bcb9_12

先程と同様に、すべて保存して新規にアプリケーションを作成し、フォーム上に TEditExコンポーネントを置くと、コンストラクタに追加したコードが実行されて、TEditExコンポーネントの色が変わったことを確認できます。

Hide image
bcb9_13

    プロパティの作成

プロパティに値を設定する方法は、第八回で説明したように、単純に数値や文字列を入力できるものや、リストから選択するものなどがあります。

プロパティを定義するためには、プロパティ名、プロパティの型、アクセスメソッドを __propertyキーワードの次に宣言します。また、設計時にオブジェクトインスペクタを使って編集を行うのであれば、__published宣言部に宣言しなければなりません。また、データを格納するデータメンバの名称は、通常、プロパティ名の先頭に Fを付けた名称とします。

    アクセスメソッド

アクセスメソッドとは、プロパティの読み書きを行った際に呼び出されるメソッドのことを意味します。

アクセスメソッドには、readメソッド、writeメソッドの2種類があり、readメソッドは命名規則により、プロパティ名の先頭に Getを付けた名称、writeメソッドは Setを付けた名称で宣言します。

readメソッドは、パラメータを持たずプロパティと同じ型の値を返し、writeメソッドは、プロパティに値を書き込んだときに動作する任意の処理を記述することができます。

    プロパティの作成例

それでは、TEditExにプロパティを追加してみましょう。

作成するプロパティは TextBoldという名前のプロパティで、プロパティの型は boolとします。

値が trueであれば Editの中に入力された文字のフォントを Boldにするという簡単なプロパティです。

作業を行うために、[ファイル|プロジェクトを開く]で、作成した EditExpackage.cbprojを選びプロジェクトを開きます。

ヘッダーファイル EditEx.h を以下のように記述します。

//---------------------------------------------------------------------------
#ifndef EditExH
#define EditExH
//---------------------------------------------------------------------------
#include <SysUtils.hpp>
#include <Classes.hpp>
#include <Controls.hpp>
#include <StdCtrls.hpp>
#include <Graphics.hpp>
//---------------------------------------------------------------------------
class PACKAGE TEditEx : public TEdit
{
private:
  bool FTextBold;
protected:
  virtual void __fastcall SetTextBold(bool Value);
public:
    __fastcall TEditEx(TComponent* Owner);
__published:
  __property bool TextBold={read=FTextBold, write=SetTextBold};

};
//---------------------------------------------------------------------------
#endif

ここで追加されたのは、

  • Fontを扱うため includeに Graphics.hppを追加
  • privateに、このプロパティの値を格納するデータメンバ FTextBoldの宣言
  • protectedに、writeアクセスメソッド SetTextBoldの宣言
  • 設計時にオブジェクトインスペクタで編集が可能なように、__publishedに __propertyを追加し、プロパティ名(TextBold)、プロパティの型(bool)、readアクセスメソッド(FTextBold)、writeアクセスメソッド(SetTextBold)を宣言

となります。

宣言された内容に対して EditEx.cppファイルに以下の処理を記述します。

//---------------------------------------------------------------------------

#include <vcl.h>

#pragma hdrstop

#include "EditEx.h"
#pragma package(smart_init)
//---------------------------------------------------------------------------
// ValidCtrCheck を使用して,作成済みコンポーネントに
// 純粋仮想関数がないことを確認。
//

static inline void ValidCtrCheck(TEditEx *)
{
    new TEditEx(NULL);
}
//---------------------------------------------------------------------------
__fastcall TEditEx::TEditEx(TComponent* Owner)
    : TEdit(Owner)
{
    Color = clSkyBlue;
}
//---------------------------------------------------------------------------
void __fastcall TEditEx::SetTextBold(bool Value)
{
    FTextBold = Value;
    if (Value)
         Font->Style = Font->Style << fsBold;
    else
         Font->Style = Font->Style >> fsBold;
}
//---------------------------------------------------------------------------
namespace Editex
{
    void __fastcall PACKAGE Register()
    {
         TComponentClass classes[1] = {__classid(TEditEx)};
         RegisterComponents(L"Samples", classes, 0);
    }
}
//---------------------------------------------------------------------------

コンストラクタの処理は既に前の項で追加されていますので、ここでは writeアクセスメソッドである SetTextBoldの処理が追加されているだけとなります。

SetTextBoldでは、プロパティにセットされた値(Value)をデータメンバ(FTextBold)に格納し、その値が trueであれば、フォントを Boldに設定し、falseであれば Boldをリセットするという処理を行っています。

コードの記入がすべて終了しましたら、メニューの [ファイル|すべて保存]を実行してコードを保存し、メニューの[プロジェクト|EditExPackageを再構築]を選び、パッケージの再コンパイル・再構築を行います。

これで TEditExにプロパティ TextBoldが追加されました。コンポーネントの動作を確認するために、先程と同様に、このパッケージを再インストール、すべて保存して新規にアプリケーションを作成し、フォーム上に TEditExコンポーネントを置きます。オブジェクトインスペクタを開くと、プロパティに TextBoldが追加されているのが確認できます。

Hide image
bcb9_14

TextBoldプロパティの値を trueにセットすると、フォーム上の TEditEx内の文字のフォントが Boldに変化します。

Hide image
bcb9_15

    イベントの作成

何らかの動作によって発生する事象をイベントといい、イベントに直接応答するコードをイベントハンドラと呼びます。このイベントとイベントハンドラはメソッドを示すメソッドポインタにより関連付けが行われています。

イベントは、メソッドポインタ型を扱うプロパティとして実装されていますので、宣言の方法はプロパティと同様に行います。

プロパティ同様、設計時にオブジェクトインスペクタを使用して編集を行うのであれば、__publishedに宣言を行う必要があります。また、標準イベント(OnClick等)は、上位クラスの protectedに宣言されているので、作成したコンポーネントで公開されていない標準イベントの処理を行うのであれば __publishedで再定義します。

    イベントの作成例

TEditExに公開されていない標準イベントを追加してみましょう。

今回は OnResizeというコントロールのサイズが変更になった際に発生する標準イベントを追加します。

作業を行うために、[ファイル|プロジェクトを開く]で、作成した EditExpackage.cbprojを選びプロジェクトを開きます。

ヘッダーファイル EditEx.h を以下のように修正します。

//---------------------------------------------------------------------------
#ifndef EditExH
#define EditExH
//---------------------------------------------------------------------------
#include <SysUtils.hpp>
#include <Classes.hpp>
#include <Controls.hpp>
#include <StdCtrls.hpp>
#include <Graphics.hpp>
//---------------------------------------------------------------------------
class PACKAGE TEditEx : public TEdit
{
private:
  bool FTextBold;
protected:
  virtual void __fastcall SetTextBold(bool Value);
public:
    __fastcall TEditEx(TComponent* Owner);
__published:
  __property bool TextBold={read=FTextBold, write=SetTextBold};
  __property OnResize;

};
//---------------------------------------------------------------------------
#endif

今回は、標準イベントの追加なので、たった1行

  __property OnResize;

のみ追加です。

コードの記入がすべて終了しましたら、メニューの [ファイル|すべて保存]を実行してコードを保存し、メニューの[プロジェクト|EditExPackageを再構築]を選び、パッケージの再コンパイル・再構築を行います。

これで TEditExに新しいイベント OnResizeが追加されました。コンポーネントの動作を確認するために、先程と同様に、このパッケージを再インストール、すべて保存して新規にアプリケーションを作成し、フォーム上に TEditExコンポーネントを置きます。オブジェクトインスペクタの「イベント」タブをクリックして表示されるイベント名を確認すると OnResizeイベントが追加されているのが確認できます。

Hide image
bcb9_16

    あとがき

第八回、第九回の2回にわたり、コンポーネントの概要・操作・作成の方法について説明いたしました。第十回は「データベースアプリケーションの作成」。最終回となりますこの回では、今まで説明いたしました内容をもとに、データベースアプリケーションの作成について説明する予定です。

Server Response from: ETNASC03