How do I create cached image of a webpage. I just wanted to create a thumbnail of a webpage based on URL. There is no way, you would find the right stuff to do so. I found Alan Dean's page on Generate an image of a web page. He has explained the technique very well. Described his search for such code. He wrote on his own. There are a very few people got it working. So here is the code, took me a lot of time to get it working. Read through the sample I added here very carefully before you copy the code as is. I tried my best to write all comments to make it easy readable.
Tried it in all possible ways to make it successful the way I wanted. This code works awesome but I wanted to use System.drawing very well to make it work. There is no way I could find to do this without using Win32 Api. Apart from that, I need to add the axWebBrowser control and it needs to be visible on form in order to find the image of the web page. Then how do I do it on the fly on my website. There must be a way to create a thumbnail from webpage with out adding ActiveX controls....
Good Luck!! Let me know if this works for you.
Imports System.Windows.Forms
Public Class Form1
Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
'Add the axWebBrowser control from SHDocVw library to your form name it as axWebBrowser
'Add the Event Handler as DocumentComplete, because we need to capture screen image when document is completely loaded.
AddHandler axWebBrowser.DocumentComplete, AddressOf Me.OnDocumentComplete
Dim document As IHTMLDocument2 = CType(Me.axWebBrowser.Document, IHTMLDocument2)
End If
Finally
'You must dispose Graphics Object for better use.
'Check out Alan Dean's explaination, because I don;t get it. He is smarter than me, so I just believed that it works.
<Guid("3050f669-98b5-11cf-bb82-00aa00bdce0b"), System.Runtime.InteropServices.InterfaceTypeAttribute(System.Runtime.InteropServices.ComInterfaceType.InterfaceIsIUnknown), System.Runtime.InteropServices.ComVisible(True), System.Runtime.InteropServices.ComImport()> _
Tried it in all possible ways to make it successful the way I wanted. This code works awesome but I wanted to use System.drawing very well to make it work. There is no way I could find to do this without using Win32 Api. Apart from that, I need to add the axWebBrowser control and it needs to be visible on form in order to find the image of the web page. Then how do I do it on the fly on my website. There must be a way to create a thumbnail from webpage with out adding ActiveX controls....
Good Luck!! Let me know if this works for you.
'*************************************************************************
'This is main form Class where you will add the basic functions.
'*************************************************************************
Imports SHDocVw ' Import the shdocvw.dll from Widnows\System32 folder.
'This is main form Class where you will add the basic functions.
'*************************************************************************
Imports SHDocVw ' Import the shdocvw.dll from Widnows\System32 folder.
Imports
mshtml
' Import the mshtml.dll from Widnows\System32 folder.
Imports
System.Runtime.InteropServices
' Need this as we added above two as Interop
Imports System.Windows.Forms
Public Class Form1
Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
'Add the axWebBrowser control from SHDocVw library to your form name it as axWebBrowser
'Add the Event Handler as DocumentComplete, because we need to capture screen image when document is completely loaded.
AddHandler axWebBrowser.DocumentComplete, AddressOf Me.OnDocumentComplete
End
Sub
Private
Sub OnDocumentComplete(ByVal
sender As Object,
ByVal e As AxSHDocVw.DWebBrowserEvents2_DocumentCompleteEvent)
Dim document As IHTMLDocument2 = CType(Me.axWebBrowser.Document, IHTMLDocument2)
If Not (document Is
Nothing) Then
Dim element As IHTMLElement
= CType(document.body, IHTMLElement)
If Not (element
Is Nothing) Then
Dim render As
IHTMLElementRender = CType(element, IHTMLElementRender)
If Not (render
Is Nothing) Then
' Using
Dim graphics
As Graphics = Me.pictureBox.CreateGraphics
Try
Dim hdcDestination
As IntPtr = graphics.GetHdc
render.DrawToDC(hdcDestination)
Dim hdcMemory
As IntPtr = gdi32.CreateCompatibleDC(hdcDestination)
Dim bitmap As IntPtr = gdi32.CreateCompatibleBitmap(hdcDestination,
Me.axWebBrowser.ClientRectangle.Width,
Me.axWebBrowser.ClientRectangle.Height)
If
Not (bitmap = IntPtr.Zero) Then
Dim
hOld As IntPtr = CType(gdi32.SelectObject(hdcMemory,
bitmap), IntPtr)
gdi32.BitBlt(hdcMemory, 0, 0, Me.axWebBrowser.ClientRectangle.Width,
Me.axWebBrowser.ClientRectangle.Height, hdcDestination, 0, 0,
CType(gdi32.TernaryRasterOperations.SRCCOPY, Integer))
gdi32.SelectObject(hdcMemory, hOld)
gdi32.DeleteDC(hdcMemory)
graphics.ReleaseHdc(hdcDestination)
'Add a PictureBox control to your form, named pictureBox. This way you can
'see the image immediately after it is generated. You can save to FS using Bitmap.Save method.
'Add a PictureBox control to your form, named pictureBox. This way you can
'see the image immediately after it is generated. You can save to FS using Bitmap.Save method.
Me.pictureBox.Image
= Image.FromHbitmap(bitmap)
End If
Finally
'You must dispose Graphics Object for better use.
CType(graphics,
IDisposable).Dispose()
End
Try
End If
End If
End If
End
Sub
Private
Sub Button1_Click(ByVal
sender As System.Object,
ByVal e As System.EventArgs)
Handles Button1.Click
' Add a button to you
form named Button1.
' This way we can control when we want to start Browsing.
' Select the URI to be browsed here.
' This way we can control when we want to start Browsing.
' Select the URI to be browsed here.
Me.axWebBrowser.Navigate(New Uri("http://www.google.com"))
End
Sub
End
Class
'*************************************************************************
'This class for dummy for calling GDI Functions from Win32 Api.
'So that you can encapsulate whole GDI work outside.
'*************************************************************************
'This class for dummy for calling GDI Functions from Win32 Api.
'So that you can encapsulate whole GDI work outside.
'*************************************************************************
Public
Class gdi32
' I copied all the signatures in this class from http://www.pinvoke.net
' I copied all the signatures in this class from http://www.pinvoke.net
Public
Declare Function
DeleteDC Lib "gdi32.dll"
(ByVal hdc As
IntPtr) As Boolean
Public
Declare Function
SelectObject Lib "gdi32.dll"
(ByVal hdc As
IntPtr, ByVal hgdiobj As
IntPtr) As IntPtr
Public
Declare Function
CreateCompatibleDC Lib
"gdi32" (ByVal hDC
As IntPtr) As IntPtr
Public
Declare Function
CreateCompatibleBitmap Lib
"gdi32" (ByVal hDC
As IntPtr, ByVal nWidth
As Integer, ByVal
nHeight As Integer)
As IntPtr
Public
Declare Function
BitBlt Lib "gdi32"
(ByVal hDestDC As
IntPtr, ByVal x As
Integer, ByVal
y As Integer,
ByVal nWidth As
Integer, ByVal
nHeight As Integer,
ByVal hSrcDC As
IntPtr, ByVal xSrc As
Integer, ByVal
ySrc As Integer,
ByVal dwRop As
Integer) As Integer
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
End
Class
'Check out Alan Dean's explaination, because I don;t get it. He is smarter than me, so I just believed that it works.
<Guid("3050f669-98b5-11cf-bb82-00aa00bdce0b"), System.Runtime.InteropServices.InterfaceTypeAttribute(System.Runtime.InteropServices.ComInterfaceType.InterfaceIsIUnknown), System.Runtime.InteropServices.ComVisible(True), System.Runtime.InteropServices.ComImport()> _
Interface
IHTMLElementRender
Sub
DrawToDC(<System.Runtime.InteropServices.In()> ByVal
hDC As IntPtr)
Sub
SetDocumentPrinter(<System.Runtime.InteropServices.In(), System.Runtime.InteropServices.MarshalAs(UnmanagedType.BStr)>
ByVal bstrPrinterName As
String, <System.Runtime.InteropServices.In()>
ByVal hDC As IntPtr)
End
Interface
2 comments:
I have been moving my old entries across from dotnetjunkies to my new domain.
As part of that process, I have been reworking some of the content, where it was worth keeping. The "[How To] Generate an image of a web page" has been extensively rewritten and I have also made a Visual Studio 2005 solution available for download as well.
See http://thoughtpad.net/alan-dean/web-page-image-thumbnail.html
Thanks for the credit given :-)
Hi Vishal,
I want to create a windows service (batch process) which will take the newly added URLs from database and create thumbnails for the URLs. How can I change your code to make a Window's sevice.
Second challege is, if there is popup or confirmation box at the time of navigating to the URL using WebBrowser control, then OnDocumentCompleted event will not be complete and code will get hang at that point. Any solution for this problem?
-Megha
Post a Comment