2
나는 다음을 얻을 수 있었다 웹 페이지의 화면 스크랩을 얻을 수

스레드

WebBrowser Control in a new thread

노력에 표시된 기술을 사용하고

에서 WebBrowser 컨트롤의 화면 풍경을 수행 에 WebBrowser 컨트롤을 배치하면 코드가 제대로 작동합니다. 그러나 스레드 내에서 실행될 때 데스크탑의 임의 이미지를 제공하여 실패합니다.

Thread browserThread = new Thread(() => 
{ 
    WebBrowser br = new WebBrowser(); 
    br.DocumentCompleted += webBrowser1_DocumentCompleted; 
    br.ProgressChanged += webBrowser1_ProgressChanged; 
    br.ScriptErrorsSuppressed = true; 
    br.Navigate(url); 
    Application.Run(); 
}); 
browserThread.SetApartmentState(ApartmentState.STA); 
browserThread.Start(); 

private Image TakeSnapShot(WebBrowser browser) 
{ 
    int width; 
    int height; 

    width = browser.ClientRectangle.Width; 
    height = browser.ClientRectangle.Height; 

    Bitmap image = new Bitmap(width, height); 

    using (Graphics graphics = Graphics.FromImage(image)) 
    { 
     Point p = new Point(0, 0); 
     Point upperLeftSource = browser.PointToScreen(p); 
     Point upperLeftDestination = new Point(0, 0); 

     Size blockRegionSize = browser.ClientRectangle.Size; 
     blockRegionSize.Width = blockRegionSize.Width - 15; 
     blockRegionSize.Height = blockRegionSize.Height - 15; 
     graphics.CopyFromScreen(upperLeftSource, upperLeftDestination, blockRegionSize); 
    } 

    return image; 
} 

이 분명히 있기 때문에 방법 Graphics.CopyFromScreen()의 발생하지만 다른 방법의 인식입니다. 누구든지이 문제를 해결할 수있는 방법이 있습니까? 또는 양식을 만들고, 컨트롤을 추가하고, 보이게 한 다음 화면을 긁어 내릴 수있는 유일한 방법입니까? 명백한 이유 때문에 나는 그러한 접근법을 피하기를 바라고 있습니다.

답변

8

당신은 쓸 수

private Image TakeSnapShot(WebBrowser browser) 
{ 
    browser.Width = browser.Document.Body.ScrollRectangle.Width; 
    browser.Height= browser.Document.Body.ScrollRectangle.Height; 

    Bitmap bitmap = new Bitmap(browser.Width - System.Windows.Forms.SystemInformation.VerticalScrollBarWidth, browser.Height); 

    browser.DrawToBitmap(bitmap, new Rectangle(0, 0, bitmap.Width, bitmap.Height)); 

    return bitmap; 
} 

코드가

var image = await WebUtils.GetPageAsImageAsync("http://www.stackoverflow.com"); 
image.Save(fname , System.Drawing.Imaging.ImageFormat.Bmp); 

public class WebUtils 
{ 
    public static Task<Image> GetPageAsImageAsync(string url) 
    { 
     var tcs = new TaskCompletionSource<Image>(); 

     var thread = new Thread(() => 
     { 
      WebBrowser browser = new WebBrowser(); 
      browser.Size = new Size(1280, 768); 

      WebBrowserDocumentCompletedEventHandler documentCompleted = null; 
      documentCompleted = async (o, s) => 
      { 
       browser.DocumentCompleted -= documentCompleted; 
       await Task.Delay(2000); //Run JS a few seconds more 

       Bitmap bitmap = TakeSnapshot(browser); 

       tcs.TrySetResult(bitmap); 
       browser.Dispose(); 
       Application.ExitThread(); 
      }; 

      browser.ScriptErrorsSuppressed = true; 
      browser.DocumentCompleted += documentCompleted; 
      browser.Navigate(url); 
      Application.Run(); 
     }); 

     thread.SetApartmentState(ApartmentState.STA); 
     thread.Start(); 

     return tcs.Task; 
    } 

    private static Bitmap TakeSnapshot(WebBrowser browser) 
    { 
     browser.Width = browser.Document.Body.ScrollRectangle.Width; 
     browser.Height= browser.Document.Body.ScrollRectangle.Height; 

     Bitmap bitmap = new Bitmap(browser.Width - System.Windows.Forms.SystemInformation.VerticalScrollBarWidth, browser.Height); 

     browser.DrawToBitmap(bitmap, new Rectangle(0, 0, bitmap.Width, bitmap.Height)); 

     return bitmap; 
    } 
} 
+0

정확히 내가 필요로하는 것. WebBrowser.DrawToBitmap()과 같은 것을 찾았지만 intellisense에는 나타나지 않았지만 여전히 괜찮습니다. 고맙습니다! –

+1

또한 System.Windows.Forms.SystemInformation을 보여 주셔서 감사합니다. 결코 전에 그것을 보지 않으며 명백하게 아주 유용하다. –

+0

우수. 정확히 내가 필요로하는 것. – Tomer

0
using (Graphics graphics = Graphics.FromImage(image)) 
    { 
     Point p = new Point(0, 0); 
     Point upperLeftSource = browser.PointToScreen(p); 
     Point upperLeftDestination = new Point(0, 0); 

     Size blockRegionSize = browser.ClientRectangle.Size; 
     blockRegionSize.Width = blockRegionSize.Width - 15; 
     blockRegionSize.Height = blockRegionSize.Height - 15; 
     graphics.CopyFromScreen(upperLeftSource, upperLeftDestination, blockRegionSize); 
    } 

정말 using statement이 필요합니까?

return image도 있지만 복사 된 이미지는 어떻게 할당 되나요?

+0

예 당신이 필요 당신이 좋은 이유가없는 한으로 IDisposable 개체를 처리하지, 사용 당신이해야 전체 작업 . 이미지는 Graphics Graphics = Graphics.FromImage (image) 라인을 통해 지정됩니다. –