「モンスター討伐ゲーム アンチ核家族化」という私が開発しているゲームがあるんですが、リニューアル版ではキャラクター設定画面にWindowsフォームを使うことにしたので、ゲームとキャラクター設定画面が別プロセスになっちゃってるんです。
そこで問題となったのが、ゲームはDXライブラリを使っていて、また、サブプロセスを作成して待機するにはWin32 API関数のWaitForSingleObject関数で待機する必要があります。
ですが、ここで一つ問題があり、WaitForSingleObject関数内では当然DXライブラリのProcessMessage関数は呼ばれませんので、待機時間が長いと処理が重くなり、結果フリーズするということになってしまいます。
ここで私が考えたのが、DXライブラリを使ったアプリケーションで使えるWaitForSingleObject関数、「DxWaitForSingleObject」関数でした。
それがこちらです。
# include "DxLib.h"
DWORD DxWaitForSingleObject(HANDLE hHandle, DWORD dwMilliSeconds) {
DWORD ReturnCode = WAIT_OBJECT_0 + 1;
if (dwMilliSeconds == INFINITE) {
while (ReturnCode != WAIT_OBJECT_0 && -1 != DxLib::ProcessMessage()) {
if (ReturnCode = WaitForSingleObject(hHandle, 100); WAIT_FAILED == ReturnCode) return ReturnCode;
}
}
else if (dwMilliSeconds > 100) {
auto GetCurrent = []() {
return std::chrono::duration_cast<std::chrono::milliseconds>(std::chrono::system_clock::now().time_since_epoch()).count();
};
const auto WaitStart = GetCurrent();
for (long long elapsed = 0; elapsed < dwMilliSeconds && -1 != DxLib::ProcessMessage(); elapsed = GetCurrent() - WaitStart) {
if (ReturnCode = WaitForSingleObject(hHandle, 100); WAIT_FAILED == ReturnCode) return ReturnCode;
if (ReturnCode == WAIT_OBJECT_0) break;
}
}
else ReturnCode = WaitForSingleObject(hHandle, dwMilliSeconds);
return ReturnCode;
}
やってることはすごくシンプルで、100ミリ秒を超える時間待機したい場合はWaitForSingleObject関数での待機時間を100ミリ秒とし、有限待機の場合はforで指定時間まで、INFINITEの場合はwhileでシグナル状態になるまで待機させるという方式です。
もちろんループ条件にProcessMessage関数が入ってるので、アプリケーションが終了すればこの関数もループアウトします。
使い方はこちらを見てください。これはあくまでもWaitForSingleObject関数をDXライブラリを使ったアプリケーションでも使えるようにしてるだけなので、使い方はWaitForSingleObjectと丸っきり同じです。