コンピューターと戯れて
-- Williamの窓 つー! --






さて、前回作成した窓に引き続き、今回もまたシンプルな窓の実装を紹介します。
この時点でご興味の薄れた方、残念ですがごきげんよう、また次回お会いしましょう。

戻る




















さて、改めてこんにちは
前回、 MessageBox 関数を用いた窓(メッセージボックス)を表示させましたが、
今回はもう少しグレードを上げて(?)、メッセージボックスの親分格にあたるダイアログボックスで窓を表示させます。

まぁ、気張ったところで用いる関数( Windows用API、Win32API )は、前回と同様一つなので気楽にいきましょう。当然のことですが、今回も前回と同じように MSDN の焼き直しになることは明らかだし・・・


取り敢えず気を取り直して、ながながと MSDN の焼き直しにお付合いください。

今回取り扱う関数は、すばり DialogBox です。

ところでこの DialogBox の語源ですが ・・・・
Dialog とは、
名詞では、対話(による意見交換)
動詞では、対話を
になります(三省堂 新コンサイス英和辞典 第二版より)。

って云うと、DialogBox だから直訳では、 『対話箱』 になります ・・・ このイメージで以後認識して頂ければ、心が掴めると思います ;^^



まずこの関数が定義されているヘッダーは winuser.h で、インポートライブラリは user32.lib になります。ヘッダーやライブラリなる用語が分からない方は申し訳ございませんが、C 言語の参考書等を参照してみてください



つぎにこの関数の仕様ですが、
簡単に説明しますと、DialogBox 関数はダイアログボックステンプレートリソースからモーダルダイアログボックスを作成します。ほら、簡単でしょう?・・・・どこがじゃ!


ひとまずダイアログテンプレートリソースの説明から致しましょうか

( MSDN を要約すると)DialogBox 関数に受け渡すダイアログボックステンプレートとは、
ダイアログボックスの特性を指定したものだそうです ・・・ もっともテンプレートって云うほどだからそうじゃないと意味が通じないじゃん

さて、テンプレートに対してダイアログウィンドウの特性を与えるわけですが
具体的には、サイズ・表示位置・ウィンドウスタイル・ダイアログウィンドウ上に追加されるコントロールタイプなどの位置と状態を指定します。

百聞は一見にしかずってなことで簡単な例ですが、以下にテンプレートのサンプルを上げます。

---テンプレートのサンプル---
IDD_DIAGGUI DIALOG DISCARDABLE  0, 0, 187, 145
STYLE DS_MODALFRAME | DS_CENTER | WS_MINIMIZEBOX | WS_MAXIMIZEBOX | WS_POPUP | WS_CAPTION | WS_SYSMENU
FONT 9, "MS Pゴシック"
BEGIN
END
なんだかめんどくさそうに思えますか?
でも、安心してください。市販の開発環境の大半には、テンプレートを自動生成してくれるダイアログエディタなるツールが存在するはずです。
このツールを用いれば上記のテンプレートなんて簡単に作成できちゃいます ・・・たぶんそのはずです。ちがったらごめんね

ちなみにわたくしが使っている VisualStudio の機能ですと、以下のことができます。
1.ダイアログボックスの表示位置・サイズの調整
2.コントロールパレットを用いて様々なコントロールをドラッグして、ダイアログボックス内にドロップしてデザインすることが可能 (まるでDephiやVisualBasicのように・・・かな?)
3.各コントロールのリソース名をきちんと管理!  本当かよ?
ほら〜、このような強力無敵な(?)ツールを用いることで、簡単にしかもお手軽にダイアログボックスの外観を整えることができるでしょう?

後は、作成したダイアログボックステンプレート名を DialogBox 関数に渡せば OK!





では改めまして、DialogBox 関数についていろいろと見てみましょう。

まずは DialogBox 関数の関数定義を


int DialogBox(
  HINSTANCE hInstance,
  LPCTSTR lpTemplate,
  HWND hWndParent,
  DLGPROC lpDialogFunc
);
hInstance:アプリケーションのインスタンスハンドル
lpTemplate:ダイアログボックステンプレートの識別名
hWndParent:親窓のハンドル
lpDialogFunc:ダイアログプロシージャーへのポインター(コールバック関数へのポインター)



この関数 I/F の仕様を見る限り、MessageBox 関数より強力なことは一目瞭然ですね

でぇ、そこを踏まえて関数の I/F をよ〜っく見てみますと、最後の引数がコールバック関数への入り口になっているかと思われます。
改めて云われるまでもなく、コールバック関数へのエントリーが存在するのに気付かれた方もいるとは思いますが・・・
このコールバック関数が実装されている点が、前回用いた MessageBox 関数との大きな相違点です。これによって生成される 窓 に対して EventDriven な環境が実装されます。

ちなみに MSDN 上では、コールバック関数のことを OS から発信されるメッセージを受信する関数であると説明しています。コールバック関数やイベント駆動に関しては、例によって例の如く、これ以上言及するつもりがないのでごめんなさい。

さて、先に進みましょう。
関数 I/F から言えることは、繰り返しになりますが、コールバックが実装されているため、作成された窓は本格的なメッセージ駆動型 ・・・ イベント駆動型モジュールとなります。
ちなみに MSDN の説明を補足しますが、
この DialogBox 関数は、指定されたコールバック関数が EndDialog 関数を呼び出してダイアログボックスを閉じるまで、制御をメインスレッドに返しません ・・・・ 補足終わり

さてさて、MSDN では DialogBox 関数のことを、DialogBox マクロと明記されていますが ・・・ 確かに DialogBox はマクロだったりします。
マクロなる語の意味は、ちーっと話が飛躍しますが、コンパイラーがサポートするプリプロセッサの機能で、 #define で呼び出された機能です。役割は、単純に説明しますと値の置き換えです。
さて、いろいろと調べてみると DialogBox とは、CreateWindowEx 関数を使って実装されているようです。


でも ・・・ 直接、grep なんぞして VC の include ディレクトリをソートしてみますと、WINUSER.H 上に次の如く定義されていました。
興味の無い人は先に進んでください。

#ifdef UNICODE
#define DialogBox DialogBoxW
#else
#define
DialogBox DialogBoxA
#endif // !UNICODE

さらに DialogBoxW や DialogBoxA に辿りますと


#ifdef UNICODE
#define DialogBoxParam DialogBoxParamW
#else
#define
DialogBoxParam DialogBoxParamA
#endif // !UNICODE

もう数段階辿りまして ・・・・


#define DialogBoxA(hInstance, lpTemplate, hWndParent, lpDialogFunc) \
   DialogBoxParamA(hInstance, lpTemplate, hWndParent, lpDialogFunc, 0L)


#define DialogBoxW(hInstance, lpTemplate, hWndParent, lpDialogFunc) \
   DialogBoxParamW(hInstance, lpTemplate, hWndParent, lpDialogFunc, 0L)


最後、とどめです。

	WINUSERAPI int WINAPI DialogBoxParamA(
		    HINSTANCE hInstance,
		    LPCSTR lpTemplateName,
		    HWND hWndParent ,
		    DLGPROC lpDialogFunc,
		    LPARAM dwInitParam);
			
	WINUSERAPI int WINAPI DialogBoxParamW(
		    HINSTANCE hInstance,
		    LPCWSTR lpTemplateName,
		    HWND hWndParent ,
		    DLGPROC lpDialogFunc,
		    LPARAM dwInitParam);

取り敢えずこんな感じでした・・・・





さて、行き成り実装して見ましょう。(百聞は一見に ・・・・)
え〜っと、ソースが小さくって見難いときは、取り敢えず以下のソースをカットアンドペースとしてメモ帳にでも貼り付けてから参照してください。


simpledialog.c

//コンパイラのバージョン定義
//Microsoft Visual C++R 6.0 の場合は 1200 として定義
#if _MSC_VER > 1000
#pragma once
#endif // _MSC_VER > 1000

// Windows ヘッダーから殆ど使用されないスタッフを除外
#define WIN32_LEAN_AND_MEAN
//MFC を使わない C++ および C 言語アプリケーションでは、
//WIN32_LEAN_AND_MEAN および適用可能な NOservice 定義 (NOSOUND など) を
//定義してビルド時間を短縮する。詳細は、VCをお使いの方は以下の箇所などを参照のこと  
//ProgramFiles\Microsoft Visual Studio\VC98\include\Windows.h
//ProgramFiles\Microsoft Visual Studio\VC98\MFC\Include\afxv_w32.h を参照
//Knowledge baseの項目 Q151666 でも可!

//必要ヘッダーのインクルード
#include <windows.h>
#include <winuser.h>
#include "resource.h"

//コールバック関数の定義
LRESULT CALLBACK   DialogProc(HWND, UINT, WPARAM, LPARAM);

//アプリのエントリー
int APIENTRY WinMain(HINSTANCE    hInstance,
                     HINSTANCE    hPrevInstance,
                     LPSTR        lpCmdLine,
                     int          nCmdShow)
{
   //お目当ての関数を呼び出す
   DialogBox(hInstance, (LPCTSTR) IDD_DIAGGUI, NULL, (DLGPROC) DialogProc);
   return (0);
}


//メッセージ ハンドラ
LRESULT CALLBACK DialogProc(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam)
{
   switch(message)
   {
   case WM_INITDIALOG :
      return TRUE;
   case WM_COMMAND :
      if (LOWORD(wParam) == IDCANCEL){
         EndDialog(hDlg, LOWORD(wParam));
         return TRUE;
      }
      break;
   }
   return FALSE;
}



上記がプログラムの骨格、所謂ソースコードと呼ばれるものです。
下はリソースファイルです。

simpledialog.rc

#include "resource.h"
#include "afxres.h"

IDD_DIAGGUI DIALOG DISCARDABLE  0, 0, 187, 145
STYLE DS_MODALFRAME | DS_CENTER | WS_MINIMIZEBOX | WS_MAXIMIZEBOX | WS_POPUP | WS_CAPTION | WS_SYSMENU
FONT 9, "MS Pゴシック"
BEGIN
END


最後にヘッダを

resource.h

#define IDD_DIAGGUI                     101




さて上記の三本のファイルをコンパイラーに渡すと ・・・

ダイアログボックスサンプル ←こんな画面が出てくると思います。
ほ〜ら、窓を実装するのは簡単でしょう?




しかもソースの骨格、つまりは窓を表示させている箇所は一行に過ぎません。

DialogBox(hInstance, (LPCTSTR) IDD_DIAGGUI, NULL, (DLGPROC) DialogProc);

この一行の呼び出しで、窓が画面上に現れて、以後、イベントをトラップすると自動的にコールバック関数に渡されます。

コールバックの中身

LRESULT CALLBACK DialogProc(HWND hDlg,
 UINT message, WPARAM wParam, LPARAM lParam)
{
  switch(message)
  {
  case WM_INITDIALOG :
      return TRUE;
  case WM_COMMAND :
      if (LOWORD(wParam) == IDCANCEL){
          EndDialog(hDlg, LOWORD(wParam));
          return TRUE;
      }
      break;
  }
  return FALSE;
}


コールバック関数の中身は右に示すような内容になります。
関数内の動きにつきましてはおいおいということで・・・・おぃおぃ!
取り敢えずは気にしないでください。



ポイントは DialogBox 関数です!
この関数を使うことで MessageBox 関数よりもより多くのことが可能になります。


DialogBox 関数の紹介は、こんなもんで如何でしょうか?
今回はこの辺りで締め括らせていただきます。



ご意見、ご感想、ご要望等々はこちらのメールアドレス takamegu@lycos.ne.jp までご一報ください。

では、また
 高松 恵





目次に戻る
全文メニュー
サイトの玄関