Windows窗体与IDownloadManager Webbrowswer控制 [英] Windows Forms Webbrowswer control with IDownloadManager
问题描述
我使用了 Systems.Windows.Forms.Webbrowser
控制和需要覆盖的下载管理器。我跟着指示 的子类的形式和覆盖 CreateWebBrowserSiteBase()
I'm using the Systems.Windows.Forms.Webbrowser
control and need to override the download manager. I've followed the instructions here to subclass the form and override CreateWebBrowserSiteBase()
/// <summary>
/// Browser with download manager
/// </summary>
public class MyBrowser : WebBrowser
{
/// <summary>
/// Returns a reference to the unmanaged WebBrowser ActiveX control site,
/// which you can extend to customize the managed <see ref="T:System.Windows.Forms.WebBrowser"/> control.
/// </summary>
/// <returns>
/// A <see cref="T:System.Windows.Forms.WebBrowser.WebBrowserSite"/> that represents the WebBrowser ActiveX control site.
/// </returns>
protected override WebBrowserSiteBase CreateWebBrowserSiteBase()
{
var manager = new DownloadWebBrowserSite(this);
manager.FileDownloading += (sender, args) =>
{
if (FileDownloading != null)
{
FileDownloading(this, args);
}
};
return manager;
}
}
在 DownloadWebBrowserSite
,我实施的IServiceProvider
提供一个 IDownloadManager
时提出要求。
In the DownloadWebBrowserSite
, I implement IServiceProvider
to provide an IDownloadManager
when requested.
/// <summary>
/// Queries for a service
/// </summary>
/// <param name="guidService">the service GUID</param>
/// <param name="riid"></param>
/// <param name="ppvObject"></param>
/// <returns></returns>
public int QueryService(ref Guid guidService, ref Guid riid, out IntPtr ppvObject)
{
if ( (guidService == Constants.IID_IDownloadManager && riid == Constants.IID_IDownloadManager ))
{
ppvObject = Marshal.GetComInterfaceForObject(_manager, typeof(IDownloadManager));
return Constants.S_OK;
}
ppvObject = IntPtr.Zero;
return Constants.E_NOINTERFACE;
}
的
下载管理器
是从上面的例子所
/// <summary>
/// Intercepts downloads of files, to add as PDFs or suppliments
/// </summary>
[ComVisible(true)]
[Guid("bdb9c34c-d0ca-448e-b497-8de62e709744")]
[CLSCompliant(false)]
public class DownloadManager : IDownloadManager
{
/// <summary>
/// event called when the browser is about to download a file
/// </summary>
public event EventHandler<FileDownloadEventArgs> FileDownloading;
/// <summary>
/// Return S_OK (0) so that IE will stop to download the file itself.
/// Else the default download user interface is used.
/// </summary>
public int Download(IMoniker pmk, IBindCtx pbc, uint dwBindVerb, int grfBINDF, IntPtr pBindInfo,
string pszHeaders, string pszRedir, uint uiCP)
{
// Get the display name of the pointer to an IMoniker interface that specifies the object to be downloaded.
string name;
pmk.GetDisplayName(pbc, null, out name);
if (!string.IsNullOrEmpty(name))
{
Uri url;
if (Uri.TryCreate(name, UriKind.Absolute, out url))
{
if ( FileDownloading != null )
{
FileDownloading(this, new FileDownloadEventArgs(url));
}
return Constants.S_OK;
}
}
return 1;
}
}
的问题是, pmk.GetDisplayName
返回初始URL,而不是项目的网址下载。如果URI指向一个动态页面,如 http://www.example.com/download.php ,我没有收到实际的文件被下载。我需要从标题获取URL,这样我得到我应该要下载的实际文件。
The problem is that the pmk.GetDisplayName
returns the initial URL, not the URL of the item to be downloaded. If the URI points to a dynamic page, such as http://www.example.com/download.php, I'm not getting the actual file to be downloaded. I need to get the URL from the header so that I get the actual file I'm supposed to be downloading.
谷歌表示,我要创建一个 IBindStatusCallback
的实施也实现 IHttpNegotiate
和的IServiceProvider
对 IID_IHttpNegotiate
,这样我可以看到 IHttpNegotiate.OnResponse
。我已经成功地实施,但是, QueryService的
似乎只问过了 IID_IInternetProtocol
从不 IID_IHttpNegotiate
。
Google indicates that I have to create a IBindStatusCallback
implementation that also implements IHttpNegotiate
and IServiceProvider
to respond to IID_IHttpNegotiate
, so that I can see the IHttpNegotiate.OnResponse
. I've managed to implement that, however, QueryService
only seems to ever ask for IID_IInternetProtocol
and never IID_IHttpNegotiate
.
任何意见将是巨大的。
推荐答案
您缺少一个电话:CreateBindCtx
Your missing a call to: CreateBindCtx.
以下内容添加到您的下载管理器:
Add the following to your DownloadManager:
[DllImport("ole32.dll")]
static extern int CreateBindCtx(uint reserved, out IBindCtx ppbc);
然后确保您在注册回调之前调用它。我在你的下载实现()这个方法如下:
Then make sure you call this before registering your callback. I have implemented this in your Download() method as follows:
public int Download(IMoniker pmk, IBindCtx pbc, uint dwBindVerb, int grfBINDF, IntPtr pBindInfo,
string pszHeaders, string pszRedir, uint uiCP)
{
// Get the display name of the pointer to an IMoniker interface that specifies the object to be downloaded.
string name;
pmk.GetDisplayName(pbc, null, out name);
if (!string.IsNullOrEmpty(name))
{
Uri url;
if (Uri.TryCreate(name, UriKind.Absolute, out url))
{
Debug.WriteLine("DownloadManager: initial URL is: " + url);
CreateBindCtx(0, out pbc);
RegisterCallback(pbc, url);
BindMonikerToStream(pmk, pbc);
return MyBrowser.Constants.S_OK;
}
}
return 1;
}
有了这个地方,你IHttpNegotiate执行将被调用,你就会有访问响应头。
With this in place, your IHttpNegotiate implementation will be called and you'll have access to the response headers.
这篇关于Windows窗体与IDownloadManager Webbrowswer控制的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!