Thumbnail thumbnail = new Thumbnail(html, 800, 600, width, height, Thumbnail.ThumbnailMethod.Html);Then the GenerateThumbnail method is the most important bit. However in-order to use WebBrowser control in a web page (MTA – Multi Threaded Apartment) we have to execute the WebBrowser control in a STA (Single Thread Apartment). For this I create a separate thread a set apartment state to STA.
public Bitmap GenerateThumbnail() { Thread thread = new Thread(new ThreadStart(GenerateThumbnailInteral)); thread.SetApartmentState(ApartmentState.STA); thread.Start(); thread.Join(); return ThumbnailImage; }In the thread start, as the internal method I use GenerateThumbnailInternal method. In that method, I assign an event handler to the web browser object’s DocumentCompleted method. But the problem is it takes a while to web browser complete the request. By that time page finishes the execution. So we have to delay the page execution until WebBrowser completes the request. For this I use Application.DoEvents() method. I put the execution in a loop while WebBrowser is not completed its navigation.
private void GenerateThumbnailInteral() { WebBrowser webBrowser = new WebBrowser(); webBrowser.ScrollBarsEnabled = false; if (this.Method == ThumbnailMethod.Url) webBrowser.Navigate(this.Url); else webBrowser.DocumentText = this.Html; webBrowser.DocumentCompleted += new WebBrowserDocumentCompletedEventHandler(WebBrowser_DocumentCompleted); while (webBrowser.ReadyState != WebBrowserReadyState.Complete) Application.DoEvents(); webBrowser.Dispose(); }Then in the DocumentCompleted method, I create the bitmap using WebBrowser’s DrawToBmp(...) method.
/// /// this.ThumbnailImage is a BitMap object /// this.ThumbnailImage = new Bitmap(webBrowser.Bounds.Width, webBrowser.Bounds.Height); webBrowser.BringToFront(); webBrowser.DrawToBitmap(ThumbnailImage, webBrowser.Bounds); this.ThumbnailImage = (Bitmap)ThumbnailImage.GetThumbnailImage(Width, Height, null, IntPtr.Zero);
Putting all together
Markup:
<%@ Page Language="C#" CodeBehind="~/Test.aspx.cs" Inherits="ActiveTest.Test" %> <html xmlns="http://www.w3.org/1999/xhtml"> <head id="Head1" runat="server"> </head> <body> <form id="form1" runat="server"> <div> <asp:TextBox ID="txtWebsiteAddress" runat="server" Text="www.google.com" /> <asp:Button ID="btnCreateThumbnailImage" runat="server" Text="Create Thumbnail Image" OnClick="CreateThumbnailImage" /></td> <asp:TextBox ID="txtWidth" runat="server" Text="200" /> <asp:TextBox ID="txtHeight" runat="server" Text="200" /> <asp:Image ID="imgThumbnailImage" runat="server" Visible="false" /> </div> </form> </body> </html>
Code:
public partial class Test : Page { bool snap = false; protected void CreateThumbnailImage(object sender, EventArgs e) { snap = true; } protected override void Render(HtmlTextWriter writer) { if (snap) { int width = Int32.Parse(txtWidth.Text); int height = Int32.Parse(txtHeight.Text); StringBuilder builder = new StringBuilder(); HtmlTextWriter htw = new HtmlTextWriter(new StringWriter(builder)); base.Render(htw); string html = builder.ToString(); Thumbnail thumbnail = new Thumbnail(html, 800, 600, width, height, Thumbnail.ThumbnailMethod.Html); Bitmap image = thumbnail.GenerateThumbnail(); image.Save(Server.MapPath("~") + "/Thumbnail.bmp"); writer.Write(html); writer.Write("<img src=\"Thumbnail.bmp\" />"); } else base.Render(writer); } } public class Thumbnail { public enum ThumbnailMethod { Url, Html }; public string Url { get; set; } public Bitmap ThumbnailImage { get; set; } public int Width { get; set; } public int Height { get; set; } public int BrowserWidth { get; set; } public int BrowserHeight { get; set; } public string Html { get; set; } public ThumbnailMethod Method { get; set; } public Thumbnail(string data, int browserWidth, int browserHeight, int thumbnailWidth, int thumbnailHeight, ThumbnailMethod method) { this.Method = method; if (method == ThumbnailMethod.Url) this.Url = data; else if (method == ThumbnailMethod.Html) this.Html = data; this.BrowserWidth = browserWidth; this.BrowserHeight = browserHeight; this.Height = thumbnailHeight; this.Width = thumbnailWidth; } public Bitmap GenerateThumbnail() { Thread thread = new Thread(new ThreadStart(GenerateThumbnailInteral)); thread.SetApartmentState(ApartmentState.STA); thread.Start(); thread.Join(); return ThumbnailImage; } private void GenerateThumbnailInteral() { WebBrowser webBrowser = new WebBrowser(); webBrowser.ScrollBarsEnabled = false; if (this.Method == ThumbnailMethod.Url) webBrowser.Navigate(this.Url); else webBrowser.DocumentText = this.Html; webBrowser.DocumentCompleted += new WebBrowserDocumentCompletedEventHandler(WebBrowser_DocumentCompleted); while (webBrowser.ReadyState != WebBrowserReadyState.Complete) Application.DoEvents(); webBrowser.Dispose(); } private void WebBrowser_DocumentCompleted(object sender, WebBrowserDocumentCompletedEventArgs e) { WebBrowser webBrowser = (WebBrowser)sender; webBrowser.ClientSize = new Size(this.BrowserWidth, this.BrowserHeight); webBrowser.ScrollBarsEnabled = false; this.ThumbnailImage = new Bitmap(webBrowser.Bounds.Width, webBrowser.Bounds.Height); webBrowser.BringToFront(); webBrowser.DrawToBitmap(ThumbnailImage, webBrowser.Bounds); this.ThumbnailImage = (Bitmap)ThumbnailImage.GetThumbnailImage(Width, Height, null, IntPtr.Zero); } }
5 comments:
Hi
Good Morning
Thanks for the code
At the same time if you put explaination for the above code it will be very useful
Thanks
Updated - 12/10/2010
Thanks for the Updation
Thanks for the gr8 code
But the function
GenerateThumbnailInteral()
is taking infinite time and not returning anything.. Iam following the same your code ,is there anything else ???
Thanks
"Thanks for the gr8 code
But the function
GenerateThumbnailInteral()
is taking infinite time and not returning anything.. Iam following the same your code ,is there anything else ???"
This is because your web hosting provider does not allow STA threads.
Post a Comment