2013. 7.17.
石立 喬

Visual Studio 2012 Expressの易しい使い方(5)

――― Win32 で、グラフを表示、メニューを使う ――

 理工系技術者に興味があるグラフを作成し、ウィンドウ画面上に表示する。ウインドウツールの一例として、「メニュー」を増設し、これを使って、グラフ表示の切り替えを行う。
 ここでは、メニュー作成のために、リソーススクリプトファイル(Resource Script File)に記述する。これは、自動的に作成されているが、それに追加する。ただし、Express Editionでは、これの編集に、少し手間がかかる。

プログラム作成の進め方
 ここでは、プロジェクト名を「Win32Project3」として、話を進める。プログラムの内容は、「一次式」、「二次式」、「三次式」、それらの「すべて」、をメニューにより切り替えて表示するもので、グラフの作成及び表示と、メニューの作成方法の参考となる。
 今回の作成手順は以下の通りとする。
 1)プロジェクトのスケルトンを作成する(方法は解説済み)。
 2)メニューをWin32Project3.rcに記述する。
 3)メニューの識別子をResource.hに定義する。
この段階でビルドを行い、メニューが正常に出来ていることを確認する。
 4)メニューの選択に対応するコードを記述する。
 5)UserProgramと言う名称でユーザ関数を作成する。
 6)UserProgramをプロトタイプ宣言する。
 7)WM_PAINTからUserProgramを呼び出すようにする。
 8)最後に、UserProgramに合わせて、適切なウインドウサイズ、タイトルを設定する(方法は解説済み)。

メニューを作成する
 ここでは、デフォルトで、すでに、できている「ファイル」と「ヘルプ」のメニューの間に、「グラフの表示」と言う親メニューを配置し、それに、、「一次式」、「二次式」、「三次式」、「すべて」の子メニューを作成する。
 メニューは、リソースの一つであり、新しくメニューを追加するには、リソーススクリプトファイル(Win32Aplication3.rc)に、これらを追加記述する必要がある。また、ここで決めた識別子をリソースヘッダファイル(Resource.h)で定義しておく。

Win32Project3.rcの編集方法
 画面右側の「ソリューションエクスプローラ」から、Win32Project3.rcを選択し、ダブルクリックしても、「リソースの編集はVisual C++ Express SKUでサポートされていません」のウインドウが開くだけで、見ることも、編集することもできない。SKU(Stock Keeping Unit)とは、製品種別を意味する(他の有料Editionでは編集可能)。
 しかし、次の方法で、これは解決する。
 1)「ソリューションエクスプローラ」で、「Win32Project3.rc」を右クリックする
 2)「ファイルを開くアプリケーションの選択」を選択する。
 3)図1のような、「ファイルを開くアプリケーションの選択」ウインドウが開くので、「リソースビュー(規定値)」が選択されているのを、「ソースコード(テキスト)エディター」の選択に変更する(図は、変更済みの状態を示す)。
 6)「OK」をクリックする。
 

図1 「ファイルを開くアプリケーションの選択」ウインドウ


 7)図2のように、コードエディタ部に、スケルトン状態のWin32Project3.rcが現れるので、"ファイル"と"ヘルプ"の間に追記する(図2の44行〜50行)。たとえば、IDM_GRAPH1は、メニュー(M)の識別子(ID)で、一次式グラフ(GRAPH1)のためのものであることを意味して命名した。


図2 Win32Project3.rcの「メニュー」の部分


 この「Win32Project3.rc」は、ビルドを行うと、他のファイルと同様に、自動的に保存される。閉じないでおくと、次に、再びVisual Sdudio を起動したときにも、タブが残っているので、閉じる必要はない。

Resource.hへの追加
 「ソリューションエクスプローラ」から、「Resource.h」を選択して、ダブルクリックすると、コードエディタ部に、図3のように現れるので、必要事項を追記する(図3の13行〜16行)。ここで、201〜204の値は、他と重ならないように、任意に決めたものである。


図3 Resource.hの最初の部分に、IDM_GRAPH1等を定義しておく


WndProc関数への追加
 メッセージが発生すると、WndProcが受け止め、メニューの選択などであれば、WM_COMMANDが、ウインドウの描画(プログラムのスタート時や、再描画の要請があった時)であれば、WM_PAINTが対応する。
◎int wmId をstatic int wnId に変更
 メニュー選択により、WndProcが呼び出され、さらにIDM_GRAPH1などが選ばれると、InvalidateRect()によって、再び、WndProcが呼び出され、WM_PAINTを実行する。このとき、wmId(IDM_GRAPH1などが入る)をWndProc内で、単にintだけで宣言すると、折角のIDM_GRAPH1などの選択が消えてしまう。そこで、デフォルトでint wmId となっているのを、static int wmId に変更する(図4の129行)。
◎case IDM_GRAPH1などの記述
 WM_COMMANDはさらに分かれ、スケルトン状態ではIDM_ABOUTとIDM_EXITのみがある。ここへ、新しくIDM_GRAPH1などのイベントを追加し、そこに動作を記述する。ただし、IDM_GRAPH1〜IDM_GRAPHAまで、すべて同じ動作で良い(図4の145行〜150行)
 メニューが選択されると、InvalidateRect()で、親ウインドウの全領域の最描画を指示して、WM_PAINTを実行させる。
 InvalidateRect関数の第1引数は、対象となるウインドウで、ここでは、hWnd、第2引数は全領域描画を意味するNULL、第3引数は背景を完全に消去するためにTRUEとしておく。


図4 WinProcの中のcase WM_COMMANDにcase IDM_PROG1などを記述


◎WM_PAINTへの記述(図5の161行)
 ここでは、指定されたwmId、すなわち、IDM_GRAPH1〜IDM_GRAPHAを引数として与えて、UserProgram関数を呼び出す。


図5 WM_PAINTはUserProgram関数を呼び出すのみである


プロジェクトの最初の部分の記述
 プロジェクトの中に、自作関数UserProgramを追加するので、あらかじめ宣言しておく(図6の19行)。


図6 プログラムの最初の部分


グラフの書き方
 関数(一次式、二次式など)の計算は、x、yを実数として、y = f ( x ) の形で行い、画面表示上の座標は、それらを整数に変換する。xを小刻みに変化し、折れ線グラフを描く。ただし、刻み幅が十分小さいので、スムーズさは失われない。折れ線グラフを描くには、線分の出発点となる古い座標をnOldXAxisとnOlsYAxisで、終点となる新しい座標をnXAxisとnYAXisで表し、
   MoveToEx(hdc,nOldXAxis,nOldYAxis,NULL);
   LineTo(hdc,nXAxis,nYAxis);
を用いる。
 描画が終わると、次の描画のために、
   nOldXAxis=nXAxis
   nOldYAxis=nYAxis
としておく。
 グラフの表示範囲をはみ出した場合と、グラフの最初の点では、描画を行わず、nOldXAxis=nXAxis、nOldYAxis=nYAxis のみとする。

UserProgramの内容
 グラフに色を付けるためには、対応するペンを用意する必要があり、そのために、hUserPenとhDefPenを用意する。また、すでに説明した通り、nXAxis、nYAxisなどを宣言しておく。
◎方眼紙の作成
 図7は、UserProgramの最初の部分で、まず、方眼紙を作成している。


図7 UserProgram の最初の部分(方眼紙の作成)


◎一次式の描画
 図8は、一次式を描くプログラムを示す。case IDM_GRAPHA が、先にあるのは、これが選ばれた場合には、IDM_GRAPH1以降を、すべて実行するからである(図8のフローチャート参照)。
 グラフ描画の方法は、以下の通り。
 1)赤色のペン、hUserPenを作成する。
 2)hUserPenを選択し、同時に、それまでのデフォルトペンをhDefPenとして保管する。
 3)x を-10から10まで、0.02刻みで変化させ、
      ・ yを計算する。
      ・ xとyを方眼紙に対応させ、整数化して、新しい座標点nXAxis、nYAxisに変換する
      ・ 古い座標点と新しい座標点の間に線を引く(最初の点と、範囲外では、線を引かない)
      ・ 現在の座標点を、古い座標点として保存する
 4)hDefPenを選択し、それまで使っていたhUserPenを破棄する。
 5)メニューがIDM_GRAPHAの場合は、二次式の描画へ、そうでない場合は、終了する。


図8 一次式を描画するプログラム


◎二次式の描画
 図9は、二次式を描くプログラムを示す。250行、254行以外は、一次式の場合と同じである。


図9 二次式を描画するプログラム


◎三次式の描画
 図10は、三次式を描くプログラムを示す。269行、273行以外は、一次式の場合と同じである。


図10 三次式を描画するプログラム


フローチャートによる説明
 図11は、このプログラムのフローチャートである。プロジェクトが起動されると、まず、描画のために、WM_PAINTで、UserProgramが呼び出される。この段階では、メニューは選択されていない(default状態)ので、方眼紙を描くのみで終了する。
 メニューが選択されると、WM_COMMANDが働き、メニューの種類に関わらず、再描画を指示するので、WM_PAINTが働き、UserProgramを呼び出す。
 方眼紙を描画したのちに、今度は、メニューが選択されているので、その識別子(wmId)に応じて、一次式、二次式、三次式などを描画して、元へ戻る。メニューとしてIDM_GRAPHA、すなわち、「すべて」が選ばれた場合は、一次式〜三次式のすべてを順次描画する。


図11 フローチャート


得られた結果
 図12は、メニューから「グラフの表示」→「すべて」を選択した結果を示す。「一次式」などを選択すると、対応する一本のグラフのみが表示される。


図12 メニューから「すべて」を選んで、すべてのグラフを表示させた