none
WebBrowserの画面をBMP出力できません RRS feed

  • 質問

  • WebBrowserコントロールを張り付けたフォームで、コードは以下です。

    画像ファイルは保存されるのですが、真っ黒な画像が出力されるだけでうまくいきません。
    何か問題がありますでしょうか?
    どうかよろしくお願いいたします。

    (urlの部分はもちろんxxxxじゃなくて適当なurlを使っています)

    using System;
    using System.Drawing;
    using System.Windows.Forms;

    namespace WindowsFormsApplication1
    {
     public partial class Form1 : Form
     {
      public Form1()
      {
       InitializeComponent();
      }

      private void Form1_Load(object sender, EventArgs e)
      {
       this.webBrowser1.ScrollBarsEnabled = false;
       this.webBrowser1.ScriptErrorsSuppressed = true;
       this.webBrowser1.DocumentCompleted += new WebBrowserDocumentCompletedEventHandler(browser1_DocumentCompleted);
       string url = "http://xxxxxxxxxx";
       this.webBrowser1.Navigate(url);
      }

      [System.Runtime.InteropServices.DllImport("ole32.dll")]
      extern static int OleDraw(IntPtr pUnk, int dwAspect, IntPtr hdcDraw, ref Rectangle lprcBounds);
      const int DVASPECT_CONTENT = 1;

      private void browser1_DocumentCompleted(object sender, WebBrowserDocumentCompletedEventArgs e)
      {
       webBrowser1.Width = webBrowser1.Document.Body.ScrollRectangle.Width;
       webBrowser1.Height = webBrowser1.Document.Body.ScrollRectangle.Height;
       try
       {
        Bitmap bmp = null;
        Graphics graph = null;
        IntPtr hdc = IntPtr.Zero;
        IntPtr browser = IntPtr.Zero;
        try
        {
         bmp = new Bitmap(webBrowser1.Width, webBrowser1.Height);
         graph = Graphics.FromImage(bmp) ;
         hdc = graph.GetHdc();
         browser = System.Runtime.InteropServices.Marshal.GetIUnknownForObject(webBrowser1.ActiveXInstance);
         Rectangle rect = new Rectangle(0, 0, bmp.Width, bmp.Height);
         OleDraw(browser, DVASPECT_CONTENT, hdc, ref rect);
         bmp.Save(Application.StartupPath + "\\XXX.bmp", Imaging.ImageFormat.Bmp);
        }
        finally
        {
         bmp.Dispose();
         graph.ReleaseHdc(hdc);
         graph.Dispose();
         System.Runtime.InteropServices.Marshal.Release(browser);
        }
       }
       catch (Exception ex)
       {
        MessageBox.Show(ex.Message);
       }
      }
     }
    }


    • 編集済み princeman 2012年4月24日 11:17
    2012年4月24日 11:14

回答

  • GetHdc メソッドをリファレンスで引けば、やんわり書いてありますが、GDI+ のキャンバスに GDI の操作を適用する……つまり、Bitmap に描画を適用する……ためには ReleaseHdc() を呼び出す必要があります。

    ReleaseHdc を呼び出さずに Save を呼び出しているのが原因ではないでしょうか。

    直接の問題ではないですが、全体的に try-finally の目的と用法を誤っているようなので、なぜ try-finally を使用する必要があるのか(例外から保護しなければならない範囲はどこからどこまでなのか)とか、using ブロックについて勉強しなおされることをオススメします。

    • 回答としてマーク princeman 2012年4月26日 2:40
    2012年4月24日 13:29

すべての返信

  • GetHdc メソッドをリファレンスで引けば、やんわり書いてありますが、GDI+ のキャンバスに GDI の操作を適用する……つまり、Bitmap に描画を適用する……ためには ReleaseHdc() を呼び出す必要があります。

    ReleaseHdc を呼び出さずに Save を呼び出しているのが原因ではないでしょうか。

    直接の問題ではないですが、全体的に try-finally の目的と用法を誤っているようなので、なぜ try-finally を使用する必要があるのか(例外から保護しなければならない範囲はどこからどこまでなのか)とか、using ブロックについて勉強しなおされることをオススメします。

    • 回答としてマーク princeman 2012年4月26日 2:40
    2012年4月24日 13:29
  • Takaokaさん

    ありがとうございます。ご指摘の通りReleaseHdc()でした。
    あとfinallyブロックの件もご指摘の通りです。
    重ねてありがとうございました。

    2012年4月26日 2:39