Реализовать IDispatch::Invoke для вызова элементом управления WebBrowser

#c# #internet-explorer #webbrowser-control

#c# #internet-explorer #webbrowser-control

Вопрос:

Я пытаюсь сделать то, что они объясняют в этой статье в Controlling Download and Execution разделе . Я понимаю Web Browser Control , что в этом контексте это не так.СЕТИ WebBrowser .

Что я пытаюсь сделать, так это получить контроль над тем WebBrowser , что загружает элемент управления. Я много искал это и всегда попадал в csEXWB , в котором есть огромный код, который я просто не могу расшифровать.

То, что я сделал до сих пор, — это наследование .NET WebBrowser , сделайте мой унаследованный класс com видимым с помощью [ComVisible(true)] атрибута, добавьте этот метод в мой класс (взятый из csEXWB):

     [DispId(HTMLDispIDs.DISPID_AMBIENT_DLCONTROL)]
    public int Idispatch_AmbiantDlControl_Invoke_Handler()
    {
        return (int)m_DLCtlFlags;
    }
  

А затем вызовите эту строку кода, где Browser находится экземпляр моего производного класса:

 IfacesEnumsStructsClasses.IOleControl oleControl = Browser.ActiveXInstance as IfacesEnumsStructsClasses.IOleControl;
oleControl.OnAmbientPropertyChange(IfacesEnumsStructsClasses.HTMLDispIDs.DISPID_AMBIENT_DLCONTROL);
  

Итак, я надеюсь, что oleControl вызовет мой Idispatch_AmbiantDlControl_Invoke_Handler метод, чего он не делает. Я не знаю, как, и, вероятно, именно этого не хватает в моем коде, oleControl предполагается, что я знаю, для какого объекта вызывать мой Idispatch_AmbiantDlControl_Invoke_Handler метод.

В статье, на которую я ссылался выше, говорится it will call your IDispatch::Invoke следующее. Что это значит your . Как мне определить oleControl , какой объект является моим IDispatch . Надеюсь, я что-то понимаю.

Комментарии:

1. Вы не близки, требуется настройка хоста. Внутренний класс с именем WebBrowserSite в случае WebBrowser . Переопределение реализации IDispatch является сложной проблемой, она реализуется CLR для управляемого кода. Трудно понять, как вы могли бы заставить это работать без собственного кода.

2. Ну, csEXWB написан на C # AFAIK. Знаете ли вы какое-нибудь место, где я мог бы начать с того, как переопределить реализацию IDispatch?

3. Система классов. Windows. Формы. AmbientProperties закрыт. Время отказаться от оболочки, как это сделал csEXWB.

Ответ №1:

Вот настраиваемый веб-браузер, который позволяет изменять флаги DLCONTROL.

Это пример кода:

 public partial class Form1 : Form
{
    private MyWebBrowser _webBrowser;

    public Form1()
    {
        InitializeComponent();

        _webBrowser = new MyWebBrowser();
        _webBrowser.Dock = DockStyle.Fill;

        Controls.Add(_webBrowser);
    }

    private void button1_Click(object sender, EventArgs e)
    {
        _webBrowser.DownloadControlFlags = (int)WebBrowserDownloadControlFlags.DOWNLOADONLY;
        _webBrowser.Navigate("http://mysamplewebsite");
    }
}
  

И настроенный код веб-браузера:

 public class MyWebBrowser : WebBrowser
{
    private const int DISPID_AMBIENT_DLCONTROL = -5512;
    private int _downloadControlFlags;

    // we want our site class, not the default one
    protected override WebBrowserSiteBase CreateWebBrowserSiteBase()
    {
        return new MyWebBrowserSite(this);
    }

    [DispId(DISPID_AMBIENT_DLCONTROL)]
    public int DownloadControlFlags
    {
        get
        {
            return _downloadControlFlags;
        }
        set
        {
            if (_downloadControlFlags == value)
                return;

            _downloadControlFlags = value;
            IOleControl ctl = (IOleControl)ActiveXInstance;
            ctl.OnAmbientPropertyChange(DISPID_AMBIENT_DLCONTROL);
        }
    }

    protected class MyWebBrowserSite : WebBrowserSite, IReflect
    {
        private Dictionary<int, PropertyInfo> _dispidCache;
        private MyWebBrowser _host;

        public MyWebBrowserSite(MyWebBrowser host)
            : base(host)
        {
            _host = host;
        }

        object IReflect.InvokeMember(string name, BindingFlags invokeAttr, Binder binder, object target, object[] args, ParameterModifier[] modifiers, CultureInfo culture, string[] namedParameters)
        {
            object ret = null;
            // Check direct IDispatch call using a dispid (see http://msdn.microsoft.com/en-us/library/de3dhzwy.aspx)
            const string dispidToken = "[DISPID=";
            if (name.StartsWith(dispidToken))
            {
                int dispid = int.Parse(name.Substring(dispidToken.Length, name.Length - dispidToken.Length - 1));
                if (_dispidCache == null)
                {
                    // WebBrowser has many properties, so we build a dispid cache on it
                    _dispidCache = new Dictionary<int, PropertyInfo>();
                    foreach (PropertyInfo pi in _host.GetType().GetProperties(BindingFlags.Public | BindingFlags.Instance))
                    {
                        if ((!pi.CanRead) || (pi.GetIndexParameters().Length > 0))
                            continue;

                        object[] atts = pi.GetCustomAttributes(typeof(DispIdAttribute), true);
                        if ((atts != null) amp;amp; (atts.Length > 0))
                        {
                            DispIdAttribute da = (DispIdAttribute)atts[0];
                            _dispidCache[da.Value] = pi;
                        }
                    }
                }

                PropertyInfo property;
                if (_dispidCache.TryGetValue(dispid, out property))
                {
                    ret = property.GetValue(_host, null);
                }
            }
            return ret;
        }

        FieldInfo[] IReflect.GetFields(BindingFlags bindingAttr)
        {
            return GetType().GetFields(bindingAttr);
        }

        MethodInfo[] IReflect.GetMethods(BindingFlags bindingAttr)
        {
            return GetType().GetMethods(bindingAttr);
        }

        PropertyInfo[] IReflect.GetProperties(BindingFlags bindingAttr)
        {
            return GetType().GetProperties(bindingAttr);
        }

        FieldInfo IReflect.GetField(string name, BindingFlags bindingAttr)
        {
            throw new NotImplementedException();
        }

        MemberInfo[] IReflect.GetMember(string name, BindingFlags bindingAttr)
        {
            throw new NotImplementedException();
        }

        MemberInfo[] IReflect.GetMembers(BindingFlags bindingAttr)
        {
            throw new NotImplementedException();
        }

        MethodInfo IReflect.GetMethod(string name, BindingFlags bindingAttr)
        {
            throw new NotImplementedException();
        }

        MethodInfo IReflect.GetMethod(string name, BindingFlags bindingAttr, Binder binder, Type[] types, ParameterModifier[] modifiers)
        {
            throw new NotImplementedException();
        }

        PropertyInfo IReflect.GetProperty(string name, BindingFlags bindingAttr, Binder binder, Type returnType, Type[] types, ParameterModifier[] modifiers)
        {
            throw new NotImplementedException();
        }

        PropertyInfo IReflect.GetProperty(string name, BindingFlags bindingAttr)
        {
            throw new NotImplementedException();
        }

        Type IReflect.UnderlyingSystemType
        {
            get { throw new NotImplementedException(); }
        }
    }

    [ComImport, InterfaceType(ComInterfaceType.InterfaceIsIUnknown), Guid("B196B288-BAB4-101A-B69C-00AA00341D07")]
    internal interface IOleControl
    {
        void Reserved0();
        void Reserved1();
        void OnAmbientPropertyChange(int dispID);
        void Reserved2();
    }
}

[Flags]
public enum WebBrowserDownloadControlFlags: uint
{
    DLIMAGES                          = 0x00000010,
    VIDEOS                            = 0x00000020,
    BGSOUNDS                          = 0x00000040,
    NO_SCRIPTS                        = 0x00000080,
    NO_JAVA                           = 0x00000100,
    NO_RUNACTIVEXCTLS                 = 0x00000200,
    NO_DLACTIVEXCTLS                  = 0x00000400,
    DOWNLOADONLY                      = 0x00000800,
    NO_FRAMEDOWNLOAD                  = 0x00001000,
    RESYNCHRONIZE                     = 0x00002000,
    PRAGMA_NO_CACHE                   = 0x00004000,
    NO_BEHAVIORS                      = 0x00008000,
    NO_METACHARSET                    = 0x00010000,
    URL_ENCODING_DISABLE_UTF8         = 0x00020000,
    URL_ENCODING_ENABLE_UTF8          = 0x00040000,
    NOFRAMES                          = 0x00080000,
    FORCEOFFLINE                      = 0x10000000,
    NO_CLIENTPULL                     = 0x20000000,
    SILENT                            = 0x40000000,
    OFFLINEIFNOTCONNECTED             = 0x80000000,
    OFFLINE                           = OFFLINEIFNOTCONNECTED,
}
  

Комментарии:

1. Большое вам спасибо!!! На самом деле это было намного проще, чем я ожидал. Мне все еще нужно взглянуть на этот код немного ближе, но я протестировал его, и он сработал :).