2010.5.24.
石立 喬

Visual C++ 2010 Expressの易しい使い方(4)

――― メニュー選択を使用する入力と別フォームを使用する入力―――

 ここでは、やや本格的なWindowsプログラムを作成する方法を二種類説明する。一つは、メニューの中から数値を選んで数値を入力し、演算結果を画面に出力する。もう一つは、メニューをクリックすると別のフォーム(子フォーム、ダイアログボックス)が現れ、これに数値を入力する。これらを基礎にして、さらに本格的なプログラムに進むことができる。すでに別項で説明した部分は省略または簡略化されているので、注意して欲しい。

1.メニューで数値を設定する場合

プロジェクトの目的とする機能
 実行画面で、メニューバー上にある「Aの値」メニューをクリックすると、その下にサブメニューが現れ、「A=1」、「A=2」、「A=3」などの選択ができる。同様に「Bの値」メニューをクリックすると、その下にサブメニューが現れて、Bの値を選択できる。「演算」と名付けられたメニューをクリックすると、加減乗除を選択するサブメニューが現れ、これをクリックすると演算結果が表示される。

プロジェクトの生成
 従来説明した方法に従って、「CLR」→「Windowsフォーム アプリケーション」を選択し、プロジェクト名を付ける。

フォームにメニューを作成する方法
1)すでに述べた方法で 「ツールボックス」ウインドウを開き、「メニューとツールバー」を展開すると、図1に示すようなリストが表示されるので、「MenuStrip」をダブルクリックする。


図1 開いた「ツールボックス」の一部


2)図2に示すように、「ここへ入力」と表示された場所ができるので、カーソルを持って行き、順次、メニューのキャプションを入力する。


図2 「MenuStrip」をダブルクリックしてできた、メニューキャプション入力欄


 メインメニューは、「Aの値」、「Bの値」、「演算」とする。
 サブメニューは、「Aの値」に対し「A=1」、「A=2」、「A=3」、「Bの値」に対し「B=1」、「B=2」、「B=3」、「演算」に対し、「加算」、「減算」、「乗算」、「除算」とする。
 図3は、すでに述べた方法でタイトルを「四則演算」に設定し、メインメニューのキャプションを入力した後に、「A=3」までのサブメニューの入力を行った状態を示す。


図3 メニューのキャプションを入力する


3)メインメニューにコードを記載する必要はないので、サブメニューから作業を始める。まず、「A=1」サブメニューを選択し、右クリックして、「プロパティ」を選択する。「デザイン」欄の「(Name)」の右に、自動的に「a1ToolStripMenuItem」のメニュー名が生成されているが、これは長すぎ、また日本語でメニューのキャプションをつけた場合には、それがそのまま残るので、「menuA1」などの、簡略化した分かり易いメニュー名に書き換える。
 図4は、「B=1」サブメニューについての「プロパティ」ウインドウの様子を示す(「(Name」欄を書き換えた後の)。


図4 メニューにコードを記述する準備中のフォームと「プロパティ」ウインドウ


 その他のサブメニューの命名例については、表1を参照されたい。自動的な命名では、メニューキャプションの英字は小文字に変換され、「=」などの記号は無視され、日本語文字はそのままメニュー名の頭に付加される。

表1 各メニューとプログラム上の名称

  メニューの
キャプション
自動的に付けられた名称 書き換えた名称 イベントハンドラ名
(自動的に付く)
メインメニュー Aの値 aの値ToolStripMenuItem 書き換え不要 なし
Bの値 bの値ToolStripMenuItem 書き換え不要 なし
演算 演算ToolStripMenuItem 書き換え不要 なし
サブメニュー A=1 a1ToolStripMenuItem menuA1 menuA1_Click()
A=2 a2ToolStripMenuItem menuA2 menuA2_Click()
A=3 a3ToolStripMenuItem menuA3 menuA3_Click()
B=1 b1ToolStripMenuItem menuB1 menuB1_Click()
B=2 b2ToolStripMenuItem menuB2 menuB2_Click()
B=3 b3ToolStripMenuItem menuB3 menuB3_Click()
加算 加算ToolStripMenuItem menuAdd menuAdd_Click()
減算 減算ToolStripMenuItem menuSub menuSub_Click()
乗算 乗算ToolStripMenuItem menuMult menuMult_Click()
除算 除算ToolStripMenuItem menuDiv menuDiv_Click()


4)次に、メニュー選択の結果を表示するラベルをフォーム上に配置する。メニュー「Aの値」の下方のフォーム中央部に「label1」を配置し、「A=1」などの選択結果を表示するのに使用する。同様に、メニュー「Bの値」の下方に「label2」を配置する。メニュー「演算」の下方に「label3」を配置し、「A+B=」などに続いて演算結果を表示する場所を作る。
5)各サブメニューをダブルクリックすると、自動的に「menuA1_Click()」などのイベントハンドラが作成されるので、それぞれにコードを記述する。

イベントハンドラの記述
 図5は、「コードエディタ」上に表示された「Form1.h」の一部である。サブメニュー「A=1」に対するmenuA1_Click()では、まず a=1 で、Aを設定し、「label3」にある古い演算結果(もしあれば)を消去し、「A=1」と表示する。これらは、サブメニュー「B=3」まで、同様である。
 サブメニュー「加算」に対するmenuAdd_Click()では、まず c=a+b で演算を実行し、演算種類を表す「A+B=」に続いて、演算結果を出力する(結果の数値を文字列に変換して)。他の演算についても同様である。
 本来ならば、プログラムを見易くするために、「;」の後は改行すべきであるが、スペース節減のために一行に書いてある。


図5 コードエディタ画面上の Form1.h の一部(最後尾)


変数a、b、cの宣言
 変数 a、bは、他のハンドラからも呼び出されるので、共通変数として外部で宣言しておく必要がある。変数cは、使用されるハンドラ内のみなので、内部で宣言しても良いが、簡単のために、ついでに外部で宣言した。これらは、自動的ではなく、手で入力する必要がある(図6参照)。「//ここに追加」のコメントは、説明のために付けた。


図6 Form1.h の上方にあるメンバ変数宣言部


最終的に得られた実行画面
 図7は、得られた実行画面を示したもので、図の左上と右上は、数値を選択するためのメニューを開いた状態を示し、左下は演算の種類を選択するメニューを開いたところである。
 右下は、「除算」をクリックした場合の演算結果である。念のために、試みに、AやBの値を設定しないで「演算」をクリックすると、それぞれ0に設定されていることが分かった。


図7 得られたフォームのメニューと演算結果


2.子フォーム(ダイアログボックス)で数値を入力する場合

プロジェクトの目的とする機能
 親フォームで、「Aの値の設定」メニューをクリックすると、子フォームが現れ、Aの値を入力するテキストボックスが表示される。これに入力して「設定」ボタンをクリックすると、その値が設定され、親フォームに表示されて、子フォームが閉じる。「取消」ボタンをクリックすると、設定しないで子フォームが閉じる。親フォームで「演算」メニューを使用し、演算の種類を選択すると、計算式と計算結果が表示される。

メニューの作成とイベントハンドラの生成
 前述の方法に従って、メニューを作成し、名前を書き換え、イベントハンドラのスケルトンを作成する。メニューのキャプション、メニュー名、イベントハンドラ名の関係をまとめて表2に示す。

表2 各メニューとプログラム上の名称

  メニューの
キャプション
自動的に付けられた名称 書き換えた名称 イベントハンドラ名
(自動的に付く)
メインメニュー Aの値 aの値ToolStripMenuItem menuDialogA menuDialogA_Click()
Bの値 bの値ToolStripMenuItem menuDialogB menuDialogB_Click()
演算 演算ToolStripMenuItem 書き換え不要 なし
サブメニュー 加算 加算ToolStripMenuItem menuAdd menuAdd_Click()
減算 減算ToolStripMenuItem menuSub menuSub_Click()
乗算 乗算ToolStripMenuItem menuMult menuMult_Click()
除算 除算ToolStripMenuItem menuDiv menuDiv_Click()

新しいフォーム(子フォーム)を追加する方法
1) 統合開発環境の「ソリューション エクスプローラ」(左欄にある)で、プロジェクトのトップ(たとえば「C1006」など)を右クリックし、「追加」→「新しい項目」を選択する。
2)「新しい項目の追加」ウインドウが開くので、左の欄から「UI(User Interfaceの意)」、右の欄から 「Windowsフォーム」を選び、「名前」を「FormDialogA」(一例、Aの値を設定させるダイアログボックスなので)と入力して、「追加」ボタンをクリックする。
3)FormDialogA.cpp と FormDialogA.h が生成され、FormDialogA の「フォームデザイナ」画面が現れる。
4)フォームの中央で右クリックして、「プロパティ」ウインドウで下記のように設定する。
  「表示」欄で、
      FormBorderStyle --- FixedDialog (アイコンが無く、サイズの変更ができない)
      Text -------------- Aの値の設定(これは一例で、キャプションを付ける)
  「ウインドウスタイル」欄で、
      MaximizeBox ------- False (最大化ボタンを消す)
      MinimizeBox ------- False (最小化ボタンを消す)
 「Text」項目以外は、項目を選択すると、右側に下向きの三角矢印が現れるので、これをクリックし、選択する。

親フォームのメニューから子フォームをモーダル・ダイアログボックスとして呼び出す方法
 モーダルとは、子フォームを閉じるまで、親フォームでの実行が出来ないことで、そうでないものにモードレスがある。特に目的が無い限り、一般的にはモーダルが用いられる。モーダルを用いると、子フォームが閉じられると同時に、親フォームに制御が戻るので、子フォームからの情報の転送に便利である。
1) 親フォームで、「Aの値の設定」メニュー(一例、子フォーム呼び出しのために作成したメニュー)をダブルクリックする。
2)menuDialogA_Click() メソッド(一例)が現れるので、
      FormDialogA^ dlg=gcnew FormDialogA();
      dlg->ShowDialog();
と記述する。ただし、FormDialogA は、さきに命名した、開きたい子フォームの名称(一例)である。子フォームからの入力情報を受け取るには、この下に続けてコードを記入する。
3) 親フォームの Form1.h の最初の部分に
      #include “FormDialogA.h”
  と記述する。
 「Bの値の設定」メニューについても、menuDialogB_Click() メソッドを作成し、同様にコードを記述する。

子フォームの入力を直ちに親フォームに反映させる方法
 モーダル・ダイアログボックスである子フォームのテキストボックスに数値を文字列として入力し、子フォームの「設定」ボタンをクリックすると親フォームのラベルに直ちに表示させるには、Form1.hに
      FormDialogA^ dlg=gcnew FormDialogA();
      dlg->ShowDialog();
      if(dlg->DialogResult==::DialogResult::OK){
         label1->Text=dlg->textBox1->Text;
      }
と書いておく。ただし、子フォームの「設定」ボタンの「プロパティ」ウインドウの「動作」欄で、「DialogResult」を「None」から「OK」に変更しておく必要がある。
 また、子フォームの「FormDialogA.h」の頭で、
      private: System::Windows::Forms::TextBox^ textBox1;
を public に書き換えておく。
 Visual C++ 2008 Express Edition では、Microsoft社の資料通り、「::DialogResult::OK」で動作したが、Visual C++ 2010 Express では、「Windows::Forms::DialogResult::OK」と記述しないと、エラーになった。
 namespace に
System::Windows::Forms があるのに・・・。

子フォームで作成したデータを親フォームで使う方法
1) 子フォームで作成される変数をdouble型で aとすると、子フォームのFormDialogA.h において、
      public: static double a;
と宣言しておく。 public でなく、private にすると、親フォームクラスから呼び出せなくなり、static を省くと親フォームに渡せなくなって、いずれもエラーになってビルドできない。
2) 親フォームクラスで子フォームクラスの変数を呼び出すには、
     FormDialogA::a や FormDialogB::b
を用いる。

子フォームの作成
  「Aの値の設定」と「Bの値の設定」子フォームは、図8のように作成する。「Aの値を入力して下さい」は「label1」に、「A=」は「label2」に書いておく。「button1」と「button2」を設置し、それぞれ「設定」と「取消」の名前を付ける。
 「button1」は、「プロパティ」ウインドウの「動作」欄で、「DialogResult」を「None」から「OK」に変更しておく。「button2」は、同様に「Cancel」に設定しておく。
 子ウインドウが開いたときに、入力用カーソルがテキストボックスに現れるように、「textBox1」の「プロパティ」ウインドウの「動作」欄で、「TabIndex」を「button1」や「button2」より先にしておく(具体的には、0、1、2の順になっていることを確認しておく)。
 「TabIndex」は、デフォルトでは、フォームへ部品を配置した順序に付けられるので、ボタンを配置するより先に、テキストボックスを配置すれば問題は無い。


図8 「FormDialogA.h[デザイン]」ウインドウで作られた子フォーム


親フォーム(Form1.h)に記述するプログラム
 図9~12は、親フォームのForm1.h に記述するコードを示す。各イベントハンドラ名は前掲の表2に示したとおりである。
 変数a、b、cは、前述と同様に、共通変数として外部で宣言しておく。
 「Aの値の設定」メニューをクリックしたときに子ウインドウを呼び出すコードには、子ウインドウからの値を親フォームに表示するコードも記述する。「Bの値の設定」メニューについても同様である。

             

図9 子フォームの値を読み出すために、「FormDialogA.h」などをインクルードしておく



図10 Form1.h の上部に追加した、複数のイベントハンドラに共通する変数の宣言



図11 子ウインドウを呼び出し、結果を表示するコード例



図12 「加算」メニュー(それ以外は省略)に対するコード例


子フォーム(FormDialogA.hなど)に記述するプログラム
 図13、14は、子フォームのFormDialogA.h (FormDialogB.hも同様、変数は double b)に記述したコードを示す。「設定」ボタン(名称はbutton1のまま)をクリックしたときのイベントハンドラの内容は、テキストボックスの読み込みと、フォームの閉鎖である。「取消」ボタン(名称はbutton2のまま)のイベントハンドラは、フォームの閉鎖のみである。


図13 親フォームから読めるように追加した変数の宣言例



図14 子フォームのボタンをクリックしたときのコード例


得られた結果
  図15は、親フォームで「Aの値の設定」メニューをクリックし、「A=1234」を入力して表示させた後に、「Bの値の設定」メニューで現れた子フォームに入力して、「設定」ボタンをクリックする直前の状態を示す。


図15 「Aの値の設定」ウインドウの入力画面


 図16は、親フォームの「演 算」メニューをクリックし、さらに「除算」メニューを選択したところを示す。


図16 親フォームのメニューで「除算」を選択したところ


 図17は、最終的に得られた結果である。


図17 演算実行結果



「Visual C++ の勉強部屋」(目次)へ