2013. 7. 4.
2014. 5.12. プログラム205行で、M_PI_2を2πと勘違いしている。
        実際はπ/2なので、角度の範囲0〜360は、0〜90と読み替えてほしい。
2015.11.25. 三角関数表で、角度の範囲を0〜90に直した。
石立 喬

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

――― Win32 で、計算結果を表示、ボタンを使う ――

 これからは、Visual Studio 2012 ExpressのVisual C++を使ったWin32プロジェクトを紹介する。理工系技術者に興味がある、数値演算関数を使って、簡単な計算を行い、それをウィンドウ画面上に表示する。ウインドウツールの一例として、「ボタン」を設置し、これを使って、プログラムの切り替えを行う。
 ここでの内容は、「Visual C++ 2010 Expressの易しい使い方(2)」と類似している。すなわち、簡単な計算を行い、計算結果の数値を文字化して、画面に出力するものである。ただし、今回は、Win32アプリケーションのため、コードに大きな違いがある。
 「Visual Studio 2012 Expressの易しい使い方(3)」では、WndProcのcase WM_PAINTの中にプログラムの主要部を記述したが、この方法では、主要部が全体のプログラムに紛れて見にくいので、ここでは、UserProgramと言う名前の関数にして、別の場所に配置した。case WM_PAINTは、この関数を呼び出す。

プログラム作成の進め方
 以下のようにして、作成する。
 1)プロジェクトのスケルトンを作成する(方法は解説済み)。
 2)ウインドウサイズ、タイトルを設定する(方法は解説済み)。
 3)UserProgramと言う名称の関数を作成する(ボタン関係は除く)。
 4)UserProgramをプロトタイプ宣言する。
 5)WM_PAINTからUserProgramを呼び出すようにする。
ここまでの動作を確認して、OKならば、ボタンのプログラム作成に移る。
 6)ボタンを作成する。
 7)ボタンのイベントへのコードを記述する。
 8)UserProgramに、ボタン関係の記述を追加する。

UserProgram関数の内容
 図1は、このプロジェクトで作成したUserProgram関数の前半を示す。UserProgram関数の引数は、描画のためのデバイスコンテキストへのハンドルと、三角関数表と対数関数表を切り替えるためのスイッチのBOOL変数である。
 C言語の標準関数として、文字の出力にはprintfがある。これは、コンソールに出力するもので、文字列変数として書き出す関数としては、sprintfがあった。その、Unicodeにも対応するのが、_stprintfである.。しかし、現在は、セキュリティが強化された、_stprintf_sでないと使えない。
 _stprintf_s関数は、ヌル終端文字列(ゼロ終端文字列とも)として出力するので、あらかじめszBufferを用意して、そこへ書き込む。szBufferの内容は、既に述べたTextOut関数によって、ウインドウ画面上に描画する。szの接頭語は、string terminated by zero の意味とされる。
◎三角関数表の作成
 角度nAngleは、0°から90°まで、10°おきの整数とする。三角関数の計算では、これをラジアンに変換するために、π/180を掛ける必要がある。πは組み込み定数M_PIを使用し、180で割ったものを定数として定義しておく(図1の205行参照)。 三角関数表は、bTypeがTRUEでUserProgramが呼び出された時に、計算して表示する。
 最後に、SetWindowTextで、ボタンのラベルを「→対数関数表」に設定しておく。図1は、三角関数のための、UserProgram関数の前半部分を示す。


図1 UserProgram関数の前半部(三角関数表の部)


◎対数関数表の作成
 ここでは、常用対数(log10)と自然対数(loge)を計算する。対数関数表は、bTypeがFALSEでUserProgramが呼び出された時に、計算して表示する。さらに、SetWindowTextで、ボタンのラベルを「→三角関数表」に設定しておく。
 図2は、対数関数表のための、UserProgram関数の後半部分を示す。さきの、三角関数表の場合と共通であるが、ShowWindowによって、ボタンを表示する(244行)。


図2 UserProgram関数の後半部(対数関数表の部)


プロジェクトの最初の部分の記述
◎数学関数を用いるための、ヘッダーファイルのインクルード(図3の6行〜7行)
 ここでは、三角関数、対数関数などの数学関数を使用するので、<cmath>をインクルードしておく。また、πなどに関連した定数を使用するため、#define _USE_MATH_DEFINESを、<cmath>のインクルードに先立って記述しておく。
◎ボタン識別子の定義(図3の10行)
 作成するボタンを識別するためにID_BUTTON1を定義しておく。これは、intの数値であるが、既存のものと重ならないようにする必要がある(99は、まず、無いと思うので)。
◎グローバル変数の宣言(図3の16行〜17行)
 「三角関数表」と「対数関数表」を切り替えるbTrigonは、ボタンをクリックした際に呼び出されるWndProcのcase ID_BUTTON1の中で切替えられる。
WndProcの内部でbTrigonを宣言し、bTrigonを初期化する(TRUEなどに)と、ボタンをクリックしても、常に一定になり、変更することができない。したがって、bTrigonはグローバル変数として、WndProcの外で宣言しておく。Trigonは、Trigonometric Functionから採ったもので、これがTRUEの場合は、「三角関数表」を表示し、FALSEの時は、「対数関数表」を表示する。
 ボタンhButton1は、InitInstanceで作られるが、UserProgramの中で、そのラベルを変更するので、グローバル変数とした。、
◎UserProgramのプロトタイプ宣言(図3の24行)
 プロジェクトの中に、自作関数を追加するので、あらかじめ宣言しておく。


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


InitInstance関数への追加
◎ボタンの設定
 ボタンは、子ウインドウの一つとして扱われる。したがって、子ウインドウ作成の関数、CreateWindowを使って、ボタンを作成する。
 CreateWindow関数は、以下に示す引数を取るので、図4の119行〜121行のように記述する。

  HWND WINAPI CreateWindow(
       LPCTSTR   lpClassName,  クラス名で、ボタンの時は L"BUTTON"にする
       LPCTSTR   lpWindowName,  ボタン上のラベルで、L" " で、空白にしておく
       DWORD    dwStyle,    ウインドウスタイル WS_CHILD, BS_PUSHBUTTON など
       int     x,       親ウインドウ上のX座標位置
       int     y,       親ウインドウ上のY座標位置
       int     nWidth,     ボタンなどの幅
       int     nHeight,    ボタンなどの高さ
       HWNP     hWndParent,   親ウインドウ、ボタンなどの場合はhWnd
       HMENU    hMenu,     子ウインドウのIDを、ID_BUTTON1に設定する
       HINSTANCE  hInstance,   特に指定しないで良い
       LPVOID    IpParam     一般的にNULLで良い
   )


図4 ボタンの設定


WndProc関数への追加
 メッセージが発生すると、WndProcが受け止め、ボタンのクリックなどであれば、WM_COMMANDが、ウインドウの描画(プログラムのスタート時や、再描画の要請があった時)であれば、WM_PAINTが対応する。
◎case ID_BUTTON1の記述
 WM_COMMANDはさらに分かれ、スケルトンではIDM_ABOUTとIDM_EXITのみがある。ボタンのクリックは、ここへ、新しくID_BUTTON1のイベントを追加し、そこに動作を記述る。(図5の156行〜159行)
 ボタンがクリックされると、
 1)bTrigonを逆転させる(TRUEならFALSEに、FALSEならTRUEに)
 2)InvalidateRect()で、親ウインドウの全領域の最描画を指示して、WM_PAINTを実行させる。
 InvalidateRect関数の第1引数は、対象となるウインドウで、ここでは、hWnd、第2引数は全領域描画を意味するNULL、第3引数は背景を完全に消去するためにTRUEとしておく。


図5 WinProcの中にcase ID_BUTTON1を記述


◎WM_PAINTへの記述(図6の167行)
 既に説明したように、ここに直接書くべきコードを、UserProgram関数として独立させたので、ここでは、UserProgram関数を呼び出すだけである。


図6 WM_PAINTにはUserProgram関数を書くにとどめる


フローチャートによる説明
 プロジェクトが起動されると、「三角関数表」と「対数関数表」を切り替えるbTrigonをTRUTH(三角関数表)に設定して、ウインドウを描画する。WM_PAINTを通じて、UserProgramが呼び出され、最初は、bTrogonがTRUEなので、三角関数表を描き、ボタンのラベルを「→対数関数表」に設定し、ボタンを表示する。
 ボタンがクリックされるまで、何もしない。
 ボタンがクリックされてID_BUTTON1メッセージが出ると、bTrigonを反転し(TRUEならばFALSEに)、ウインドウを再描画する。WM_PAINTを通じて、再び、UserProgramが呼び出されるが、今度は、bTrigonがFALSEなので、対数関数表を描き、ボタンのラベルを「→三角関数表」に設定し、ボタンを表示する。
 ボタンがクリックされるまで、何もしない。


図7 プロジェクトのフローチャート


得られた結果
 図8は、プログラム起動で、最初に現れるウインドウを示す。「→対数関数表」のラベルの付いたボタンをクリックすると、図9のように変わる。図9のウインドウで、「→三角関数表」ボタンをクリックすると、再び図8に戻る。


図8 プログラムを実行すると三角関数表が現れる



図9 ボタンをクリックして対数関数表に変えた