private Bitmap m_CapturedImage = null;
/// <summary>
/// Captures the current web page
/// </summary>
/// <overloads>
/// <summary>
/// Captures the current web page
/// </summary>
/// <example>
/// Capture the full image of a page (scrolls down the page) and returns an image
/// <code>
/// Image pageCapture = browser.CapturePage();
/// pageCapture.Save("C:\\test.bmp", ImageFormat.Bmp);
/// </code>
/// </example>
/// <example>
/// Capture top section of a page
/// <code>
/// Image pageCapture = browser.CapturePage(new Rectangle(0,0, 50, 50), false);
/// pageCapture.Save("C:\\test.bmp", ImageFormat.Bmp);
/// </code>
/// </example>
/// </overloads>
/// <example>
/// Capture the full image of a page (scrolls down the page) and save to the harddrive.
/// <code>
/// Image pageCapture = browser.CapturePage();
/// pageCapture.Save("C:\\test.bmp", ImageFormat.Bmp);
/// </code>
/// </example>
/// <returns>Image object of the requested capture</returns>
public Image CapturePage() { return CapturePage(new Rectangle(0,0,0,0), true); }
/// <summary>
/// Captures the current web page
/// </summary>
/// <example>
/// Capture top section of a page
/// <code>
/// Image pageCapture = browser.CapturePage(new Rectangle(0,0, 50, 50), false);
/// pageCapture.Save("C:\\test.bmp", ImageFormat.Bmp);
/// </code>
/// </example>
/// <param name="captureRegion">Coordinates to capture on the page.</param>
/// <param name="scrollDownPage">Scroll down the page when capturing
/// (this is better disabled on framesets)</param>
/// <returns>Image object of the requested capture</returns>
public Image CapturePage(Rectangle captureRegion, bool scrollDownPage)
{
if(this.ParentForm != null)
{
if(this.ParentForm.Opacity < 1.0)
{
this.ParentForm.Top = SystemInformation.VirtualScreen.Top - this.ParentForm.Height - 100;
this.ParentForm.Left = SystemInformation.VirtualScreen.Left - this.ParentForm.Width - 100;
this.ParentForm.Opacity = 1.0;
}
}
int VScrollBarOffset = 0;
int HScrollBarOffset = 0;
int PixelsScrolled = 0;
int CaptureHeight = 0;
int CaptureWidth = 0;
int FinalPageHeight = 0;
int CaptureDestinationY = 0;
int CaptureDestinationX = 0;
Rectangle CaptureRectangle;
// Captured page specific properties.
bool m_ScrollV = true;
// Get fresh copy of the doc objects (they need to be updated whenever the Navigation changes)
HTMLDocumentClass m_HTMLDoc = (HTMLDocumentClass)this.Document;
HTMLBodyClass m_HTMLBody = (HTMLBodyClass) m_HTMLDoc.body;
#region Figure Max Height and Set destination bitmap
// Check if there is a Horizontal Scroll bar
if(m_HTMLBody.scrollWidth > m_HTMLBody.clientWidth)
{
HScrollBarOffset = SystemInformation.HorizontalScrollBarHeight;
}
// Get final page height and height of capture area
CaptureHeight = browser.Height -
SystemInformation.Border3DSize.Height -
HScrollBarOffset;
if(m_ScrollV) // || m_HTMLBody.scrollHeight < m_PageHeight)
{
FinalPageHeight = m_HTMLBody.scrollHeight;
}
else
{
FinalPageHeight = CaptureHeight;
}
#endregion
#region Figure Width minus Vertical Scroll bar
VScrollBarOffset = SystemInformation.Border3DSize.Width;
// Set offset (0 if scroll bar is on right, VSBarWidth if on left (RTL)
if((m_HTMLDoc.dir != null && m_HTMLDoc.dir.ToLower() == "rtl") ||
(m_HTMLBody.dir != null && m_HTMLBody.dir.ToLower() == "rtl"))
{
VScrollBarOffset += SystemInformation.VerticalScrollBarWidth;
}
CaptureWidth = browser.Width -
SystemInformation.VerticalScrollBarWidth -
SystemInformation.Border3DSize.Width -
SystemInformation.Border3DSize.Width;
#endregion
#region Capture Full Web Page
// Create a Bitmap of the final size
m_CapturedImage = new Bitmap(CaptureWidth, FinalPageHeight);
PixelsScrolled = CaptureHeight - SystemInformation.Border3DSize.Height;
m_HTMLBody.scrollTop = 0;
// Build a full picture from each section of the page.
if(!m_ScrollV)
{
CaptureRectangle = new Rectangle(VScrollBarOffset, CaptureHeight - PixelsScrolled, CaptureWidth, CaptureHeight);
AddToScreenShot(CaptureRectangle, CaptureDestinationX, CaptureDestinationY);
}
else
{
int MaxScrolls = 0;
if(scrollDownPage)
{
MaxScrolls = m_HTMLBody.scrollHeight / CaptureHeight;
}
do
{
CaptureRectangle = new Rectangle(VScrollBarOffset, CaptureHeight - PixelsScrolled, CaptureWidth, PixelsScrolled);
AddToScreenShot(CaptureRectangle, CaptureDestinationX, CaptureDestinationY);
CaptureDestinationY = CaptureDestinationY + PixelsScrolled;
PixelsScrolled = scrollDown(HScrollBarOffset);
MaxScrolls--;
}
while(MaxScrolls > -1);
}
#endregion
if(captureRegion.Width != 0 && captureRegion.Height != 0)
{
return m_CapturedImage.Clone(captureRegion, m_CapturedImage.PixelFormat);
}
return m_CapturedImage;
}
/// <summary>
/// Scroll the page down one page.
/// </summary>
/// <returns>Number of pixels scrolled</returns>
private int scrollDown(int HScrollBarOffset)
{
HTMLDocumentClass m_HTMLDoc = (HTMLDocumentClass)this.Document;
HTMLBodyClass m_HTMLBody = (HTMLBodyClass) m_HTMLDoc.body;
int CaptureHeight = m_HTMLBody.offsetHeight;
int ScrollTop = m_HTMLBody.scrollTop;
int scrollAmount = ScrollTop + CaptureHeight - (m_HTMLBody.clientTop * 2) - HScrollBarOffset;
m_HTMLBody.scrollTop = scrollAmount;
int ScrollTopAfterScroll = 0;
if(m_HTMLBody.scrollTop == 0 && m_HTMLBody.scrollHeight >= scrollAmount)
{
Object parent = m_HTMLDoc.documentElement;
PropertyInfo prop = parent.GetType().GetProperty("scrollTop");
prop.SetValue(parent, scrollAmount, null);
ScrollTopAfterScroll = (int)prop.GetValue(parent, null);
}
else
{
ScrollTopAfterScroll = m_HTMLBody.scrollTop;
}
int PixelsScrolled = ScrollTopAfterScroll - ScrollTop;
if(PixelsScrolled <= 0)
{
return 0;
}
else
{
return PixelsScrolled;
}
}
/// <summary>
/// Copies visible image to a destination bitmap
/// </summary>
/// <param name="CaptureRectangle">Size within browser control to capture</param>
/// <param name="CaptureDestinationY">Starting Y postion for image in destination bitmap</param>
/// <param name="CaptureDestinationX">Starting X postion for image in destination bitmap</param>
private void AddToScreenShot(Rectangle CaptureRectangle, int CaptureDestinationX, int CaptureDestinationY)
{
if(this.ParentForm != null)
this.ParentForm.TransparencyKey = this.ParentForm.TransparencyKey; // Without this images off main montior won't display
Application.DoEvents(); // Makes sure the screen redraws
Graphics g1 = null;
Graphics g2 = null;
try
{
// Get Graphic object for source and destination
g1 = browser.CreateGraphics();
g2 = Graphics.FromImage(m_CapturedImage);
IntPtr dc1 = IntPtr.Zero;
IntPtr dc2 = IntPtr.Zero;
try
{
// Get the handles for the Graphics which are needed to perform the image copy
dc1 = g1.GetHdc();
dc2 = g2.GetHdc();
// Create a destination image the size of the visible browser window
BitBlt(dc2, CaptureDestinationX, CaptureDestinationY, CaptureRectangle.Width, CaptureRectangle.Height,
dc1, CaptureRectangle.X , CaptureRectangle.Y , 13369376);
}
finally
{
// Release holds on handles
if(dc1 != IntPtr.Zero) g1.ReleaseHdc(dc1);
if(dc2 != IntPtr.Zero) g2.ReleaseHdc(dc2);
}
}
finally
{
// Release holds on graphics
if(g1 != null) g1.Dispose();
if(g2 != null) g2.Dispose();
}
}
/// <summary>
/// BitBlit it a core GDI call which can copy an image from one hdc to another
/// </summary>
[DllImport("GDI32.DLL", EntryPoint="BitBlt", SetLastError=true,
CharSet=CharSet.Unicode, ExactSpelling=true,
CallingConvention=CallingConvention.StdCall)]
static extern bool BitBlt(IntPtr hdcDest, int nXDest, int nYDest,
int nWidth, int nHeight, IntPtr hdcSrc,
int nXSrc, int nYSrc, System.Int32 dwRop);