Bart_Michael
asked on
Web Page Snapshot (BITMAP) in WebBrowser / Internet Explorer - FIX A BUG
Hello!
To "convert" a web page to a bitmap I have used excellent rllibby's code from
https://www.experts-exchange.com/questions/21608891/Web-Page-Snapshots-good-solution-but-help-needed.html
for example: CreateScaledImage(WebBrows er1,1).Sav eToFile('C :\test.bmp ');
It worked very well, but now...
In Internet Explorer 8 it does not work on MANY PAGES - for example
http://www.ableget.com
http://www.cnet.com
I spent lot of time trying to figure, what is wrong but I did not found the solution.
Does anybody has an idea, what is wrong? Did Microsoft changed something?
On simple pages this code works correctly - for example
http://www.google.com
I would be VERY GRATEFUL for suggestions.
Best regards
Bart
unit WebUtils;
////////////////////////// ////////// ////////// ////////// ////////// ////////// ////
//
// Ā Unit Ā Ā Ā Ā : Ā WebUtils
// Ā Date Ā Ā Ā Ā : Ā 10.27.2005 (updated 10.28.2005)
// Ā Description : Ā Utility functions based on the TWebBrowser object
//
//
// Ā function GetDocumentSize(Browser: TWebBrowser): TPoint;
//
// Ā Ā Ā Returns the document's body size as a TPoint, where X = width and Y = height
//
// Ā function GetBrowserElement(Browser: TWebBrowser; out Element: IHTMLElement2): HResult;
//
// Ā Ā Ā Returns the actual element required to perform the rendering to a canvas handle.
// Ā Ā Ā For most pages, this will be the body element. But for some, eg:
//
// Ā Ā Ā Ā https://www.experts-exchange.com
// Ā Ā Ā Ā http://www.msn.com
//
// Ā Ā Ā the parent element will need to be used. The element to use is based on
// Ā Ā Ā getting the parent and checking it for a clientwidth/height of zero. If zero,
// Ā Ā Ā then the body element can be used. If not zero, then the parent must be used.
//
// Ā function CreateThumbnailImage(Brows er: TWebBrowser; OutputSize: TPoint): TBitmap;
//
// Ā Ā Ā Returns a bitmap object of the document page where the width and height is
// Ā Ā Ā determined by the point (x = width, y=height) passed in OutputSize.
//
// Ā function CreateScaledImage(Browser: TWebBrowser; Scale: Double): TBitmap;
//
// Ā Ā Ā Returns a scaled bitmap object of the document page. A scaling of 1.0 will
// Ā Ā Ā return the page at its actual size. To return a 1/10 scaled image of the
// Ā Ā Ā document for example, 0.1 would be passed to Scale.
//
////////////////////////// ////////// ////////// ////////// ////////// ////////// ////
interface
////////////////////////// ////////// ////////// ////////// ////////// ////////// ////
// Ā Include units
////////////////////////// ////////// ////////// ////////// ////////// ////////// ////
uses
Ā Windows, SysUtils, Classes, Graphics, ShdocVW, ActiveX, MSHTML;
////////////////////////// ////////// ////////// ////////// ////////// ////////// ////
// Ā Constants
////////////////////////// ////////// ////////// ////////// ////////// ////////// ////
const
Ā IID_IHTMLElementRender: TGUID = Ā '{3050F669-98B5-11CF-BB82- 00AA00BDCE 0B}';
////////////////////////// ////////// ////////// ////////// ////////// ////////// ////
// Ā Interfaces
////////////////////////// ////////// ////////// ////////// ////////// ////////// ////
type
Ā IHTMLElementRender Ā = Ā interface(IUnknown)
Ā Ā Ā ['{3050F669-98B5-11CF-BB82 -00AA00BDC E0B}']
Ā Ā Ā function Ā Ā Ā Ā Ā DrawToDC(_hDC: HDC): HResult; stdcall;
Ā Ā Ā function Ā Ā Ā Ā Ā SetDocumentPrinter(bstrPri nterName: WideString; _hDC: HDC): HResult; stdcall;
Ā end;
////////////////////////// ////////// ////////// ////////// ////////// ////////// ////
// Ā Utility functions
////////////////////////// ////////// ////////// ////////// ////////// ////////// ////
function Ā GetDocumentSize(Browser: TWebBrowser): TPoint;
function Ā GetBrowserElement(Browser: TWebBrowser; out Element: IHTMLElement2): HResult;
function Ā CreateThumbnailImage(Brows er: TWebBrowser; OutputSize: TPoint): TBitmap;
function Ā CreateScaledImage(Browser: TWebBrowser; Scale: Double): TBitmap;
implementation
function GetBrowserElement(Browser: TWebBrowser; out Element: IHTMLElement2): HResult;
var Ā pDoc: Ā Ā Ā Ā Ā IHTMLDocument2;
Ā Ā Ā pElemParent: Ā IHTMLElement;
Ā Ā Ā pElement: Ā Ā Ā IHTMLElement;
Ā Ā Ā pElement2: Ā Ā IHTMLElement2;
begin
Ā // Check browser document
Ā if Assigned(Browser.Document) then
Ā begin
Ā Ā Ā // QI for document 2 interface
Ā Ā Ā result:=Browser.Document.Q ueryInterf ace(IHTMLD ocument2, pDoc);
Ā Ā Ā // Check result
Ā Ā Ā if Succeeded(result) then
Ā Ā Ā begin
Ā Ā Ā Ā // Resource protection
Ā Ā Ā Ā try
Ā Ā Ā Ā Ā Ā // Check document body
Ā Ā Ā Ā Ā Ā if Assigned(pDoc.Body) then
Ā Ā Ā Ā Ā Ā begin
Ā Ā Ā Ā Ā Ā Ā // QI for body element
Ā Ā Ā Ā Ā Ā Ā result:=pDoc.Body.QueryInt erface(IHT MLElement, pElement);
Ā Ā Ā Ā Ā Ā Ā // Check result
Ā Ā Ā Ā Ā Ā Ā if Succeeded(result) then
Ā Ā Ā Ā Ā Ā Ā begin
Ā Ā Ā Ā Ā Ā Ā Ā Ā // Resource protection
Ā Ā Ā Ā Ā Ā Ā Ā Ā try
Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā // Get parent element
Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā pElemParent:=pElement.pare ntElement;
Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā // Check parent
Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā if Assigned(pElemParent) then
Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā begin
Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā // Resource protection
Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā try
Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā // Get the element 2 interface
Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā if Succeeded(pElemParent.Quer yInterface (IHTMLElem ent2, pElement2)) then
Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā begin
Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā // Check parent interface for zero client width or height
Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā if (pElement2.clientWidth = 0) or (pElement2.clientHeight = 0) then
Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā // QI for element 2 interface
Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā result:=pElement.QueryInte rface(IHTM LElement2, Element)
Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā else
Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā // We have the element we are after
Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Element:=pElement2;
Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā end
Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā else
Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā // QI for element 2 interface
Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā result:=pElement.QueryInte rface(IHTM LElement2, Element);
Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā finally
Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā // Release the interface
Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā pElemParent:=nil;
Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā end;
Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā end
Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā else
Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā // Return nearest COM error
Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā result:=E_NOINTERFACE;
Ā Ā Ā Ā Ā Ā Ā Ā Ā finally
Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā // Release the interface
Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā pElement:=nil;
Ā Ā Ā Ā Ā Ā Ā Ā Ā end;
Ā Ā Ā Ā Ā Ā Ā end;
Ā Ā Ā Ā Ā Ā end
Ā Ā Ā Ā Ā Ā else
Ā Ā Ā Ā Ā Ā Ā // Return nearest COM error
Ā Ā Ā Ā Ā Ā Ā result:=E_NOINTERFACE;
Ā Ā Ā Ā finally
Ā Ā Ā Ā Ā Ā // Release the interface
Ā Ā Ā Ā Ā Ā pDoc:=nil;
Ā Ā Ā Ā end;
Ā Ā Ā end;
Ā end
Ā else
Ā Ā Ā // Return nearest COM error
Ā Ā Ā result:=E_NOINTERFACE;
end;
function GetDocumentSize(Browser: TWebBrowser): TPoint;
var Ā pElement: Ā Ā Ā IHTMLElement2;
begin
Ā // Get the browser body element interface
Ā if Succeeded(GetBrowserElemen t(Browser, pElement)) then
Ā begin
Ā Ā Ā // Resource protection
Ā Ā Ā try
Ā Ā Ā Ā // Set result size
Ā Ā Ā Ā result:=Point(pElement.Scr ollWidth, pElement.ScrollHeight);
Ā Ā Ā finally
Ā Ā Ā Ā // Release the interface
Ā Ā Ā Ā pElement:=nil;
Ā Ā Ā end;
Ā end
end;
function CreateScaledImage(Browser: TWebBrowser; Scale: Double): TBitmap;
var Ā ptActual: Ā Ā Ā TPoint;
Ā Ā Ā ptScale: Ā Ā Ā TPoint;
begin
Ā // Get actual size
Ā ptActual:=GetDocumentSize( Browser);
Ā // Apply the scaling to it
Ā ptScale.x:=Round(ptActual. x * Scale);
Ā ptScale.y:=Round(ptActual. y * Scale);
Ā // Get the image
Ā result:=CreateThumbnailIma ge(Browser , ptScale);
end;
function CreateThumbnailImage(Brows er: TWebBrowser; OutputSize: TPoint): TBitmap;
var Ā pElement: Ā Ā Ā IHTMLElement2;
Ā Ā Ā pRender: Ā Ā Ā IHTMLElementRender;
Ā Ā Ā bmpRender: Ā Ā Array [0..1] of TBitmap;
Ā Ā Ā dwClientWidth: Integer;
Ā Ā Ā dwClientHeight:Integer;
Ā Ā Ā dwIndex: Ā Ā Ā Integer;
Ā Ā Ā dwX: Ā Ā Ā Ā Ā Integer;
Ā Ā Ā dwLastX: Ā Ā Ā Integer;
Ā Ā Ā bDoneX: Ā Ā Ā Ā Boolean;
Ā Ā Ā dwY: Ā Ā Ā Ā Ā Integer;
Ā Ā Ā dwLastY: Ā Ā Ā Integer;
Ā Ā Ā bDoneY: Ā Ā Ā Ā Boolean;
begin
Ā // Create resulting image
Ā result:=TBitmap.Create;
Ā // Set size
Ā result.Width:=OutputSize.x ;
Ā result.Height:=OutputSize. y;
Ā // Lock update
Ā LockWindowUpdate(Browser.H andle);
Ā // Resource protection
Ā try
Ā Ā Ā // Get the browser body element interface
Ā Ā Ā if Succeeded(GetBrowserElemen t(Browser, pElement)) then
Ā Ā Ā begin
Ā Ā Ā Ā // Resource protection
Ā Ā Ā Ā try
Ā Ā Ā Ā Ā Ā // Get the renderer
Ā Ā Ā Ā Ā Ā if Succeeded(pElement.QueryIn terface(II D_IHTMLEle mentRender , pRender)) then
Ā Ā Ā Ā Ā Ā begin
Ā Ā Ā Ā Ā Ā Ā // Resource protection
Ā Ā Ā Ā Ā Ā Ā try
Ā Ā Ā Ā Ā Ā Ā Ā Ā // Create images to blit the parts to
Ā Ā Ā Ā Ā Ā Ā Ā Ā for dwIndex:=0 to 1 do
Ā Ā Ā Ā Ā Ā Ā Ā Ā begin
Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā bmpRender[dwIndex]:=TBitma p.Create;
Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā bmpRender[dwIndex].Width:= pElement.s crollWidth ;
Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā bmpRender[dwIndex].Height: =pElement. scrollHeig ht;
Ā Ā Ā Ā Ā Ā Ā Ā Ā end;
Ā Ā Ā Ā Ā Ā Ā Ā Ā // Set render "printer"
Ā Ā Ā Ā Ā Ā Ā Ā Ā pRender.SetDocumentPrinter ('Bitmap', bmpRender[0].Canvas.Handle );
Ā Ā Ā Ā Ā Ā Ā Ā Ā // Get client width and height
Ā Ā Ā Ā Ā Ā Ā Ā Ā dwClientWidth:=pElement.cl ientWidth;
Ā Ā Ā Ā Ā Ā Ā Ā Ā dwClientHeight:=pElement.c lientHeigh t;
Ā Ā Ā Ā Ā Ā Ā Ā Ā // Resource protection
Ā Ā Ā Ā Ā Ā Ā Ā Ā try
Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā // Set starting X variables
Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā dwX:=pElement.scrollWidth;
Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā dwLastX:=(-1);
Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā bDoneX:=False;
Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā // Loop while X not done
Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā while not(bDoneX) do
Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā begin
Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā // Scroll
Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā pElement.scrollLeft:=dwX;
Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā // Get scroll
Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā dwX:=pElement.scrollLeft;
Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā // Check for (-1)
Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā if (dwLastX = (-1)) then dwLastX:=dwX + dwClientWidth;
Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā // Set starting Y variables
Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā dwY:=pElement.scrollHeight ;
Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā dwLastY:=(-1);
Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā bDoneY:=False;
Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā // Loop while Y not done
Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā while not(bDoneY) do
Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā begin
Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā // Scroll
Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā pElement.scrollTop:=dwY;
Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā // Get scroll
Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā dwY:=pElement.scrollTop;
Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā // Check for (-1)
Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā if (dwLastY = (-1)) then dwLastY:=dwY + dwClientHeight;
Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā // Draw to bitmap handle
Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā if (pRender.DrawToDC(bmpRende r[0].Canva s.Handle) = S_OK) then
Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā begin
Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā // Blit the image
Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā BitBlt(bmpRender[1].Canvas .Handle, dwX, dwY, dwLastX-dwX, dwLastY-dwY, bmpRender[0].Canvas.Handle , 2, 2,SRCCOPY);
Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā end;
Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā // Update the Y variables
Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā bDoneY:=(dwY = 0);
Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā dwLastY:=dwY;
Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Dec(dwY, (dwClientHeight-4));
Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā end;
Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā // Update the X variables
Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā bDoneX:=(dwX = 0);
Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā dwLastX:=dwX;
Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Dec(dwX, (dwClientWidth-4));
Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā end;
Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā // Stretch draw the image to the resulting bitmap
Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā StretchBlt(result.Canvas.H andle, 0, 0, OutputSize.x, OutputSize.y, bmpRender[1].Canvas.Handle , 0, 0, bmpRender[1].Width, bmpRender[1].Height, SRCCOPY);
Ā Ā Ā Ā Ā Ā Ā Ā Ā finally
Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā // Free the bitmap
Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā for dwIndex:=0 to 1 do FreeAndNil(bmpRender[dwInd ex]);
Ā Ā Ā Ā Ā Ā Ā Ā Ā end;
Ā Ā Ā Ā Ā Ā Ā finally
Ā Ā Ā Ā Ā Ā Ā Ā Ā // Release the interface
Ā Ā Ā Ā Ā Ā Ā Ā Ā pRender:=nil;
Ā Ā Ā Ā Ā Ā Ā end;
Ā Ā Ā Ā Ā Ā end;
Ā Ā Ā Ā finally
Ā Ā Ā Ā Ā Ā // Release the interfaces
Ā Ā Ā Ā Ā Ā pElement:=nil;
Ā Ā Ā Ā end;
Ā Ā Ā end;
Ā finally
Ā Ā Ā // Unlock update
Ā Ā Ā LockWindowUpdate(0);
Ā end;
end;
end.
To "convert" a web page to a bitmap I have used excellent rllibby's code from
https://www.experts-exchange.com/questions/21608891/Web-Page-Snapshots-good-solution-but-help-needed.html
for example: CreateScaledImage(WebBrows
It worked very well, but now...
In Internet Explorer 8 it does not work on MANY PAGES - for example
http://www.ableget.com
http://www.cnet.com
I spent lot of time trying to figure, what is wrong but I did not found the solution.
Does anybody has an idea, what is wrong? Did Microsoft changed something?
On simple pages this code works correctly - for example
http://www.google.com
I would be VERY GRATEFUL for suggestions.
Best regards
Bart
unit WebUtils;
//////////////////////////
//
// Ā Unit Ā Ā Ā Ā : Ā WebUtils
// Ā Date Ā Ā Ā Ā : Ā 10.27.2005 (updated 10.28.2005)
// Ā Description : Ā Utility functions based on the TWebBrowser object
//
//
// Ā function GetDocumentSize(Browser: TWebBrowser): TPoint;
//
// Ā Ā Ā Returns the document's body size as a TPoint, where X = width and Y = height
//
// Ā function GetBrowserElement(Browser:
//
// Ā Ā Ā Returns the actual element required to perform the rendering to a canvas handle.
// Ā Ā Ā For most pages, this will be the body element. But for some, eg:
//
// Ā Ā Ā Ā https://www.experts-exchange.com
// Ā Ā Ā Ā http://www.msn.com
//
// Ā Ā Ā the parent element will need to be used. The element to use is based on
// Ā Ā Ā getting the parent and checking it for a clientwidth/height of zero. If zero,
// Ā Ā Ā then the body element can be used. If not zero, then the parent must be used.
//
// Ā function CreateThumbnailImage(Brows
//
// Ā Ā Ā Returns a bitmap object of the document page where the width and height is
// Ā Ā Ā determined by the point (x = width, y=height) passed in OutputSize.
//
// Ā function CreateScaledImage(Browser:
//
// Ā Ā Ā Returns a scaled bitmap object of the document page. A scaling of 1.0 will
// Ā Ā Ā return the page at its actual size. To return a 1/10 scaled image of the
// Ā Ā Ā document for example, 0.1 would be passed to Scale.
//
//////////////////////////
interface
//////////////////////////
// Ā Include units
//////////////////////////
uses
Ā Windows, SysUtils, Classes, Graphics, ShdocVW, ActiveX, MSHTML;
//////////////////////////
// Ā Constants
//////////////////////////
const
Ā IID_IHTMLElementRender: TGUID = Ā '{3050F669-98B5-11CF-BB82-
//////////////////////////
// Ā Interfaces
//////////////////////////
type
Ā IHTMLElementRender Ā = Ā interface(IUnknown)
Ā Ā Ā ['{3050F669-98B5-11CF-BB82
Ā Ā Ā function Ā Ā Ā Ā Ā DrawToDC(_hDC: HDC): HResult; stdcall;
Ā Ā Ā function Ā Ā Ā Ā Ā SetDocumentPrinter(bstrPri
Ā end;
//////////////////////////
// Ā Utility functions
//////////////////////////
function Ā GetDocumentSize(Browser: TWebBrowser): TPoint;
function Ā GetBrowserElement(Browser:
function Ā CreateThumbnailImage(Brows
function Ā CreateScaledImage(Browser:
implementation
function GetBrowserElement(Browser:
var Ā pDoc: Ā Ā Ā Ā Ā IHTMLDocument2;
Ā Ā Ā pElemParent: Ā IHTMLElement;
Ā Ā Ā pElement: Ā Ā Ā IHTMLElement;
Ā Ā Ā pElement2: Ā Ā IHTMLElement2;
begin
Ā // Check browser document
Ā if Assigned(Browser.Document)
Ā begin
Ā Ā Ā // QI for document 2 interface
Ā Ā Ā result:=Browser.Document.Q
Ā Ā Ā // Check result
Ā Ā Ā if Succeeded(result) then
Ā Ā Ā begin
Ā Ā Ā Ā // Resource protection
Ā Ā Ā Ā try
Ā Ā Ā Ā Ā Ā // Check document body
Ā Ā Ā Ā Ā Ā if Assigned(pDoc.Body) then
Ā Ā Ā Ā Ā Ā begin
Ā Ā Ā Ā Ā Ā Ā // QI for body element
Ā Ā Ā Ā Ā Ā Ā result:=pDoc.Body.QueryInt
Ā Ā Ā Ā Ā Ā Ā // Check result
Ā Ā Ā Ā Ā Ā Ā if Succeeded(result) then
Ā Ā Ā Ā Ā Ā Ā begin
Ā Ā Ā Ā Ā Ā Ā Ā Ā // Resource protection
Ā Ā Ā Ā Ā Ā Ā Ā Ā try
Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā // Get parent element
Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā pElemParent:=pElement.pare
Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā // Check parent
Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā if Assigned(pElemParent) then
Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā begin
Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā // Resource protection
Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā try
Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā // Get the element 2 interface
Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā if Succeeded(pElemParent.Quer
Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā begin
Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā // Check parent interface for zero client width or height
Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā if (pElement2.clientWidth = 0) or (pElement2.clientHeight = 0) then
Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā // QI for element 2 interface
Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā result:=pElement.QueryInte
Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā else
Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā // We have the element we are after
Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Element:=pElement2;
Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā end
Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā else
Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā // QI for element 2 interface
Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā result:=pElement.QueryInte
Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā finally
Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā // Release the interface
Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā pElemParent:=nil;
Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā end;
Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā end
Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā else
Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā // Return nearest COM error
Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā result:=E_NOINTERFACE;
Ā Ā Ā Ā Ā Ā Ā Ā Ā finally
Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā // Release the interface
Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā pElement:=nil;
Ā Ā Ā Ā Ā Ā Ā Ā Ā end;
Ā Ā Ā Ā Ā Ā Ā end;
Ā Ā Ā Ā Ā Ā end
Ā Ā Ā Ā Ā Ā else
Ā Ā Ā Ā Ā Ā Ā // Return nearest COM error
Ā Ā Ā Ā Ā Ā Ā result:=E_NOINTERFACE;
Ā Ā Ā Ā finally
Ā Ā Ā Ā Ā Ā // Release the interface
Ā Ā Ā Ā Ā Ā pDoc:=nil;
Ā Ā Ā Ā end;
Ā Ā Ā end;
Ā end
Ā else
Ā Ā Ā // Return nearest COM error
Ā Ā Ā result:=E_NOINTERFACE;
end;
function GetDocumentSize(Browser: TWebBrowser): TPoint;
var Ā pElement: Ā Ā Ā IHTMLElement2;
begin
Ā // Get the browser body element interface
Ā if Succeeded(GetBrowserElemen
Ā begin
Ā Ā Ā // Resource protection
Ā Ā Ā try
Ā Ā Ā Ā // Set result size
Ā Ā Ā Ā result:=Point(pElement.Scr
Ā Ā Ā finally
Ā Ā Ā Ā // Release the interface
Ā Ā Ā Ā pElement:=nil;
Ā Ā Ā end;
Ā end
end;
function CreateScaledImage(Browser:
var Ā ptActual: Ā Ā Ā TPoint;
Ā Ā Ā ptScale: Ā Ā Ā TPoint;
begin
Ā // Get actual size
Ā ptActual:=GetDocumentSize(
Ā // Apply the scaling to it
Ā ptScale.x:=Round(ptActual.
Ā ptScale.y:=Round(ptActual.
Ā // Get the image
Ā result:=CreateThumbnailIma
end;
function CreateThumbnailImage(Brows
var Ā pElement: Ā Ā Ā IHTMLElement2;
Ā Ā Ā pRender: Ā Ā Ā IHTMLElementRender;
Ā Ā Ā bmpRender: Ā Ā Array [0..1] of TBitmap;
Ā Ā Ā dwClientWidth: Integer;
Ā Ā Ā dwClientHeight:Integer;
Ā Ā Ā dwIndex: Ā Ā Ā Integer;
Ā Ā Ā dwX: Ā Ā Ā Ā Ā Integer;
Ā Ā Ā dwLastX: Ā Ā Ā Integer;
Ā Ā Ā bDoneX: Ā Ā Ā Ā Boolean;
Ā Ā Ā dwY: Ā Ā Ā Ā Ā Integer;
Ā Ā Ā dwLastY: Ā Ā Ā Integer;
Ā Ā Ā bDoneY: Ā Ā Ā Ā Boolean;
begin
Ā // Create resulting image
Ā result:=TBitmap.Create;
Ā // Set size
Ā result.Width:=OutputSize.x
Ā result.Height:=OutputSize.
Ā // Lock update
Ā LockWindowUpdate(Browser.H
Ā // Resource protection
Ā try
Ā Ā Ā // Get the browser body element interface
Ā Ā Ā if Succeeded(GetBrowserElemen
Ā Ā Ā begin
Ā Ā Ā Ā // Resource protection
Ā Ā Ā Ā try
Ā Ā Ā Ā Ā Ā // Get the renderer
Ā Ā Ā Ā Ā Ā if Succeeded(pElement.QueryIn
Ā Ā Ā Ā Ā Ā begin
Ā Ā Ā Ā Ā Ā Ā // Resource protection
Ā Ā Ā Ā Ā Ā Ā try
Ā Ā Ā Ā Ā Ā Ā Ā Ā // Create images to blit the parts to
Ā Ā Ā Ā Ā Ā Ā Ā Ā for dwIndex:=0 to 1 do
Ā Ā Ā Ā Ā Ā Ā Ā Ā begin
Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā bmpRender[dwIndex]:=TBitma
Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā bmpRender[dwIndex].Width:=
Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā bmpRender[dwIndex].Height:
Ā Ā Ā Ā Ā Ā Ā Ā Ā end;
Ā Ā Ā Ā Ā Ā Ā Ā Ā // Set render "printer"
Ā Ā Ā Ā Ā Ā Ā Ā Ā pRender.SetDocumentPrinter
Ā Ā Ā Ā Ā Ā Ā Ā Ā // Get client width and height
Ā Ā Ā Ā Ā Ā Ā Ā Ā dwClientWidth:=pElement.cl
Ā Ā Ā Ā Ā Ā Ā Ā Ā dwClientHeight:=pElement.c
Ā Ā Ā Ā Ā Ā Ā Ā Ā // Resource protection
Ā Ā Ā Ā Ā Ā Ā Ā Ā try
Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā // Set starting X variables
Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā dwX:=pElement.scrollWidth;
Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā dwLastX:=(-1);
Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā bDoneX:=False;
Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā // Loop while X not done
Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā while not(bDoneX) do
Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā begin
Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā // Scroll
Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā pElement.scrollLeft:=dwX;
Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā // Get scroll
Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā dwX:=pElement.scrollLeft;
Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā // Check for (-1)
Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā if (dwLastX = (-1)) then dwLastX:=dwX + dwClientWidth;
Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā // Set starting Y variables
Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā dwY:=pElement.scrollHeight
Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā dwLastY:=(-1);
Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā bDoneY:=False;
Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā // Loop while Y not done
Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā while not(bDoneY) do
Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā begin
Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā // Scroll
Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā pElement.scrollTop:=dwY;
Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā // Get scroll
Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā dwY:=pElement.scrollTop;
Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā // Check for (-1)
Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā if (dwLastY = (-1)) then dwLastY:=dwY + dwClientHeight;
Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā // Draw to bitmap handle
Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā if (pRender.DrawToDC(bmpRende
Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā begin
Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā // Blit the image
Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā BitBlt(bmpRender[1].Canvas
Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā end;
Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā // Update the Y variables
Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā bDoneY:=(dwY = 0);
Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā dwLastY:=dwY;
Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Dec(dwY, (dwClientHeight-4));
Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā end;
Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā // Update the X variables
Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā bDoneX:=(dwX = 0);
Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā dwLastX:=dwX;
Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Dec(dwX, (dwClientWidth-4));
Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā end;
Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā // Stretch draw the image to the resulting bitmap
Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā StretchBlt(result.Canvas.H
Ā Ā Ā Ā Ā Ā Ā Ā Ā finally
Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā // Free the bitmap
Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā for dwIndex:=0 to 1 do FreeAndNil(bmpRender[dwInd
Ā Ā Ā Ā Ā Ā Ā Ā Ā end;
Ā Ā Ā Ā Ā Ā Ā finally
Ā Ā Ā Ā Ā Ā Ā Ā Ā // Release the interface
Ā Ā Ā Ā Ā Ā Ā Ā Ā pRender:=nil;
Ā Ā Ā Ā Ā Ā Ā end;
Ā Ā Ā Ā Ā Ā end;
Ā Ā Ā Ā finally
Ā Ā Ā Ā Ā Ā // Release the interfaces
Ā Ā Ā Ā Ā Ā pElement:=nil;
Ā Ā Ā Ā end;
Ā Ā Ā end;
Ā finally
Ā Ā Ā // Unlock update
Ā Ā Ā LockWindowUpdate(0);
Ā end;
end;
end.
ASKER CERTIFIED SOLUTION
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
ASKER
Thank You VERY MUCH!
Your code works correctly. I have found on the Internet, that Internet Explorer 8 has bugs in IHTMLElementRender.DrawToD C
Your solution uses IViewObject.Draw, and it works fine (until a new bug will be introduced :-)
Best regards
Bart
Your code works correctly. I have found on the Internet, that Internet Explorer 8 has bugs in IHTMLElementRender.DrawToD
Your solution uses IViewObject.Draw, and it works fine (until a new bug will be introduced :-)
Best regards
Bart
the suggested solution however only creates a screenshot of the part of the website visible in the browser, the first code makes a full copy of the website, regardless of the size of the TWebbrowser.
Open in new window