パソコン活用研究シリコンバレー(C、C++、の活用研究)

Windowsプログラミングの特長

MS-DOSのCUI(Character Based User Interface)プログラムとWindowsのGUI(Graphical User
Interface)プログラムは、プログラムの動く仕組みが大きく違うので、プログラムの構造もまったく
違ったものになります。
WindowsのGUIプログラムの方が、複雑な仕掛けが必要です。MS-DOSのCUIプログラムをBasic
インタプリタで作るのが1000mくらいの山にハイキングに行く感覚でこなせるとすると、Cで作るのは、
2000m級山に上る感じで、ちょこっと気合が必要てなところ。それがC++でWindowsプログラムを
作るとなると、5000m級の高峰に登山する感じで、ちょっと簡単には手がでないしろものになります。
それなりのトレーニングと装備が必要となります。

一番はじめに、おじさんがWindowsプログラムに取り組もうと思った時は、参考書籍もわかりやすい
ものがなかったので、プログラムを見た瞬間、絶句してあえなく挫折。それから、何度、最初の10
ページで挫折したことでしょうか。

とりあえずC++はおいといて、Visual Basicで何本かプログラムを作り、WindowsというOSについて
ある程度わかってから、ようやく手がつけられるようになりました。
MS-DOSで"Hello World"を表示するプログラムを作るのに、MS-DOSについての知識は特に必要
なく、Cの関数について知っていればOKだったのに対し、Windowsプログラムを作るには、C++だけ
の知識ではだめで、WindowsというOSについてある程度理解が必要です。

というわけで、前置きが長くなりましたが、C++でWindowsプログラムを作るのに必要な前提知識
についてまとめてみました。

1 MS-DOSのプログラム構造とWindowsのプログラム構造(メッセージ駆動型)

では、何もせず、何かキーをおすと終了するプログラムで比較してみましょう。
MS-DOSでは、以下のようなプログラムになりますね。

#include <stdio.h>
#include <stdlib.h>

main(){
while( !kbhit() ) { }
}

では、何かキーを押すという部分の、MS-DOSとプログラム(アプリケーション)の動きについて
みてみましょう。
MS-DOSプログラム
  キーボードが押されると、押されたキーの情報は
  MS-DOSの標準入力のバッファに格納されます。

  そして、キーが押されたかどうかは、アプリケーション
  側でkbhitという関数で調べに行きます。
  
  調べた結果、キーが入力されていなければ、while
  でループし、キー入力があれば、終了になります。

すなわち、キー入力があったかどうかは、アプリケーション側で調べるコードを記述して、アプリ
ケーション側から調べにいくわけです。このアプリケーションでは、キーの入力しか調べません
ので、マウスが押されてもまったく感知しません。マウスのクリックや動きに応じてある動作を
させたければ、マウスの動きを調べるコードをプログラムに記述したやる必要があります。


さて、これがWindowsプログラムになると様相がかなり異なってきます。


  キー入力の情報は、まずWindowsがうけとり、「キー
  入力された」という情報(メッセージ)が、Windowsから
  アプリケーションに伝えられます。

  アプリケーション側は、メッセージをうけると、メッセージ
  に応じた処理をします。



すなわち、キー入力があったかどうかをアプリケーション側で調べに行くのではなく、Windows
からの通知があったら、それぞの処理を行う、というプログラミングスタイルになります。
Windowsからは「キーが押された」「マウスがクリックされた」「画面サイズが変更された」など
さまざまなメッセージがプログラム(アプリケーション)に通知されてきます。このさまざまなメッセージ
に対し、それがキー入力のメッセージがあれば、キー入力の処理を行い、マウスの左クリックで
あれば、マウスの左クリックの処理を行い、というような感じになります。
Windowsから通知されるメッセージはものすごく大量ですが、全てのメッセージに対応する
コードをいちいち記述する必要はありません。不要なメッセージはデフォルト(何もしないという)
処理に全て任せます。
このように、Windowsから通知されるメッセージにより、アプリケーションが動いていく方式を
メッセージ駆動型と呼んでいます。
ここでは、プログラムのコードは示しませんが、MS-DOSのCUIプログラムとはまったく別物の
プログラムとなります。
MS-DOSでプログラムを組んできた人は、さいしょはものすごく面食らうかもしれません。

ちなみに、Windowsのメッセージは1000種類程度あります。主なメッセージには以下のような
ものがあります。
(A) ウィンドウ関連
ウィンドウが作成された / ウィンドウが破棄された/ ウィンドウを再描画する必要がある/
ウィンドウのサイズが変更された
(B) マウスの入力関連
左ボタンが押された/ 左ボタンが離された/ 左ボタンがダブルクリックされた
右ボタンが押された/ 右ボタンが離された/ 右ボタンがダブルクリックされた
(C) キー入力関連
キーが押された/ キーが離された/ システムキーが押された/ システムキーが離された/
文字が入力された


2 Windowsプログラムの仕組み(枠組み)
Windowsがメッセージを送る −> プログラム側でメッセージを適切に処理 というのが、
Windowsプログラムのスタイルだと、上で書きました。従って、Windowsプログラムには、
"プログラム側でメッセージを適切に処理"するための関数の記述が必須となります。
この関数を一般的に
ウインドウプロシージャと呼んでいます。
ウインドウプロシージャは、Windowsから呼び出され、Windowsから渡されたメッセージを
適切に処理する関数です。一般的には
WndProcという関数名で記述されます。
ウインドウプロシージャのようにWindowsから呼び出される関数を
コールバック関数
呼びます。

メッセージボックスのところで、プログラム起動時に呼ばれる(エントリーポイント)関数として
WinMain関数を説明しましたが、このWinMainとWndProcの2つの関数を持つ構造がWindows
プログラムの構造です。

WinMain (
HINSTANCE hInstance,
HINSTANCE hPrevInstance,
LPSTR lpCmdLine,
int nCmdShow )
{
}

WndProc (
HWND hWnd,
UNIT message,
WPARAM wParam,
LPARAM lParam )
{
}

WndProc関数にも4つのパラメータがあります。これらのパラメータを設定するのは、もちろん
この関数を呼び出すWindowsそのものです。各パラメータについて説明します。

hWnd
これは、ウインドウハンドルです。ウインドウハンドルとはわかりにく表現かもしれませんが、
マルチタスクで動く複数のアプリケーションを識別するためにつけられた番号と考えて下さい。
Windowsではマルチタスクですので、多数のアプリケーションが同時に動いています。例えば、
マウスをクリックした時に、そのマウスをクリックしたというメッセージが伝えられるべきアプリケー
ションが適切に識別されなくてはなりません。そのために、アプリケーションの起動時に、Windows
がそのアプリケーションに識別番号をつけます。その識別番号の値がウインドウハンドルです。
このウインドウハンドルの値は、ウインドウプロシージャWinProcの中で使われるさまざまな
API関数を呼び出すときに、パラメータとして渡します。
ちなみに、HWNDというデータ型はlong型別名をつけたものです。

message
Windowsから渡されたメッセージです。

wParam,lParam
どちらもメッセージの補足情報です。例えば、キーが押されたというメッセージの場合、
押されたキーの文字コードが補足情報として格納されます。
補足情報が2つまでの時は、wParam,lParamに情報が直接格納され、補足情報が3つ以上
の場合は、補足情報の格納されたメモリ領域のポインタと、補足情報の数が格納されます。

以上が、Windowsプログラムの枠組みですが、初めてWindowsプログラムに取り組む人には
この枠組みの説明だけではまだあまりぴんとこないかもしれません。次回、一番単純な
プログラムを実際に取り上げて説明してみたいと思います。具体的なコードをみてみると、
ここに書いてあることが、ああそうかと理解できると思います。


TopPage