c++ - Problema de emulación de control del navegador web(FEATURE_BROWSER_EMULATION)
registry webbrowser-control (2)
Con VS2013 creé una aplicación de control de navegador web muy simple que navega a http://demos.dojotoolkit.org/demos/calendar/demo.html
Cuando no se establece FEATURE_BROWSER_EMULATION para esta aplicación en el registro, el sitio funciona correctamente. Al agregar la aplicación a esta clave de registro (bajo HKLM) funciona hasta la emulación IE9 pero falla con los valores IE10 e IE11 (tengo IE11 en mi máquina).
ejemplo:
FEATURE_BROWSER_EMULATION
myApp=9999 - works
myApp=10001 - doesn''t work
no funciona = el selector de fecha del mes no funciona ¿Alguna sugerencia de cuál puede ser el problema?
Gracias amigo
A continuación se muestra mi aplicación de juegos
WebBrowser
(en C #) que funciona bien con su URL (
http://demos.dojotoolkit.org/demos/calendar/demo.html
).
Creo que deshabilitar
FEATURE_NINPUT_LEGACY_MODE
es lo que marcó la diferencia.
También hay un par de otras configuraciones que habilité.
También muestra cómo usar
HKEY_CURRENT_USER
lugar de
HKLM
, por lo que la aplicación no requiere derechos de administrador.
using Microsoft.Win32;
using System;
using System.ComponentModel;
using System.Threading;
using System.Threading.Tasks;
using System.Windows.Forms;
namespace WebBrowserApp
{
public partial class MainForm : Form
{
const int POLL_DELAY = 250;
WebBrowser _webBrowser;
// set WebBrowser features, more info: http://.com/a/18333982/1768303
static void SetWebBrowserFeatures()
{
// don''t change the registry if running in-proc inside Visual Studio
if (LicenseManager.UsageMode != LicenseUsageMode.Runtime)
return;
var appName = System.IO.Path.GetFileName(System.Diagnostics.Process.GetCurrentProcess().MainModule.FileName);
var featureControlRegKey = @"HKEY_CURRENT_USER/Software/Microsoft/Internet Explorer/Main/FeatureControl/";
Registry.SetValue(featureControlRegKey + "FEATURE_BROWSER_EMULATION",
appName, GetBrowserEmulationMode(), RegistryValueKind.DWord);
// enable the features which are "On" for the full Internet Explorer browser
Registry.SetValue(featureControlRegKey + "FEATURE_ENABLE_CLIPCHILDREN_OPTIMIZATION",
appName, 1, RegistryValueKind.DWord);
Registry.SetValue(featureControlRegKey + "FEATURE_AJAX_CONNECTIONEVENTS",
appName, 1, RegistryValueKind.DWord);
Registry.SetValue(featureControlRegKey + "FEATURE_GPU_RENDERING",
appName, 1, RegistryValueKind.DWord);
Registry.SetValue(featureControlRegKey + "FEATURE_WEBOC_DOCUMENT_ZOOM",
appName, 1, RegistryValueKind.DWord);
Registry.SetValue(featureControlRegKey + "FEATURE_NINPUT_LEGACYMODE",
appName, 0, RegistryValueKind.DWord);
}
static UInt32 GetBrowserEmulationMode()
{
int browserVersion = 0;
using (var ieKey = Registry.LocalMachine.OpenSubKey(@"SOFTWARE/Microsoft/Internet Explorer",
RegistryKeyPermissionCheck.ReadSubTree,
System.Security.AccessControl.RegistryRights.QueryValues))
{
var version = ieKey.GetValue("svcVersion");
if (null == version)
{
version = ieKey.GetValue("Version");
if (null == version)
throw new ApplicationException("Microsoft Internet Explorer is required!");
}
int.TryParse(version.ToString().Split(''.'')[0], out browserVersion);
}
if (browserVersion < 7)
{
throw new ApplicationException("Unsupported version of Microsoft Internet Explorer!");
}
UInt32 mode = 11000; // Internet Explorer 11. Webpages containing standards-based !DOCTYPE directives are displayed in IE11 Standards mode.
switch (browserVersion)
{
case 7:
mode = 7000; // Webpages containing standards-based !DOCTYPE directives are displayed in IE7 Standards mode.
break;
case 8:
mode = 8000; // Webpages containing standards-based !DOCTYPE directives are displayed in IE8 mode.
break;
case 9:
mode = 9000; // Internet Explorer 9. Webpages containing standards-based !DOCTYPE directives are displayed in IE9 mode.
break;
case 10:
mode = 10000; // Internet Explorer 10.
break;
}
return mode;
}
// static constructor, runs first
static MainForm()
{
SetWebBrowserFeatures();
}
public MainForm()
{
InitializeComponent();
_webBrowser = new WebBrowser() { Dock = DockStyle.Fill };
this.Controls.Add(_webBrowser);
this.Size = new System.Drawing.Size(800, 600);
this.Load += MainForm_Load;
}
// start the task
async void MainForm_Load(object sender, EventArgs e)
{
try
{
dynamic document = await LoadDynamicPage("http://demos.dojotoolkit.org/demos/calendar/demo.html",
CancellationToken.None);
MessageBox.Show(new { document.documentMode, document.compatMode }.ToString());
}
catch (Exception ex)
{
MessageBox.Show(ex.Message);
}
}
// navigate and download
async Task<object> LoadDynamicPage(string url, CancellationToken token)
{
// navigate and await DocumentCompleted
var tcs = new TaskCompletionSource<bool>();
WebBrowserDocumentCompletedEventHandler handler = (s, arg) =>
tcs.TrySetResult(true);
using (token.Register(() => tcs.TrySetCanceled(), useSynchronizationContext: false))
{
this._webBrowser.DocumentCompleted += handler;
try
{
this._webBrowser.Navigate(url);
await tcs.Task; // wait for DocumentCompleted
}
finally
{
this._webBrowser.DocumentCompleted -= handler;
}
}
// get the root element
var documentElement = this._webBrowser.Document.GetElementsByTagName("html")[0];
// poll the current HTML for changes asynchronosly
var html = documentElement.OuterHtml;
while (true)
{
// wait asynchronously, this will throw if cancellation requested
await Task.Delay(POLL_DELAY, token);
// continue polling if the WebBrowser is still busy
if (this._webBrowser.IsBusy)
continue;
var htmlNow = documentElement.OuterHtml;
if (html == htmlNow)
break; // no changes detected, end the poll loop
html = htmlNow;
}
// consider the page fully rendered
token.ThrowIfCancellationRequested();
return this._webBrowser.Document.DomDocument;
}
}
}
Esto funciona para mi:
yourWebBrowser.ScriptErrorsSuppressed = true;
Revise el siguiente sitio web para obtener información sobre ScriptErrorsSuppressed
Extracto del sitio web:
Comentarios Establezca esta propiedad en falso para depurar las páginas web que muestra en el control WebBrowser. Esto es útil cuando usa el control para agregar controles basados en web y código de secuencias de comandos a su aplicación. Es menos útil cuando usa el control como un navegador genérico. Cuando haya terminado de depurar su aplicación, establezca esta propiedad en verdadero para suprimir los errores de script.
Nota
Cuando ScriptErrorsSuppressed se establece en verdadero, el control WebBrowser oculta todos sus cuadros de diálogo que se originan en el control ActiveX subyacente, no solo los errores de script. Ocasionalmente, es posible que deba suprimir los errores de script al mostrar cuadros de diálogo como los que se usan para la configuración de seguridad del navegador y el inicio de sesión del usuario. En este caso, establezca ScriptErrorsSuppressed en falso y suprima los errores de script en un controlador para el evento HtmlWindow.Error. Para obtener más información, consulte el ejemplo de código en este tema.