X
dnn.blog.
Back

Creating thumbs from a webpage

pizza Often it is a good thing to visualize a link to something with a thumb of the page you linked to. Imagine you have a link-module where you sample interesting links to, let’s say … pizza services. You want to add a screenshot of their homepage to help your visitors to identify the pizza service they are looking for. But adding all these thumbs manually is something you don’t wish your hardest enemy has to do. So, how can we accomplish this automatically ?

 

 

The WebBrowser Control

Most of the magic is done by the WebBrowser Control. We can instantiate a WebBrowser-Control, let it navigate to the Url we entered before.

WebBrowser ieBrowser = new WebBrowser();
ieBrowser.ScrollBarsEnabled = false; 
ieBrowser.ScriptErrorsSuppressed = true;
ieBrowser.DocumentCompleted += new WebBrowserDocumentCompletedEventHandler(IEBrowser_DocumentCompleted);
ieBrowser.Navigate(Url);

When the DocumentCompleted - event is fired, we are able to take a snapshot of the content. We have to deal a little bit with scrollbars but that is no magic at all.

void IEBrowser_DocumentCompleted(object sender, WebBrowserDocumentCompletedEventArgs e) 
{ 
   WebBrowser browser = (WebBrowser)sender; 
   browser.Width = doc.Body.ScrollRectangle.Width; 
   browser.Height = doc.Body.ScrollRectangle.Height; 
   Bitmap bitmap = new Bitmap(browser.Width, browser.Height); 
   browser.DrawToBitmap(bitmap, new Rectangle(0, 0, browser.Width, browser.Height));
   browser.Dispose(); 
   bitmap.Save(File, ImageFormat.Jpeg); 
}

Ups we need this in a static thread

If you integrate this in your DNN-Module and try to use it you get an error. You have to run the WebBrowser Control in a static thread. So we have to do a little bit more. Lets add a new class to our module:

using System.Windows.Forms; 
using System.Threading; 
using System.Drawing; 
using System.Drawing.Imaging; 

public class IEBrowser : System.Windows.Forms.ApplicationContext 
{ 
   string File; 
   AutoResetEvent ResultEvent; 

   public IEBrowser(string url, string file, AutoResetEvent resultEvent) 
   { 
      ResultEvent = resultEvent; 
      Thread thrd = new Thread(new ThreadStart( delegate { Init(url, file); System.Windows.Forms.Application.Run(this); })); 
      // set thread to STA state before starting 
      thrd.SetApartmentState(ApartmentState.STA);
      thrd.Start(); 
   } 

   private void Init(string Url, string file) 
   { 
      // create a WebBrowser control 
      WebBrowser ieBrowser = new WebBrowser(); 
      ieBrowser.ScrollBarsEnabled = false; 
      ieBrowser.ScriptErrorsSuppressed = true; 
      // set WebBrowser event handle 
      ieBrowser.DocumentCompleted += new WebBrowserDocumentCompletedEventHandler(IEBrowser_DocumentCompleted); 
      ieBrowser.Navigate(Url); File = file; 
   } 

   // DocumentCompleted event handle 
   void IEBrowser_DocumentCompleted(object sender, WebBrowserDocumentCompletedEventArgs e) 
   {
       try 
      { 
         WebBrowser browser = (WebBrowser)sender; 
         browser.Width = doc.Body.ScrollRectangle.Width; 
         browser.Height = doc.Body.ScrollRectangle.Height; 
         Bitmap bitmap = new Bitmap(browser.Width, browser.Height); 
         browser.DrawToBitmap(bitmap, new Rectangle(0, 0, browser.Width, browser.Height)); 
         browser.Dispose(); 
         bitmap.Save(File, ImageFormat.Jpeg); 
      } 
      catch (System.Exception) { } 
      finally 
      { 
         ResultEvent.Set(); 
      }
    } 
}

Now you can call the following code to save the snapshot:

AutoResetEvent resultEvent = new AutoResetEvent(false); 
IEBrowser browser = new IEBrowser("http://www.bitboxx.net", @"C:\InetPub\wwwroot\dnn\Portals\25\images/thumbs\22.jpg", resultEvent); 
EventWaitHandle.WaitAll(new AutoResetEvent[] { resultEvent });

Thats all. Only some bits of code but impressive when you see it in action.

Just another tip. If you want to save a snapshot from a HTML-snippet and not from a  webpage, you can inject this HTML into the WebBrowser control. The only thing you have to change is navigating to “about:blank” and in the DocumentCompleted-event add a little bit of code:

HtmlDocument doc = browser.Document; 
doc.OpenNew(true); 
doc.Write(Html);

If you read my blog post about flexible module design with templates, you can use this mimic to visualize the entered HTML in the template textbox. The only thing you must have in mind is, that you have to add references to all CSS files to your generated HTML. And don’t forget to add the opening and closing and tags

Example:

private void GenThumb(ProductTemplateInfo Template, string thumb)
{
    StringBuilder sb = new StringBuilder();
    sb.AppendLine("<html><head>");
    sb.AppendLine("<link href=\"file:///" + Server.MapPath("~/Portals/_default/default.css") + "\" rel=\"stylesheet\" type=\"text/css\" />");
    sb.AppendLine("<link href=\"file:///" + Server.MapPath("~/DesktopModules/BBStore/module.css") + "\" rel=\"stylesheet\" type=\"text/css\" />");
    sb.AppendLine("<link href=\"file:///" + Server.MapPath(PortalSettings.ActiveTab.SkinPath + "skin.css") + "\" rel=\"stylesheet\" type=\"text/css\" />");
    sb.AppendLine("<link href=\"file:///" + Server.MapPath(PortalSettings.HomeDirectory + "portal.css") + "\" rel=\"stylesheet\" type=\"text/css\" />");
    sb.AppendLine("</head>");
    sb.AppendLine("<body>");
    sb.Append(Template.Template);
    sb.AppendLine("</body></html>");

    sb.Replace("[TITLE]", "Product Title");
    sb.Replace("[PRODUCTDESCRIPTION]", "Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum .");
    sb.Replace("[PRODUCTOPTIONS]", "<span class=\"Normal\">ProductOption</span>&nbsp;<select class=\"NormalTextBox\" name=\"Select1\"><option>Option1</option></select>");
    sb.Replace("[MANDATORYERROR]", "Error Message");
    sb.Replace("[PRICE]", "123.44");
    sb.Replace("[CURRENCY]", PortalSettings.Currency);
    sb.Replace("[ADDCARTIMAGE]", "<img src=\"file:///" + Server.MapPath("~/images/cart.gif") + "\" />");
    sb.Replace("[ADDCARTLINK]", "Add to cart");
    sb.Replace("[TAX]", "includes tax (19%)");
    sb.Replace("[AMOUNT]", "<input name=\"Text1\" type=\"text\" size=\"3\" value=\"1\"/>");

    AutoResetEvent resultEvent = new AutoResetEvent(false);
    IEBrowser browser = new IEBrowser(false, sb.ToString(), thumb, resultEvent);
    EventWaitHandle.WaitAll(new AutoResetEvent[] { resultEvent });
}
Back

about.me.

Torsten WeggenMy name is Torsten Weggen and I am CEO of indisoftware GmbH in Hanover, Germany. I'm into DNN since 2008. Before this, I did a lot of desktop stuff mainly coded with Visual Foxpro (see http://www.auktionsbuddy.de). 

I'm programmer, husband, father + born in 1965.

Please feel free to contact me if you have questions.

Latest Posts

DNN module development with Angular 2+ (Part 7)
6/10/2018 1:43 PM | Torsten Weggen
DNN module development with AngularJS (Part 6)
12/16/2016 7:00 AM | Torsten Weggen
DNN module development with AngularJS (Part 5)
12/16/2016 6:00 AM | Torsten Weggen
DNN module development with AngularJS (Part 4)
12/16/2016 5:00 AM | Torsten Weggen
DNN module development with AngularJS (Part 3)
12/16/2016 4:00 AM | Torsten Weggen
DNN module development with AngularJS (Part 2)
12/16/2016 3:00 AM | Torsten Weggen
DNN module development with AngularJS (Part 1)
12/15/2016 7:19 AM | Torsten Weggen
Blogging in DNN with Markdown Monster by Rick Strahl
11/27/2016 1:14 PM | Torsten Weggen
Creating a global token engine
11/18/2016 10:25 AM | Torsten Weggen
DnnImagehandler - Hot or not ?
2/21/2015 11:52 PM | Torsten Weggen

My Twitter

Keine News gefunden!