19章 ダイアログボックス(その2)

<html>

<head>
<meta http-equiv="Content-Type" content="text/html; charset=shift_jis"></meta>
<title>19章 ダイアログボックス(その2)</title>
</head>

<body bgcolor="WHITE">
<font size="5">19章 ダイアログボックス(その2)</font>
<hr>
<p>
 この章では、モーダルダイアログボックスの作成の仕方を学びます。
<p align="CENTER">
<img src="/web/20150425235821im_/http://web.kyoto-inet.or.jp:80/people/ysskondo/from16/img18b.gif"><br><a href="chap18a.lzh">ダウンロード</a>
<p>
 教材となるサンプルプログラムは18章の物です。したがって、18章でダウンロードされた方は再度ダウンロードする必要はありません。
<hr>
<p>
<b>・普通のウインドウ作成の簡単な復習</b>
<p>
 3章と16章で詳細に説明したように、コントロールを含む普通のウインドウを開くには、以下のステップを踏みます。
<p align="CENTER">
<table border="1" bgcolor="#F0F0F0">
<tr><td>
・ウインドウプロシージャの定義(この中で、コントロールの作成などを行う)<br>
・ウインドウクラスの作成<br>
・CreateWindow関数またはCreateWindowEx関数でウインドウを作成
</table>
<p>
 概念的には3ステップで作成ですが、実際は、習得しなければいけない概念が多く、大変な作業でした。また、コントロールを作成する場合、親ウインドウとなるウインドウのウインドウプロシージャの中で、CreateWindow関数を用いて作成する必要がありました。この方法で、想定しているレイアウト通りにコントロールを配置する事は、極めて困難です。
<p>
<b>・モーダルダイアログボックス作成の簡単な予習</b>
<p align="CENTER">
<table border="1" bgcolor="#F0F0F0">
<tr><td>
・ダイアログテンプレートの作成<br>
・ダイアログボックスプロシージャの定義<br>
・専用の関数でモーダルダイアログボックスを作成する
</table>
<p>
 こちらも概念的に3ステップで作成です。しかし、その作業の仕方は大きく異なります。<b><i><u>コントロールを含む画面のレイアウトは、全てダイアログテンプレートで定義します</u></i></b>。ダイアログテンプレートと言うのは、「6章 メニューを付けてみよう」で紹介した<b><i><u>リソースの一種</u></i></b>です。そして、6章でメニューをビジュアル環境で作成した様に、<b><i><u>ダイアログテンプレートもビジュアル環境で作成できます</u></i></b>。リソーススクリプトを覚える必要は特にありません。
<p>
 <b><i><u>ダイアログプロシージャと言うのは、ウインドウプロシージャに良く似たコールバック関数です</u></i></b>。つまり、ダイアログボックスで生じたメッセージをここで処理します。ただ、戻り値の型が異なりますし、ウインドウプロシージャのように処理しなかったメッセージをデフォルトの関数に渡したりはしません。
<p>
 そして、実際の作成は、<b><i><u>DialogBoxParam関数</u></i></b>などの関数やマクロで作成します。
<hr>
<p>
<b>・とにかくソースコードを眺めてみよう</b>
<p>
 とにかくソースコードを眺めてみましょう。今まで通り、重要な個所だけ載せました。全部を見たい方は、サンプルをダウンロードして見てください。
<p>
<table border="1" bgcolor="#F0F0F0">
<caption align="BOTTOM">リスト19-1(Resource.rcより抜粋)
<tr><td>
<pre>
IDD_DIALOG1 DIALOG DISCARDABLE 0, 0, 154, 115
STYLE DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU
CAPTION "モーダルダイアログボックス"
FONT 9, "MS Pゴシック"
BEGIN
  DEFPUSHBUTTON   "OK",IDOK,100,10,50,14,WS_GROUP
   PUSHBUTTON      "キャンセル",IDCANCEL,100,27,50,14
   EDITTEXT        IDC_XS,35,15,40,14,ES_AUTOHSCROLL | WS_GROUP
   EDITTEXT        IDC_YS,35,35,40,14,ES_AUTOHSCROLL
   EDITTEXT        IDC_XE,35,70,40,14,ES_AUTOHSCROLL | WS_GROUP
   EDITTEXT        IDC_YE,35,90,40,14,ES_AUTOHSCROLL
   LTEXT           "X=",IDC_STATIC,10,21,12,8
   LTEXT           "Y=",IDC_STATIC,10,35,12,8
   LTEXT           "X=",IDC_STATIC,10,75,12,8
   LTEXT           "Y=",IDC_STATIC,10,90,12,8
   GROUPBOX        "描画開始位置",IDC_STATIC,5,5,90,50
   GROUPBOX        "描画終止位置",IDC_STATIC,5,60,90,50
END
</pre>
</table>
<p>
 リスト19-1、これがダイアログテンプレートです。リソーススクリプトという言語で書かれているのですが、HTMLの様にロジックを記述する言語ではありませんので、今までの知識があれば、ほんのり理解できますね。興味があれば、個々のトークンをリファレンスマニュアルで調べてください。実際は、メニューと同様にビジュアル編集が出来ますので、スクリプト言語を覚える必要はありません。
<p>
 さて、BEGINとENDで囲まれた範囲の中でコントロールのレイアウトが定義されているのが分かりますね。
<p>
 まず、BEGINからENDへコントロールを指定するスクリプト文が並んでいますが、この順番でコントロールが作成されます。また、WS_GROUPを用いてのグループ化の為の重要な情報になっています。つまり、WS_GROUPが指定されているコントロールから次のWS_GROUPが指定されているコントロールの1つ前までが一つのグループになり、[←][→][↑][↓]キーでフォーカスを移動できるのです。また、コントロールが作成される順番は、TABキーによるフォーカスの移動の順番でもあります。
<p>
 さて、ダイアログテンプレートで用いられている数値は、全て、ダイアログボックスやその中に配置されるコントロールの位置やサイズなのですが、<b><i><u>単位は物理的なピクセルではありません</u></i></b>。つまり、これは<b><i><u>フォントの大きさを基準にした相対的な単位</u></i></b>です。このため、ダイアログボックスで用いるフォントが大きくなればダイアログボックスもその中のコントロールも大きくなります。このため、<b><i><u>プログラマはフォントサイズ変更による画面の乱れから開放されます</u></i></b>。
<p>
<table border="1" bgcolor="#F0F0F0">
<caption align="BOTTOM">リスト19-2(Chap18.h)
<tr><td>
<pre>
/*
  『C言語で始めるWindowsプログラミング』
   18章のサンプルプログラム
                   Programmed by Y.Kondo

/


#ifndef __chap18__
#define __chap18__
  /*  直線描画用の構造体  */
   typedef struct
   {
       int     xs;
       int     ys;
       int     xe;
       int     ye;
   }   TLineData;
#endif
</pre>
</table>
<p>
<table border="1" bgcolor="#F0F0F0">
<caption align="BOTTOM">リスト19-3(DlgProc1.c)
<tr><td>
<pre>
/*
  『C言語で始めるWindowsプログラミング』
   18章のサンプルプログラム
                   Programmed by Y.Kondo

/


#define STRICT

#include &lt;windows.h&gt;
#include &lt;stdio.h&gt;
#include "DlgProc1.h"
#include "chap18.h"
#include "resource.h"

/* このファイル内でのみ用いられる変数 */
static TLineData *gVarLineData;

/* このファイル内でのみ用いられる関数のプロトタイプ宣言 */
static BOOL Wm_InitDialogProc(HWND,HWND,TLineData*);
static BOOL Wm_CommandProc(HWND,WORD,WORD,HWND);
static BOOL IsNumber(HWND);

/* ダイアログプロシージャ */
BOOL CALLBACK ModalDialogBoxProc(HWND hwnd,UINT msg,WPARAM wparam,LPARAM lparam)
{
  switch(msg)
   {
       case    <b>WM_INITDIALOG</b>:
           return  Wm_InitDialogProc(hwnd,(HWND)wparam,(TLineData*)lparam);
       case    WM_COMMAND:
           return  Wm_CommandProc(hwnd,HIWORD(wparam),LOWORD(wparam),(HWND)lparam);
   }
   return  FALSE;
}

static BOOL Wm_InitDialogProc(HWND hwnd,HWND hwndFocus,TLineData* LineData )
{
  int         c;
   int         EditControl[]={IDC_XS,IDC_YS,IDC_XE,IDC_YE};
   char        strbuf[100];

  /*  ラインデータのアドレスを保存    */
   gVarLineData=LineData;

  /*  入力できる文字数を4に制限している  */
   for(c=0;c&lt;(sizeof(EditControl)/sizeof(EditControl[0]));c++)
           SendDlgItemMessage(hwnd,EditControl[c],EM_SETLIMITTEXT,4,0);

  /*  エディットコントロールの初期化  */
   sprintf(strbuf,"%d",LineData-&gt;xs);
   SetWindowText(GetDlgItem(hwnd,IDC_XS),strbuf);
   sprintf(strbuf,"%d",LineData-&gt;ys);
   SetWindowText(GetDlgItem(hwnd,IDC_YS),strbuf);
   sprintf(strbuf,"%d",LineData-&gt;xe);
   SetWindowText(GetDlgItem(hwnd,IDC_XE),strbuf);
   sprintf(strbuf,"%d",LineData-&gt;ye);
   SetWindowText(GetDlgItem(hwnd,IDC_YE),strbuf);

  <b>SetFocus(GetDlgItem(hwnd,IDC_XS))</b>;
   return  <b>FALSE</b>;  
}

static BOOL Wm_CommandProc(HWND hwnd,WORD wNotifyCode,WORD wID,HWND hwndCtl)
{
  int     c;
   int     EditControl[]={IDC_XS,IDC_YS,IDC_XE,IDC_YE};
   char    strbuf[5];

  switch(wID)
   {
       case    IDOK:
           /*  ここで入力エラーを検出する  */
           for(c=0;c&lt;(sizeof(EditControl)/sizeof(EditControl[0]));c++)
           {
               if(!IsNumber(GetDlgItem(hwnd,EditControl[c])))
               {
                   MessageBox(hwnd,"入力が不正です","エラー",MB_OK);
                   /*  入力エラーがあるエディットコントロールにフォーカスを戻す    */
                   SetFocus(GetDlgItem(hwnd,EditControl[c]));
                   return  TRUE;
               }
           }
           
           /*  親の描画データを変更する    */
           GetWindowText(GetDlgItem(hwnd,IDC_XS),strbuf,5);
           gVarLineData-&gt;xs=strtol(strbuf,NULL,10);
           GetWindowText(GetDlgItem(hwnd,IDC_YS),strbuf,5);
           gVarLineData-&gt;ys=strtol(strbuf,NULL,10);
           GetWindowText(GetDlgItem(hwnd,IDC_XE),strbuf,5);
           gVarLineData-&gt;xe=strtol(strbuf,NULL,10);
           GetWindowText(GetDlgItem(hwnd,IDC_YE),strbuf,5);
           gVarLineData-&gt;ye=strtol(strbuf,NULL,10);

          <b>EndDialog(hwnd,IDOK)</b>;
           break;

      case    IDCANCEL:
           <b>EndDialog(hwnd,IDCANCEL)</b>;
           break;  
   }
   return  TRUE;
}

/*
  エディットコントロールに入力された文字列が整数に変換できるか調べる関数
   変換できる場合  :  TRUE
   変換できない場合:  FALSE

/

static BOOL IsNumber(HWND hwnd)
{
  char    *p;     /* for strbuf() */
   char    strbuf[5];

  GetWindowText(hwnd,strbuf,5);
   if(strlen(strbuf)==0)
       return  FALSE;
   strtol(strbuf,&p;,10);
   if(strlen(p)!=0)
       return  FALSE;
   return  TRUE;
}
</pre>
</table>
<p>
 リスト19-3がダイアログボックスプロシージャを定義しているファイルの中身です。ダイアログプロシージャは、戻り値がBOOLである事や、処理しなかったメッセージをDefWindowProc関数に渡していないなど、違いはありますが、引数の型など良く似ている所があります。
<p>
 そして、ここでは、ウインドウプロシージャのようにCreateWindow関数でコントロールを作成していない事に気が付いてください。
<p>
<table border="1" bgcolor="#F0F0F0">
<caption align="BOTTOM">リスト19-4(WndProc.c)
<tr><td>
<pre>
/*
  『C言語で始めるWindowsプログラミング』
   18章のサンプルプログラム
                   Programmed by Y.Kondo

/


#define STRICT
#include &lt;windows.h&gt;
#include "wndproc.h"
#include "resource.h"
#include "DlgProc1.h"
#include "chap18.h"
#include "string.h"

/*===============================================================================*/

/* このファイル内でのみ用いられる関数のプロトタイプ宣言 */
static LRESULT Wm_CreateProc(HWND,LPCREATESTRUCT);
static LRESULT Wm_DestroyProc(HWND);
static LRESULT Wm_CommandProc(HWND,WORD,WORD,HWND);
static LRESULT Wm_PaintProc(HWND);

/* このファイル内でのみ用いられる変数 */
static TLineData ForModal; /* モーダルダイアログボックス用 */
static TLineData ForModeless; /* モードレスダイアログボックス用 */

static HPEN ForModalPen; /* モーダルダイアログで指定した範囲を描画するペン */
static HPEN ForModelessPen; /* モードレスダイアログで指定した範囲を描画するペン*/

static HWND hModelessDlg; /* モードレスダイアログボックスのハンドル */

/* メインウインドウのウインドウプロシージャ */
LRESULT CALLBACK WindowProc(HWND hwnd,UINT message,WPARAM wparam,LPARAM lparam)
{
  switch(message)
   {
       case    WM_CREATE:
           return  Wm_CreateProc(hwnd,(LPCREATESTRUCT)lparam);
       case    WM_DESTROY:
           return  Wm_DestroyProc(hwnd);
       case    WM_COMMAND:
           return  Wm_CommandProc(hwnd,HIWORD(wparam),LOWORD(wparam),(HWND)lparam);
       case    WM_PAINT:
           return  Wm_PaintProc(hwnd);
   }
   return  DefWindowProc(hwnd,message,wparam,lparam);
}

/*===============================================================================*/

static LRESULT Wm_CreateProc(HWND hwnd,LPCREATESTRUCT cs)
{
  /*  直線の描画データ初期化  */
   TLineData   org={0,0,100,100};
   ForModal    =org;

  return  0;
}
static LRESULT Wm_DestroyProc(HWND hwnd)
{
  PostQuitMessage(0);
   return  0;
}

static LRESULT Wm_CommandProc(HWND hwnd,WORD wNotifyCode,WORD wID,HWND hwndCtl)
{
  HINSTANCE   hInstance;
   switch(wID)
   {
       case    IDM_MODAL:
           /*  モーダルダイアログボックス  */
           hInstance=(HINSTANCE)GetWindowLong(hwnd,GWL_HINSTANCE);
           if(<b>DialogBoxParam(hInstance,MAKEINTRESOURCE(IDD_DIALOG1),
                       hwnd,(DLGPROC)ModalDialogBoxProc,(LPARAM)&ForModal;)</b>==IDOK)
           {
               InvalidateRect(hwnd,NULL,TRUE);
               UpdateWindow(hwnd);
           }
           break;
   }
   return  0;
}

static LRESULT Wm_PaintProc(HWND hwnd)
{
  PAINTSTRUCT ps;

  BeginPaint(hwnd,&ps;);
       MoveToEx(ps.hdc,ForModal.xs,ForModal.ys,NULL);
       LineTo(ps.hdc,ForModal.xe,ForModal.ye);
   EndPaint(hwnd,&ps;);
   return  0;
}
</pre>
</table>
<p>
 リスト19-4は、メインウインドウのウインドウプロシージャでです。メニューに応答する形で、ダイアログボックスが作成されている事が分かるでしょうか。この部分を太文字にしてあります。
<p>
 これともう一つ理解して欲しい事は、ダイアログボックスを作成する関数の戻り値を取得して、画面の再描画を決定している事です。つまり、<b><i><u>ウインドウプロシージャは、ダイアログボックスを作成したら、これに制御を渡してしまい、ウインドウプロシージャとメッセージループが止まってしまうのです</u></i></b>。これが理解できれば、このソースコードが読めたことになります。
<hr>
<p>
<b>・ダイアログテンプレートをビジュアル環境で作ってみよう</b>
<p>
 6章で、プロジェクトにリソースファイルを作成する方法を学びました。それゆえ、ここでは、リソースファイルがプロジェクトにすでにある物として説明します。
<p>
 ワークスペースのリソースビュータブを最前面に出して、resourceリソースノードにマウスカーソルを当てます。そして、マウスの右ボタンをクリックします。すると、下の図19-1の様になります。
<p align="CENTER">
<img src="/web/20150425235821im_/http://web.kyoto-inet.or.jp:80/people/ysskondo/from16/img19a.gif"><br><b>図19-1</b>
<p>
 そこで、[挿入]を選択します。すると、下の図19-2の様に[リソースの挿入]ダイアログボックスが出ます。そこで、図19-2の様に[Dialog]を選択して、[新規作成]ボタンを押します。すると、図19-3の様な画面になります。そして、ここから、ダイアログボックスのビジュアル編集が始まるのです。
<p align="CENTER">
<img src="/web/20150425235821im_/http://web.kyoto-inet.or.jp:80/people/ysskondo/from16/img19b.gif"><br><b>図19-2</b>
<p>
 図19-3の様に「コントロール」ツールバーから、コントロールを選択して、マウスの左ボタンを押しながら、ダイアログボックスの形をしたフォームの中にドラッグ&ドロップします。
<p align="CENTER">
<img src="/web/20150425235821im_/http://web.kyoto-inet.or.jp:80/people/ysskondo/from16/img19c.gif"><br><b>図19-3</b>
<p>
 図19-4は、エディットコントロール(エディットボックスとも言います)をドラッグ&ドロップしたところです。
<p>
 この様にして、必要なコントロールをダイアログボックスにビジュアル的に配置していきます。実際に操作をすれば分かりますが、いったん置いたコントロールを移動さすことも削除することも、そして大きさを買えることも自由自在です。もちろん、ダイアログボックスの大きさを変えることも可能です。
<p align="CENTER">
<img src="/web/20150425235821im_/http://web.kyoto-inet.or.jp:80/people/ysskondo/from16/img19d.gif"><br><b>図19-4</b>
<p>
 さて、お好みの位置や大きさに、コントロールを配置したら、スタイルやコントロールIDなどの設定です。これには、設定変更したいコントロールや設定変更したいダイアログボックスそのものをマウスカーソルとマウスの左ボタンで選択して、マウス右クリックです。すると、図19-5の様な画面になります。
<p align="CENTER">
<img src="/web/20150425235821im_/http://web.kyoto-inet.or.jp:80/people/ysskondo/from16/img19e.gif"><br><b>図19-5</b>
<p>
 図19-5で、プロパティーを選択します。すると、エディットボックスを選択していたのなら、
図19-6の様に[EDIT プロパティー]ダイアログボックスが表示されます。そして、このダイアログボックスがアクティブな状態にして、[F1]キーを押すと、図19-6の様に、ここの設定項目の説明が現れます。分からないときは、これを参考にするようにしてください。
<p align="CENTER">
<img src="/web/20150425235821im_/http://web.kyoto-inet.or.jp:80/people/ysskondo/from16/img19f.gif"><br><b>図19-6</b>
<p>
 図19-6の様に、親ウインドウとデータのやり取りをするコントロールは、まず、配置したら、IDを入力しましょう。IDとは、WM_COMMANDメッセージの付加情報のwID=LOWPRD(wparam)となる値のことです。IDは、分かりやすいシンボリックな物にするように心がけましょう。実際の値は考える必要はありません。
<p align="CENTER">
<img src="/web/20150425235821im_/http://web.kyoto-inet.or.jp:80/people/ysskondo/from16/img19g.gif"><br><b>図19-7</b>
<p>
 さて、コントロールが作成される順序は極めて重要です。なぜならば、それは、TABキー(SHIFT-TABで逆の動きも可)でフォーカスの移動をするときの順序でもありますし、[←][→][↑][↓]キーでフォーカスを移動できるグループの定義にも関係があるからです。
<p>
 そこで、メニュー[レイアウト]→[タブオーダー]で図19-7の画面の様になります。各々のコントロールの左上に表示されている数字は、コントロールが作成される順序です。この画面で、コントロールをマウスの左ボタンで選択することにより、その作成順序を変更できます。
<p>
 そして、コントロールが作成される順序を決定した後、図19-6の画面の様に、TABキーでフォーカスを循環させたいコントロールにはタブストップチェックボックスをONにし、グループの先頭にさせたいコントロールにはグループチェックボックスをオンにすればいいのです。
<p>
 ダイアログボックスの動作の確認は、メニュー[レイアウト]→[テスト]で行えます。必ず、行いましょう。
<p>
 この様にしてビジュアルツールで画面を作ると、リスト19-1の様なダイアログテンプレートが出来るのです。まぁ、ダイアログテンプレートは、自動生成されるが、どのような物が出来たかテキストエディタで確認して置く事も大切でしょう。
<hr>
<p>
<b>・ダイアログボックスプロシージャ</b>
<p>
 ダイアログプロシージャは、ウインドウプロシージャの様に、ダイアログボックスの動きを定義する関数です。その型は、ヘッダファイルWINUSER.Hで以下のように定義されています。
<p align="CENTER">
<table border="1" bgcolor="#F0F0F0">
<tr><td>
<pre>
typedef BOOL (CALLBACK* DLGPROC)(HWND, UINT, WPARAM, LPARAM);
</pre>
</table>
<p>
 戻り値の型がBOOL以外は、ウインドウプロシージャと同じです。しかし、その実装の仕方は、ウインドウプロシージャと異なります。また、<b><i><u>同じダイアログボックスでも、モーダルダイアログボックスとモードレスダイアログボックスでは異なります</u></i></b>。今回は、モーダルダイアログボックスがテーマですので、モーダルダイアログボックスのダイアログプロシージャのスケルトンを提示しましょう。
<p align="CENTER">
<table border="1" bgcolor="#F0F0F0">
<tr><td>
<pre>
BOOL CALLBACK ModalDialogBoxProc(HWND hwnd,UINT msg,WPARAM wparam,LPARAM lparam)
{
  switch(msg)
   {
       case    <b>WM_INITDIALOG</b>:
           /*  初期化処理  */
           return  TRUE;
       case    WM_COMMAND:
           switch(LOWORD(wparam))
           {
               case    IDOK:
                   /*  終了処理1  */
                   <b>EndDialog(hwnd,IDOK)</b>;
                   <b>return  TRUE</b>;
               case    IDCANCEL:
                   /*  終了処理2  */
                   <b>EndDialog(hwnd,IDCANCEL)</b>;
                   <b>return  TRUE</b>;
           }
   }
   <b>return  FALSE</b>;
}
</pre>
</table>
<p>
 ダイアログプロシージャは、<b><i><u>WM_INITDIALOGメッセージに対する応答を除き、メッセージを処理したらTRUEを返し、そうでなければFALSEを返します</u></i></b>。
<p>
 WM_INITDIALOGメッセージは、プログラマにダイアログボックスを初期化するタイミングを与えてくれます。この時、最初にフォーカスを持つコントロールを自前で<b><i><u>SetFocus関数</u></i></b>を用いて設定した場合はFALSEを返します。そうでなく、Windowsにお任せする場合は、TRUEを返します。リスト19-3の場合、自前でコントロールにフォーカスを与えていますので、FALSEを返しています。
<p>
 さてモーダルダイアログボックスにおいて、一般に、[OK]ボタンのコントロールIDはIDOK、[キャンセル]ボタンのコントロールIDはIDCANCELと決まっています。これらのボタンが押された場合は、必ず、<b><i><u>EndDialog関数</u></i></b>でモーダルダイアログボックスを閉じなければいけません。EndDialog関数は二つの引数を取ります。第一引数は、破壊するダイアログボックスのウインドウハンドル。第二引数は、後で説明する、<b><i><u>DialogBoxParam関数</u></i></b>の戻り値となる値です。
<p>
 今回は、もう1つモーダルダイアログボックスを閉じる術が与えられています。つまり、タイトルバーの[×]ボタンですね。これを押した場合、基本的に、[キャンセル]ボタンを押した場合と同じです。しかし、相違点もあります。[×]ボタンが押された場合、まず、ダイアログプロシージャに<b><i><u>WM_CLOSEメッセージ</u></i></b>が送られてきます。この時、ダイアログプロシージャがこのメッセージを処理した様にTRUEを返せば、画面は閉じません。つまり、ボタンの押下は無視されます。これに対し、WM_CLOSEに対してFALSEを返せば、あたかもキャンセルボタンが押されたかのようにWM_COMMANDをSENDしてきます。つまり、[×]ボタンの場合は、このままキャンセルとしてダイアログボックスを閉じるか閉じないかの選択する機会が与えられるのです。今回は、WM_CLOSEメッセージにはいっさい応答していませんので、FALSEが返されているのと同等ですね。
<hr>
<p>
<b>・モーダルダイアログボックスを作成する</b>
<p>
 モーダルダイアログボックスを作成する関数の代表的なものは、<b><i><u>DialogBoxParam関数</u></i></b>です。
<p align="CENTER">
<table border="1" bgcolor="#F0F0F0">
<tr><td>
<pre>
int DialogBoxParam(
  HINSTANCE hInstance,    // handle to application instance
   LPCTSTR lpTemplateName, // identifies dialog box template
   HWND hWndParent,        // handle to owner window
   DLGPROC lpDialogFunc,   // pointer to dialog box procedure  
   LPARAM dwInitParam      // initialization value
  );
</pre>
</table>
<p>
 第一引数は、アプリケーションのインスタンスハンドルです。第二引数は、ダイアログボックステンプレートの名前です。実際は、リソースエディタで作成した場合、ダイアログテンプレート名は、整数値なので、MAKEINTRESOURCEマクロで、コンバートする必要があります。第三引数は、親ウインドウのウインドウハンドルです。第四引数は、ダイアログプロシージャのアドレスです。そして、第五引数はLPARAM型の実引数です。これは、WM_INITDIALOGメッセージの付加情報となり、ダイアログボックスの初期化情報をダイアログプロシージャに渡す手段を提供しています。
<p>
 DialogBoxParam関数によく似た物に、<b><i><u>DialogBoxマクロ</u></i></b>と言うのがありますが、これは、DialogBoxParam関数の第五引数を常に0Lとした簡略版です。一般に、DialogBoxマクロの方が、普及している様ですが、この場合、ダイアログプロシージャにグローバル変数で初期化情報を渡すことになります。基本的に1ファイル-1ダイアログプロシージャに徹するなら、DialogBoxマクロは使わない方が良いでしょう。
<p>
 さて、DialogBoxParam関数やDialogBoxマクロの戻り値は、そのダイアログプロシージャがEndDialog関数に渡した値になります。リスト19-4では、[OK]ボタンが押された時のみ、つまり、IDOKが返されたときのみ、画面の再描画を行っています。
<hr>
<p>
 結局、今回は、モーダルダイアログボックスの骨格の作り方だけの説明になってしまいました。本当は、ダイアログボックスの中で用いたエディットコントロールやボタンコントロールの説明もする予定でした。しかし、切りが良いので、これらは次回に回します。
<p>
 では、お楽しみに。
<p align="RIGHT">
1999年12月04日<br>
加筆修正1999年12月04日<br>
修正1999年12月05日<br>
加筆修正1999年12月06日<br>
加筆修正1999年12月08日<br>
<hr>
<p>
<b>・1999年12月05日の修正について</b>
<p>
 すみません、バグを修正する前のソースコードを載せていました。<br>
<p align="RIGHT">
1999年12月05日
<hr>
<p align="RIGHT">
<a href="/web/20150425235821/http://web.kyoto-inet.or.jp:80/people/ysskondo/index.html">目次</a><br>
<a href="chap20.html">次へ</a>
<hr>
<p align="RIGHT">
著作権者:近藤妥

</body>
</html>

  • 最終更新:2018-03-11 05:02:45

このWIKIを編集するにはパスワード入力が必要です

認証パスワード