デスクトップコンポジションの無効化

プログラミング関連のことは、とりわけ自分が書くことが殆ど無くて放置気味になっているこのはてダ。
今回、Windows Vistaから導入されたAeroの描画に用いられている、「デスクトップコンポジション」の無効化について書きます。

デスクトップコンポジションとは

そもそも何それ?という方もおられると思います。そもそもWindows XPをまだ使っている方には関係ない話ですからね。
ゲームなどを起動したとき、画面のスタイルが変更されて、以下のようなポップアップが出たことがないでしょうか。

これが、デスクトップコンポジションが無効になったことの合図です。
これが出たとき、Windows Aeroが無効になり、描画スタイルがベーシックになっているかと思います。

何故無効にするのか

Windows Aeroの描画にはDirectX9が利用されています。
たいていのゲームにも、描画にDirectXが使われます。
これらの両方が同時にDirectXを利用すると、場合によっては不具合が発生することがあります。
とはいっても、そんなに頻発するものではありません。これが大きく影響するのはマルチディスプレイ環境の時です。
マルチディスプレイ環境でゲーム中、デスクトップコンポジションを有効にしたまま「ウィンドウモード→フルスクリーンモード」としたりすると、画面に何も映らなくなったりします。
これはデスクトップコンポジション絡みの不具合であることが多いです。
デスクトップコンポジションはユーザが有効/無効をアプリケーションごとに切り替えられますが、ほぼ大半のユーザはそんなこと知りませんし、それ任せにするのはあまりに不親切です。
そこで、プログラム側から無効化させてやることを考えます。

無効化

デスクトップコンポジションの無効化には、 DwmEnableComposition 関数を呼び出します。
DwmEnableComposition( DWM_EC_DISABLECOMPOSITION ); とすれば無効化されます。
しかし、デスクトップコンポジションWindows Vista以降で導入されたものなので、Windows XPでこの関数を呼び出すことは出来ません。
つまり、OSのバージョン判定が必要になります。
OSのバージョン判定については色々ネット上に資料があるので、ここでは割愛します(自分で調べてね)。
コード例は以下のようになります。

#include <Dwmapi.h>

  OSVERSIONINFO os_info;
  os_info.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);
  GetVersionEx(&os_info);
  if( os_info.dwPlatformId == 2 && os_info.dwMajorVersion >= 6 ) {
    HMODULE hLibrary = LoadLibrary( "Dwmapi.dll" );
    if( hLibrary ) {
      DwmProc lpfnDwmEnableComposition;    // Function pointer
      lpfnDwmEnableComposition = reinterpret_cast<DwmProc>(::GetProcAddress( hLibrary, "DwmEnableComposition" ));
      if( lpfnDwmEnableComposition ) {
        lpfnDwmEnableComposition( DWM_EC_DISABLECOMPOSITION );
      }
    }
    FreeLibrary(hLibrary);
  }

ちなみに、このコードはメインのウィンドウが表示されてからじゃないとうまく動かないことがあります。
ウィンドウ生成のコードを先に書いてからこのコードを書きましょう。

上記のプログラムは、if( os_info.dwPlatformId == 2 && os_info.dwMajorVersion >= 6 ) の部分が、Windows Vista以降であるかどうかをチェックしています。
そしてWindows Vista以降であることが分かったらDwmapi.dllを遅延ロードしています。このdllの中にDwmEnableComposition関数が入っています。
(これ書いている間に、そもそもWindows XP以前であったらDLLの遅延ロードが失敗して関数が実行出来ないので、OSのバージョン判定がいらない気がしてきました…)
以上のコードでデスクトップコンポジションが無効化できます。やったね!

有効/無効

デスクトップコンポジションの無効化がこれでできるようになりましたが、問答無用でデスクトップコンポジションを無効化されるのが嫌な人もいます。
ですが、何も知らない人にとっては、無効化されずに不具合が発生するのも嫌でしょう。
これに対する正確な解はないですが、プログラム内の設定項目にデスクトップコンポジションの無効化、という項目を入れるなどの対処方法があります。
ここらへんは、作るものの種類によって考えていくといいのではないでしょうか。