Windows API の勉強を始めた者です。
CreateWindow関数を使ったときに発行されるWM_CREATEについて質問させていただきます。
以下のようなプログラムを作りました。このプログラムはウインドウを作るプログラムなのですが、はじめにウインドウを作るかどうかをWindowProcの中で聞いています。
このプログラムでウインドウを作らないという選択肢をとった時が分かりません。
WindowProcでは return -1 をするのでウインドウは作られず、従ってhWndにはNULLが入ります。そして次の文で、
if (hWnd == NULL) {
MessageBox(NULL,TEXT("CreateWindow failed"),NULL,MB_OK);
return 0;
}
メッセージボックスが表示されてからプログラムが終了すると思ったのですが、実際にはメッセージボックスは表示されませんでした。
なぜでしょうか。return -1 をした時点で、ウインドウが作られないのでWM_DESTROYがウインドウプロシージャにSendされるのかと考えたのですが、そうなのでしょうか。
よろしくお願いします。
/* 作ったプログラム */
#include <windows.h>
LRESULT CALLBACK WindowProc (HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
int YESNO;
switch(uMsg) {
case WM_DESTROY:
PostQuitMessage(0);
return 0;
case WM_CREATE:
YESNO = MessageBox(NULL, TEXT("Create a new window?"),
((LPCREATESTRUCT)lParam)->lpszName, MB_YESNO);
if (YESNO == IDYES)
return 0;
if (YESNO == IDNO)
return -1;
}
return DefWindowProc(hWnd, uMsg, wParam, lParam);
}
int WINAPI WinMain(HINSTANCE hInstance,
HINSTANCE hPrevInstance,
PSTR lpCmdLine,
int nCmdShow)
{
WNDCLASS wc;
ATOM atom;
MSG msg;
HWND hWnd;
wc.style = CS_HREDRAW| CS_VREDRAW;
wc.lpfnWndProc = WindowProc;
wc.cbClsExtra = 0;
wc.cbWndExtra = 0;
wc.hInstance = hInstance;
wc.hIcon = NULL;
wc.hCursor = NULL;
wc.hbrBackground = (HBRUSH)COLOR_BACKGROUND + 1;
wc.lpszMenuName = NULL;
wc.lpszClassName = TEXT("sample_window");
if ((atom = RegisterClass(&wc)) == 0) {
MessageBox(NULL,TEXT("RegisterClass failed"),NULL,MB_OK);
return 0;
}
hWnd = CreateWindow((LPCTSTR)atom, TEXT("Sampe window"),
WS_OVERLAPPEDWINDOW | WS_VISIBLE,
100, 100, 400, 300,
NULL, NULL, hInstance, NULL);
if (hWnd == NULL) {
MessageBox(NULL,TEXT("CreateWindow failed"),NULL,MB_OK);
return 0;
}
while (GetMessage(&msg, NULL, 0, 0) > 0) {
DispatchMessage(&msg);
}
return msg.wParam;
}
No.4ベストアンサー
- 回答日時:
こんばんは。
御礼頂きました。>>WM_CREATEメッセージが送られた後にWM_DESTROYが送られるのは、なぜなのでしょうか?return -1 をすることでウインドウが破棄されるのでDestroyWindow()関数が使われるためなのでしょうか。
に関してですが、流石に当方もWindows OSの実装者では無いので其処までは分かりません・・・。
ただ、想像する分には、そのサイトの一番下にも書いて有る様に、「GetMessage()に到達するまでの間に必要なコールバックはKiUserCallbackDispatcher()を介して行われる」と言うのですから、その中でWM_CREATEを呼び出して戻り値を確認し、エラー値が返された場合は即座にWM_DESTROYを呼び出しているのではないでしょうか。
此れならば、GetMessage()に到達していなくても、WM_DESTROY位は呼び出せる筈です。
単純な関数ポインタの呼び出し見たいな感覚で行われる物なのかもしれません。
>>もう一点に関して
取り敢えずPostQuitMessage()をコメントアウトしてWM_CREATEに失敗させると(メッセージループは無くても同じ)、MessageBox()が表示されました(Windows2000 sp4 VC++6.0で試しています)。
確かにPostQuitMessage()があると、MessageBox()が表示されなかったです(ただしサウンドだけは鳴った)。
今まで色々とWindows関連のサイトなどを見てきましたが、流石にココまでメスを入れていたものは見た事がありません。
海外から輸入されて来ているWindows関連の詳しい書籍であれば、こう言った詳細が書かれているかもしれません。
回答をありがとうございます。
回答者様のおっしゃる通り、PostQuitMessage()をコメントアウトしてWM_CREATEを失敗させるとMessageBoxが表示されました。ということは確かにWM_DESTROYのケースが行われている訳ですが、PostQuitMessage()が存在する場合でもMessageBoxのサウンドだけなるということは、やはり
if (hWnd == NULL)
のところのreturn 0; でプログラムが終了しているようです。
なぜ表示されないかについては興味深いのでもう少し他の書籍で勉強してみたいと思います。
何度もの詳しい回答、参考ページの紹介など、いろいろ本当にありがとうございました。
No.3
- 回答日時:
MessageBoxは呼ばれてますよ
デバッガでステップ実行でもすれば(しなくてもですけど)ifに入ってメッセージボックスが出る音が出てます
戻り値もGetLastErrorもエラー無しな値しか返しませんし表示されない理由もわかりませんけど
回答をありがとうございます。
回答者様のおっしゃるとおり、メッセージボックスの音が出ていました。
これはつまり、メッセージボックスは表示はされていないが、
if (hWnd == NULL)
のところのreturn 0; でプログラムが終了しているのですね。
なぜ表示されないかについてはいろいろ調べてみたいと思います。
回答をありがとうございました。
No.2
- 回答日時:
こんにちは。
WM_DESTROYの中にMessageBox()を置きます。
また、WM_CREATEはCreateWindow()APIの内部でメッセージループに先立って呼び出される物です。
http://keicode.com/windows/win01.php
ですのでWM_CREATEで失敗させる分には
while (GetMessage(&msg, NULL, 0, 0) > 0) {
DispatchMessage(&msg);
}
が無くてもWM_DESTROYが呼び出されます。
WM_DESTROYの下にあるPostQuitMessage()が呼び出されて終了したため、MessageBox()が出なかったのだと思います。
また、WM_CREATEが呼び出される順番は、
(1)WM_GETMINMAXINFO
(2)WM_NCCREATE
(3)WM_NCCALCSIZE
(4)WM_CREATE
と言う事で、四番目に位置します。
回答をありがとうございます。
参考ページをありがとうございます。いろいろ細かいところまであり参考になります。
なお、気になった点があるのですが、どうなのでしょうか。
WM_CREATEメッセージが送られた後にWM_DESTROYが送られるのは、なぜなのでしょうか?return -1 をすることでウインドウが破棄されるのでDestroyWindow()関数が使われるためなのでしょうか。
もう一点は、WM_DESTROYメッセージが送られた後、PostQuitMessage()関数が呼びだされます。
これはWM_QUITをメッセージキューにポストします。WM_QUITはGetMessage()関数にメッセージループの終了を通知するもので対象がウインドウプロシージャではないと思うのですが、もしそうするとメッセージキューからWM_QUITメッセージを取り出すにはGetMessage()関数が必要で、このプログラムが終了するにはWM_QUITを取り出さなければなりません(もしくはreturn 0 に到達する)。しかし、それ以前にメッセージボックスを出す命令がありますから、やはりメッセージボックスが出ると思うのですが、どうでしょうか?
よろしくお願いします。
No.1
- 回答日時:
WindowProc はメッセージループに入ってから呼び出される物として記憶しています。
つまりWM_CREATEが生じたときには既にwhile (GetMessage(&msg, NULL, 0, 0) > 0) {
DispatchMessage(&msg);
}
の中にいるのではないかと。
WM_CREATEで判断している以上、メッセージボックスを出したいのであればWM_DESTROYの分岐で書くのが自然な気がします。
素早い回答をありがとうございます。
私の方では、CreateWindow()関数はメッセージループに入る前の段階でウインドウプロシージャにメッセージを送ると考えています。
このプログラムではメッセージループの前の段階でコメントボックスを出すように書かれているため、どうやらこのプログラムはメッセージループに入ることなく終了しているようなのです。どうもその辺りの動きが分かりません。
回答をありがとうございました。
お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!
似たような質問が見つかりました
- C言語・C++・C# c言語の問題です 3 2023/01/10 16:15
- C言語・C++・C# c言語の問題の説明、各所ごとに 5 2023/07/26 11:03
- PHP php テーブルが作成できない 1 2022/11/17 23:41
- MySQL php テーブルを作れない 2 2022/11/17 18:22
- FX・外国為替取引 mql4のコンパイルエラー箇所の修正お願いします。 1 2023/03/15 16:14
- C言語・C++・C# バイナリファイルをコピーするのにかかる時間を測りたいのですが実行するとFatel error:gli 2 2022/11/03 01:10
- MySQL my_itemsテーブルのIDにAUTO_INCREMENT を追加ができるかで 1 2023/01/03 09:09
- C言語・C++・C# プログラミングの授業の課題です 1 2023/01/17 22:15
- 大学・短大 C言語線形リストの問題です 3 2022/12/22 00:45
- MySQL SHOW CREATE TABLE posts;これって何ですか? 3 2022/08/28 22:57
このQ&Aを見た人はこんなQ&Aも見ています
関連するカテゴリからQ&Aを探す
おすすめ情報
このQ&Aを見た人がよく見るQ&A
デイリーランキングこのカテゴリの人気デイリーQ&Aランキング
-
エディットボックスの背景の色...
-
この列挙体でsysjanの関数はあ...
-
画像を表示したいのですが……
-
不明なエラー
-
エラー Run-Time Check Failur...
-
COMPORTマルチスレッドで例外発生
-
子ウインドウの作成と破棄について
-
エディットコントロール入力時...
-
音量調節
-
WM_CREATE について
-
プログラミングでエラーが出ま...
-
Enterキーを押されたら次の処理...
-
fgetsなどのときのstdinのバッ...
-
マイナスからプラスへ転じた時...
-
複数桁10進数の*桁目だけを抽出...
-
「指定されたキャストは有効で...
-
「an=(n-1)/(n+1)のときlim[n→∞...
-
c言語で、繰り返し文の中で、0....
-
C言語での引数の省略方法
-
正負を反転させて出力するプロ...
マンスリーランキングこのカテゴリの人気マンスリーQ&Aランキング
-
Win32APIでウィンドウを中央に...
-
オーバーレイみたいな処理がしたい
-
ダイアログプログラムでEnterキ...
-
キャレットの現在位置の表示 (W...
-
PeekMessageについて
-
ウィンドウ非表示に時に表示し...
-
C#のswitch文を簡略化したいの...
-
C言語win32api、エディットボッ...
-
音量調節
-
LoadImageを使用し、タイトルバ...
-
プログラミングでエラーが出ま...
-
エディットコントロール入力時...
-
ウィンドウハンドルがメッセー...
-
ボタンの色(WINAPI)
-
画像を表示したいのですが……
-
WINAPIでキーから文字列を入力...
-
エラー Run-Time Check Failur...
-
エディットボックスの背景の色...
-
Win32APIでアイコンファイルを...
-
WM_KEYDOWNでPrtScを捕まえる方...
おすすめ情報