25章 VisualBASIC感覚でSDKプログラミング(その3)

<html>

<head>
<meta http-equiv="Content-Type" content="text/html; charset=shift_jis"></meta>
<title>25章 VisualBASIC感覚でSDKプログラミング(その3)</title>
</head>

<body bgcolor="WHITE">
<font size="5">25章 VisualBASIC感覚でSDKプログラミング(その3)</font>
<hr>
<p align="CENTER">
<p>
 今回から、23章で紹介した簡易スケジューラーの細部に渡って説明していきます。<br>
 まずは、メインウインドウを開ける前の処理から入ります。
<hr>
<p>
<b>
・WinMain
</b>
<p>
<table border="1" bgcolor="#F0F0F0">
<caption align="BOTTOM">リスト25-1
<tr><td>
<pre>
int WINAPI WinMain(HINSTANCE hInstance,
                 HINSTANCE    hPrevInstance,
                  LPSTR        CmdLine,
                  int          CmdShow)
{
  struct  _finddata_t c_file;
   long    hFile;
   char    fullfilename[13];

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

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

  /*  過ぎ去った予定を削除する:ここから  */
   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><u><i>DialogBox(hInst,MAKEINTRESOURCE(IDD_DIALOG1),NULL,(DLGPROC)MainWindowProc);</i></u></b>

  <b>_chdir("..\\");</b>         /*  カレントディレクトリを元に戻す  */
   return  0;
}
</pre>
</table>
<p>
 今回の簡易スケジューラーのからくりは、<b>カレントディレクトリにdatabaseというディレクトリを作成し、この中に、yyyymmdd.txt形式のファイルを作成し、これにテキスト形式でデータを格納するものです</b>。<br>
 それゆえ、まずは、最初の起動の時に、databaseというフォルダを作成し、ここにカレントディレクトリを移動しています。<br>
 2回目以降の起動では、すでにdatabaseディレクトリはあるのでエラーを返すのですが、当然のエラーなので無視しています。<br>
 また、過ぎ去ったデータは、物理的に削除しています。<br>
 この後に、<b><i><u>モーダルダイアログボックスをメインウインドウとして開けています。</u></i></b>親ウインドウが無いので第三引数にNULLを渡しているのに注意してください。<br>
 最後の終了処理は、カレントディレクトリを元に戻し、制御をOSに戻しています。<br>
<hr>
<p>
 さて、ダイアログボックスを開けるには、ダイアログボックスプロシージャが必要です。<br>

 ダイアログボックスプロシージャの最初の箇所を見てみましょう。<br>
<p>
<table border="1" bgcolor="#F0F0F0">
<caption align="BOTTOM">リスト25-2
<tr><td>
<pre>
BOOL CALLBACK MainWindowProc(HWND hwnd,UINT msg,WPARAM wparam,LPARAM lparam)
{
  switch(msg)
   {
       /*  ダイアログボックス初期化    */
       case    WM_INITDIALOG:
           return  Wm_InitDialogProc(hwnd);
       /*  コントロールに応答          */
       case    WM_COMMAND:
           return  Wm_CommandProc(hwnd,HIWORD(wparam),LOWORD(wparam),(HWND)lparam);
       /*  終了ボタンに対応    */
       case    WM_CLOSE:
           Wm_CloseProc(hwnd);
           return  TRUE;
   }
   return  FALSE;
}
</pre>
</table>
<p>
 さすがに、この箇所は、VisualBASIC感覚でSDKプログラミングでも隠せませんね。<br>
 しかし、応答しているメッセージは、たった3つですので、苦にならないでしょう。<br>
 16章・17章で紹介したコントロールは、ここでイベントが発生した場合、スクロール系を除いて、全てWM_COMMANDをメッセージとして送ります。このため、コントロールの数が増えたりすると、WM_COMMANDを処理する関数に負荷がかかります。それゆえ、<b>今回は、初期化処理と終了処理のみ説明しましょう</b>。
<hr>
<p>
<b>
・WM_INITDIALOGメッセージの処理
</b>
<p>
<table border="1" bgcolor="#F0F0F0">
<caption align="BOTTOM">リスト25-3
<tr><td>
<pre>
/* メインウインドウとなるダイアログボックスの初期化 */
static BOOL Wm_InitDialogProc(HWND hwnd)
{
  int     year;
   int     month;
   int     day;
   char    buf[5];
   struct  _finddata_t c_file;
   long    hFile;

  /*  コンボボックスに候補を入れる:ここから  */  
   for(year=2002;year&lt;=2030;year++)
   {
       sprintf(buf,"%04d",year);
       <b>SendDlgItemMessage(hwnd,IDC_COMBO1,CB_ADDSTRING,0,(LPARAM)buf);</b>
   }
   for(month=1;month&lt;=12;month++)
   {
       sprintf(buf,"%02d",month);
       <b>SendDlgItemMessage(hwnd,IDC_COMBO2,CB_ADDSTRING,0,(LPARAM)buf);</b>
   }
   for(day=1;day&lt;=31;day++)
   {
       sprintf(buf,"%02d",day);
       <b>SendDlgItemMessage(hwnd,IDC_COMBO3,CB_ADDSTRING,0,(LPARAM)buf);</b>
   }
   /*  コンボボックスに候補を入れる:ここまで  */

  /*  リストボックスに登録されている日付を入れる:ここから    */
   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())&gt;=0 &amp;&amp; strlen(filename)==8)
           <b>SendDlgItemMessage(hwnd,IDC_LIST1,LB_ADDSTRING,0,
               (LPARAM)ForListBoxDateType(filename));</b>
       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())&gt;=0 &amp;&amp; strlen(filename)==8)
               <b>SendDlgItemMessage(hwnd,IDC_LIST1,LB_ADDSTRING,0,
                   (LPARAM)ForListBoxDateType(filename));</b>
       }
       _findclose(hFile);
   }
   /*  リストボックスに登録されている日付を入れる:ここまで    */          

  /*  今日の予定があれば、メッセージボックスで警告する:ここから  */
   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())==0 &amp;&amp; strlen(filename)==8)
       {
           MessageBox(hwnd,"今日は予定が入っています!","注意",MB_OK|MB_ICONINFORMATION);
           /*  先頭(今日)の予定を選択する    */
           <b>SendDlgItemMessage(hwnd,IDC_LIST1,LB_SETCURSEL,0,0);</b>
       }
       _findclose(hFile);
   }
   return  FALSE;
}
</pre>
</table>
<p>
 この章で初めて登場するAPIは<b><i><u>SendDlgMessage関数</u></i></b>ですね。この関数一つで、コントロールを制御しています。<br>
 この関数はマニュアルによると、
<p align="CENTER">
<table border="1" bgcolor="#F0F0F0">
<tr><td>
<pre>
LONG SendDlgItemMessage( HWND hDlg, // handle of dialog box
                      int nIDDlgItem,  // identifier of control
                       UINT Msg,       // message to send
                       WPARAM wParam,  // first message parameter
                       LPARAM lParam   // second message parameter
                       ); </pre>
</table>
<p>
 で、第一引数はダイアログボックスのハンドル、第二引数はコントロールの識別子、第三引数はコントロールに送るメッセージ、第四・第五引数はメッセージによって付ける32ビットの付加情報です。
<p>
<table border="1" bgcolor="#F0F0F0">
<caption align="BOTTOM">リスト25-4(chap23.rcより抜粋)
<tr><td>
<pre>

IDD_DIALOG1 DIALOG DISCARDABLE 0, 0, 275, 203
STYLE DS_MODALFRAME | DS_CENTER | WS_MINIMIZEBOX | WS_CAPTION | WS_SYSMENU
CAPTION "23章サンプル:簡易スケジューラー(フリーソフト)"
FONT 9, "MS Pゴシック"
BEGIN
  COMBOBOX        <b>IDC_COMBO1</b>,7,6,38,189,CBS_DROPDOWNLIST | WS_VSCROLL | 
                   WS_TABSTOP
   COMBOBOX        <b>IDC_COMBO2</b>,57,6,31,189,CBS_DROPDOWNLIST | WS_VSCROLL | 
                   WS_TABSTOP
   COMBOBOX        <b>IDC_COMBO3</b>,100,6,33,189,CBS_DROPDOWNLIST | WS_VSCROLL | 
                   WS_TABSTOP
   EDITTEXT        <b>IDC_EDIT1</b>,7,21,210,175,ES_MULTILINE | ES_AUTOVSCROLL | 
                   ES_WANTRETURN | WS_VSCROLL
   PUSHBUTTON      "登録",<b>IDC_BUTTON1</b>,142,6,50,14
   LISTBOX         <b>IDC_LIST1</b>,220,21,48,160,LBS_SORT | LBS_NOINTEGRALHEIGHT | 
                   WS_VSCROLL | WS_TABSTOP
   PUSHBUTTON      "削除",<b>IDC_BUTTON2</b>,220,182,48,14
   LTEXT           "年",<b>IDC_STATIC</b>,46,11,8,8
   LTEXT           "月",<b>IDC_STATIC</b>,89,11,8,8
   LTEXT           "日",<b>IDC_STATIC</b>,134,11,8,8
   CTEXT           "登録済カレンダー",<b>IDC_STATIC</b>,213,10,55,10
END
</pre>
</table>
<p>
 コントロールの識別子と言うのは、リスト25-4の太い文字の箇所です。
<p>
 さて、リスト25-3では何をしているか?<br>
 予定日を選択する3つのコンボボックスに候補を入れています。この時、<b>CB_ADDSTRING</b>メッセージを使っています。次に、カレントディレクトリの中で該当するファイルを探索し、yyyy/mm/ddの形式にファイル名を変更し、<b>LB_ADDSTRING</b>メッセージを用い、右横の予約済みカレンダーとなるリストボックスに入れています。<br>
 最後に、今日、該当する項目があれば、メッセージウインドウを出し、リストボックスの先頭を選択し、内容の確認を促しています。
<hr>
<p>
<b>
・WM_CLOSEメッセージの処理
</b>
<p>
<table border="1" bgcolor="#F0F0F0">
<caption align="BOTTOM">リスト25-5
<tr><td>
<pre>
/* アプリケーションを閉じるときの確認の関数 */
static BOOL Wm_CloseProc(HWND hwnd)
{
  if(MessageBox(hwnd,"簡易スケジューラーを終了しますか?","警告",MB_YESNO|MB_ICONEXCLAMATION)==IDYES)
       EndDialog(hwnd,IDOK);
   return  TRUE;
}
</pre>
</table>
<p>
 簡単ですね。<br>
 MessageBox関数で簡易スケジューラーの終了確認をしているだけです。<br>
 終了するときは、モーダルダイアログボックスですので<b><u><i>EndDialog関数</i></u></b>を用います。
<hr>
<p>
 次章では、本命であるWM_COMMANDメッセージに対する応答について説明します。<br>
 では、お楽しみに。
<br>
<p align="RIGHT">
2002年7月2日<br>
修正2002年7月17日<br>
<hr>
<p align="RIGHT">
<a href="/web/20160505174402/http://web.kyoto-inet.or.jp:80/people/ysskondo/index.html">目次</a><br>
<a href="chap26.html">次へ</a>
<hr>
<p align="RIGHT">
著作権者:近藤妥

</body>
</html>

  • 最終更新:2018-03-11 05:21:50

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

認証パスワード