さて、SDK編第3章でも少しだけ出ていますが、通常いろいろな書物ではメッセージループは 次のように記述するように書かれています。
while (GetMessage(&msg, NULL, 0, 0)) { TranslateMessage(&msg); DispatchMessage(&msg); }最近刊行された、Windows2000プログラミング標準講座(ハーバート・シルト著、山本信雄訳、翔泳社) にも、同様のコードが記載されています。
さらに、VC++6.0で「標準的な"Hello World!"アプリケーション」を自動的に作らせても、同様な コードが出力されます。
筆者は、特に疑問も持たずにこのように記載していましたが、実はこれが危険なコードで あることがある方よりメールでご指摘いただきました。
改めてGetMessage関数をMSDNライブラリで調べてみると、
GetMessage関数は WM_QUIT 以外のメッセージを取得した場合、0 以外の値が返ります。 WM_QUIT メッセージを取得した場合、0 が返ります。 エラーが発生した場合、-1 が返ります。と書かれています。つまり、この関数が失敗して-1を返した場合、ループから抜けることが出来ず 大変まずいことが起こります(このような事態が発生する確率は低いと思いますが・・・)。
以上をふまえて、MSDNには、メッセージループを次のようにしなさいとの記述があります。
MSG msg; BOOL bRet; while( (bRet = GetMessage( &msg, NULL, 0, 0 )) != 0) { if (bRet == -1) { // handle the error and possibly exit } else { TranslateMessage(&msg); DispatchMessage(&msg); } }bRetが-1の時何らかの方法でループを抜け、アプリケーションを終了するようにします。
さて、このような記述がいつなされたのかわかりませんが、VC++におまけで付いてくるMSDNライブラリにも そのような記述があります(少なくとも98年にはこの記載があった)。しかし、何と同じMSDNライブラリで2001年7月の日付の付いた記述で、 従前通りのループの記載もあります。NSDNについてくるサンプルはほとんどが従前通りのループです。
念のためVC++1.5Xのヘルプを調べたところ戻り値は、0と0以外の2通りしか記載が無く、メッセージループの 例として従前のループが載っていました。16ビット時代と仕様が変更になったのに、多くの人が16ビット時代の方法で記述していた可能性もあります。(このへんの事情はちょっとわかりません。)
従って、メッセージループを作る時は、安全な方法で記載してください。当HPのサンプルも 今後、これに従いますが、一度にすべてのサンプルを書き直すのはかなり、時間がかかりますので 当面は、従前通りの記載となります。
以上の点を十分ご理解の上、当HPをご利用ください。