なぜかWM_CREATEが届かない・・・

[戻る]
ねこまんじゅう 2006/03/28(火) 13:05:18
WinXP VisualStudio 2005 Win32

はじめて質問させて頂きます。
初心者ですが、よろしくお願いいたします。

1.
下のスケルトンプログラムにて、プロシージャ内でcase WM_CREATEがあります。
私はWM_CREATEは「ウインドウが作成されたときに送られてくる」と思っています。
下記のプログラムを実行すればウインドウが表示されますが、
case WM_CREATE: の中にMessageBox(NULL,"OK", "タイトル", MB_OK); というように
書いても、メッセージボックスが表示されません。
これはつまり、WM_CREATEが送られてきていないということですよね。
なぜ送られてこないのか、わかりません・・・。

2.
そもそも、"ウインドウ"と"ダイアログ"の違いがよくわかりません。
このスケルトンプログラムは、"ダイアログ"を表示していますが、
"ウインドウ"が表示されたときに送られてくるWM_CREATEを使用しているのが、謎です。
"ダイアログ"を表示しているわけだから、WM_INITDIALOGを使用するはずだと思い、
WM_CREATEをWM_INITDIALOGに書き換えると、コンパイルは通りますが、実行すると強制終
了します。


よろしくお願いいたします・・・・



#include "windows.h"
#include "resource.h"

HWND hDlgWnd;
static TCHAR szAppName[] = TEXT ("Dialog1") ;

LRESULT CALLBACK MainDlgProc(HWND, UINT, WPARAM, LPARAM);

int APIENTRY WinMain (HINSTANCE hInstance,
              HINSTANCE hPrevInstance,
              PSTR szCmdLine,
              int nCmdShow)
{

    MSG msg ;

    WNDCLASS wndclass ;

    wndclass.style         = 0;
    wndclass.lpfnWndProc   = MainDlgProc;
    wndclass.cbClsExtra    = 0;
    wndclass.cbWndExtra    = DLGWINDOWEXTRA;
    wndclass.hInstance     = hInstance;
    wndclass.hIcon         = LoadIcon (hInstance, szAppName);
    wndclass.hCursor       = LoadCursor (NULL, IDC_ARROW);
    wndclass.hbrBackground = (HBRUSH) GetStockObject (WHITE_BRUSH);
    wndclass.lpszMenuName  = NULL;
    wndclass.lpszClassName = szAppName;

    if (!RegisterClass (&wndclass))
    {
        MessageBox (NULL,
            TEXT ("ウインドウクラスを登録できませんでした。"),
            szAppName,
            MB_ICONERROR);
        return 0;
    }

    //メインウインドウの生成
    if((hDlgWnd=CreateDialog(hInstance,
            MAKEINTRESOURCE(IDD_DIALOG1),
            0,
            (DLGPROC)MainDlgProc)) == NULL) {
        MessageBox(NULL,
        "メインウインドウを作成できませんでした。",
        szAppName,
        MB_APPLMODAL | MB_ICONSTOP);
        return FALSE;
    }

    ShowWindow (hDlgWnd, nCmdShow);
    UpdateWindow (hDlgWnd); 

    while (GetMessage (&msg, NULL, 0, 0)) {
        if(IsDialogMessage(hDlgWnd,&msg) == FALSE) {
            TranslateMessage (&msg);
            DispatchMessage (&msg);
        }
    }

    return (int)msg.wParam;
}



LRESULT CALLBACK MainDlgProc (HWND hWnd,
         UINT message,
        WPARAM wParam,
        LPARAM lParam) 
{
    static HINSTANCE hInstance;

    switch (message) {
        case WM_CREATE :
            hInstance = ((LPCREATESTRUCT) lParam)->hInstance;
            return TRUE;
          
        case WM_COMMAND :
          switch (LOWORD (wParam)) {
            case IDOK :
                MessageBox(NULL,"OK", "実行", MB_OK); 
                break;
            case IDCANCEL :
                DestroyWindow(hWnd);
                break;
          }
          return TRUE;
          
        //[X]ボタン
        case WM_CLOSE:
            PostMessage(hWnd,WM_COMMAND,IDCANCEL,0);
            return TRUE;

        case WM_DESTROY :
            PostQuitMessage (0);
            return TRUE;
        }
    return FALSE;
}

Kerry 2006/03/28(火) 13:40:22
1.
ダイアログボックスの場合、メッセージはWindows内部のプロシージャで
処理されてから、ダイアログプロシージャに渡されます。
WM_CREATEメッセージは内部のプロシージャで処理されてしまって、
ダイアログプロシージャには渡されないようになっています。
そのため、ダイアログには初期化のためのWM_INITDIALOGメッセージが用意
されています。

それから、ダイアログプロシージャの戻り値がLRESULT型になっていますが、
正しくはBOOL型です。

また、このコードではウィンドウクラスを登録していますが、ダイアログ
ボックスの場合は通常定義済みのダイアログボックスクラスを使用するので
不要です。(カスタムダイアログクラスを作成するのであれば別ですが)

2.
WM_CREATEメッセージとWM_INITDIALOGメッセージでは、WPARAM・LPARAM
パラメータの解釈が異なります。
WM_INITDIALOGメッセージに対して、LPARAMをLPCREATESTRUCT型にキャスト
して使っているのでおかしくなります。
詳細はヘルプを参照してください。

インスタンスハンドルが必要ならば、グローバル変数で保持するか、
以下のようにして取得してください。

  hInstance = (HINSTANCE)GetWindowLong(hWnd, GWL_HINSTANCE);

Ban 2006/03/28(火) 13:49:49
ちなみに、CreateDialog で作成するのは「モードレスダイアログ」です。
一般的な、いわゆるダイアログは「モーダルダイアログ」ですので、
区別して考えると分かりやすいかと思います。

PATIO 2006/03/28(火) 13:49:54
蛇足ですが、

各メッセージに関してはMSDNできちんと調べてから使用する様にした方がいいです。
メッセージによって各パラメータの解釈は違ってくるのでうろ覚えで使わずに
確認する習慣をつけたほうがいいです。

ねこまんじゅう 2006/03/28(火) 15:01:54
[[解決]]
Kerryさま Banさま PATIOさま
とても丁寧なご説明、アドバイス、どうもありがとうございました。
なるほど・・・ という感じです。
これからもっと勉強したいと思います。

ここはやさしい方が多くて、いいところですね。

古いスレッドには追加発言できません。