28章 ウインドウクラスレベルでダイアログボックスをカスタマイズ

<html>

<head>
<meta http-equiv="Content-Type" content="text/html; charset=shift_jis"></meta>
<title>28章 ウインドウクラスレベルでダイアログボックスをカスタマイズ
</title>
</head>

<body bgcolor="WHITE">
<font size="5">28章 ウインドウクラスレベルでダイアログボックスをカスタマイズ
</font>
<hr>
<p>
 今回は、前章の事を踏まえ、23章で作成した簡易スケジューラーを<b><u><i>ウインドウクラスレベル</i></u></b>でカスタマイズしてみようと思います。これにより、前章の理解が深まると思います。
<p align="CENTER"><img src="/web/20160727152936im_/http://web.kyoto-inet.or.jp:80/people/ysskondo/from27/chap28_0.gif"><br>
ダウンロード:<a href="chap28.lzh">ソースファイル</a>・<a href="inst28.lzh">実行ファイル</a>
<hr>
<p>
 さて、ウインドウクラスレベルでダイアログボックスをカスタマイズする事は、ある意味、2章に戻る事に他なりません。つまり、ウインドウプロシージャを定義し、これを含むウインドウクラスを定義し、これとダイアログボックス(ウインドウ)を関連付けるのです。<br>
 大きな違いは、ウインドウクラスが、<b><u><i>DefWindowProc関数</i></u></b>から派生したウインドウプロシージャを持つか、<b><u><i>DefDlgProc関数</i></u></b>から派生したウインドウプロシージャを持つかです。
<p>
 では、ダイアログボックスのウインドウクラスの作成から見てみましょう。
<p>
<table border="1" bgcolor="#F0F0F0">
<caption align="BOTTOM">リスト28-1
<tr><td>
<pre>
/* C言語で始めるWindowsプログラミング */
/* 28章のサンプルプログラム */
/* Programmed by Y.Kondo */
/* 注:TABサイズは4で見てください */

#define STRICT
#include &lt;windows.h&gt;
#include &lt;stdio.h&gt;
#include &lt;stdlib.h&gt;
#include &lt;direct.h&gt;
#include &lt;io.h&gt;
#include "resource.h"
#include "other.h"
#include "delete.h"

/* メインウインドウとなるダイアログボックスのダイアログプロシージャのプロトタイプ宣言 */
extern BOOL CALLBACK MainWindowProc(HWND,UINT,WPARAM,LPARAM);

/* ユーザー定義のダイアログボックスのウインドウプロシージャのプロトタイプ宣言 */
<b>extern LRESULT CALLBACK MyDlgProc(HWND,UINT,WPARAM,LPARAM); </b>

/* このファイルでのグローバル変数 */
HINSTANCE hInst;
<b>char DlgClassName[]="chap28_class";</b>

/* アプリケーションエントリーポイント */
int WINAPI WinMain(HINSTANCE hInstance,
                 HINSTANCE    hPrevInstance,
                  LPSTR        CmdLine,
                  int          CmdShow)
{
  struct      _finddata_t c_file;
   long        hFile;
   char        fullfilename[13];
   /*  ユーザー定義のダイアログボックス用の変数    */
   <b>WNDCLASS    wc;</b>

  /*  インスタンスハンドルをファイル内でグローバルに持つ  */
   hInst=hInstance;

  _mkdir(".\\database");  /*  エラーがあってもとにかく作る    */
   _chdir(".\\database");  /*  カレントディレクトリを変更する  */

  /*  過ぎ去った予定を削除する:ここから  */
   if(-1!=(hFile=_findfirst("20*.txt",&c;_file)))
   {
       char*   filename;   /*  .txtを取ったファイル名  */  
       filename=strtok(c_file.name,".");
       if((c_file.attrib==_A_NORMAL | | c_file.attrib==_A_ARCH) 
           &amp;&amp; strcmp(filename,NowDate1())&lt;0 &amp;&amp; strlen(filename)==8)
       {
           sprintf(fullfilename,"%s.txt",filename);
           unlink(fullfilename);
       }
       while(_findnext(hFile,&c;_file)==0)
       {
           filename=strtok(c_file.name,".");
           if((c_file.attrib==_A_NORMAL | | c_file.attrib==_A_ARCH) 
               &amp;&amp; strcmp(filename,NowDate1())&lt;0 &amp;&amp; strlen(filename)==8)
           {
               sprintf(fullfilename,"%s.txt",filename);
               unlink(fullfilename);
           }
       }
       _findclose(hFile);
   }
   /*  過ぎ去った予定を削除する:ここまで  */
   
   /*  ダイアログボックスのウインドウクラスを定義する:ここから    */
   <b>wc.style        =0;
   wc.lpfnWndProc  =MyDlgProc;
   wc.cbClsExtra   =0;
   wc.cbWndExtra   =DLGWINDOWEXTRA;    /*ダイアログクラスでは必須*/
   wc.hInstance    =hInstance;
   wc.hIcon        =LoadIcon(hInstance,MAKEINTRESOURCE(IDI_ICON1));
   wc.hCursor      =LoadCursor(NULL,IDC_ARROW);
   wc.hbrBackground=(HBRUSH)0;
   wc.lpszMenuName =NULL;
   wc.lpszClassName=DlgClassName;
   RegisterClass(&wc;);</b>
   /*  ダイアログボックスのウインドウクラスを定義する:ここまで    */

  /*  ここでメインウインドウを開ける  */
   DialogBox(hInst,MAKEINTRESOURCE(IDD_DIALOG1),NULL,(DLGPROC)MainWindowProc);

  /*  ダイアログボックスのウインドウクラスの開放  */
   <b>UnregisterClass(DlgClassName,hInstance)</b>;

  _chdir("..\\");         /*  カレントディレクトリを元に戻す  */
   return  0;
}

/* ユーザー定義のダイアログボックスのウインドウプロシージャ */
<b>LRESULT CALLBACK MyDlgProc(HWND hwnd,UINT msg,WPARAM wparam,LPARAM lparam)
{
  if(msg==WM_PAINT)
   {
       HBITMAP     hBitmap;
       HBRUSH      hBrush;
       PAINTSTRUCT ps;
       RECT        rect;
       hBitmap=LoadBitmap(hInst,MAKEINTRESOURCE(IDB_BITMAP1));
       hBrush=CreatePatternBrush(hBitmap);
       GetClientRect(hwnd,&rect;);
       BeginPaint(hwnd,&ps;);
       FillRect(ps.hdc,&rect;,hBrush);
       EndPaint(hwnd,&ps;);
       DeleteObject(hBrush);
       DeleteObject(hBitmap);
       return  0;
   }
   return  <u>DefDlgProc(hwnd,msg,wparam,lparam);</u>
}</b>
</pre>
</table>
<p>
 リスト28-1は、WINMAIN.cからの抜粋で、太文字の箇所が、ユーザー定義のダイアログボックス用のウインドウクラスの定義と登録に関係します。<br>
 基本的には、2章のウインドウクラスの定義と大差ありません。しかし、ダイアログ用のウインドウクラスの定義で、強要される箇所があります。つまり、<b><u><i>WNDCLASS構造体のcbWndExtraメンバ変数にDLGWINDOWEXTRAを指定する必要があるのです</i></u></b>。DLGWINDOWEXTRAは、WINUSER.hで定義されている整数です。<br>
 そして、今回のユーザー定義のダイアログボックスのウインドウプロシージャは、WM_PAINTメッセージにのみ応答して、画面を黒と緑の模様を描画しています。そして、<b><u><i>ウインドウプロシージャが処理しないメッセージは、DefDlgProc関数に渡しています</i></u></b>。
<p>
 さて、2章では、CreateWindow関数、14章ではCreateWindowEx関数で、ウインドウとウインドウクラスを関連付けましたが、<b><u><i>ダイアログボックスにダイアログボックス用のユーザー定義のウインドウクラスを関連付けるには、リソースで関連付けます</i></u></b>。以下、VisualC++のリソースエディタ(IDE)で、ダイアログボックスとダイアログボックス用のユーザー定義のウインドウを関連付ける方法を説明します。
<hr>
<p align="CENTER"><img src="/web/20160727152936im_/http://web.kyoto-inet.or.jp:80/people/ysskondo/from27/chap28_1.gif"><br><b>図28-1</b>
<p>
 簡単に言ってしまうと、図28-1の赤丸の中にダイアログボックス用のクラス名を入れれば終わりです。しかし、VisualC++はMFCを使う事を前提としているので、この箇所がデフォルトで使えないようになっています。
<p align="CENTER"><img src="/web/20160727152936im_/http://web.kyoto-inet.or.jp:80/people/ysskondo/from27/chap28_2.gif"><br><b>図28-2</b>
<p>
 そこで、図28-2の様に、マウスの右ボタンでメニューを出し、プロパティーを選択します。
<p align="CENTER"><img src="/web/20160727152936im_/http://web.kyoto-inet.or.jp:80/people/ysskondo/from27/chap28_3.gif"><br><b>図28-3</b>
<p>
 すると、図28-3の画面になります。
<p align="CENTER"><img src="/web/20160727152936im_/http://web.kyoto-inet.or.jp:80/people/ysskondo/from27/chap28_4.gif"><br><b>図28-4</b>
<p>
 図28-4の様に、[MFCのライブラリの使用]チェックボックスを外します。<br>
 これで、図28-1で使用できなかったエディットコントロールが図28-5の様に使用できるようになります。
<p align="CENTER"><img src="/web/20160727152936im_/http://web.kyoto-inet.or.jp:80/people/ysskondo/from27/chap28_5.gif"><br><b>図28-5</b>
<p align="CENTER"><img src="/web/20160727152936im_/http://web.kyoto-inet.or.jp:80/people/ysskondo/from27/chap28_6.gif"><br><b>図28-6</b>
<p align="CENTER"><img src="/web/20160727152936im_/http://web.kyoto-inet.or.jp:80/people/ysskondo/from27/chap28_7.gif"><br><b>図28-7</b>
<p>
 そして、図28-6、図28-7の様に、ダイアログボックス用のユーザー定義のウインドウクラスのクラス名を入れます。
<hr>
<p>
 以上の操作で、リソースファイルは、以下のように変ります。
<p>
<table border="1" bgcolor="#F0F0F0">
<caption align="BOTTOM">リスト28-2
<tr><td>
<pre>

IDD_DIALOG1 DIALOG DISCARDABLE 0, 0, 275, 203
STYLE DS_MODALFRAME | DS_CENTER | WS_MINIMIZEBOX | WS_CAPTION | WS_SYSMENU
CAPTION "28章サンプル:簡易スケジューラー(フリーソフト)"
<b>CLASS "chap28_class"</b>
FONT 9, "MS Pゴシック"
BEGIN
  COMBOBOX        IDC_COMBO1,7,6,38,189,CBS_DROPDOWNLIST | WS_VSCROLL | 
                   WS_TABSTOP
   COMBOBOX        IDC_COMBO2,57,6,31,189,CBS_DROPDOWNLIST | WS_VSCROLL | 
                   WS_TABSTOP
   COMBOBOX        IDC_COMBO3,100,6,33,189,CBS_DROPDOWNLIST | WS_VSCROLL | 
                   WS_TABSTOP
   EDITTEXT        IDC_EDIT1,7,21,210,175,ES_MULTILINE | ES_AUTOVSCROLL | 
                   ES_WANTRETURN | WS_VSCROLL
   PUSHBUTTON      "登録",IDC_BUTTON1,142,6,50,14
   LISTBOX         IDC_LIST1,220,21,48,160,LBS_SORT | LBS_NOINTEGRALHEIGHT | 
                   WS_VSCROLL | WS_TABSTOP
   PUSHBUTTON      "削除",IDC_BUTTON2,220,182,48,14
   LTEXT           "年",IDC_STATIC,46,11,8,8
   LTEXT           "月",IDC_STATIC,89,11,8,8
   LTEXT           "日",IDC_STATIC,134,11,8,8
   CTEXT           "登録済カレンダー",IDC_STATIC,213,10,55,10
END

IDD_DIALOG2 DIALOG DISCARDABLE 0, 0, 227, 181
STYLE DS_MODALFRAME | WS_POPUP | WS_CAPTION
CAPTION "削除内容確認"
<b>CLASS "chap28_class"</b>
FONT 9, "MS Pゴシック"
BEGIN
  EDITTEXT        IDC_EDIT1,7,7,213,148,ES_MULTILINE | ES_AUTOVSCROLL | 
                   ES_READONLY | ES_WANTRETURN | WS_VSCROLL | NOT 
                   WS_TABSTOP
   DEFPUSHBUTTON   "OK",IDOK,118,160,50,14
   PUSHBUTTON      "キャンセル",IDCANCEL,170,160,50,14
END


</pre>
</table>
<p>
 リスト28-2は、chap28.rcからの抜粋で、太文字部分に注目してください。
<hr>
<p>
 さて、どうだったでしょうか?<br>
 今回のような事は、ダイアログプロシージャレベルでも可能です。特に、ダイアログボックスが2つしかないアプリケーションではありがたみを感じないでしょう。<br>
 しかし、ダイアログボックスが多くあるアプリケーションで、ウインドウクラスという型レベルで統一すると、コーディング量が減り強力です。
<hr>
<p>
 ウインドウの制御の流れを中心に、ここまで講座を行ってきました。<br>
 まだ、ウインドウのサブクラス化、マルチプル・ドキュメント・インターフェース(MDI)などの課題を残していますが、次章からは、メニューとキーボードアクセラレータの説明に入ります
<p>
 では、お楽しみに。
<br>
<p align="RIGHT">
2002年8月10日<br>
<hr>
<p align="RIGHT">
<a href="/web/20160727152936/http://web.kyoto-inet.or.jp:80/people/ysskondo/index.html">目次</a><br>
<hr>
<p align="RIGHT">
著作権者:近藤妥
</body>
</html>

  • 最終更新:2018-03-11 05:24:14

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

認証パスワード