Wednesday, August 23, 2006

Render HTML To Image

This is a piece of .NET 2.0 code I’ve been toying with for ages and finally had some time to get it working – thanks to the many other people who’ve posted articles relating to this task. Lots of people seem to be selling components that do this but it’s such a fundamentally basic task I reckon it’s better to share this with everyone as it has so many uses.

 

Imports mshtml

Imports System.Runtime.InteropServices

Public Class getWebPageThumb

    Dim MyWebBrowser As System.Windows.Forms.WebBrowser = _

            New System.Windows.Forms.WebBrowser

 

    <Guid("3050f669-98b5-11cf-bb82-00aa00bdce0b"), _

    InterfaceType(ComInterfaceType.InterfaceIsIUnknown), _

    ComVisible(True), _

    ComImport()> _

    Interface IHTMLElementRender

        Sub DrawToDC(<[In]()> _

        ByVal hDC As IntPtr)

        Sub SetDocumentPrinter(<[In](), MarshalAs(UnmanagedType.BStr)> _

        ByVal bstrPrinterName As String, <[In]()> _

        ByVal hDC As IntPtr)

    End Interface

 

    Public Function getImage(ByVal url As String, ByVal thumbSize As Size) As Image

        Dim imageThumb As Image = Nothing

        MyWebBrowser.Url = New Uri(url)

        Dim startTime As Date = Now

 

        While MyWebBrowser.ReadyState <> WebBrowserReadyState.Complete

            Application.DoEvents()

            Threading.Thread.Sleep(100)

            If Now.Subtract(startTime).TotalMinutes > 1 Then Exit While

        End While

        MyWebBrowser.Size = New Size(800, 1200)

        Dim document As IHTMLDocument2 = _

                CType(MyWebBrowser.Document.DomDocument, IHTMLDocument2)

 

        If Not (document Is Nothing) Then

            Dim element As IHTMLElement = CType(document.body, IHTMLElement)

            If Not (element Is Nothing) Then

 

                Dim render As hostingForm.IHTMLElementRender _

                        = CType(element, hostingForm.IHTMLElementRender)

 

                If Not (render Is Nothing) Then

                    Dim bm As Bitmap = New Bitmap(1024, 1024)

                    Dim g As System.Drawing.Graphics

                    g = System.Drawing.Graphics.FromImage(bm)

                    g.SmoothingMode = Drawing2D.SmoothingMode.HighQuality

                    Try

                        Dim hdcDestination As IntPtr = g.GetHdc

                        render.DrawToDC(hdcDestination)

                        Dim hdcMemory As IntPtr = GDI32.CreateCompatibleDC(hdcDestination)

Dim bitmap As IntPtr = GDI32.CreateCompatibleBitmap(hdcDestination, _

MyWebBrowser.ClientRectangle.Width, MyWebBrowser.ClientRectangle.Height)

                        If Not (bitmap = IntPtr.Zero) Then

                            Dim hOld As IntPtr = CType(GDI32.SelectObject(hdcMemory, bitmap), IntPtr)

                            GDI32.BitBlt(hdcMemory, 0, 0, MyWebBrowser.ClientRectangle.Width, _

MyWebBrowser.ClientRectangle.Height, hdcDestination, 0, 0, _

CType(GDI32.TernaryRasterOperations.SRCCOPY, Integer))

                            GDI32.SelectObject(hdcMemory, hOld)

                            GDI32.DeleteDC(hdcMemory)

                            Dim myBmp As Bitmap = New Bitmap(1024, 1024)

                            g.ReleaseHdc(hdcDestination)

                            g.DrawImage(myBmp, New Point(0, 0))

                            imageThumb = bm.GetThumbnailImage(thumbSize.Width, thumbSize.Height, Nothing, Nothing)

                        End If

                    Finally

                        CType(g, IDisposable).Dispose()

                    End Try

                End If

            End If

        End If

        Return imageThumb

    End Function

 

End Class

 

Class GDI32

 

    Enum TernaryRasterOperations As Integer

        SRCCOPY = 13369376 'dest = source

        SRCPAINT = 15597702 'dest = source OR dest

        SRCAND = 8913094 'dest = source AND dest

        SRCINVERT = 6684742 'dest = source XOR dest

        SRCERASE = 4457256 'dest = source AND (NOT dest )

        NOTSRCCOPY = 3342344 'dest = (NOT source)

        NOTSRCERASE = 1114278 'dest = (NOT src) AND (NOT dest)

        MERGECOPY = 12583114 'dest = (source AND pattern)

        MERGEPAINT = 12255782 'dest = (NOT source) OR dest

        PATCOPY = 15728673 'dest = pattern

        PATPAINT = 16452105 'dest = DPSnoo

        PATINVERT = 5898313 'dest = pattern XOR dest

        DSTINVERT = 5570569 'dest = (NOT dest)

        BLACKNESS = 66 'dest = BLACK

        WHITENESS = 16711778 'dest = WHITE

 

    End Enum

 

    Public Shared SRCCOPY As Integer = &HCC0020

    ' BitBlt dwRop parameter

 

    <DllImport("gdi32.dll")> _

    Public Shared Function BitBlt(ByVal hObject As IntPtr, ByVal nXDest As Integer, ByVal nYDest As Integer, ByVal nWidth As Integer, ByVal nHeight As Integer, ByVal hObjectSource As IntPtr, ByVal nXSrc As Integer, ByVal nYSrc As Integer, ByVal dwRop As Integer) As Boolean

    End Function

    <DllImport("gdi32.dll")> _

            Public Shared Function CreateCompatibleBitmap(ByVal hDC As IntPtr, ByVal nWidth As Integer, ByVal nHeight As Integer) As IntPtr

    End Function

    <DllImport("gdi32.dll")> _

    Public Shared Function CreateCompatibleDC(ByVal hDC As IntPtr) As IntPtr

    End Function

    <DllImport("gdi32.dll")> _

    Public Shared Function DeleteDC(ByVal hDC As IntPtr) As Boolean

    End Function

    <DllImport("gdi32.dll")> _

    Public Shared Function DeleteObject(ByVal hObject As IntPtr) As Boolean

    End Function

    <DllImport("gdi32.dll")> _

    Public Shared Function SelectObject(ByVal hDC As IntPtr, ByVal hObject As IntPtr) As IntPtr

    End Function

 

End Class 'GDI32

 

No comments: