开发者

How to take the snapshot of a IE webpage through a BHO (C#)

I am trying to build an IE BHO in C# for taking the snapshot of a webpage loaded in the IE browser. Here is what I'm trying to do:

public class ShowToolbarBHO : BandObjectLib.IObjectWithSite
{

    IWebBrowser2 webBrowser = null;

    public void SetSite (Object site)
    {
        .......
        if (site != null)
        {
            ......
            webBrowser = (IWebBrowser2)site;
            ......
        }
    }
}

Also, I p/invoke the following COM methods:

    [Guid("0000010D-0000-0000-C000-000000000046")]
    [InterfaceTypeAttribute(ComInterfaceType.InterfaceIsIUnknown)]
    [ComImportAttribute()]
    public interface IViewObject
    {
        void Draw([MarshalAs(UnmanagedType.U4)] 开发者_开发技巧int dwDrawAspect, int lindex, IntPtr pvAspect, [In] IntPtr ptd, IntPtr hdcTargetDev, IntPtr hdcDraw, [MarshalAs(UnmanagedType.LPStruct)] ref COMRECT lprcBounds, [In] IntPtr lprcWBounds, IntPtr pfnContinue, int dwContinue);
        int GetColorSet([MarshalAs(UnmanagedType.U4)] int dwDrawAspect, int lindex, IntPtr pvAspect, [In] IntPtr ptd, IntPtr hicTargetDev, [Out] IntPtr ppColorSet);
        int Freeze([MarshalAs(UnmanagedType.U4)] int dwDrawAspect, int lindex, IntPtr pvAspect, out IntPtr pdwFreeze);
        int Unfreeze([MarshalAs(UnmanagedType.U4)] int dwFreeze);
        int SetAdvise([MarshalAs(UnmanagedType.U4)] int aspects, [MarshalAs(UnmanagedType.U4)] int advf, [MarshalAs(UnmanagedType.Interface)] IAdviseSink pAdvSink);
        void GetAdvise([MarshalAs(UnmanagedType.LPArray)] out int[] paspects, [MarshalAs(UnmanagedType.LPArray)] out int[] advf, [MarshalAs(UnmanagedType.LPArray)] out IAdviseSink[] pAdvSink);
    }

    [StructLayoutAttribute(LayoutKind.Sequential)]
    public class COMRECT
    {
        public int left;
        public int top;
        public int right;
        public int bottom;

        public COMRECT()
        {
        }

        public COMRECT(int left, int top, int right, int bottom)
        {
            this.left = left;
            this.top = top;
            this.right = right;
            this.bottom = bottom;
        }
    }

    [InterfaceTypeAttribute(ComInterfaceType.InterfaceIsIUnknown)]
    [ComVisibleAttribute(true)]
    [GuidAttribute("0000010F-0000-0000-C000-000000000046")]
    [ComImportAttribute()]
    public interface IAdviseSink
    {
        void OnDataChange([In]IntPtr pFormatetc, [In]IntPtr pStgmed);
        void OnViewChange([MarshalAs(UnmanagedType.U4)] int dwAspect, [MarshalAs(UnmanagedType.I4)] int lindex);
        void OnRename([MarshalAs(UnmanagedType.Interface)] object pmk);
        void OnSave();
        void OnClose();
    }

Now When I take the snapshot:

I make a call CaptureWebScreenImage((IHTMLDocument2) webBrowser.document);

public static Image CaptureWebScreenImage(IHTMLDocument2 myDoc) {

        int heightsize = (int)getDocumentAttribute(myDoc, "scrollHeight");
        int widthsize = (int)getDocumentAttribute(myDoc, "scrollWidth");

        Bitmap finalImage = new Bitmap(widthsize, heightsize);
        Graphics gFinal = Graphics.FromImage(finalImage);
        COMRECT rect = new COMRECT();
        rect.left = 0;
        rect.top = 0;
        rect.right = widthsize;
        rect.bottom = heightsize;

        IntPtr hDC = gFinal.GetHdc();
        IViewObject vO = myDoc as IViewObject;

        vO.Draw(1, -1, (IntPtr)0, (IntPtr)0, (IntPtr)0, (IntPtr)hDC, ref rect, (IntPtr)0, (IntPtr)0, 0);
        gFinal.ReleaseHdc();

        gFinal.Dispose();

        return finalImage;

}

I am not getting the image of the webpage. Rather I am getting an image with black background. I am not sure if this is the right way of doing it, but I found over the web that IViewObject::Draw method is used for taking the image of a webpage in IE.

I was earlier doing the image capture using the Native PrintWindow() method as mentioned in the following codeproject's page - http://www.codeproject.com/KB/graphics/IECapture.aspx

But the image size is humongous! I was trying to see if I can reduce the size by using other techniques. It would be great if someone can point out the mistakes (I am sure there would be many) in my code above.

Thanks, Kapil


You can try to query IHTMLElementRender interface for the document element (which is available through IHTMLDocument3 interface) and use DrawToDC method to render page to a bitmap.


1 IHTMLElementRender::DrawToDC is deprecated, according to Microsoft's documentation. And it does not draw object and canvas, like flash, as far as I can see.

It's better to cal IViewObject::Draw() or ::OleDraw().

2 I dont know how to do it in C#, but I know how to do it in win32 program. In win32 program, you need to call IOleInplaceObject::SetObjectRect to set IWebBrowser's position and size. Or SetClientSite(), I am sure one of them does the magic.

CComQIPtr oleObject = browser;

CComQIPtr<IOleInPlaceObject> inPlaceObject(mOleObject); 
inPlaceObject->SetObjectRects(&rcClient, &rcClient); 
oleObject ->SetClientSite(clientSite);

Hope it helps

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜