関係のあるのはSDK編です。SDK編をご利用でない方は読み飛ばしてください。

さて、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をご利用ください。


Update 12/Feb/2002 By Yasutaka Kumei [E-mail] [総合INDEX]
当ホーム・ページの一部または全部を無断で複写、複製、 転載あるいはコンピュータ等のファイルに保存することを禁じます。