Visual Basic 6.0 初級講座 |
第28回 プロパティを作る
前回に予告として次はWithEventsを解説すると書いたのですが、ちょっと予定を変更しまして今回はプロパティを解説します。WithEventsの解説の前にどうもプロパティを説明したほうがいいと判断しました。(前回の予告の部分はすでに修正してあります)。
さて、 VBにはTextプロパティやBackColorプロパティなどさまざまなプロパティが用意されていますが自分でプロパティを作ることもできます。今回はこの自分で プロパティを作る方法を説明します。
1.変数をプロパティにする
VBでプログラミングをするのならプロパティなしにすますことはまずないでしょう。ですから今回ここで「プロパティとは何か」などと改めて説明することはないと思います。そこでいきなりプロパティの作り方の核心部分に迫りましょう。
プロパティの作り方は2つあります。1つは変数を使う方法で大変簡単ですが細かい制御はできません。もう1つはプロパティを作るためにプロパティプロシージャというものを作る方法で普通はこちらの方法で作ります。
今回はこの両方を解説しますがやはり簡単な方から解説しましょう。
それから、プロパティとはオブジェクト(おなじみのコマンドボタンやフォームなど多数)に属しているものですからプロパティを作るときにはオブジェクトにプログラミングすることになります。けれど、コマンドボタンのプログラムを変更することはできません。コマンドボタンのプログラムを見ることもできませんよね。そうすると、プロパティを作ることのできるのはプログラムをいじれるオブジェクトだけということになります。
プログラムをいじれるオブジェクトの代表はForm(フォーム)です。普段みなさんがフォームにプログラムしてることを思い出してください。(念のために説明しますがFormそのもののプログラムは変更できません。みなさんがプログラムしているのはフォームから派生したForm1、Form2などというオブジェクトです)。
Formの他にはActiveXコントロール(アクティブエックス)があげられます。ActiveXコントロールとは要するに自作のコントロールのことで自分でコマンドボタンやテキストボックスのようなコントロールを作ることができます。しかしながらこの機能はProfessionalエディション以上でないと使用できないため評価版やLearningエディションを使っている方には利用できません。当Visual Basic中学校では評価版を使用している方を応援しているのでActiveXコントロールの作成方法を解説する予定はいまのところありません。
さて、前置きが意外と長くなってしまいました。そろそろプログラミングに移りましょう。
VBを起動したらフォームを1つ追加してください。そしてForm1にCommandボタンを1つとテキストボックスを1つ配置して次のようにプログラミングしてください。
Public PictureName As String
'この変数がForm1のプロパティとなる Private Sub Command1_Click() PictureName = Text1.Text Form2.Show vbModal End Sub |
そして、Form2には次のようにプログラムしてください。
Private Sub Form_Load() Me.Picture = LoadPicture(Form1.PictureName) End Sub |
このプログラムはForm1のコマンドボタンをクリックするとForm2に画像を表示するというものです。表示する画像はForm1のテキストボックスに入力されたファイルです。したがって無効なファイル名を入力するとエラーになります。
この例のようなことをしなくてももうちょっと簡単に同じことができるのですが、説明用ということで少し辛抱してください。
この例のForm2の真ん中の部分 LoadPicture(Form1.PictureName) に注目してください。これはForm1のPictureNameプロパティを参照していますね? そして、VBになれている方ならわかると思いますがFormにはPictureNameという名前のプロパティは存在しないのです。
このPictureNameプロパティこそが作られたプロパティです。といっても作り方は簡単でForm1の宣言部でPublic PictureName As String としているだけです。このようにPublicで宣言された変数はすべてプロパティとなるのです。
どうでしょう。簡単でしょう? Dim PictureName As Stringの Dim を Public (パブリック)にするだけでプロパティになるのですから。
もっともこれは一応プロパティですがほとんどただの変数ですね。まぁこの程度で事足りる場合も結構ありますけど。
念のために説明しますが Publicキーワードは別にプロパティを作るためのキーワードではありません。これはDimと同じで変数を宣言するキーワードです。ただ、Dimと違って作成された変数は外部(この例ではForm2)からもアクセスできるようになります。VBではこのように外部からアクセスできる変数とプロパティは同じ意味なのです。
2.プロパティプロシージャ
次に2つ目の方法を解説します。
2つ目の方法ではプロパティを作るにプロパティプロシージャを使います。関数(Function 〜 End Function)やサブプロシージャ(Sub 〜 End Sub)に似ているのですがちょっとだけ複雑です。
プロパティプロシージャを使ってプロパティを作るとプロパティ自体にいろいろな機能を持たせることができます。たとえば、FormのBackColorプロパティにはフォームの背景色を変更する機能がありますよね。こういったことができるようになるわけです。それからプロパティを読み取り専用にすることもできます。
まず、単純にさきほどのForm1のプログラムをこの方法で書いてみましょう。次のようになります。
Dim m_PictureName As String
'プロパティの値を保存する変数 '■プロパティに代入する場合(例:PictureName = "ABC")に呼び出される。 Public Property Let PictureName(NewValue As String) m_PictureName = NewValue End Property '■プロパティを参照する場合(例:X = PictureName)に呼び出される。 Public Property Get PictureName() As String PictureName = m_PictureName End Property Private Sub Command1_Click() |
このように1つのプロパティを作るのに2つのプロパティプロシージャを作る必要があります。Property Let(プロパティ レット)プロシージャのほうはプロパティに代入する場合に自動的に呼び出され、Property Get(プロパティ ゲット)プロシージャはプロパティを参照する場合に呼び出されて関数のように値を返します。Property Letプロシージャがない場合にはそのプロパティは読み取り専用ということになります。
内容に関しては m_PictureNameという変数に注意してください。この変数はプロパティの値を保存するものです。Property Getが呼び出されたときにはこの m_PictureNameの値が返されるだけです。Property Letが呼び出された場合には新しく設定しようとする値が引数NewValueとして渡されますので、その値をm_PictureNameに代入して保存しています。
Property Letプロシージャの引数の名前は自由ですが引数は必ず1つで型はProperty Getプロシージャの戻り値の型と一致させなければなりません。この場合では両方ともString型で一致しています。
この段階で実行すると最初のサンプルと同じように動作します。ですから、この動作で満足な場合は何も死体を複雑にしてプロパティプロシージャを導入する必要はないでしょう。
そこで1つ改造します。もし、入力された画像ファイルが存在しない場合には何もしないことにします。それには次のようにたった1行を挿入するだけです。
Dim m_PictureName As String
'プロパティの値を保存する変数 '■プロパティに代入する場合(例:PictureName = "ABC")に呼び出される。 Public Property Let PictureName(NewValue As String) m_PictureName = NewValue If Len(Dir(NewValue)) = 0 Then m_PictureName = "" 'この行を追加する End Property '■プロパティを参照する場合(例:X = PictureName)に呼び出される。 Public Property Get PictureName() As String PictureName = m_PictureName End Property Private Sub Command1_Click() PictureName = Text1.Text Form2.Show vbModal End Sub |
追加した行は指定された画像ファイルが存在しない場合に変数m_PictureNameに空文字を代入する処理を行っています。
このようにプロパティプロシージャを使った場合はプロパティの代入時(または参照時)に普通の関数やプロシージャと同様に任意の処理を行わしめることができるのです。
この状態で実行してみてください。そして存在しないファイル名を入力してボタンをクリックしましょう。さっきまではエラーが発生してプログラムが中断されていたのに、今回は何も表示されていないフォームが出現したでしょう。
3.メリット
それにしても画像が存在するかしないかのチェックは別にプロパティプロシージャで行わなくてもいいはずです。画像を表示する直前にチェックしても一向に構いません。それどころかプロパティプロシージャの外でチェックすれば結局プロパティプロシージャは意味のないものとなるので面倒なコードを書く必要がなくなります。
それでもプロパティプロシージャを使うメリットはどこにあるのでしょうか。
これは、なかなか説明しづらいのです。というのはこういったことが効果を発揮するのは一定以上の規模を持つプログラムだからです。今回の例のようなプログラムではプロパティプロシージャを使うメリットははっきりいってありません。
しかし、まぁ考えてみてください。もし、今回の例のプログラムが高度に発展して画像の一覧表示や、スライドショー機能。はては画像の編集機能やらを装備したい場合、画像を表示するすべての箇所でいちいち画像が存在するかチェックするのと画像のファイル名をセットした時点で自動的にチェックされるのとどちらがプログラムとして優れているでしょうか。もちろん、後者です。
このように随所に同じ処理が分散するような場合にプロパティプロシージャはそれらを1箇所にまとめる上で非常に有効な手段になります。
その他にこった処理をするのに自作の関数を呼び出すよりもプロパティプロシージャを自作したほうが処理がすっきりする場合もあります。これから関数を自作するときはプロパティプロシージャの使用も検討されるといいでしょう。
4.注意点
一通り説明も済んだところでプロパティプロシージャの注意点をいくつか書いておきましょう。
まず、関数の呼び出しと違ってプロパティプロシージャの呼び出しは時間がたつと忘れます。たとえば Call GetImage() と記述されていればこれは自作のGetImage関数の呼び出してあることがすぐにわかりますが X = PictureName のように記述した場合にこれがProperty Getプロシージャを呼び出していることに気がつくことができるでしょうか?プログラムを作っている時点ではもちろんわかってて作っているのでしょうがしばらくたってプログラムを見直したりしているともう忘れてしまっているかもしれませんね。
次に、プロパティプロシージャは他の関数やサブプロシージャと違って2つ書かなくてはならないので面倒です。関数ですむ場合には関数を、変数ですむ場合には変数を使うのがよいでしょう。
それから、プロパティプロシージャの構造はVB6の後継バージョンでは変わります。VB.NET2002以降ではプロパティプロシージャは1つで代入も参照も対応できるようになります。といってもVB6のプロパティプロシージャがわかっていればすぐに理解できるからこのこと自体は別段気にすることはないのですが、どうも新しいプロパティプロシージャでは Value という名前が予約語のように使われるようなのです。プロパティプロシージャのパラメータの名前を Value としている人が多いのでそういうプログラムは新しいVBの形式に変換したときにちょっと名前で戸惑うかもしれません。
5.最後に
次回はWithEventsステートメントと今回紹介したプロパティプロシージャを組み合わせて今度はイベントを自作する方法を紹介するつもりです。お楽しみに。