C# WebBrowser:拖动&;滴
我想拦截WebBrowser控件上的拖放操作。更准确地说,我希望能够基于文件扩展名取消或批准拖放事件(并在WebBrowser之外处理该文件),并且我希望使拖放图标看起来像常规图标,而不是像此图标:C# WebBrowser:拖动&;滴,c#,.net,winforms,webbrowser-control,C#,.net,Winforms,Webbrowser Control,我想拦截WebBrowser控件上的拖放操作。更准确地说,我希望能够基于文件扩展名取消或批准拖放事件(并在WebBrowser之外处理该文件),并且我希望使拖放图标看起来像常规图标,而不是像此图标: 我相信为此我需要实现定制的IDocHostUIHandler并拦截GetDropTarget。不幸的是,我没有成功地做到这一点。我将此代码用作我的“基本”代码:而我制作的此部分:。GetDropTarget永远不会被调用。这里有一个完整的基于WinForms的示例,可以运行,IDocHostUIHa
我相信为此我需要实现定制的IDocHostUIHandler并拦截GetDropTarget。不幸的是,我没有成功地做到这一点。我将此代码用作我的“基本”代码:而我制作的此部分:。GetDropTarget永远不会被调用。这里有一个完整的基于WinForms的示例,可以运行,
IDocHostUIHandler。GetDropTarget确实会被调用
using System;
using System.Diagnostics;
using System.Linq;
using System.Runtime.InteropServices;
using System.Windows.Forms;
namespace CustomWebBrowser
{
public partial class MainForm : Form
{
public MainForm()
{
InitializeComponent();
}
private void MainForm_Load(object sender, EventArgs e)
{
var wb = new ImprovedWebBrowser();
wb.Dock = DockStyle.Fill;
this.Controls.Add(wb);
wb.Visible = true;
wb.DocumentText = "<body contentEditable='true'><b>Hello from ImprovedWebBrowser!</b></body>";
}
}
public class ImprovedWebBrowser : WebBrowser
{
/// <summary>
/// provide custom WebBrowserSite,
/// where we override IDocHostUIHandler and call the base implementation
/// More info: http://stackoverflow.com/a/19739699/1768303
/// </summary>
protected override WebBrowserSiteBase CreateWebBrowserSiteBase()
{
return new ImprovedWebBrowserSite(this);
}
#region ImprovedWebBrowserSite
[ClassInterface(ClassInterfaceType.None)]
protected class ImprovedWebBrowserSite :
WebBrowserSite,
NativeMethods.IDocHostUIHandler,
IDisposable,
ICustomQueryInterface
{
ImprovedWebBrowser _host;
NativeMethods.IDocHostUIHandler _baseIDocHostUIHandler;
IntPtr _unkInnerAggregated;
IntPtr _unkOuter;
Inner _inner;
// constructor
public ImprovedWebBrowserSite(WebBrowser host) :
base(host)
{
_host = (ImprovedWebBrowser)host;
// get the CCW object for this
_unkOuter = Marshal.GetIUnknownForObject(this);
Marshal.AddRef(_unkOuter);
try
{
// aggregate the CCW object with the helper Inner object
_inner = new Inner(this);
_unkInnerAggregated = Marshal.CreateAggregatedObject(_unkOuter, _inner);
// obtain private WebBrowserSite COM interfaces
_baseIDocHostUIHandler = (NativeMethods.IDocHostUIHandler)Marshal.GetTypedObjectForIUnknown(_unkInnerAggregated, typeof(NativeMethods.IDocHostUIHandler));
}
finally
{
Marshal.Release(_unkOuter);
}
}
~ImprovedWebBrowserSite()
{
// need to work out the reference counting for GC to work correctly
Debug.Print("ImprovedWebBrowserSite object finalized.");
}
void IDisposable.Dispose()
{
base.Dispose();
_baseIDocHostUIHandler = null;
if (_unkInnerAggregated != IntPtr.Zero)
{
Marshal.Release(_unkInnerAggregated);
_unkInnerAggregated = IntPtr.Zero;
}
if (_unkOuter != IntPtr.Zero)
{
Marshal.Release(_unkOuter);
_unkOuter = IntPtr.Zero;
}
}
#region Inner
// Inner as aggregated object
class Inner :
ICustomQueryInterface,
IDisposable
{
object _outer;
Type[] _interfaces;
public Inner(object outer)
{
_outer = outer;
_interfaces = _outer.GetType().BaseType.GetInterfaces();
}
public CustomQueryInterfaceResult GetInterface(ref Guid iid, out IntPtr ppv)
{
if (_outer != null)
{
var guid = iid;
var iface = _interfaces.FirstOrDefault((t) => t.GUID == guid);
if (iface != null)
{
var unk = Marshal.GetComInterfaceForObject(_outer, iface, CustomQueryInterfaceMode.Ignore);
if (unk != IntPtr.Zero)
{
ppv = unk;
return CustomQueryInterfaceResult.Handled;
}
}
}
ppv = IntPtr.Zero;
return CustomQueryInterfaceResult.Failed;
}
~Inner()
{
// need to work out the reference counting for GC to work correctly
Debug.Print("Inner object finalized.");
}
public void Dispose()
{
_outer = null;
_interfaces = null;
}
}
#endregion
#region ICustomQueryInterface
public CustomQueryInterfaceResult GetInterface(ref Guid iid, out IntPtr ppv)
{
// CustomQueryInterfaceMode.Ignore is to avoid infinite loop during QI.
if (iid == typeof(NativeMethods.IDocHostUIHandler).GUID)
{
ppv = Marshal.GetComInterfaceForObject(this, typeof(NativeMethods.IDocHostUIHandler), CustomQueryInterfaceMode.Ignore);
}
else
{
ppv = IntPtr.Zero;
return CustomQueryInterfaceResult.NotHandled;
}
return CustomQueryInterfaceResult.Handled;
}
#endregion
#region IDocHostUIHandler
int NativeMethods.IDocHostUIHandler.ShowContextMenu(int dwID, ref NativeMethods.POINT pt, IntPtr pcmdtReserved, IntPtr pdispReserved)
{
return _baseIDocHostUIHandler.ShowContextMenu(dwID, ref pt, pcmdtReserved, pdispReserved);
}
int NativeMethods.IDocHostUIHandler.GetHostInfo(ref NativeMethods.DOCHOSTUIINFO info)
{
Debug.Print("IDocHostUIHandler.GetHostInfo");
return _baseIDocHostUIHandler.GetHostInfo(ref info);
}
int NativeMethods.IDocHostUIHandler.ShowUI(int dwID, IntPtr activeObject, IntPtr commandTarget, IntPtr frame, IntPtr doc)
{
return _baseIDocHostUIHandler.ShowUI(dwID, activeObject, commandTarget, frame, doc);
}
int NativeMethods.IDocHostUIHandler.HideUI()
{
return _baseIDocHostUIHandler.HideUI();
}
int NativeMethods.IDocHostUIHandler.UpdateUI()
{
return _baseIDocHostUIHandler.UpdateUI();
}
int NativeMethods.IDocHostUIHandler.EnableModeless(bool fEnable)
{
return _baseIDocHostUIHandler.EnableModeless(fEnable);
}
int NativeMethods.IDocHostUIHandler.OnDocWindowActivate(bool fActivate)
{
return _baseIDocHostUIHandler.OnDocWindowActivate(fActivate);
}
int NativeMethods.IDocHostUIHandler.OnFrameWindowActivate(bool fActivate)
{
return _baseIDocHostUIHandler.OnFrameWindowActivate(fActivate);
}
int NativeMethods.IDocHostUIHandler.ResizeBorder(ref NativeMethods.COMRECT rect, IntPtr doc, bool fFrameWindow)
{
return _baseIDocHostUIHandler.ResizeBorder(ref rect, doc, fFrameWindow);
}
int NativeMethods.IDocHostUIHandler.TranslateAccelerator(ref NativeMethods.MSG msg, ref Guid group, int nCmdID)
{
return _baseIDocHostUIHandler.TranslateAccelerator(ref msg, ref group, nCmdID);
}
int NativeMethods.IDocHostUIHandler.GetOptionKeyPath(string[] pbstrKey, int dw)
{
return _baseIDocHostUIHandler.GetOptionKeyPath(pbstrKey, dw);
}
int NativeMethods.IDocHostUIHandler.GetDropTarget(IntPtr pDropTarget, out IntPtr ppDropTarget)
{
Debug.Print("IDocHostUIHandler.GetDropTarget");
return _baseIDocHostUIHandler.GetDropTarget(pDropTarget, out ppDropTarget);
}
int NativeMethods.IDocHostUIHandler.GetExternal(out object ppDispatch)
{
return _baseIDocHostUIHandler.GetExternal(out ppDispatch);
}
int NativeMethods.IDocHostUIHandler.TranslateUrl(int dwTranslate, string strURLIn, out string pstrURLOut)
{
return _baseIDocHostUIHandler.TranslateUrl(dwTranslate, strURLIn, out pstrURLOut);
}
int NativeMethods.IDocHostUIHandler.FilterDataObject(IntPtr pDO, out IntPtr ppDORet)
{
return _baseIDocHostUIHandler.FilterDataObject(pDO, out ppDORet);
}
#endregion
}
#endregion
}
public static class NativeMethods
{
#region IDocHostUIHandler
public enum DOCHOSTUIDBLCLICK
{
DEFAULT = 0x0,
SHOWPROPERTIES = 0x1,
SHOWCODE = 0x2
}
public enum DOCHOSTUIFLAG
{
DIALOG = 0x1,
DISABLE_HELP_MENU = 0x2,
NO3DBORDER = 0x4,
SCROLL_NO = 0x8,
DISABLE_SCRIPT_INACTIVE = 0x10,
OPENNEWWIN = 0x20,
DISABLE_OFFSCREEN = 0x40,
FLAT_SCROLLBAR = 0x80,
DIV_BLOCKDEFAULT = 0x100,
ACTIVATE_CLIENTHIT_ONLY = 0x200,
NO3DOUTERBORDER = 0x00200000,
THEME = 0x00040000,
NOTHEME = 0x80000,
DISABLE_COOKIE = 0x400
}
[StructLayout(LayoutKind.Sequential)]
public struct DOCHOSTUIINFO
{
[MarshalAs(UnmanagedType.U4)]
public int cbSize;
[MarshalAs(UnmanagedType.I4)]
public int dwFlags;
[MarshalAs(UnmanagedType.I4)]
public int dwDoubleClick;
[MarshalAs(UnmanagedType.I4)]
public int dwReserved1;
[MarshalAs(UnmanagedType.I4)]
public int dwReserved2;
}
[StructLayout(LayoutKind.Sequential)]
public struct COMRECT
{
public int left;
public int top;
public int right;
public int bottom;
}
[StructLayout(LayoutKind.Sequential)]
public struct POINT
{
public int x;
public int y;
}
[StructLayout(LayoutKind.Sequential)]
public struct MSG
{
public IntPtr hwnd;
public int message;
public IntPtr wParam;
public IntPtr lParam;
public int time;
POINT pt;
}
[ComImport(), Guid("BD3F23C0-D43E-11CF-893B-00AA00BDCE1A"),
InterfaceTypeAttribute(ComInterfaceType.InterfaceIsIUnknown)]
public interface IDocHostUIHandler
{
[return: MarshalAs(UnmanagedType.I4)]
[PreserveSig]
int ShowContextMenu(
[In, MarshalAs(UnmanagedType.U4)]
int dwID,
[In]
ref POINT pt,
[In]
IntPtr pcmdtReserved,
[In]
IntPtr pdispReserved);
[return: MarshalAs(UnmanagedType.I4)]
[PreserveSig]
int GetHostInfo(
[In, Out]
ref DOCHOSTUIINFO info);
[return: MarshalAs(UnmanagedType.I4)]
[PreserveSig]
int ShowUI(
[In, MarshalAs(UnmanagedType.I4)]
int dwID,
[In]
IntPtr activeObject,
[In]
IntPtr commandTarget,
[In]
IntPtr frame,
[In]
IntPtr doc);
[return: MarshalAs(UnmanagedType.I4)]
[PreserveSig]
int HideUI();
[return: MarshalAs(UnmanagedType.I4)]
[PreserveSig]
int UpdateUI();
[return: MarshalAs(UnmanagedType.I4)]
[PreserveSig]
int EnableModeless(
[In, MarshalAs(UnmanagedType.Bool)]
bool fEnable);
[return: MarshalAs(UnmanagedType.I4)]
[PreserveSig]
int OnDocWindowActivate(
[In, MarshalAs(UnmanagedType.Bool)]
bool fActivate);
[return: MarshalAs(UnmanagedType.I4)]
[PreserveSig]
int OnFrameWindowActivate(
[In, MarshalAs(UnmanagedType.Bool)]
bool fActivate);
[return: MarshalAs(UnmanagedType.I4)]
[PreserveSig]
int ResizeBorder(
[In]
ref COMRECT rect,
[In]
IntPtr doc,
bool fFrameWindow);
[return: MarshalAs(UnmanagedType.I4)]
[PreserveSig]
int TranslateAccelerator(
[In]
ref MSG msg,
[In]
ref Guid group,
[In, MarshalAs(UnmanagedType.I4)]
int nCmdID);
[return: MarshalAs(UnmanagedType.I4)]
[PreserveSig]
int GetOptionKeyPath(
[Out, MarshalAs(UnmanagedType.LPArray)]
String[] pbstrKey,
[In, MarshalAs(UnmanagedType.U4)]
int dw);
[return: MarshalAs(UnmanagedType.I4)]
[PreserveSig]
int GetDropTarget(
[In]
IntPtr pDropTarget,
[Out]
out IntPtr ppDropTarget);
[return: MarshalAs(UnmanagedType.I4)]
[PreserveSig]
int GetExternal(
[Out, MarshalAs(UnmanagedType.IDispatch)]
out object ppDispatch);
[return: MarshalAs(UnmanagedType.I4)]
[PreserveSig]
int TranslateUrl(
[In, MarshalAs(UnmanagedType.U4)]
int dwTranslate,
[In, MarshalAs(UnmanagedType.LPWStr)]
string strURLIn,
[Out, MarshalAs(UnmanagedType.LPWStr)]
out string pstrURLOut);
[return: MarshalAs(UnmanagedType.I4)]
[PreserveSig]
int FilterDataObject(
[In]
IntPtr pDO,
[Out]
out IntPtr ppDORet);
}
#endregion
}
}
使用系统;
使用系统诊断;
使用System.Linq;
使用System.Runtime.InteropServices;
使用System.Windows.Forms;
命名空间自定义浏览器
{
公共部分类主窗体:窗体
{
公共表格(
{
初始化组件();
}
私有void主窗体加载(对象发送方、事件参数e)
{
var wb=新改进的WebBrowser();
wb.Dock=DockStyle.Fill;
this.Controls.Add(wb);
wb.Visible=true;
wb.DocumentText=“来自ImprovedWebBrowser的您好!”;
}
}
公共类改进型WebBrowser:WebBrowser
{
///
///提供自定义WebBrowserSite,
///我们重写IDocHostUIHandler并调用基本实现
///更多信息:http://stackoverflow.com/a/19739699/1768303
///
受保护的重写WebBrowserSiteBase CreateWebBrowserSiteBase()
{
返回新的改进WebBrowserSite(本);
}
#区域改良网状硅钙石
[ClassInterface(ClassInterfaceType.None)]
受保护级别改进的WebBrowserSite:
韦伯氏体,
NativeMethods.IDocHostUIHandler,
可识别,
ICustomQueryInterface
{
改进的网络浏览器主机;
NativeMethods.IDocHostUIHandler(基本IDocHostUIHandler);
IntPtr _;
IntPtr_unkOuter;
内(内);;
//建造师
公共改进的WebBrowser站点(WebBrowser主机):
基地(主机)
{
_主机=(改进的WebBrowser)主机;
//为此获取CCW对象
_unknouter=Marshal.getiunknownfobject(this);
Marshal.AddRef(_unkouther);
尝试
{
//将CCW对象与辅助对象内部对象聚合
_内部=新内部(本);
_unkInnerAggregated=Marshal.CreateAggregatedObject(\u unkOuter,\u inner);
//获取专用WebBrowserSite COM接口
_baseIDocHostUIHandler=(NativeMethods.IDocHostUIHandler)Marshal.GetTypedObjectForIUnknown(_UnknownerAggregated,typeof(NativeMethods.IDocHostUIHandler));
}
最后
{
封送员放行(_);
}
}
~ImprovedWebBrowserSite()
{
//需要计算出GC正常工作的引用计数
打印(“改进的WebBrowserSite对象已完成”);
}
void IDisposable.Dispose()无效
{
base.Dispose();
_baseIDocHostUIHandler=null;
如果(_=IntPtr.Zero)
{
封送放行(_);
_unkInnerAggregated=IntPtr.Zero;
}
如果(_unkouther!=IntPtr.Zero)
{
封送员放行(_);
_unkOuter=IntPtr.0;
}
}
#区域内部
//内部作为聚合对象
类内部:
ICustomQueryInterface,
可识别
{
物体外;
[]_型接口;
公共内部对象(外部对象)
{
_外部=外部;
_接口=_outer.GetType().BaseType.GetInterfaces();
}
公共CustomQueryInterfaceResult GetInterface(参考Guid iid,out IntPtr ppv)
{
如果(_outer!=null)
{
变量guid=iid;
var iface=\u interfaces.FirstOrDefault((t)=>t.GUID==GUID);
如果(iface!=null)
{
var unk=Marshal.GetComInterfaceForObject(_outer,iface,CustomQueryInterfaceMode.Ignore);
如果(unk!=IntPtr.Zero)
{
ppv=unk;
返回CustomQueryInterfaceResult.Handled;
}
}
}
ppv=整数零;
返回CustomQueryInterfaceResult。失败;
}
~Inner()
{
//需要计算出GC正常工作的引用计数
打印(“内部对象已完成”);
}
公共空间处置()
{
_外部=空;
_接口=空;
}
}
#端区
#区域ICustomQueryInterface
公共CustomQueryInterfaceResult GetInterface(参考Guid iid,out IntPtr ppv)
{
//忽略是为了避免QI过程中的无限循环。
if(iid==typeof(NativeMethods.IDocHostUIHandler.GUID)
{
ppv=Marshal.GetComInterfaceForObject(此