Javascript Window.Opener Object Null su .NET WebBrowser Control Nuova finestra
-
20-08-2019 - |
Domanda
Bene, ho un pop-up nel controllo WebBroswer di .NET Framework che acquisisco in questo modo con il gestore di eventi NewWindow.
WebBrowser w = new WebBrowser();
SHDocVw.WebBrowser_V1 web = (SHDocVw.WebBrowser_V1)w.ActiveXInstance;
web.NewWindow += new SHDocVw.DWebBrowserEvents_NewWindowEventHandler(web_NewWindow);
Il nuovo popup è in una nuova forma con una nuova istanza del controllo WebBrowser.
void web_NewWindow(string URL, int Flags, string TargetFrameName, ref object PostData, string Headers, ref bool Processed)
{
Processed = true;
WebBrowser w2 = new WebBrowser();
Form PopUp = new Form();
PopUp.Controls.Clear();
PopUp.Controls.Add(w2);
w2.Dock = DockStyle.Fill;
PopUp.Show();
w2.Navigate(URL);
w2.DocumentCompleted += new WebBrowserDocumentCompletedEventHandler(w2_DocumentCompleted);
}
Il mio problema è che l'oggetto Window.Opener è nullo nel processo.
La pagina utilizza quel campo per riportare l'utente nella finestra originale e riempire alcuni valori nel modulo.
Esiste un modo per passare l'oggetto Window.Opener da un controllo WebBrowser al successivo? Sembra impossibile che funzioni, ma devo provare.
Grazie
Soluzione
Sì, esiste un modo per passare l'oggetto Window.Opener da un controllo WebBrowser al successivo.
Vedi il codice sotto per i dettagli.
public class WebBrowserTest
{
private WebBrowser _wParent;
// entry point
public void Navigate(string url)
{
_wParent = new WebBrowser();
SHDocVw.WebBrowser_V1 v1 = (SHDocVw.WebBrowser_V1)w.ActiveXInstance;
v1.NewWindow += v1_NewWindow;
}
private void v1_NewWindow(string URL, int Flags, string TargetFrameName, ref object PostData, string Headers, ref bool Processed)
{
// tell, that we'll open new page by ourselves
Processed = true;
// open page by ourselves
WebBrowser w2 = new WebBrowser();
w2.Navigate(url);
// wait for document will be loaded to do some magic stuff then
w2.DocumentCompleted += w2_DocumentCompleted;
}
// sets opener for popup window
// after document in popup window was loaded
private void w2_DocumentCompleted(object sender, EventArgs e)
{
WebBrowser popup = (WebBrowser)sender;
SetOpener(_wparent, popup);
}
// My most favorite method :)
// Contains exactly that hack, we're talking about
private void SetOpener(WebBrowser opener, WebBrowser popup)
{
HtmlWindow htmlPopup = popup.Document.Window;
HtmlWindow htmlOpener = opener.Document.Window;
// let the dark magic begin
// actually, WebBrowser control is .NET wrapper around IE COM interfaces
// we can get a bit closer to them access by getting reference to
// "mshtml.IHTMLWindow2" field via Reflection
FieldInfo fi = htmlPopup.GetType().GetField("htmlWindow2", BindingFlags.Instance | BindingFlags.NonPublic);
mshtml.IHTMLWindow2 htmlPopup2 = (mshtml.IHTMLWindow2)fi.GetValue(htmlPopup);
mshtml.IHTMLWindow2 htmlOpener2 = (mshtml.IHTMLWindow2)fi.GetValue(htmlOpener);
// opener is set here
htmlPopup2.window.opener = htmlOpener2.window.self;
}
}
P.S. Capisco, è probabile che sia ancora attuale, sono molto piccoli, ma comunque =)
Altri suggerimenti
Per coloro che cercano la versione WPF della soluzione, riscrivi la funzione SetOpener in basso:
public static void SetOpener(System.Windows.Controls.WebBrowser opener, System.Windows.Controls.WebBrowser popup)
{
mshtml.IHTMLWindow2 htmlPopup = (popup.Document as mshtml.HTMLDocument).parentWindow;
mshtml.IHTMLWindow2 htmlOpener = (opener.Document as mshtml.HTMLDocument).parentWindow;
htmlPopup.window.opener = htmlOpener.window.self;
}
Usalo nel gestore eventi sul WebBrowser lato figlio:
private void browser_LoadCompleted(object sender, NavigationEventArgs eventArgs)
{
WebBrowser popup = (WebBrowser)sender;
SetOpener(parentWebBrowser, popup);
}
E la parte WPF:
<Grid>
<WebBrowser Name="webBrowser" LoadCompleted="browser_LoadCompleted" />
</Grid>
Spero di aver appena salvato qualcun altro da ore di prove, errori e google infinite.