• デスクトップのサイズをはみ出るぐらい大きなwebページ
  • 縦に長いwebページ
のスクリーンショットをどうやってキャプチャするか。
見回せばそういう目的のツールが結構あるんだけど、「どうやって実現するのか?」を知りたくて、調べてみた。
まずは「IEコンポーネントをフォームに貼り付け、なんちゃってブラウザを作成。IEコンポーネント内に表示されているwebページをキャプチャする。」

下のやり方で大体目的は達成できるみたい。
  • キャプチャする矩形(ピクセル単位)を決める。
    • IWebBrowser2::Document → IHTMLDocument2を得る
    • IHTMLDocument2.body → IHTMLElement2を得る
    • IHTMLDocument2::frames → IHTMLFramesCollection2を得る
    • IHTMLDocument2::IHTMLFrameSetElementを得る(ない時もある)
    • webページがframeを含む場合は、frameが内包するbodyに対して再帰的に矩形を求める。
    • bodyの矩形を求める
    • frameの配置(縦横)に応じて加算するなりなんなり。bodyの矩形と比較しつつ最終的なキャプチャ矩形を決める。
  • System.Drawing.Bitmapに書き込む
    • デスクトップにコンパチなデバイスコンテキストとビットマップを作成する。
    • IHTMLDocument2 → IOleObjectを得る
    • IOleObject::GetExtent()で、現在のエクステントサイズを保存
    • キャプチャ矩形サイズをHIMETRIC単位に変換し、IOleObject::SetExtent()で描画範囲を設定
    • IHTMLDocument2 → IViewObjectを得る
    • OleDraw()でIViewObject→デバイスコンテキストに描画
    • 保存しておいたエクステントサイズで元に戻しておく(フォーム上のIEコンポーネントの描画サイズが変わってしまうから)
    • デバイスコンテキストに割りついているビットマップからBitmapオブジェクトを生成
  • 後はSystem.Drawing.Bitmapオブジェクトを、クリップボードに貼り付けるなり、任意の画像形式でファイルに落とすなりする。
列挙するとなんだかあっさりしてる・・・。
あまり大きいビットマップを作ろうとするとビットマップの作成がコケる。800×37000ピクセルはアウトだった。何か回避方法があるんだろう。

キャプチャイメージこんな感じ。