【问题标题】:How to take the snapshot of a IE webpage through a BHO (C#)如何通过 BHO (C#) 拍摄 IE 网页的快照
【发布时间】:2013-02-01 23:04:29
【问题描述】:

我正在尝试在 C# 中构建一个 IE BHO,以获取 IE 浏览器中加载的网页的快照。这是我想要做的:

public class ShowToolbarBHO : BandObjectLib.IObjectWithSite
{

    IWebBrowser2 webBrowser = null;

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

另外,我 p/调用以下 COM 方法:

    [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();
    }

现在当我拍摄快照时:

我打电话 CaptureWebScreenImage((IHTMLDocument2) webBrowser.document);

公共静态图像捕获WebScreenImage(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;

}

我没有得到网页的图像。相反,我得到的是黑色背景的图像。我不确定这是否是正确的做法,但我在网上发现 IViewObject::Draw 方法用于在 IE 中获取网页的图像。

我之前使用 Native PrintWindow() 方法进行图像捕获,如以下代码项目页面中所述 - http://www.codeproject.com/KB/graphics/IECapture.aspx

但是图像大小是巨大的!我试图看看是否可以通过使用其他技术来减小尺寸。如果有人能指出我上面代码中的错误(我相信会有很多),那就太好了。

谢谢, 卡皮尔

【问题讨论】:

    标签: bho iwebbrowser2


    【解决方案1】:

    您可以尝试在IHTMLElementRender接口中查询文档元素(可通过IHTMLDocument3接口获取),并使用DrawToDC方法将页面渲染为位图。

    【讨论】:

      【解决方案2】:

      1 根据 Microsoft 的文档,IHTMLElementRender::DrawToDC 已被弃用。据我所知,它不会像 flash 那样绘制对象和画布。

      最好调用 IViewObject::Draw() 或 ::OleDraw()。

      2 我不知道如何在 C# 中执行此操作,但我知道如何在 win32 程序中执行此操作。在win32程序中,需要调用IOleInplaceObject::SetObjectRect来设置IWebBrowser的位置和大小。 或者 SetClientSite(),我相信其中的一个会变魔术。

      CComQIPtr oleObject = 浏览器;

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

      希望对你有帮助

      【讨论】:

        猜你喜欢
        • 2019-12-19
        • 2015-02-13
        • 2010-11-07
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2013-02-14
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多