はじめに
本連載では、実際にVB6で開発したソフトウェアをC#に置き換えながら基本的な技術を学んでいただきます。
前回は、C#の開発環境を構築して、空のウィンドウを表示するところまでを作成してみました。
今回は、ウィンドウにコントロールを貼り付け、各コントロールのイベントを作成し、これによって自動生成されたコードに関する説明をして行きたいと思います。
フォームを作成
最初にフォームを作成しましょう。
C#を起動したら、スタートアップページ左上の「最近使ったプロジェクト」から「WindowsFormsApplication1」をクリックして前回作成したプロジェクトを開いてください。
その後、画面右上にある「ソリューションエクスプローラー」の「Form1.cs」をダブルクリックしてフォームエディタを開きます。
このフォームのサイズを調整して、必要なコントロールを配置します。やり方は、VB6と同様です。
以前作成した上記のVB6サンプルソフトのフォームを参考に、ツールボックスからコントロールを配置してみてください。
次に画面右下の「プロパティ」から、すべてのラベルコントロールとボタンコントロールに表示されている文字を変更します。また、フォームのタイトルも変更しましょう。
なお、VB6ではCaptionプロパティにて文字を変更していましたが、.NETからはTextプロパティで変更します。
同様に、Nameプロパティを変更して以下の名前を付けてください。この時、英字の大文字と小文字の使い分けにも注意してください。
- ラベル(Label)
- 番号:(label1)
- 名前:(label2)
- 電話番号:(label3)
- コマンドボタン(Button)
- 読込み(readButton)
- 追加(addButton)
- 更新(updateButton)
- 削除(deleteButton)
- 閉じる(closeButton)
- テキストボックス(TextBox)
- 番号(codeTextBox)
- 名前(nameTextBox)
- 電話番号(telephoneNumberTextBox)
名前を変更するたびにリファクタという処理が走ります。リファクタは、プログラムの振る舞いを変更することなくソースコードを整形してくれるための機能です。
画面上部に同名のメニューがあるのでクリックしてみてください。「名前の変更(R)」と「メソッドの抽出(M)」が表示されるかと思います。
コントロールの名前を変更することによって、この「名前の変更(R)」という機能が働いています。
しかし、考えてみると現段階でソースコードは一切記述していません。それなのに何故リファクタリングする必要があるのでしょうか?
その理由は自動生成されたコードにあります。
自動生成されたコードに関する説明は後述しますので、現時点では気にせずにすべての名前を変更してください。
イベント処理を作成
次にイベントが発生した時に呼び出されるメソッドを追加していきましょう。
まず「フォームエディタ」上の「closeButton」をクリックして選択状態にします。
画面右下の「プロパティ」の画面をイベント表示に切り替えます。
稲妻のアイコンをクリックすることでイベント画面に切り替わります。
再度プロパティ画面に切り替える時は、稲妻のアイコンの右隣りのアイコンをクリックしてください。
表示されたButtonコントロールのイベント名の一覧からClickをダブルクリックすることで、次の処理が自動的に行われます。
- closeButton_ClickメソッドがForm1.csファイルに追加されます。
- closeButton_Clickメソッドを呼び出すためのイベントハンドラがcloseButton.Clickイベントに追加されます。
- Form1.csコードエディタが起動します。
イベントハンドラを追加する方法は、以上の通り簡単です。
しかし、2番目のcloseButton_Clickメソッドを呼び出すためのイベントハンドラの追加について疑問を持たれた方も多いのではないでしょうか?
VB6では、1番目の処理だけが行われるのみでした。そして、closeButtonがクリックされた場合の処理が不要になったら、対応するメソッドを削除するだけでよかったハズです。
しかし、C#では、イベントハンドラを追加する必要があります。
では、どこで追加しているのでしょうか?
この答も自動生成されたコードにあります。
自動生成されたコードに関する説明は後述しますので、そちらを参考にしてください。
さて、VB6サンプルソフトのコードに記述されているイベントハンドラは、ほかにも複数ありました。
再度「Form1.cs[デザイン]」タブをクリックして、以下のコントロールのイベントハンドラも作成してしまいましょう。
- addButton.Click
- readButton.Click
- updateButton.Click
- deleteButton.Click
- Form1.Load
- Form1.FormClosed
なお、Unloadイベントは、Formクラスのメンバではないため、FormClosedイベントを代用します。
自動生成されたコード
今までの説明で、2つの疑問を残してきました。
ひとつ目は、Nameプロパティの値を変更した時にリファクタリングする理由について。もう一つは、各メソッドを呼び出すためのイベントハンドラが存在するという点についてです。
これらの答えは、自動生成コードにあります。
ここでは、自動生成されたコードの内容を解説しながら、上記の疑問を解決していきたいと思います。
複雑そうに見えるかも知れませんが、現時点では雰囲気をつかんでいただけるだけで大丈夫です。
まずは、Form1.csタブをクリックして、Form1.csのコードエディタに切り替えてください。
ここには、先ほど皆さんがイベントハンドラを登録したことによって生成されたメソッドも含めて、自動生成されたコードが大量に記述されています。
この先頭部分にある「InitializeComponent()」の記述によってInitializeComponent()というメソッドを呼び出しています。
C#では、キーワードの後ろに()が付いているものをメソッドとして扱います。
つまりVB6で記述するとCall InitializeComponentあるいは単純にInitializeComponentと記述されていることと同じ意味です。
しかし、InitializeComponentなどというメソッドの本体は、どこにも記述されていません。
そこで、InitializeComponentと記述されている部分で右クリックしてコンテキストメニューを開き、ここから「定義へ移動(G)」を選択してみてください。
Form1.Designer.csのコードエディタが新たに開き、InitializeComponent()メソッド本体を確認することができます。
なお、Form1.Designer.csファイルですが、ソリューションエクスプローラーのForm1.csファイルの右にある+マークをクリックして展開すると、その存在を確認できます。
このファイルを眺めてみてください。何となく今までフォームエディタやプロパティ、さらにイベントで登録した内容が記述されているらしいC#のコードであることがわかるかと思います。
実は、このファイルに格納されている自動生成されたコードが、フォームエディタやプロパティ、イベントによって設定した内容の本体です。
したがって、このコードを削除してすべて自分で記述してもフォームにコントロールは配置できますし、また、仮に注意書きを無視してコードエディタで値を直接編集してもフォームエディタにその変更内容が反映されます。
ただし、上記はあくまでも例え話で、実際に上記のコードを編集すると、フォームエディタのエラーを招く恐れがあるのでお勧めはしません。
VB6では、フォームデザイナやプロパティウィンドウ、またはイベントハンドラによる呼び出しに関する部分については、コードとして明示されることはありませんでした。
しかし、C#ではこれらの内容がC#のコードとして記述されています。
以下にInitializeComponent()メソッド本体のコードを抜粋してみましょう。
最初に、///から始まる行があります。これは、特別な意味を持つコメントです。詳細は後述します。
次に、Form1に配置されたコントロールの名前が全て列挙されています。これは各コントロールオブジェクトを生成するためのコードです。VB6では次のように記述できます。
updateButton変数にオブジェクトを生成しているということは、VB6のコードで以下のようにupdateButton変数を定義している部分に相応する記述もある筈です。
これは、一番下にまとまって定義されています。
privateはVB6でもありましたね。
その後のSystem.Windows.Forms.Buttonは、コントロールの型を示しています。
そして、最後に変数名です。一番上がupdateButtonを定義している部分です。
両者を見比べると、各キーワードが前後したり、長くなっているだけの違いでしかありません。
さて、その後に// updateButtonと記述されています。
この//から始まる行は単純なコメントです。//から行の終端までに記述された部分がコメントとして扱われます。
その後に、updateButtonのプロパティの値を設定するためのコードが書かれています。
さて、この部分を見れば、何故コントロール名を変更する度にリファクタリングされたのかがご理解いただけたかと思います。
Nameプロパティの値をupdateButtonと変更したことによって、上記のコードのButton1のように記述されていた部分がupdateButtonに自動的に変更されていたためなのです。
最後にClickイベントに対して、updateButton_Clickメソッドを呼び出すためのイベントハンドラが登録されている記述になります。
VB6のコードエディタは、updateButtonコントロールのClickイベントが不要になった時、closeButtonメソッドを削除するだけでした。
しかし、C#は、updateButton_Clickメソッドのみを削除しても、上記のイベントハンドラでupdateButton_Clickを呼び出そうとするためにエラーが発生します。
私自身VB6からC#に移行した直後は、このエラーに悩みました。
しかし、今回のように仕組みがわかってしまえば簡単です。
例えば、closeButtonのClickイベントが不要になった時は、まず、以下の画面からcloseButton_Clickと記述されている部分を削除してからcloseButton_Clickメソッドのコードを削除するように注意してください。
次回の予定
今回は、C#3.0を使ってフォームを作成し、イベントに対するメソッドを登録しました。
また、これによって自動生成されたコードについても、雰囲気がつめたかと思います。
次回からは、C#のコーディングと言語の解説を行います。