/// キャプチャしたHBitmapをBitmapSource(Freezed)にして返す
        /// @param request スクリーンキャプチャ設定をまとめたリクエスト
        /// @return スクリーンキャプチャ結果が格納されたBitmapSource
        private BitmapSource Capture(ScreenCaptureRequest request)
        {
            if (request.ClippingWidth <= 0 || request.ClippingHeight <= 0) {
              // Debug.WriteLine("Invalid clipping size", "ScreenCaptureTimer.CaptureByGetDIBits");
              return null;
            }

            // HBitmapからBitmapSourceを作成
            BitmapSource bitmap = null;
            using (var result = request.Execute()) {
              if (result == null) return bitmap;

              // HBitmapからBitmapSourceに変換
              bitmap = Imaging.CreateBitmapSourceFromHBitmap(
              result.Bitmap, IntPtr.Zero, Int32Rect.Empty,
              BitmapSizeOptions.FromEmptyOptions());

              // Debug.WriteLine(string.Format("Captured: {0:D}x{1:D}",
              //                 bitmap.PixelWidth, bitmap.PixelHeight),
              //                 "ScreenCapture");
            }

            // Alphaチャンネル情報を削除
            bitmap = new FormatConvertedBitmap(bitmap, PixelFormats.Bgr32, null, 0.0);

            /// @todo(me) あまり大きな画像をメモリにおいておきたくない。
            ///           とはいえ、TransformedBitmapはちょっと重過ぎる。
            ///           メモリよりもCPUリソースを残しておきたいのでこのままでいいかも。
            //bitmap = this.Resize(bitmap);

            // スレッド越しにアクセスされるためFreeze
            bitmap.Freeze();
            return bitmap;
        }
        /// キャプチャしたbyte[]をBitmapSource(Freezed)にして返す
        /// @param request スクリーンキャプチャ設定をまとめたリクエスト
        /// @return スクリーンキャプチャ結果が格納されたBitmapSource
        private BitmapSource CaptureByGetDIBits(ScreenCaptureRequest request)
        {
            if (request.ClippingWidth <= 0 || request.ClippingHeight <= 0) {
              // Debug.WriteLine("Invalid clipping size", "ScreenCaptureTimer.CaptureByGetDIBits");
              return null;
            }

            // GetDIBitsでbyte[]にデータを格納
            int dpiX, dpiY;
            var result = request.ExecuteByGetDIBits(out dpiX, out dpiY);
            if (result == null) return null;

            var bitmap = BitmapSource.Create(request.ClippingWidth, request.ClippingHeight,
                                 dpiX, dpiY, PixelFormats.Bgr32, null, result, request.Stride);

            result = null;
            /// @todo(me) あまり大きな画像をメモリにおいておきたくない。
            ///           とはいえ、TransformedBitmapはちょっと重過ぎる。
            ///           メモリよりもCPUリソースを残しておきたいのでこのままでいいかも。
            //bitmap = this.Resize(bitmap);

            // スレッド越しにアクセスされるためFreeze
            bitmap.Freeze();
            return bitmap;
        }
        /// 結果を取得
        /// @param layoutElement 対象のレイアウト要素
        /// @return 生成済みならBitmapSourceを。でなければNullを返す。
        public BitmapSource GetBitmapSource(LayoutElement layoutElement)
        {
            if (!layoutElement.IsWindowValid) return null;
            var request = new ScreenCaptureRequest(layoutElement);

            /// ディクショナリはスレッドセーフではない
            lock (this.sharedLock) {
              BitmapSource result;
              var success = this.cache.TryGetValue(request, out result);
              Debug.WriteLineIf(!success, "No request in cache", "ScreenCaptureTimer");
              return result;
            }
        }