GetDCPolite

上記ネタと全く同じ話でGetDCPoliteを用意したよ。これはGetDCしたら必ずReleaseDCをしましょうという教訓をマクロにまとめてしまい、教訓をうっかり忘れても大丈夫なようにしよう、いやむしろ、積極的に教訓は忘れてこっちを使おう!というためのものだ。ソースは以下に。

struct GetDCPolite_t
{
  GetDCPolite_t(){}
  GetDCPolite_t( HWND hw, HDC* pdc ): _hw(hw){
    *pdc = GetDC( hw );
    _hdc = *pdc; 
  }
  ~GetDCPolite_t( void ){
    ::ReleaseDC( _hw, _hdc );
  }
  operator bool(){ return !0; }
  HWND _hw;
  HDC _hdc;
};
#define GetDCPolite( hwnd, pdc ) \
  if( GetDCPolite_t tmp = GetDCPolite_t( hwnd, pdc ) ) \
// 上記if文スコープの終端を処理が必ず通過することが前提です。
// 途中のreturnやbreakなどで、本マクロスコープを中断するような
// 場合は処理を分岐させる前に必ず、
// ::ReleaseDC( tmp._hw, tmp._hdc );
// をして下さい!

使い方は、今まで

 HDC hdc = GetDC( hw );
  {
    //
    // hdc を使った自分のやりたい描画処理
    //
  }
  ReleaseDC( hw, hdc );// これを忘れてはならぬ

という感じに書くしかなかったところを、

      HDC hdc;
      GetDCPolite( hw, &hdc )
      {
        //
        // hdc を使った自分のやりたい描画処理
        //
      }

と書いてすんでしまうという話だ。
最後に、SelectObjectPoliteでも同じ話だけど、これらはいずれも「if文の条件式の中で宣言された変数のスコープはそのif文ブロックのスコープになる」というANSI Cの挙動を利用した、例えばBOOST_FOREACHの実装なんかで使われてるのと同様な手口を利用したものだ。
なのでこのスコープを処理が必ず通過してくることが前提となっている。従って、途中でreturnしたりしてスコープの最後を通過しないような処理では、その際には忘れずに、ReleaseDCやSelectObjectをしないといけなくなってくるよ。そこのところはくれぐれも気をつけてほしい。