#pragma twice

KAB-studio > プログラミング > #pragma twice > 185 Version 10.07 メッセージを待つ!

#pragma twice 185 Version 10.07 メッセージを待つ!

前のページへ 表紙・目次へ 次のページへ

 Version 10.07
メッセージを待つ!

さて、今回はちょっと重要なことを説明します
重要ってどのくらい
そうだね、他のアプリとか、あと使ってる人を困らせる可能性がある、そ
のくらい重要かな
つまり自分のアプリだけの問題じゃない、と
そういうこと。まず、 Main.cpp ファイルの最初のところ

#include <Windows.h>
#include <stdio.h>

っていうふうに、 stdio.h をインクルードしておいて
ほい
次に、メッセージループを

// メッセージループ。
int MessageLoop()
{
    BOOL bRes;
    MSG stMsg;

    // カウンター。
    int iCounter = 0;
    // カウンターを入れる文字列。
    char pchCounter[128];

    // メッセージループです。
    while( 1 )
    {
        // メッセージをキューから取り出します。
        bRes = GetMessage( &stMsg, NULL, 0, 0 );
        if  ( 
                ( bRes == 0 )
            || 
                ( bRes == -1 )
            )
        {
            // 終了するのでループから抜けます。
            break;
        }

        // カウンターとメッセージを出力します。
        ++iCounter;
        sprintf
            ( pchCounter
            , "メッセージ : %d, %X, %X\n"
            , iCounter, stMsg.message, stMsg.hwnd 
            );
        OutputDebugString( pchCounter );

        // メッセージを変換します。
        TranslateMessage( &stMsg );
        // ウィンドウプロシージャに送ります。
        DispatchMessage( &stMsg );
    }

    return stMsg.wParam;
}

って修正して。 while の前に変数をふたつ追加して、あと〈カウンター
と……〉ってコメントのとこのを追加して
この前の WM_KEYDOWN とかのは削除するんでしょ?
あ、そうそう。あとは、 IME を MS-IME に変えて、と……
何してるの?
ちょっと小細工。えっと、とりあえずビルドして実行して
ほい
で、出力結果は

メッセージ : 1, 401, 1C013A
メッセージ : 2, C055, 1C013A
メッセージ : 3, C066, 1C013A
メッセージ : 4, 200, 1F0106
メッセージ : 5, F, 360120
メッセージ : 6, 113, 1C013A
メッセージ : 7, 200, 1F0106
メッセージ : 8, 200, 1F0106
メッセージ : 9, 200, 1F0106
メッセージ : 10, 200, 1F0106
メッセージ : 11, 200, 1F0106
……

って感じになると思うんだけど、もし右から2番目の数字が 113 、つま


メッセージ : 18, 113, 210106
メッセージ : 19, 113, 210106
メッセージ : 20, 113, 210106
メッセージ : 21, 113, 210106
メッセージ : 22, 113, 210106
メッセージ : 23, 113, 210106
メッセージ : 24, 113, 210106

ってなっていた場合には、コントロールパネルの【地域のオプション】
の【入力ロケール】のページで【MS-IME】系の IME にしておいてくださ

どゆこと?
その辺はあとで。えっと、もう一度仕切直し。実行してみて
ほい。うん、さっきみたいに色々出てくるね
プログラムと付き合わせてみるとわかると思うけど

メッセージ : 7, 200, 1F0106

の数字の、1番目がメッセージのカウンター
つまり今までに送られてきてるメッセージの数ね
2番目はメッセージそのものの値。メッセージは本当は整数値で、 
Winuser.h ってファイルの中で定義されてます
その数字を出してるわけね
3番目は送り先ウィンドウハンドル
ウィンドウハンドル?
 Version 10.04 ( No.182 ) で言ったように、メッセージループにはいろ
んなウィンドウのメッセージが送られてくるんです
そっか、これを見ないとどのウィンドウのメッセージかわからないわけ

そういうこと。ま、いろんなって言ってもそのアプリに関係してるメッ
セージだけだけどね。ちなみに、この辺の値を変換してる

        sprintf
            ( pchCounter
            , "メッセージ : %d, %X, %X\n"
            , iCounter, stMsg.message, stMsg.hwnd 
            );

については Version 5.07 ( No.072 ) を参照してください
数値を文字列にするってゆーのね、 TRACE() みたいなので
ちなみに、最初に

#include <stdio.h>

ってしたのはこの sprintf() を使うため。そのへんは Version 8.03 
( No.145 )
 を参照してください
そっか、 MFC を使わないでランタイム使う時は、こういうふうにしな
きゃいけないんだ……
さて。ここからが本題。実行中に、何もしないでみて
ほい、何もしない
メッセージはどう?
送られてきてないみたい。カウンター増えてないから
そう、そこが重要

メッセージループって while のループだけど、ずーっとぐるぐる回って
るわけじゃないってこと
そういえば、回ってたらその度になんか出るはずだもんね
 GetMessage() がメッセージキューの中身を見に行って、メッセージがひ
とつも入ってないときには、メッセージがキューに入るまでずっと待つんで

あ、だから止まってるんだ
この機能のおかげで、アプリはなにも操作をしなければずーっと待ち状態
になってるんです
待ち状態? 何もせずに待ってるの?
そう、〈何もしてない〉っていうのがとても重要。アプリが何かをして
るってことは、その間は CPU がそのアプリの処理をしてるってこと
 CPU ってパソコンの頭よね、つまりアプリのことを色々してくれてるっ
てこと……そっか、それが〈してない〉ってことは、アプリのことをほっ
ぽっといてるってことね
放っておいてるってことは、逆に言うと他のアプリの処理をすることがで
きるってこと
……ちょっと待った。つまり、 CPU ってひとつのアプリしか面倒見られ
ないの? マルチタスクって、確か
複数のアプリを処理できる、けど、それは CPU が同時にできるわけじゃ
なくて、まずアプリ1、次にアプリ2、アプリ3、またアプリ1、アプリ
2、っていうふうに
とっかえひっかえして見ていくんだ……マルチタスクって、完全に平行に
処理できるんじゃないんだね
今の CPU はそう。将来は改善されるだろうし、今でも CPU を複数使え

コンピューターとしては並行処理……でも CPU はいっぺんにひとつしか
処理できないんだよね
だから! Version 7.18 ( No.138 ) の時のループを思い出して
あ……あの時はアニメーションでループさせてて、そしたらその間は動か
したり他のアプリ使ったりできなかった……
ああいうふうに CPU がしっかり処理を始めちゃうと、マルチタスク環境
でも他のアプリの処理に移らないんです
だからずーっと固まったままなわけね。あれ? でもそれじゃいつ他のア
プリに……あ! そのための GetMessage() !
そゆこと。メッセージが送られてきて、ウィンドウプロシージャで処理し
て、また GetMessage() に戻ってきたら、実はここで一度このアプリの処理
は休止するんです
あ、そうなんだ。で、他のアプリに移る?
そういうこと。他のアプリの処理に移ると、そこでもメッセージループで
GetMessage() でメッセージを待ってて
もしキューに入ってたら取り出して処理、終わったらまた他のアプリへ
処理が移って、っていうふうになるわけです。つまり

1: GetMessage() メッセージを取り出す。
2: ウィンドウプロシージャで処理する。
3: ふたたび GetMessage() に戻った所で他のアプリへバトンを渡す。

これがひとつのメッセージの処理内容。これを、今実行されてるアプリが
代わる代わるしてるんです
そっか、あのとき WM_TIMER を使ったのは……
そういうこと。メッセージを使えば、一度の処理ごとに必ずメッセージ
ループが一周するでしょ
それで他のアプリの処理に移ることができる……なるほどねー
あとは、その Version 7.18 ( No.138 ) の時の話を思い出して
……そっか、こういう理由だから、ああいうループはしちゃいけないんだ

マルチタスクの仕組みを知らないと、普通にものすごく重い処理をさせ
ちゃうかもしれないけど、それは使う人にとってはすごく迷惑
そのために、 WM_TIRMER とかを使って、他のアプリも動けるようにする
わけねー
と、最後に IME のことについて
あ、そうそう、それそれ
まず、 IME って実はアプリの中に埋め込まれた形になってるんです
埋め込まれる?
そう。埋め込まれるって事は、 IME に対してのメッセージもそのアプリ
のメッセージキューに入れられるってこと
ってことは

メッセージ : 18, 113, 210106

は、その IME のメッセージ?
調べてみたら、 ATOK15 はタイマー、あ、 WM_TIMER って整数値だと 113 
なんだけど、それを送ってもらってるみたいで
なるほどねー。……試してみると、これ、かなりの数来てない?
たぶん 0.1 秒間隔くらいかな?
それじゃあ、さっきのメッセージループの意味が……
そんなことはない、って Version 7.18 ( No.138 ) で説明したでしょ?
そっか、処理する時間に比べたら 0.1 秒なんてかなり長いんだ
この辺の話は、実感としての時間よりも、 CPU にとっての時間を考える
ことが重要、かな

/*
    Preview Next Story!
*/
ってゆーか、普通に動いてたプログラムもこういう裏事情があるんだね
でもこういうこと知ってると
あ、そっか、プログラムがいきなり止まっちゃう理由とか分かるね
逆にプログラマーはそういう部分も気を付ける必要があるってこと
むー、なんかどんどん気にしなきゃいけないことが増えてない?
それはたぶん、減ることはないよ……

というわけで次回
< Version 10.08 ウィンドウクラスとアトム >
につづく!
アトムっていうのも結構やっかいなものでねー
そんな、やるまえからそーゆーこと言わないでよ……
 
del.icio.us 登録する
Yahoo!ブックマーク 詳細を表示 users
livedoorクリップ 詳細を表示 livedoorクリップ ブックマーク数
はてなブックマーク 詳細を表示 はてなブックマーク ブックマーク数
RSSに登録
del.icio.us 登録する
Yahoo!ブックマーク 詳細を表示 users
livedoorクリップ 詳細を表示 livedoorクリップ ブックマーク数
はてなブックマーク 詳細を表示 はてなブックマーク ブックマーク数
 
このページは、Visual C++ 6.0を用いた C++ 言語プログラミングの解説を行う#pragma twiceの一コンテンツです。
詳しい説明は#pragma twiceのトップページをご覧ください。