Top > プログラミング関連 > WTLでアイドル時に繰り返し処理を行うには
2006/ 6/23 記述
WTLを使用して、アイドル時に処理を繰り返し行う為の方法を示します。
ウィンドウが処理すべきメッセージがないときだけ処理を行う、いわゆる「アイドル処理」を行うには、SDKスタイルの方法で
MSG msg;
for(;;){
if(PeekMessage(&msg, NULL, 0, 0, PM_REMOVE)){
if(WM_QUIT==msg.message){
break;
}
TranslateMessage(&msg);
DispatchMessage(&msg);
}
else{
アイドル処理();
}
}
とやることができます。
しかし、WTLを使ったプログラムではWTLスタイルの処理方法があります。
それは、for(;;){...}
の代わりに、メッセージループにCMessageLoop
を使い、CIdleHandler
を継承したクラスをAddIdleHandler()
でアイドルハンドラに追加するというものです。
こうすると、アイドル状態になる度にOnIdle()
を呼んでくれます。
このあたりの例は、http://home.att.ne.jp/banana/akatsuki/doc/atlwtl/atlwtl03-07/を参照してください。
なお、上のページにあるコードだと抜けているのですが、OnDestroy()
の中でRemoveIdleHandler()
でアイドルハンドラから自分を抜いておいた方が良いです。ウィンドウのオブジェクトが、まだメッセージループが回っているうちにdetele
されてしまうような時には、これを忘れるととAccess Violationを起こします。
上で見たように、WTLを使うときにはWTLスタイルのアイドル処理を行うことができます。しかし、このやり方だとSDKスタイルのアイドル処理とは異なる結果が得られます。
すなわち、
ゲームなどでは、アイドル時にゲームループを回すのは良くある手ですが、この目的ではWTL標準のメッセージループを使うことは出来ません。
ではどうすればいいのかというと、CMessageLoop
の動作を変更すればいいのです。
WTLのincludeフォルダにあるatlapp.hを覗いてみると、CMessageLoop
の実装が見えます。
この中に、virtual BOOL OnIdle()
の実装があり、コメントにはoverride to change idle processing
とあります。
return FALSE; // don't continue
とあるのを、
return TRUE; // continue
に変えてやるだけで良さそうです。
ただし、atlapp.hに手を加えてはいけません。CMessageLoop
からクラスを派生させて使います。
この実装は次のようになります。
//派生させたメッセージループ
//OnIdle()をオーバーロードし、繰り返しアイドル処理を行うようにしてある
class CCustomMessageLoop:public CMessageLoop{
public:
CCustomMessageLoop(){}
virtual ~CCustomMessageLoop(){}
virtual BOOL OnIdle(int /*nIdleCount*/)
{
for(int i = 0; i < m_aIdleHandler.GetSize(); i++)
{
CIdleHandler* pIdleHandler = m_aIdleHandler[i];
if(pIdleHandler != NULL)
pIdleHandler->OnIdle();
}
return TRUE; //continue
}
};
アイドル処理で数字をインクリメントし、ウィンドウ中央に表示するサンプルをつけておきました。
CCustomMessageLoop
をCMessageLoop
と置き換えて、動作の違いを確かめてみてください。
このコードにはNYSL 0.9982を適用します。