Scenario: web application in Asp.NET per la gestione e pubblicazione di un piccolo magazine informativo ad uso interno.

Oltre al numero attuale, gli utenti possono accedere, da una apposita pagina di archivio, alle precedenti pubblicazioni.
Perche' non realizzare qualcosa per creare in tempo reale uno screenshot del numero in archivio, ridurlo a piccolo thumbnail e affiancarlo alla descrizione del numero in elenco?

Di gia' fatto non ho trovato niente, a parte un controllo ActiveX 'commerciale' e sinceramente molto poco economico, quindi ho deciso di realizzare qualcosa partendo da zero.

L'idea e' questa: perche' non utilizzare un controllo di tipo WebBrowser per caricare la pagina della quale vogliamo realizzare lo screenshot e poi 'ritagliare' il contenuto, salvando il tutto in una immagine?
Il tutto si puo' fare anche in maniera non 'visuale', impacchettando tutto in una bella classe che automatizza la procedura: in questo modo l'oggetto puo' essere usato indifferentemente in una web application o in una applicazione stand-alone.

Ho realizzato il tutto in C#: una volta impacchettato l'oggetto in una classlibrary ci si ritrova tra le mani un bel file .DLL da includere nella propria applicazione.

Di seguito il sorgente

[sourcecode language='csharp']
using System;
using System.Drawing;
using System.Windows.Forms;
using System.Threading;
using System.IO;
using System.Reflection;

using WinHttp;

public class WebSiteThumbnail
{
private string url = null;
private Bitmap bmp = null;
public Bitmap Image
{
get
{
return bmp;
}
}
private ManualResetEvent mre = new ManualResetEvent(false);
private int timeout = 5; // Da raffinare
private int thumbWidth;
private int thumbHeight;
private int width;
private int height;

#region Metodi Statici
public static Bitmap GetSiteThumbnail(string url, int width, int height, int thumbWidth, int thumbHeight)
{
WebSiteThumbnail thumb = new WebSiteThumbnail(url, width, height, thumbWidth, thumbHeight);
Bitmap b = thumb.GetScreenShot();
if (b == null)
b = (Bitmap)System.Drawing.Image.FromStream(Assembly.GetExecutingAssembly().GetManifestResourceStream("PAB.WebControls.Notavailable.jpg"));
return b;
}

#endregion

#region Constructors
public WebSiteThumbnail(string url, int width, int height, int thumbWidth, int thumbHeight)
{
this.url = url;
this.width = width;
this.height = height;
this.thumbHeight = thumbHeight;
this.thumbWidth = thumbWidth;
}
#endregion

#region ScreenShot
public Bitmap GetScreenShot()
{
Thread t = new Thread(new ThreadStart(_GetScreenShot));
t.SetApartmentState(ApartmentState.STA);
t.Start();
mre.WaitOne();
t.Abort();
return bmp;
}
#endregion
private void _GetScreenShot()
{
WebBrowser webBrowser = new WebBrowser();
webBrowser.ScrollBarsEnabled = false;
DateTime time = DateTime.Now;

webBrowser.Navigate(url);

webBrowser.DocumentCompleted += new WebBrowserDocumentCompletedEventHandler(WebBrowser_DocumentCompleted);
while (true)
{
Thread.Sleep(0);
TimeSpan elapsedTime = DateTime.Now - time;
if (elapsedTime.Seconds >= timeout)
{
mre.Set();
}
Application.DoEvents();
}

}
private void WebBrowser_DocumentCompleted(object sender, WebBrowserDocumentCompletedEventArgs e)
{
WebBrowser webBrowser = (WebBrowser)sender;
webBrowser.ClientSize = new Size(this.width, this.height);
webBrowser.ScrollBarsEnabled = false;
bmp = new Bitmap(webBrowser.Bounds.Width, webBrowser.Bounds.Height);
webBrowser.BringToFront();
webBrowser.DrawToBitmap(bmp, webBrowser.Bounds);
Image img = bmp.GetThumbnailImage(thumbWidth, thumbHeight, null, IntPtr.Zero);
bmp = (Bitmap)img;
webBrowser.Dispose();
if (mre != null)
mre.Set();
}

public void Dispose()
{
if (bmp != null) this.bmp.Dispose();
}
}[/sourcecode]
Veniamo a un esempio di utilizzo: una pagina .aspx che accetta come parametro l'url della pagina e restituisce uno stream con l'immagine della pagina.Realizzate quindi una nuova classlibrary, copiate il codice in GetSiteThumbnail.cs e compilate il tutto.Copiate poi la DLL generata nella directory 'bin' di un nuovo progetto web e realizzate un pagina chiamata (ad esempio) getsitethumb.aspx:
[sourcecode language="vb"]
< %@ Import Namespace="System.Drawing" %>
< %@ Import Namespace="System" %>
< %@ Import Namespace="System.Web" %>
< %@ Import Namespace="WebSiteThumbnail" %>

< %@ Page MaintainScrollPositionOnPostback="false" %>


[/sourcecode]
A questo punto, richiamando http://sito/getsitethumb.aspx?url=http://www.google.it visualizzerete sul browser un thumbnail di 1000x100px contenente una sezione di 715x715px dell'homepage di google.L'utilizzo all'interno di una normale pagina web e' quindi il seguente:

<img src="http://sito/getsitethumb.aspx?url=http://www.google.it">