Click here to Skip to main content
14,641,849 members
Rate this:
Please Sign up or sign in to vote.
See more:
Hi,

I need to show the preview of a webpage (html text) as a thumbnail image. Can someone suggest some ways to implement this functionality?

Thanks.
Posted
Comments
charles henington 14-May-13 4:40am
   
are you trying to show a preview of the html source or the webpage the way it looks in browser?
Amogh Natu 14-May-13 4:41am
   
I want to show the web page as it would have been rendered in the browser
Rate this:
Please Sign up or sign in to vote.

Solution 1

public static class NativeMethods
    {
        private const int SM_CXVSCROLL = 2;

        [ComImport]
        [Guid("0000010D-0000-0000-C000-000000000046")]
        [InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
        private interface IViewObject
        {
            void Draw([MarshalAs(UnmanagedType.U4)] uint dwAspect, int lindex, IntPtr pvAspect, [In] IntPtr ptd, IntPtr hdcTargetDev, IntPtr hdcDraw, [MarshalAs(UnmanagedType.Struct)] ref Rect lprcBounds, [In] IntPtr lprcWBounds, IntPtr pfnContinue, [MarshalAs(UnmanagedType.U4)] uint dwContinue);
        }

        public static int GetSystemMetrics()
        {
            return GetSystemMetrics(SM_CXVSCROLL);
        }

        [DllImport("user32.dll")]
        public static extern int GetSystemMetrics(int smIndex);

        public static void GetImage(object obj, Image destination, Color backgroundColor)
        {
            using (var graphics = Graphics.FromImage(destination))
            {
                var deviceContextHandle = IntPtr.Zero;
                var rectangle =
                    new Rect
                    {
                        Right = destination.Width,
                        Bottom = destination.Height
                    };

                graphics.Clear(backgroundColor);
                try
                {
                    deviceContextHandle = graphics.GetHdc();

                    var viewObject = obj as IViewObject;
                    viewObject.Draw(1, -1, IntPtr.Zero, IntPtr.Zero, IntPtr.Zero, deviceContextHandle, ref rectangle, IntPtr.Zero, IntPtr.Zero, 0);
                }
                finally
                {
                    if (deviceContextHandle != IntPtr.Zero)
                    {
                        graphics.ReleaseHdc(deviceContextHandle);
                    }
                }
            }
        }
    }


Heres where the magic happens

public class HtmlToBitmapConverter : IDisposable
	{
		private const int SleepTimeMiliseconds = 5000;
//the output from the Render call
        internal static Bitmap Output;
		public Bitmap Render(string html, Size size)
		{
			var browser = CreateBrowser(size);
			browser.Navigate("about:blank");
			browser.Document.Write(html);
            Output = GetBitmapFromControl(browser, size);
			return Output;
		}
		public Bitmap Render(Uri uri, Size size)
		{
			var browser = CreateBrowser(size);            
			NavigateAndWaitForLoad(browser, uri, 0);
            Output = GetBitmapFromControl(browser, size);
            return Output;			
		}
		public void NavigateAndWaitForLoad(WebBrowser browser, Uri uri, int waitTime)
		{
			browser.Navigate(uri);
			var count = 0;
			while (browser.ReadyState != WebBrowserReadyState.Complete)
			{
				Thread.Sleep(SleepTimeMiliseconds);
				
				Application.DoEvents();
				count++;
				
				if (count > waitTime / SleepTimeMiliseconds)
				{
					break;
				}
			}
			while (browser.Document.Body == null)
			{
				Application.DoEvents();
			}
			HideScrollBars(browser);
		}
		private void HideScrollBars(WebBrowser browser)
		{
			const string Hidden = "hidden";
			var document = (IHTMLDocument2)browser.Document.DomDocument;
			var style = (IHTMLStyle2)document.body.style;
			style.overflowX = Hidden;
			style.overflowY = Hidden;            
		}
		private WebBrowser CreateBrowser(Size size)
		{
			var 
				newBrowser =
					new WebBrowser
					{
						ScrollBarsEnabled = false,
						ScriptErrorsSuppressed = true,
						Size = size
					};
			newBrowser.BringToFront();
			return newBrowser;
		}
		private Bitmap GetBitmapFromControl(WebBrowser browser, Size size)
		{
			var bitmap = new Bitmap(size.Width, size.Height);
			NativeMethods.GetImage(browser.Document.DomDocument, bitmap, Color.White);
			return bitmap;
		}
        void IDisposable.Dispose()
        {
            GC.SuppressFinalize(this);
        }
    }


[StructLayout(LayoutKind.Sequential, Pack = 4)]
    public struct Rect
    {
        public int Left;

        public int Top;

        public int Right;

        public int Bottom;
    }
   
Comments
Amogh Natu 14-May-13 6:07am
   
Thanks a lot. It is working as expected except when I have an <img /> tag in the html string. Whenever I put an img tag in the HTML string, it just displays a 'X' mark in the output bitmap image. Any suggestions on this?
Rate this:
Please Sign up or sign in to vote.

Solution 2

I used an external dll (HtmlRenderer) that needs to be added in out project. HtmlRenderer namespace provides a class “HtmlRender” that provides an overloaded method “Render“. This method saves renders the html text and saves the outcome as an image.

The following code shows the usage of the method.

namespace HtmlToBmpImageDemo
{
     class Program
     {
         static void Main(string[] args)
         {
               Bitmap m_Bitmap = new Bitmap(400, 600);
               PointF point = new PointF(0, 0);
               SizeF maxSize = new System.Drawing.SizeF(500, 500);
               HtmlRenderer.HtmlRender.Render(Graphics.FromImage(m_Bitmap), "<html><body><p>This is a sample html code</p><p>This is another html line</p></body>", point, maxSize);
               
               m_Bitmap.Save(@"C:\Test.bmp");
         }
     }
}



The problem with this method is that if we include images in the HTML mark up text, the resultant image saved in C:\Test.bmp doesn’t show the image. There is yet another method of taking a screenshot of rendered html by opening a browser process in the background and then taking a screen shot of that. But I wanted a more lighter and simpler process and found this.

Hope this helps and please do let me know if there is any method of displaying images and then taking a screen shot of that rendered HTML.
   

This content, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)




CodeProject, 503-250 Ferrand Drive Toronto Ontario, M3C 3G8 Canada +1 416-849-8900 x 100