SDKおしえて 「DialogBox」が失敗する

[戻る]
wood 2003/12/03(水) 07:08:16
SDKやらなくっちゃいけなくなって、猫さんの以下のページ参考(ほとんどコピペ)
ではじめたんですけど、周りに聞く人がいないので助言お願いします。
http://www.kumei.ne.jp/c_lang/sdk/sdk_13.htm

環 境      :VC++6.0(SP5)
O S      :XP Pro(WinUpdateはすべて適用)
プロジェクトタイプ:Win32 Application

質問に関係ありそうな部分のソース
------------------------------------------------------------------
#include    "stdafx.h"

プロトタイプ宣言  略

int APIENTRY WinMain(HINSTANCE hInstance,
                     HINSTANCE hPrevInst,
                     LPSTR     lpCmdLine,
                     int       nCmdShow )
{
  // TODO: この位置にコードを記述してください。
  MSG msg;
  char szClassName[] = "W32CHG";        //ウィンドウクラス
    hInst1 = hInstance;
    
    if (!hPrevInst) {
        if (!InitApp(hInstance, szClassName))
            return FALSE;
    }
    if (!InitInstance(hInstance, szClassName, nCmdShow)) {
        return FALSE;
    }
    while (GetMessage(&msg, NULL, 0, 0)) {
        TranslateMessage(&msg);
        DispatchMessage(&msg);
    }
    return msg.wParam;
}

//ウィンドウ・クラスの登録

BOOL InitApp(HINSTANCE hInst, LPCSTR szClassName)
{
    WNDCLASS wc;
    wc.style = CS_HREDRAW | CS_VREDRAW;
    wc.lpfnWndProc = WndProc;    //プロシージャ名
    wc.cbClsExtra = 0;
    wc.cbWndExtra = 0;
    wc.hInstance = hInst;        //インスタンス
    wc.hIcon = LoadIcon(NULL, IDI_APPLICATION);
    wc.hCursor = LoadCursor(NULL, IDC_ARROW);
    wc.hbrBackground = (HBRUSH)GetStockObject(WHITE_BRUSH);
    wc.lpszMenuName = NULL/*"TIMERMENU"*/;    //メニュー名
    wc.lpszClassName = (LPCSTR)szClassName;
    return (RegisterClass(&wc));
}
BOOL InitInstance(HINSTANCE hInst, LPCSTR szClassName, int nCmdShow)
{
  略
}
LRESULT CALLBACK WndProc(HWND hWnd, UINT msg, WPARAM wp, LPARAM lp)
{
    int id;
  id = DialogBox(hInst1, "IDD_FORMVIEW", hWnd, (DLGPROC)MyDlgProc);
  if (id == IDOK) {}   ←ブレークポイント1
     ・
     ・
  以下 略
}
LRESULT CALLBACK MyDlgProc(HWND hDlgWnd, UINT msg, WPARAM wp, LPARAM lp)
{
    switch (msg) {  ←ブレークポイント2
     ・
     ・
  以下 略
}


リソース(VC++ リソースエディタで作成したものを、
     STYLE DS_MODALFRAME部分だけ秀丸で手修正しています) 
##########################
     ・
     ・
     略

IDD_FORMVIEW DIALOG DISCARDABLE  0, 0, 215, 124
STYLE DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU
FONT 9, "MS Pゴシック"
     ・
     ・
  以下 略
##########################

-------------------------------------------------------------------------

本題
「ブレークポイント1」で「DialogBox」が失敗を告げる「−1」を返してきます
何がエラーのため失敗しているのか
調べ方がわかりません、どうやったら調べることができるでしょうか
エラー詳細コードが入っている変数などはないのでしょうか

デバック実行では「ブレークポイント2」には到達していないようです

MSDNの解説では
>戻り値
>関数が成功すると、ダイアログボックスの終了時に使われた EndDialog 関数の
>nResult パラメータの値が返ります。
>関数が失敗すると、-1 が返ります。
としか書いてませんでした

また、「CALLBACK MyDlgProc」の「UINT msg」は「36」でした
「36」の意味するものは何か教えてください
たぶん「WM_?????」なんでしょうけどVCからWINDOWS.Hを開いても
「36」の意味するものを見つけることができませんでした

質問2つになってますが、よろしくお願いします

επιστημη [E-Mail] [HomePage] 2003/12/03(水) 08:43:51
> たぶん「WM_?????」なんでしょうけどVCからWINDOWS.Hを開いても
> 「36」の意味するものを見つけることができませんでした

#define WM_GETMINMAXINFO                0x0024

コレかしら…

774RR 2003/12/03(水) 08:56:15
WndProc() 内で switch(msg) もなく DialogBox() してるのですか?変。
エラーが起こったら GetLastError() でしょう。
36 は10進ですか? 36=0x24 なら WM_GETMINMAXINFO です。

SunPac 2003/12/03(水) 10:04:47
WndProcは必要な物(メッセージ)のみを処理して、それ以外の物はDefWindowProcを処理
してその戻り値を返さねばなりません。

一般のウィンドウ関数
LRESULT CALLBACK WindowProc(HWND hwnd, UINT mes, WPARAM wp, LPARAM lp)
{
    switch(mes){
    case WM_****:
         何かしらの処理
     break;
    default:
         return DefWindowProc(hwnd, mes, wp, lp);
    }

    return 0;
}

ちなみにメッセージループは実はそのままでは危険でして、その点は猫さんのHPに
書いてあったはずです。(GetMessage()は-1を返す事があるらしいのです)

masaki 2003/12/03(水) 10:27:31
ダイアログボックスを表示するだけのシンプルなコードからスクラッチ
してみてはどうでしょう。
動作確認:VC++6SP5 Win2000SP3
ダイアログボックスリソースは別途VisualStudio上で作成してください。
-----

#include <windows.h>
#include "resource.h"

int WINAPI
DialogProc( HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam ) {
    switch( uMsg ) {
        /*case WM_INITDIALOG:
        return TRUE;*/

        default:
        return DefWindowProc( hwndDlg, uMsg, wParam, lParam );
        }
    }

int WINAPI
WinMain( HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int
nShowCmd ) {
    DialogBox(
        hInstance,
        MAKEINTRESOURCE( IDD_DIALOG1 ),
        NULL,
        DialogProc );

    return 0;
    }

ku 2003/12/03(水) 13:09:00
プロジェクトを作るときは(VC6なら)新規作成のプロジェクトで
「Win32 Application」で「標準的な"Hello World!"アプリケーション」を選ぶと
最初のウィンドウ(+Aboutダイアログ)を出すところまでは楽にいけます

1.ダイアログしか表示しないなら、メッセージループを作らずに
int APIENTRY WinMain(...)
{
    DialogBox( , , GetDesktopWindow(), );
    return ?;
}
のようにやってみる

2.メインウィンドウがあるなら、最初に書いた方法でできたスケルトンに
Aboutダイアログがあるので、それをまねる

wood 2003/12/04(木) 03:29:49
επιστημηさん、774RRさん 回答ありがとうございました
>WM_GETMINMAXINFO
をキーワードにGREP検索したら「WINUSER.H」に記述されているのを見つけることができ
ました

>WndProc() 内で switch(msg) もなく DialogBox() してるのですか?変。
なぜ?やはり特定のWM メッセージじゃないと処理しちゃいけない関数なんですね
その種類と解説はMSDNの何を見ればわかりますでしょうか
DialogBoxの解説には、やっちゃいけないまたは、このメッセージIDの時以外処理を
してはいけないなんて書いてませんでしたよ

SunPacさん、ありがとうございます
実は
LRESULT CALLBACK WndProc(HWND hWnd, UINT msg, WPARAM wp, LPARAM lp)
{
    int id;
  id = DialogBox(hInst1, "IDD_FORMVIEW", hWnd, (DLGPROC)MyDlgProc);
  if (id == IDOK) {}   ←ブレークポイント1


              ここから略していた部分
  switch (msg) {
        case WM_INITDIALOG:
            SetWinCenter(hWnd);
            return TRUE;
        case WM_CLOSE:
            id = MessageBox(hWnd,
                (LPCSTR)"終了してもよいですか",
                (LPCSTR)"終了確認",
                MB_YESNO | MB_ICONQUESTION);
            if (id == IDYES) {
                DestroyWindow(hWnd);
            }
            break;
        case WM_DESTROY:
            PostQuitMessage(0);
            break;
        default:
            return FALSE; ←修正箇所ミスっていて、いきなり終わってました

    }
ダイアログ出ないけど、タスクバーに表示されるようになった
右クリック→閉じる→WM_CLOSEの処理されている
くらいまではできるようになりました

ちょっと前までは、タスクマネージャにアプリケーションと認めてもらえず
ただのプロセスにしかなってませんでした
何か動いていたけどタスクマネージャ以外終了方法がない状態でした



masaki さん ありがとうございます
たぶん自分が思い描いていること、そのままのような気がします
CreateWindowや、ShowWindow(hWnd, SW_SHOW);UpdateWindow(hWnd);DrawMenuBar(hWnd);
を気にせづダイアログボックス表示して
ボタン押されたらとかが処理可能なんですよね
早速試して見ます、後日報告します

kuさん ありがとうございます
プロジェクト作り直して見ます、後日報告します

でも「masaki さん」・「kuさん」 最初に提示したソースで何とかしたいと
思ってるんですけど、
やはり無理なのであきらめたほうがいいのでしょうか?

masaki 2003/12/04(木) 08:34:39
woodさんのコードを動くようにするというのは、かわりにデバッグする
ということなので、私はそういうことはしていません。

なのでいつもは問題点の指摘はしないのですが、ふと気づいたので。

id = DialogBox(hInst1, "IDD_FORMVIEW", hWnd, (DLGPROC)MyDlgProc);

を

id = DialogBox(hInst1, MAKEINTRESOURCE(IDD_FORMVIEW), hWnd, (DLGPROC)MyDlgProc);
                       ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
としたら動かないでしょうか?
また、GetLastError()を使ってエラーの内容がわかるかもしれません。

774RR 2003/12/04(木) 08:42:19
そりゃいついかなるときでも DialogBox() してかまわんでしょう。
メッセージ1つにつき1つ Dialog 出てよいなら。
WM_MOUSEMOVE の度に Dialog 出てよいのですね。
そのたびに WindowProc() は走らなくなりますなw
猫さんとこでもそんなことはしてないでしょ。

ku 2003/12/04(木) 13:09:18
ダイアログ(DialogBox等のモーダルダイアログ系のAPIで作成したウィンドウ)の場合は
メッセージループはいらないのですが
通常のウィンドウ(CreateWindow等のAPIで作成したウィンドウ)の場合はメッセージループが
必要となります
ですからダイアログだけを表示する場合はメッセージループがいりません

> なぜ?やはり特定のWM メッセージじゃないと処理しちゃいけない関数なんですね
> その種類と解説はMSDNの何を見ればわかりますでしょうか
論理的に考えるしかないかと思います
タイミングが限定できない、何度も呼ばれる可能性がある
などのメッセージはとりあえずはさけた方が良いかもしれません
(必要なときはやってよいと思いますが)
> DialogBoxの解説には、やっちゃいけないまたは、このメッセージIDの時以外処理を
> してはいけないなんて書いてませんでしたよ
現在、WndProc()にどんなメッセージがきてもDialogBox()を呼んでしまうのが問題です
呼んではいけないメッセージというのは無いのかもしれませんが
たとえばWndProc()にWM_PAINTのような描画時にくるメッセージでDialogBox()を呼ぶと
再描画時に毎回DialogBox()を呼んでしまいますので、
実際に処理できるメッセージというのは限定されてくると思います

> 最初に提示したソースで何とかしたいと
> 思ってるんですけど、
> やはり無理なのであきらめたほうがいいのでしょうか?
ウィンドウプロシージャ(WndProc)でmsgによって分岐する手前で
DialogBoxのような関数は使わない方が良いと思います
無理でないのかもしれませんが、やらない方が良いでしょう

おまけですがWndProc()はCreateWindow()で作成されているのでしょうから
WM_INITDIALOGメッセージがくることはないと思います
それに近い、または似たような処理を書けるメッセージはWM_CREATEです
MyDlgProc()はDialogBox()で作成されているので
WM_INITDIALOGメッセージがくるはずです。WndProc()とは逆にWM_CREATEはきません

ひろぴー 2003/12/04(木) 16:54:30
『なぜDialogBoxが失敗するのか?』
についてはmasakiさんが仰るように『MAKEINTRESOURCE』を使えばよいと思います。

皆さんご指摘の『呼び出す場所がおかしい』についてですが、もしかして、ダイアログベースの
アプリケーションを作成したいのでしょうか?

上記を前提とした場合、見ている章が間違っています。
http://www.kumei.ne.jp/c_lang/sdk/sdk_22.htm
こちらではないかと...。

違う場合は
http://www.kumei.ne.jp/c_lang/sdk/sdk_13.htm
にある通りに、『表示するべきタイミング』で呼び出せばOKです。

終了するまでダイアログがひっきりなしに出るアプリを作成したいのでしたら、皆さん(私も含
む)の心配は必要ないですが。

モーダルダイアログだからOKを押すまで次のダイアログが出ないと思ってないですか?
仮にダイアログの表示に成功した場合、このアプリを『正当な方法』で終了させるのは至難の業
かと思います。(てか不可能?)

wood 2003/12/05(金) 06:43:57
ひろぴーさんの言うとおりダイアログベースのプログラム作りたかったんです

kuさん 親切丁寧な解説ありがとうございます
今週 月曜から初めていてもう既にくじけそうだったんですけど
もう少しがんばれそうです

wood 2003/12/07(日) 08:33:24
[[解決]]
根本的つくりに間違があるようなので、このスレッド中止します
もう少し、参考書なども探してみます
また、別スレッドの質問の時よろしくお願いします

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