我试图在我的monogame项目中渲染一个浏览器,用于绘制一些界面&东西。我过去用旧版本的awesomium完成了这个,没有任何问题。但我无法弄清楚如何在这个新版本中正确地初始化awesomium,无论我如何尝试,我都会收到错误。据我所知,我需要调用WebCore.Run()一次,而不是WebCore.Update(),但我从该方法得到varius异常。
以下是我到目前为止所遵循的步骤:
\1.7.4.2\wrappers\Awesomium.NET\Assemblies\Packed\Awesomium.Core.dll
以下是我的一些尝试:
WebCore.Initialize(new WebConfig());
WebCore.Run();
//Error: Starting an update loop on a thread with an existing message loop, is not supported.
WebCore.Initialized += (sender, e) =>
{
WebCore.Run();
};
WebCore.Initialize(new WebConfig());
WebView WebView = WebCore.CreateWebView(500, 400);
//Error: Starting an update loop on a thread with an existing message loop, is not supported.
WebCore.Initialize(new WebConfig());
WebView WebView = WebCore.CreateWebView(500, 400);
WebView.Source = new Uri("http://www.google.com");
WebView.DocumentReady += (sender, e) =>
{
JSObject js = WebView.CreateGlobalJavascriptObject("w");
};
// No errors, but DocumentReady is never fired..
我还设法得到NullRefrence错误,如果我在调用WebCore.Run()之前等待Thread.Sleep(400),它只是进入WebCore.Run()并且永远不会完成该行。
我该如何设置?在任何地方找不到任何例子。在线的所有示例仍然告诉您使用更新,这是过时的
答案 0 :(得分:13)
我刚刚开始工作,你必须创建一个新线程,然后调用Run,然后监听由WebCore引发的事件,该事件将在那时创建一个新的SynchronizationContext。然后,您希望在主线程上保留对该上下文的引用...
Thread awesomiumThread = new System.Threading.Thread(new System.Threading.ThreadStart(() =>
{
WebCore.Started += (s, e) => {
awesomiumContext = SynchronizationContext.Current;
};
WebCore.Run();
}));
awesomiumThread.Start();
WebCore.Initialize(new WebConfig() { });
...然后,您可以使用该SynchronizationContext ...
调用所有WebView方法awesomiumContext.Post(state =>
{
this.WebView.Source = "http://www.google.com";
}, null);
我会用未来的编辑来整理这个,但为了让你们开始,这是我的组件...
using Awesomium.Core;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Input;
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
namespace AwesomiumComponent
{
public class BasicAwesomiumComponent : DrawableGameComponent
{
private Byte[] imageBytes;
private Rectangle area;
private Rectangle? newArea;
private Boolean resizing;
private SpriteBatch spriteBatch;
private Texture2D WebViewTexture { get; set; }
private SynchronizationContext awesomiumContext = null;
private WebView WebView { get; set; }
private BitmapSurface Surface { get; set; }
private MouseState lastMouseState;
private MouseState currentMouseState;
private Keys[] lastPressedKeys;
private Keys[] currentPressedKeys = new Keys[0];
private static ManualResetEvent awesomiumReady = new ManualResetEvent(false);
public Rectangle Area
{
get { return this.area; }
set
{
this.newArea = value;
}
}
public BasicAwesomiumComponent(Game game, Rectangle area)
: base(game)
{
this.area = area;
this.spriteBatch = new SpriteBatch(game.GraphicsDevice);
Thread awesomiumThread = new System.Threading.Thread(new System.Threading.ThreadStart(() =>
{
WebCore.Started += (s, e) => {
awesomiumContext = SynchronizationContext.Current;
awesomiumReady.Set();
};
WebCore.Run();
}));
awesomiumThread.Start();
WebCore.Initialize(new WebConfig() { });
awesomiumReady.WaitOne();
awesomiumContext.Post(state =>
{
this.WebView = WebCore.CreateWebView(this.area.Width, this.area.Height, WebViewType.Offscreen);
this.WebView.IsTransparent = true;
this.WebView.CreateSurface += (s, e) =>
{
this.Surface = new BitmapSurface(this.area.Width, this.area.Height);
e.Surface = this.Surface;
};
}, null);
}
public void SetResourceInterceptor(IResourceInterceptor interceptor)
{
awesomiumContext.Post(state =>
{
WebCore.ResourceInterceptor = interceptor;
}, null);
}
public void Execute(string method, params object[] args)
{
string script = string.Format("viewModel.{0}({1})", method, string.Join(",", args.Select(x => "\"" + x.ToString() + "\"")));
this.WebView.ExecuteJavascript(script);
}
public void RegisterFunction(string methodName, Action<object, CancelEventArgs> handler)
{
// Create and acquire a Global Javascript object.
// These object persist for the lifetime of the web-view.
using (JSObject myGlobalObject = this.WebView.CreateGlobalJavascriptObject("game"))
{
// The handler is of type JavascriptMethodEventHandler. Here we define it
// using a lambda expression.
myGlobalObject.Bind(methodName, true, (s, e) =>
{
handler(s, e);
// Provide a response.
e.Result = "My response";
});
}
}
public void Load()
{
LoadContent();
}
protected override void LoadContent()
{
if (this.area.IsEmpty)
{
this.area = this.GraphicsDevice.Viewport.Bounds;
this.newArea = this.GraphicsDevice.Viewport.Bounds;
}
this.WebViewTexture = new Texture2D(this.Game.GraphicsDevice, this.area.Width, this.area.Height, false, SurfaceFormat.Color);
this.imageBytes = new Byte[this.area.Width * 4 * this.area.Height];
}
public override void Update(GameTime gameTime)
{
awesomiumContext.Post(state =>
{
if (this.newArea.HasValue && !this.resizing && gameTime.TotalGameTime.TotalSeconds > 0.10f)
{
this.area = this.newArea.Value;
if (this.area.IsEmpty)
this.area = this.GraphicsDevice.Viewport.Bounds;
this.WebView.Resize(this.area.Width, this.area.Height);
this.WebViewTexture = new Texture2D(this.Game.GraphicsDevice, this.area.Width, this.area.Height, false, SurfaceFormat.Color);
this.imageBytes = new Byte[this.area.Width * 4 * this.area.Height];
this.resizing = true;
this.newArea = null;
}
lastMouseState = currentMouseState;
currentMouseState = Mouse.GetState();
this.WebView.InjectMouseMove(currentMouseState.X - this.area.X, currentMouseState.Y - this.area.Y);
if (currentMouseState.LeftButton == ButtonState.Pressed && lastMouseState.LeftButton == ButtonState.Released)
{
this.WebView.InjectMouseDown(MouseButton.Left);
}
if (currentMouseState.LeftButton == ButtonState.Released && lastMouseState.LeftButton == ButtonState.Pressed)
{
this.WebView.InjectMouseUp(MouseButton.Left);
}
if (currentMouseState.RightButton == ButtonState.Pressed && lastMouseState.RightButton == ButtonState.Released)
{
this.WebView.InjectMouseDown(MouseButton.Right);
}
if (currentMouseState.RightButton == ButtonState.Released && lastMouseState.RightButton == ButtonState.Pressed)
{
this.WebView.InjectMouseUp(MouseButton.Right);
}
if (currentMouseState.MiddleButton == ButtonState.Pressed && lastMouseState.MiddleButton == ButtonState.Released)
{
this.WebView.InjectMouseDown(MouseButton.Middle);
}
if (currentMouseState.MiddleButton == ButtonState.Released && lastMouseState.MiddleButton == ButtonState.Pressed)
{
this.WebView.InjectMouseUp(MouseButton.Middle);
}
if (currentMouseState.ScrollWheelValue != lastMouseState.ScrollWheelValue)
{
this.WebView.InjectMouseWheel((currentMouseState.ScrollWheelValue - lastMouseState.ScrollWheelValue), 0);
}
lastPressedKeys = currentPressedKeys;
currentPressedKeys = Keyboard.GetState().GetPressedKeys();
// Key Down
foreach (var key in currentPressedKeys)
{
if (!lastPressedKeys.Contains(key))
{
this.WebView.InjectKeyboardEvent(new WebKeyboardEvent()
{
Type = WebKeyboardEventType.KeyDown,
VirtualKeyCode = (VirtualKey)(int)key,
NativeKeyCode = (int)key
});
if ((int)key >= 65 && (int)key <= 90)
{
this.WebView.InjectKeyboardEvent(new WebKeyboardEvent()
{
Type = WebKeyboardEventType.Char,
Text = key.ToString().ToLower()
});
}
else if (key == Keys.Space)
{
this.WebView.InjectKeyboardEvent(new WebKeyboardEvent()
{
Type = WebKeyboardEventType.Char,
Text = " "
});
}
}
}
// Key Up
foreach (var key in lastPressedKeys)
{
if (!currentPressedKeys.Contains(key))
{
this.WebView.InjectKeyboardEvent(new WebKeyboardEvent()
{
Type = WebKeyboardEventType.KeyUp,
VirtualKeyCode = (VirtualKey)(int)key,
NativeKeyCode = (int)key
});
}
}
}, null);
base.Update(gameTime);
}
public override void Draw(GameTime gameTime)
{
awesomiumContext.Post(state =>
{
if (Surface != null && Surface.IsDirty && !resizing)
{
unsafe
{
// This part saves us from double copying everything.
fixed (Byte* imagePtr = this.imageBytes)
{
Surface.CopyTo((IntPtr)imagePtr, Surface.Width * 4, 4, true, false);
}
}
this.WebViewTexture.SetData(this.imageBytes);
}
}, null);
Vector2 pos = new Vector2(0, 0);
spriteBatch.Begin();
spriteBatch.Draw(this.WebViewTexture, pos, Color.White);
spriteBatch.End();
GraphicsDevice.Textures[0] = null;
base.Draw(gameTime);
}
public Uri Source
{
get
{
return this.WebView.Source;
}
set
{
awesomiumContext.Post(state =>
{
this.WebView.Source = value;
}, null);
}
}
public void Resize(int width, int height)
{
this.newArea = new Rectangle(0, 0, width, height); ;
}
}
}