通常のウィンドウ

GENERICプログラム

今回から、ダイアログボックスではなく、通常のウィンドウをメインウィンドウにしたものを作成します。 以下は、Windows3.1SDKのGENERICプログラムを、さらに単純にしたものです。

GENERIC ソース

まず、RegisterClass() APIでウインドウクラスをOSに登録します。これはウィンドウの 性質を定義します。もっとも重要なのはクラス名とウィンドウプロシージャです。 この登録は一度行えば、同じ性質をもつ複数のウインドウで共有できます。

WinMainの第二引数hPrevInstanceをチェックしてからRegisterClass()してますが、実はこの チェックは32ビットに限れば不要です。16ビットでは同じプログラムを複数回起動した場合でも 複数プロセスでウインドウクラスを共有できるのですが、32ビットではこれができません。 よってソース互換性のため、32ビットではhPrevInstanceは必ずNULLになります。

次に、CreateWindow() ShowWindow() UpdateWindow()を続けて呼び出します。 CreateWindow()は、モードレスダイアログの時のCreateDialog()に対応しています。 ただし、ダイアログテンプレートが無いので、必要な引数が増えています。 ShowWindow()は、WinMainの第四引数nCmdShow(これは通常起動かアイコン起動かなどの 情報が入っている。プログラムマネージャやエクスプローラの「ファイル名を指定して実行」 ダイアログには「アイコンの状態で起動」チェックボックスがありますね。)に従って ウインドウを可視化したりアイコン化したりします。 UpdateWindow()は、それをただちに画面に反映させる動きをします。

これらの処理を直接WinMainでやらずに、InitApplication()とInitInstance()という関数に分離していますが 別にこの程度ならWinMainで直接やって問題ありません。しかし、プログラムが大きくなると、これらの 処理もふくれあがるので、分けておいたほうが無難です。

あとは、何の変哲もないメッセージループに突入してWinMainは終わりです。モードレスダイアログ でも出てきたのと同じですね。

次に、ウインドウプロシージャMainWndProc()です。これもダイアログプロシージャと良く似ています。 最も大きな違いは「デフォルト処理の実行のさせかた」です。ダイアログでは、returnする時の戻り値 がFALSEの時に、OSが自動的にデフォルト処理を実行しましたが、通常のウィンドウでは DefWindowProc()というAPIを明示的に呼ばなければなりません。このAPIがメッセージのデフォルト 処理を実行します。(ではウインドウプロシージャの戻り値はと言いますと、LONGになってますね。 メッセージがSendMessage()等で送られたとき、SendMessageの戻り値として返されます。 たいていは0を返しておけばokですが、メッセージによっては固有の意味をもつものがあります。)

タイトルバー上のクローズボタンやシステムメニューの「閉じる」を選んだときの処理は、 モードレスダイアログでは明示的にDestroyWindow()を呼ぶ必要がありました。 (モーダルならEndDialog()。) しかし通常のウインドウではデフォルト処理に含まれるので 必要ありません。もちろん後に出てくるように、別途クローズボタンや「ファイル」メニュー の「閉じる」等をつけくわえた場合はこのかぎりではありません。

ダイアログボックスの場合、最初にWM_INITDIALOGというメッセージがきました。 通常のウインドウの場合は、WM_CREATEになります。(今回は使ってませんが)

メインウインドウの場合は、プログラム自体を終わらせるために、 WM_DESTROYメッセージに応答して、PostQuitMessage()APIを呼びます。これも以前も出てきました。

ボタン等の追加

通常のウインドウにも、ボタンやエディットコントロール等を貼りつけることができます。 コントロールは、システムによってあらかじめRegisterClassされたウインドウクラスです。 よって、直接CreateWindowするだけです。 IsDialogMessage()を使うと、キーボード入力をサポートできます。 (これ最近まで私も知らなかった。API名からダイアログ専用だと思ってた。) 逆に、自分でRegisterClassしたウインドウを貼りつけることもできます。

このようにすると、一見ダイアログに見える通常ウインドウができます。この場合サイズは固定 にしたほうが良いでしょう。(これはちゃんとサポートしようとすると、けっこう難しい。 タイトルバー・メニューバー等のサイズ変更に対応しないといけないので。) 枠をダイアログそっくりにすることもできます。(WS_DLGFRAMEを指定) このやりかたの欠点は、ダイアログエディタが使えないため、位置決めがカット&トライになることです。 また、システムフォントのサイズを変更すると、ボタン等の文字サイズも変わりますが、ボタン等のウインドウサイズをこれに追随するようにしておかないと、文字が読めなくなる可能性があります。そのためシステムフォントのサイズを取得して、コントールの位置やサイズをそれに基づいて決めるように記述してあります。 (ダイアログの場合、このへんは自動でやってくれたのですが…)

実例。ついでに、システムメニューに「バージョン情報」を追加しました。 これも以前出てきたやりかたと同じです。

こうしてみると、通常のウィンドウとモードレスダイアログって、よく似てますね。

前のページ

次のページ

一つ上のページに戻る