確認したいのですが、
MSG msg;
while(TRUE)
{
if(PeekMessage(&msg,NULL,0,0,PM_REMOVE))
{
if(msg.message==WM_QUIT)
{
return (int) msg.wParam;
}
TranslateMessage(&msg);
DispatchMessage(&msg);
}
else
{
}
}
このPeekMessageというものですがキューに溜めているということでいいのでしょうか。
後、
MSG msg;
while(TRUE)
{
if(PeekMessage(&msg,NULL,0,0,PM_REMOVE))
{
if(!GetMessage(&msg,NULL,0,0))
{
return (int) msg.wParam;
}
if(msg.message==WM_QUIT)
{
return (int) msg.wParam;
}
TranslateMessage(&msg);
DispatchMessage(&msg);
}
else
{
}
}
のif(PeekMessage(&msg,NULL,0,0,PM_REMOVE))
{
if(!GetMessage(&msg,NULL,0,0))
{
return (int) msg.wParam;
}
はキューから出してGetMessageは待機してるということでいいのでしょか?
if(PeekMessage(&msg,NULL,0,0,PM_NOREMOVE))
{
if(!GetMessage(&msg,NULL,0,0))
{
return (int) msg.wParam;
}
これはキューの中は出さないで、GetMessageでPeekMessageからのキューを出しているということでいいのでしょか?
No.3ベストアンサー
- 回答日時:
「キューからメッセージを取り出して消える」ってのが分かってないのでしょうか。
もしくは、PeekMessageやGetMessageが、引数のmsgを書き換えるというのが分からないのでしょうか。
基本的に、せっかくGetなりPeekなりでメッセージを取得しても、
TranslateMessage & DispatchMessageにそのデータを渡さなければ意味がありません。
[A]の前の時点でキューに、
メッセージ1
メッセージ2
メッセージ3
と格納されていたとして、PeekMessageでREMOVE成功した[B]の時点では、
メッセージ2
メッセージ3
になります。メッセージ1の情報はmsgに取り出された状態で、キューからはREMOVEされます。
そして、GetMessageに成功した[C]の時点では
メッセージ3
になります。メッセージ2の情報はmsgに取り出された状態で、キューからはREMOVEされます。
そして、同時にその前まで[A]でmsgに格納していたメッセージ1の情報は、
GetMessageによって上書きされて失われます。既にキューにもありません。
メッセージ1は一度もTranslateMessage&DispatchMessageに渡されませんでした。
[C]に渡すのはあくまでGetMessageの引数であるmsg(=メッセージ2)であって、
メッセージ1ではありません。メッセージ1はTranslateもDispatchもされずに終わりました。
if(PeekMessage(&msg,NULL,0,0,PM_REMOVE))// <- ここでmsgにメッセージ1を取得(キューから削除) [A]
{
if(!GetMessage(&msg,NULL,0,0))// <- ここで、メッセージ1が格納されたmsgにメッセージ2を上書き [B]
{
return (int) msg.wParam;
}
if(msg.message==WM_QUIT)
{
return (int) msg.wParam;
}
TranslateMessage(&msg);// <- ここで渡しているmsgはメッセージ2 [C]
DispatchMessage(&msg);
}
ゆえに、PeekMessageで取得したmsg(=メッセージ1)はTranslateMessage&DispatchMessageに渡ることがありません。
わかりやすい回答ありがとうございます。メッセージ1が通ることがなく1つ飛ばしてしまうからバグが発生すると言ってもいいのでしょうか。わかりました。何回も説明ありがとうございました。
No.2
- 回答日時:
メッセージキューの話で言えば、
・GetMessage:成功すれば取り出したメッセージがキューから消えます。
・PeekMessage(REMOVE):成功すれば取り出したメッセージがキューから消えます。
・PeekMessage(NOREMOVE):メッセージはキューから消えません。
そして、キューからメッセージが消えた場合、そのメッセージは引数のmsgに入ってます。
(NOREMOVEでない限り、同じものを二回取り出すことはできません)
> PeekMessageによってキューから取り出して
> またGetMessageが待機してキューからまた取り直して
> 前のpeekMessageによって取り出されたキューは消されてしまういうことでよろしいのでしょうか?
REMOVEを指定している以上、取り出したメッセージは勿論キューから消えますので、
GetMessageが取り出すのはその次のメッセージになります。
そして、PeekMessageの引数msgに取り出した最初のメッセージは、
何も処理されないまま、GetMessageの引数として上書きされています。
> msgにGetMessageで渡された値が次のPeekMessageでバグってしまうと言うことでしょうか?
いいえ。
> なぜバグってしまうのでしょうか?
Windowsのルールでは、基本的に、受け取ったメッセージは
TranslateMessage(&msg);
DispatchMessage(&msg);
に渡してあげる必要があります。
PeekMessage(NOREMOVE)であれば、キューからメッセージを捨てないので、
もう一度GetMessageすればそのメッセージが取得でき、Translate&Dispatchが可能ですが、
提示のPeekMessage(REMOVE)の例では、PeekMessageでmsg構造体に格納したデータを、
次のGetMessageで上書きしており、そのmsgはTranslate&Dispatchされません。
したがって、Windows OSから通知されるメッセージが予期せず歯抜けし、おかしな挙動をする可能性があります。(←バグ)
回答ありがとうございます。GetMessageで上書きとかいてありますが、
上書きしたらしたで、なぜTranslate&Dispatchされないのでしょうか?GetMessageメッセージでmsgを取得しているのに・・・勉強不足ですみません。
No.1
- 回答日時:
MSDNを読んでください。
> このPeekMessageというものですがキューに溜めているということでいいのでしょうか。
いいえ。PeekMessageにキューに溜める機能はありません。
PM_REMOVEを指定してますので、キューから取り出してます。
(GetMessageとはブロッキングの有無などが違います)
> はキューから出してGetMessageは待機してるということでいいのでしょか?
PeekMessageでキュー内からmsgを取り出した場合(PeekMessageが0以外を返す)に、
GetMessageで待機して次のキューを取り出しmsgを上書きしていますので、
最初のPeekMessageで取り出したmsgは処理せずに捨ててます。
(つまり、バグってます)
> これはキューの中は出さないで、GetMessageでPeekMessageからのキューを出しているということでいいのでしょか?
PeekMessageでキューの中身があれば(この時点ではキューの中身を取り出さず)、GetMessageでその中身を取得しています。
PeekMessage自体は予めキューにメッセージがあるか確認しているだけで、
PeekMessageがキューにメッセージを溜めているわけではありません。
GetMessageもPeekMessageもキューの中身を取り出すためのAPIで、
キューに溜める機能はありません。(通常はシステムが溜めます。自分で溜めるには例えばPostMessage等を使います)
GetMessageはキューの中身がなければキューイングされるまで待ちます。
PeekMessageはキューの中身がなければ無かったといって処理を返します。
また、PeekMessageは、その際にキューの中身を消すか否かを選択できます。
(つまり、削除せずに中身があるか確認することもできますし、削除してしまうこともできます)
わかりやすい説明ありがとうございます。まとめると
> はキューから出してGetMessageは待機してるということでいいのでしょか?
は、PeekMessageによってキューから取り出してまたGetMessageが待機してキューからまた取り直して前のpeekMessageによって取り出された
キューは消されてしまういうことでよろしいのでしょうか?そして
msgにGetMessageで渡された値が次のPeekMessageでバグってしまうと言うことでしょうか?なぜバグってしまうのでしょうか?どうかご教授よろしくお願いします。
お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!
似たような質問が見つかりました
- JavaScript javascriptで入力フォームが空欄の時にアラートによるエラーを出すコードを書いています。 2 2023/06/13 17:58
- JavaScript セレクトを全て選択されていないと、文字によるエラーメッセージを表示させるコードを調べています 2 2023/06/22 15:48
- JavaScript 入力フォームの javascript で メールアドレスの正規チェックをを行い、ボタンをクリックして 2 2022/04/27 16:06
- HTML・CSS ボタンをクリックした時に、入力フォームのすぐ下部に、「入力欄が空白です」というテキストメッセージが表 1 2022/04/27 16:25
- FX・外国為替取引 mql4のコンパイルエラー箇所の修正お願いします。 1 2023/03/15 16:14
- Excel(エクセル) エクセルVBA Msgboxでの変数の活用 4 2023/07/23 08:33
- PHP php ログイン 1 2022/11/01 00:24
- C言語・C++・C# c言語の問題の説明、各所ごとに 5 2023/07/26 11:03
- C言語・C++・C# c言語の問題です 3 2023/01/10 16:15
- JavaScript Javascriptが機能せず原因が分からないので教えて頂きたいです 3 2023/06/04 14:50
このQ&Aを見た人はこんなQ&Aも見ています
関連するカテゴリからQ&Aを探す
おすすめ情報
このQ&Aを見た人がよく見るQ&A
デイリーランキングこのカテゴリの人気デイリーQ&Aランキング
-
MessageBoxについて
-
エディットコントロール入力時...
-
Win32APIでウィンドウを中央に...
-
ダイアログプログラムでEnterキ...
-
キャレットの現在位置の表示 (W...
-
音量調節
-
エディットボックスの背景の色...
-
C言語win32api、エディットボッ...
-
ツリーコントロールの開閉アイ...
-
Win32APIにて、ウィンドウ全体...
-
ウィンドウハンドルがメッセー...
-
信頼区間の1.96や1.65ってどこ...
-
マイナスからプラスへ転じた時...
-
C言語での引数の省略方法
-
【C++】関数ポインタの使い方
-
2÷3などの余りについて
-
「指定されたキャストは有効で...
-
Enterキーを押されたら次の処理...
-
CTRL+Dでループを抜けるには
-
#if 1 #elseの意味について
マンスリーランキングこのカテゴリの人気マンスリーQ&Aランキング
-
音量調節
-
return文がない場合の戻り値は...
-
C#のswitch文を簡略化したいの...
-
ゲームとかの解像度変更&全画...
-
エラー Run-Time Check Failur...
-
コンソールアプリケーションの...
-
キャレットの現在位置の表示 (W...
-
エディットボックスの背景の色...
-
COMPORTマルチスレッドで例外発生
-
ツリーコントロールの開閉アイ...
-
C言語win32api、エディットボッ...
-
Win32APIにて、ウィンドウ全体...
-
Win32APIでウィンドウを中央に...
-
エディットコントロール入力時...
-
ダイアログプログラムでEnterキ...
-
不思議な現象が起こるプログラ...
-
Win32のファイルダイアログのサ...
-
C言語のswitch case文で、scanf...
-
WM_CREATE について
-
ボタンのアイコン表示
おすすめ情報