2011-09-30 11 views
7

Sto cercando di fare quello che spiegano su articolo this nella sezione Controlling Download and Execution. Capisco che lo Web Browser Control in quel contesto non sia lo WebBrowser di .NET.Implementare IDispatch :: Invoke per essere chiamato da un controllo WebBrowser

Quello che sto cercando di fare è ottenere il controllo su ciò che il controllo WebBrowser scarica. L'ho cercato molto e sempre nello csEXWB, che ha un codice enorme che non riesco a decifrare.

Quello che ho fatto finora è eredita di WebBrowser NET, fare il mio com classe ereditata visibile utilizzando l'attributo [ComVisible(true)], aggiungere questo metodo per la mia classe (tratto da csEXWB):

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

E poi chiamare questa riga di codice, dove Browser è un'istanza della mia classe derivata:

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

Quindi quello che sto sperando è che il oleControl chiamerà il mio metodo Idispatch_AmbiantDlControl_Invoke_Handler, che non è così. Non so come, e questo è probabilmente quello che manca il mio codice, è il oleControl supposto sapere su quale oggetto chiamare il mio metodo Idispatch_AmbiantDlControl_Invoke_Handler.

L'articolo che ho collegato sopra è it will call your IDispatch::Invoke. Cosa significa per your. Come posso dire a oleControl quale oggetto è il mio IDispatch. Spero di avere un senso.

+0

Tu non sei vicino, personalizzando l'host è richiesto. Una classe interna denominata WebBrowserSite nel caso di WebBrowser. Sovrascrivere l'implementazione di IDispatch è un problema difficile, è implementato dal CLR per il codice gestito. Difficile vedere come si possa fare questo senza codice nativo. –

+0

Bene, csEXWB è scritto in C# AFAIK. Conosci qualche posto dove potrei iniziare a sovrascrivere l'implementazione di IDispatch? – Ahmet

+1

La classe System.Windows.Forms.AmbientProperties è sigillata. È ora di abbandonare il wrapper come ha fatto csEXWB. –

risposta

17

Ecco un WebBrowser personalizzato che consente di modificare i flag DLCONTROL.

Questo è un esempio di codice:

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"); 
    } 
} 

E il codice del browser web personalizzato:

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) && (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, 
} 
+0

Grazie mille !!! Questo è stato in realtà molto più facile di quanto mi aspettassi. Ho ancora bisogno di guardare questo codice un po 'più vicino ma l'ho testato e ha funzionato :). – Ahmet

Problemi correlati