さて、今日は久しぶりにVisual Studio講座を書いてみた。
ワテの場合、
- C言語
- VB.NET
- C#
- C++
の順に覚えた。
VB.NETを覚えたのはもう10年以上前だ。
その当時はVisual Studio 2003を使っていた。
今ではVisual StudioのVB.NETやC#を使って各種のアプリケーションを自作している。
特に最近はASP.NETと言うツール(と言うか開発環境かな)を使って、各種の革新的WEBサービスを無償公開している。
Wareko.NET 公式サイト
だ。
さて、そんなワテであるが、マイクロソフト社のVB.NETを覚え立ての頃は、Formアプリを作る事さえとっても苦労した記憶がある。
それは何故かと言うと、Newの概念を理解出来ていなかったからだ。
今ならこんなに沢山のオブジェクト指向プログラミング関連教科書がある。
この記事では、そんなワテがVB.NETでNewを覚えた当時を思い出しながら、ワテと同じく今でもNewが理解できない人向けに、Newの完全マスターを目指している。
では、本題に入ろう。
オブジェクト指向プログラミングにおけるNew
上で紹介したこれらの教科書を読めば、オブジェクト指向プログラミングにおけるNewの意味は詳しく書いてある。
詳しい説明は教科書を読んで頂くとして、要するにNewとはクラス(Class)の実体を作成する演算子だ。
クラスとは、オブジェクトの設計図。
その設計図に基づいて実体(インスタンス)を生成するのがNew演算子だ。
しかしながら、抽象的な説明は中々理解し辛いものだ。
昔のFORTRANやC言語にはNewなんてのは無かった。
ワテも必死でオブジェクト指向の教科書を読んだのだが、さっぱり分からん。
分からないながらもVB.NETでフォームアプリケーション作った記憶がある。
ところがNewの概念が分かっていないとVB.NETのフォームアプリケーションすらまともに作れないのだ。
VB.NETでWindows Formアプリを作る
まずは、昔のワテと同じく、VB.NETでフォームアプリケーションを作ってみよう。
Formを開くだけの簡単なアプリだ。
そのアプリを作る際にもNewとは何かを理解していないと、訳分からなくなるのだ。
VB.NETのFormプロジェクトを新規作成する
図 新規作成メニューのプロジェクトを開く
下図が開く。
図 Visual BasicのWindowsデスクトップテンプレート画面
上図で、Visual BasicのWindowsデスクトップのWindowsフォームアプリケーションを選ぶ。
場所:E:\MyDocuments\Visual Studio 2017\Projects
ソリューション名:2018-05-23-WindowsFormApp1
は適当に入力する。
フレームワークは、最新版を選んでおけば良い。今回は .NET Framework 4.7 を使う事にした。
[OK]ボタンをクリックすると下図が開く。
図 Visual BasicのWindowsフォームアプリケーションのテンプレートが読み込まれた
上図は、Visual BasicのWindowsフォームアプリケーションのテンプレートが読み込まれた直後の状態だ。
中央にある Form1 と言うやつが、フォームアプリケーションのベースとなる。
この上に各種のパーツ(Button、Checkbox、RadioButtonその他)を配置して自分の好きなユーザーインターフェースを作成する事が出来るのだ。
Windowsフォームを表示してみる
取り敢えず実行してみよう。
下図はワテのVS2017のツールバーだが、皆さんとはアイコンの種類や配置が異なっているはずだ。
理由はワテ流に使い易くカスタマイズしているから。
下図において、緑の三角矢印が二つある。
デバッグ実行とデバッグ無し実行だ。
ここではどちらでも良いが、右側のデバッグ無し実行(CTRL+F5)をクリックする。
図 ツールバーのデバッグ実行とデバッグ無し実行のアイコン
なお、ツールバーカスタマイズの説明はこの記事が詳しい。
自称、ツールバーカスタマイズの達人のワテなので、参考にして下さい。
もし実行アイコンが見当たらない人は、下図に示すメニューから呼び出す事も可能だ。
図 メニューからデバッグ実行やデバッグ無し実行を呼び出す方法
兎に角、無事にデバッグ無し実行に成功すると下図が出る。
図 Form1を表示した例
まあ、何の変哲もない単なるFormが表示された。
Formの右上には最小化アイコン、最大化アイコン、閉じる為の✖ボタンが標準で付いている。
必要ならこれらのアイコンは非表示にするなど出来る。
具体的には、このあとで説明するFormのプロパティ設定でMinimizeBoxやMaximizeBoxの属性をFalseにすれば良い。
さて、VB.NETプログラミング初心者の人は、下図のように「参照」やForm1.vbを展開表示してみると良い。
図 「参照」やForm1.vbの中身を展開表示した例
初心者の人はこの辺りを見て何が何だか分からなくなり挫折する人も多い。
まあ、あくまでワテ流に説明するなら、「参照」の中に表示されている項目は、各種のライブラリだ。
Systemで始まるやつはマイクロソフト純正のやつ。
必要なら自作のライブラリをここに追加する事も可能だ。
一方、Form1.vbを展開して表示されている項目(=関数名)
- Dispose(Boolean)
- components As IContainer
- InitializeComponent()
は、先ほどWindows Formプロジェクトのテンプレートを読み込んだ時点で自動的に生成されたVB.NETのソースコードだ。
これらの目的は、名前を見れば何となく推測できると思うが、要するに、Windows Formを作成して表示したり、表示終了して破棄する際に実行される関数だ。
詳しい事が知りたい人は各自で調べて下さい。ワテの場合、これ以上は説明出来ないので。
さて、下図に於いてForm1の上で右クリックメニューを出す。
図 Form1の上で右クリックメニューを出した例
上図において、「コードの表示」を実行すると下図が出る。
Public Class Form1 End Class
今のワテならこのコードを見ても平気なのだが、その当時のワテは
「Classって何やねん?」
「Publicって言うのは、Privateとかの親戚のやつか?」
「ClassもPublicもオブジェクト指向プログラミングの本に書いていあるけど良く分からん」
と言う感じで、この二行の短いコードすら良く理解出来ていなかった。
さて、下図に於いて「Form1.vb」と「Form1.vb[デザイン]」のタブをクリックすれば、それぞれの画面を表示する事が出来る。
図 「Form1.vb」と「Form1.vb[デザイン]」のタブをクリックで切り替え可能
下図のようにForm1のデザイン画面に戻ってフォームの右下をドラッグすれば大きさを変える事が出来る。
図 マウスドラッグでForm1の大きさを変える方法
フォームの上にボタンを配置する
無地のフォームだと何も出来ないので、部品を配置してみよう。
まずはボタンを一個置く。
その為には、メニューの
表示
ツールボックス
を開く。
図 メニューの「表示」→「ツールボックス」を開く
そうすると下図が出る。
下図に於いて、「すべてのWindowsフォーム」の中にある[Button]をマウスドラッグでForm1の上に持って行く。
図 Form1にButton1を載せた例
無事にButton1が追加出来たら、下図のように大きさや位置を変更してみると良い。
そして、Button1の上で右クリックメニューを表示して「プロパティ」を実行する。
図 Button1のプロパティを表示する
Button1のプロパティ設定画面が出た(下図)。
これが物凄く沢山の設定項目がある。
図 Button1の全プロパティ
勉強熱心な人は、ここで全てのプロパティを一個ずつクリックしてみてその意味を見ておくと良い。
完全には理解出来なくても、何となくどんな項目があるのか見ておくだけでも後々で役に立つからだ。
上図において赤枠で囲っているのは、ワテが良く使うプロパティ。
と言うか、それ以外は良く知らないのだ。
(Name)はボタンの名前
Anchorはボタンを親Form1にどのように配置するかを決める。
Formの伸縮に応じてButtomも大きさを変えたい場合に設定すると良い。
「表示」の項目は、ボタンの色とか文字フォントとかのボタンの見栄えを設定出来る。
最後の「Text」は、ボタンに表示する文字列だ。
下図のように適当に変更してみると良い。
図 Button1のTextプロパティを編集した例
その結果、下図のようになる。
図 Button1のTextプロパティを設定した例
プロパティ設定ウインドウは出したままにしておいて、下図のようにButton1の親であるForm1をマウスクリックする。
図 Form1のプロパティ設定
そうすると、上図のようにプロパティ設定ウインドウはForm1の設定ウインドウに変わる。
必要ならこの画面でForm1の各種プロパティを設定しても良い。
プロパティウインドウは✖で閉じておく。
Button1のイベントハンドラを設定する
Button1の長方形の上でマウスダブルクリックを行う。
そうすると下図が出るはずだ。
Public Class Form1 Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click End Sub End Class
図 Form1クラスに自動追加されたButton1のClickイベントハンドラ関数
このコードは今のダブルクリックで自動追加されたコードだ。
関数名を見れば分ると思うが、Button1をクリックした場合に実行される関数だ。
引数も自動で追加されているが、
- sender As Object
- e As EventArgs
の二つがある。
senderはButton1であり、eはボタンクリックのイベント情報が入っている。
まあその辺りは次回以降に説明したい。
このようにButtonをクリックして実行されるイベントハンドラ関数の仕組みは、X-WindowシステムとかOpenGLなどのグラフィックのAPIなら大体似た様な仕組みになっている。まあもちろん、内部的な作りは違うんだろうけれど、詳しい事は良く知らない。
さて、Button1をクリックしたらメッセージボックスを開いてみよう。
下図のコードを追加する。
Public Class Form1 Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click MessageBox.Show(text:="Hello Kitty!", caption:="captionはタイトル", buttons:=MessageBoxButtons.OK) End Sub End Class
図 Button1をクリックしたらメッセージボックスを開くVB.NETコード
コードの意味は見れば分ると思う。
ちなみに、下図のように記述しても良い。
MessageBox.Show("Hello Kitty!", "captionはタイトル", MessageBoxButtons.OK)
図 関数の引数名を省略する記述方法
ちなみにワテの場合は、気分に応じてどちらの書き方もやるので一貫性は無い。
さて、コードを追加したら実行してみる。
CTRL+F5のデバッグ無し実行をすると下図が出る。
図 Button1のクリックで表示したMessageBoxの例
無事にMessageBoxが表示出来た。
下図に於いて、先ほど表示した「ツールボックス」が表示されている。
図 ソリューションエクスプローラーや他のタブの切り替え方法
上図に於いて、現在は右端の「ツール」が表示されているが、左端にあるのが「ソリューションエクスプローラー」で最初に表示さていたメニューだ。
それをクリックすると下図に戻る。
Dispose()やInitializeComponent()などの関数の中身を見る
図 Form1に自動追加された関数群
上図に於いて、Dispose()やInitializeComponent()は自動追加された関数だ。
また、先ほどダブルクリックで追加されたButton1_Click()もある。
さて、参考までにDispose()やInitializeComponent()を見ておこう。
<Global.Microsoft.VisualBasic.CompilerServices.DesignerGenerated()> _ Partial Class Form1 Inherits System.Windows.Forms.Form 'フォームがコンポーネントの一覧をクリーンアップするために dispose をオーバーライドします。 <System.Diagnostics.DebuggerNonUserCode()> _ Protected Overrides Sub Dispose(ByVal disposing As Boolean) Try If disposing AndAlso components IsNot Nothing Then components.Dispose() End If Finally MyBase.Dispose(disposing) End Try End Sub 'Windows フォーム デザイナーで必要です。 Private components As System.ComponentModel.IContainer 'メモ: 以下のプロシージャは Windows フォーム デザイナーで必要です。 'Windows フォーム デザイナーを使用して変更できます。 'コード エディターを使って変更しないでください。 <System.Diagnostics.DebuggerStepThrough()> _ Private Sub InitializeComponent() Me.Button1 = New System.Windows.Forms.Button() Me.SuspendLayout() ' 'Button1 ' Me.Button1.Location = New System.Drawing.Point(93, 52) Me.Button1.Name = "Button1" Me.Button1.Size = New System.Drawing.Size(162, 45) Me.Button1.TabIndex = 0 Me.Button1.Text = "ワテがButton1でんがな" Me.Button1.UseVisualStyleBackColor = True ' 'Form1 ' Me.AutoScaleDimensions = New System.Drawing.SizeF(6.0!, 12.0!) Me.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font Me.ClientSize = New System.Drawing.Size(340, 247) Me.Controls.Add(Me.Button1) Me.Name = "Form1" Me.Text = "Form1" Me.ResumeLayout(False) End Sub Friend WithEvents Button1 As Button End Class
図 Dispose()やInitializeComponent()の中身
このコードでMeとはForm1自身を指す。
C#の場合なら this に相当する。
じゃあ何でMeなんてのを使うのか?
Form1でいいんじゃ無いのか?
う~ん、それはVB.NETがオブジェクト指向言語だからだ。
Form1はオブジェクトなので、そのまま使う訳には行かない。
あくまでForm1オブジェクトのインスタンス(実体)を作ってそれを利用するのだ。
今の場合はそのインスタンスがMeと言う名前になっている。
何でMeなのかは知らない。
- f1
- fm1
- form1
などでも良かったと思うが。
上図において沢山のNew演算子が登場している。
まあこのコードはVisual Studioが自動生成したコードなので、必要に応じてNewが使われている。これらを見てもVB.NETがオブジェクト指向言語で有る事が分る。
でも自分が追加したNewは今のところ一つもない。
Newはどこ行った?
当記事の目的はVB.NETに於いて実例を通してNewの意味を理解する事だった。
ところがここまで一つも自分ではNewを使っていない。
う~ん、その理由はこの後で説明する。
取り敢えず、次に進もう。
Form2を追加してForm1から開く
さて、Windows Formアプリを作っていて良くやりたくなるのが、Form2などの別のフォームを開きたい事が良くある。
一つのForm1だけだと、一つの画面しか作れない。
多数の画面で構成されるシステムの場合には、画面毎にFormを分けるのが自然だろう。
そう言う訳で、現在のVB.NETプロジェクトに新しいWindowsフォームを追加する。
下図のようにプロジェクト名の辺りで右クリックメニューを表示して、「追加」の「Windowsフォーム」を実行する。
図 「追加」の「Windowsフォーム」を実行する前
「追加」の「Windowsフォーム」を実行すると下図が出る。
図 「追加」の「Windowsフォーム」を実行して「Windowsフォーム」を開く
上図において「Windowsフォーム」を選択して「追加」ボタンをクリックすると下図が出る。
図 プロジェクトにForm2が追加された状態
Button1_Click関数の中身を以下のコードで置き換えよう。
Public Class Form1 Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click 'MessageBox.Show(text:="Hello Kitty!", caption:="captionはタイトル", buttons:=MessageBoxButtons.OK) Me.Hide() Form2.ShowDialog() Me.Show() End Sub End Class
図 Form2を開くコード
このコードの意味であるが、Button1がクリックされるとここに来る。
Me.Hide()
で現在表示されているForm1を非表示にする。
その状態で、
Form2.ShowDialog()
を実行するとForm2が表示される。
ちなみに、
Form2.Show()
でも良い。
今の例では、ShowでもShowDialogでもどちらでも違いは無い。
もし、Me.Hide()を実行していないと、ShowあるいはShowDialogでForm2が表示されるので、画面上にはForm1とForm2が同時に表示出来る。
その時に、もしForm2をShowDialogで開いた場合には、Form1画面は操作出来ない。
もしForm2をShowで開いた場合には、Form1画面の操作は可能になる。
要するにShowDialogはモーダル表示、Showはモードレス表示になるのだ。
実際に実行してみよう。
Form2をShowDialogで表示してみる
まず、CTRL+F5でデバッグ実行すると下図が出る。
図 Form1が表示された
上図に於いて、ボタンをクリックすると下図が出る。
図 Form1は非表示、Form2は表示された状態
この時点では、MeすなわちForm1が非表示状態になっていて、Form2は表示状態だ。
処理は
Form2.ShowDialog()
の直後で停止していてForm2画面のイベントを受け付ける状態になっている。
Form2の上にもButtonなどの部品を配置しても良い。それらのイベントハンドラ関数があればイベントが発生するとそれらの関数に制御が移る。
ここでForm2を✖で閉じると、制御は
Me.Show()
に進むので、Form1が再び表示される。
そしてForm1を✖で閉じるとアプリケーションは終了する。
Form1は必ず閉じる必要がある
ここで一つ注意すると、上でやったようにMe.Hide()で隠したForm1は最後には閉じる必要がある。
もし、Form2を閉じた後で、
Me.Show()
を実行しないと、Form1は非表示のままだか、裏で動いている。
でも、画面上にはForm1もForm2も出ていないので、あたかも全てのウインドウが閉じてプログラムは終了したと錯覚する場合がある。
ところがその状態で、再びプロジェクトをビルドすると、裏でプログラムがまだ実行中なので、ビルドで生成される最新実行ファイルが古い実行ファイルと置き換える事が出来ない。
つまり、「この実行ファイルは別のプロセスが使用中なのでコピー出来ません」と言ったエラーメッセージが出るのだ。
慣れた人でも良くやるミスなので皆さんも注意すると良いだろう。
実際にやってみたら以下のエラーメッセージが表示された。
1> C:\Program Files (x86)\Microsoft Visual Studio\2017\Community\MSBuild\15.0\Bin\Microsoft.Common.CurrentVersion.targets(4172,5): error MSB3021: ファイル "obj\Debug\2018-05-23-WindowsFormApp1.exe" を "bin\Debug\2018-05-23-WindowsFormApp1.exe" にコピーできません。別のプロセスで使用されているため、プロセスはファイル 'bin\Debug\2018-05-23-WindowsFormApp1.exe' にアクセスできません。 1> 1> 11 個の警告 1> 2 エラー 1> 1>経過時間 00:00:11.05 ========== すべてリビルド: 0 正常終了、1 失敗、0 スキップ ==========
図 「別のプロセスで使用されている」エラーの例
「別のプロセスで使用されている」エラーの解決方法
この状況になった場合には、タスクマネージャーを開く(下図)。
図 タスクマネージャーで該当アプリケーションを探す
上図に於いて、該当アプリケーションを見付けたら右クリックメニューを表示して「タスクの終了」を実行する。
これで、再びプロジェクトをビルド出来るようになる。
いよいよNewの登場
さて、ここまでは自分では一切New演算子を使っていない。
と言う事はVB.NETでプログラム書く場合にはNewを使わなくても(知らなくても)プログラムは書けるのか?と思う人も居るに違いない。
まあ、今までやって来たFormの表示だけなら確かにNewは使わなくても良い。
でも現実的にはVB.NETプログラミングにおいてNewの使用は避けて通れないのだ。
まず、Formの表示でNewを使う方法を解説しよう。
Newを使ってForm2を表示する
以下のようにコードを書き換える。
Public Class Form1 #If False Then Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click Me.Hide() Form2.ShowDialog() Me.Show() End Sub #Else Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click Me.Hide() Dim fm2 As New Form2 fm2.ShowDialog() Me.Show() End Sub #End If End Class
図 New無しでForm2を表示する方式とNewを使って表示する方式
上図で、前半部分は Falseで無効化されているが、今までやって来たNew無しでForm2を表示する方式だ。
一方、Elseで有効化されている部分は、Newを使って表示する方式だ。
このコードでは、以下の部分が重要だ。
Dim fm2 As New Form2 fm2.ShowDialog()
図 初めて使うNew演算子
Form2と言うオブジェクト(まあテンプレートみたいなもんかな)があって、そいつの実体(インスタンス)を作成するのがNew演算子だ。
そうやって作成したインスタンスfm2に対してShowDialog()メソッドを実行している。
これが本来のオブジェクト指向プログラミングだな。
ではなぜNew無しでForm2が表示出来るのか?
それは、以下のマイクロソフトのサイトに詳しく説明されているが、
「既定のインスタンス」と言うのが導入されているからだ。
まあ、ワテ流に平たく言えば、Newを使わずにいきなり
Form2.ShowDialog()
を実行出来るようにするための小細工的手法が「既定のインスタンス」と言うやつだ。
Visual Studio 2005から導入されたらしい。
確かにVisual Studio 2003では無かったのでNewしてからでないとFormの表示は出来なかった。
なぜ「既定のインスタンス」が導入されたのかと言うと、聞くところによると、VB.NETの前の世代の言語であるVisual Basic 6.0では、まさに
Form1.Show()
と記述するだけでフォームの表示が出来ていたのだ。
それがVisual Studio 2002や2003ではその文法が使えなくなった。
その代わりにインスタンスをNewで作成して使う方式に変わった。
でもそれだとVisual Basic 6.0に慣れている人には逆に使い勝手が悪い。
それでVisual Studio 2005から、既定のインスタンスと言う名前でNew無しでもフォームの表示が出来るようになったらしい。
まあそう言う歴史が有るらしいのだが、本来のオブジェクト指向的考え方ならNewしてインスタンスを作成するのが本筋であるにもかかわらず、New無しでも行けるようにしてしまったのは果たして良いのか悪いのか?
ワテには分からない。
でも、ネット上の色んな掲示板を見ていると、Newを使ってインスタンスを作成する方式でやるほうが良いと言う意見が多いようだ。
なぜならそれがオブジェクト指向プログラミングの正統的スタイルなので。
と言う訳で、ワテの場合もNewしている。
なお、「既定のインスタンス」が使えるのはVB.NETだけなので、C#でプログラミングする場合はNewは必須となる。
C#でForm1からForm2をNew生成して表示する例
参考までにC#版のコードも作成してみた。
using System; using System.Windows.Forms; namespace WindowsFormApp1_CSharp { public partial class Form1 : Form { public Form1() { InitializeComponent(); } private void button2_Click(object sender, EventArgs e) { this.Hide(); //this.Visible = false; // これでも良い var fm2 = new Form2(); fm2.ShowDialog(); this.Show(); //this.Visible = true; // これでも良い } } }
図 C#ではNewでForm2のインスタンスを作成する必要あり。規定のインスタンスは使えない
上図のように、C#ではNewでインスタンスを作成する記述方法となる。
規定のインスタンスは使えないので要注意だ。
まとめ
当記事では、VB.NETでForm1からForm2を開くとプログラミングの例を紹介した。
まずはNew演算子を使わない方式でやった。
それは「規定のインスタンス」と言う機能を使う事で実現出来た。
規定のインスタンスはVisual Basic 6.0の時代の名残である。
そんな大昔の言語と無関係な人は、正統的なオブジェクト指向プログラミングの手法に則って、Newでインスタンスを作成するコーディングスタイルを身に付けると良い。
あるいは、「規定のインスタンス」などと言うヘンテコな文法が利用出来るのはVB.NETだけなので、C#でプログラミングをすれば否応なくNewが必要になる。
ちなみにこれはハローキティのコーヒーメーカーだ。
キティのインスタントコーヒーでは無くて、キティの本格コーヒーメーカー。
キティのインスタントではないが規定のインスタンスに似ている。
なんのこっちゃ。
インスタントコーヒーよりも遥かにいい味わいのコーヒーが抽出できるに違いない。
本を読む
まずは、Visual Studioの教科書だ。
こう言う本を一冊読んでおけば超多機能なVisual Studioの全体像を掴む事が出来るだろう。
次はC#とVB.NET
この本は、いろんなサイトで良く見かける。良い本なのかな。ワテは読んでいないので分からない。
パーフェクトマスターか。完全理解やで。
この本を読めばVB.NETプログラミングの達人になれるのか!?
独習シリーズ
この独習シリーズも人気ある教科書だ。
特に独習ASP.NETはアマゾンでも良く売れている感じ。
ASP.NET関連
「絵本」って何だよ!
と思ったが、この絵本シリーズは何冊も種類があるのだ。
いろんなプログラミング言語に応じて絵本シリーズがある。
最近のプログラミング事情は、ちょっとチャライぞ。
プログラミングって言うのは、そんなチャラチャラしたもんでは無くて、もっとストイックなもんだろ!
まあいいか。
コメント