问题描述
我试着去渲染渲染一边我monogame项目浏览器,绘制一些接口和放大器;东东。我已经在过去与没有问题旧版本awesomium的做到了这一点。但我无法弄清楚如何在properbly这个新版本初始化awesomium,我得到一个错误,不管我如何努力去做。据我了解,我需要调用WebCore.Run()一次,而不是WebCore.Update(),但我从那个方法杂色山雀例外。
Im trying to render render a browser in side my monogame project, for drawing some interface & stuff. I've done this in the past with older versions of awesomium with no problems. But i can't figure out how to properbly initialize awesomium in this new version, I get an error no matter how i try to go about it. As i understand it i need to call WebCore.Run() once, instead of WebCore.Update(), but i get varius exceptions from that method.
下面是我一直沿袭至今步骤:
Here are the steps that i've followed so far:
- 安装Awesomium 1.7.4.2
- Refrenced
\1.7.4.2\wrappers\Awesomium.NET\Assemblies\Packed\Awesomium.Core.dll
在我的项目
- Install Awesomium 1.7.4.2
- Refrenced
\1.7.4.2\wrappers\Awesomium.NET\Assemblies\Packed\Awesomium.Core.dll
in my project
下面是我的一些尝试:
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(),并永远不会完成该行。
I have also managed to get NullRefrence errors, and if i wait Thread.Sleep(400) before calling WebCore.Run(), it just enters the WebCore.Run() and never completes that line.
我要如何设置?找不到任何地方的任何实例。所有在线的例子还告诉你用更新至极已经过时了。
How do i set this up? Can't find any examples anywhere. All the examples online still tells you to use Update wich is Obsolete
推荐答案
我刚刚得到这个工作,你必须创建一个新线程,然后调用运行,然后听一听是这将由随后创建了一个新的SynchronizationContext通过的WebCore被引发的事件。那么你要保持你的主线程这方面的参考...
I have just got this working, you have to create a new thread, then call Run, then listen for an event to be raised by WebCore which will have created a new SynchronizationContext by then. You then want to keep a reference to that context on your main thread...
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 ...
... you can then call all your WebView methods using that SynchronizationContext ...
awesomiumContext.Post(state =>
{
this.WebView.Source = "http://www.google.com";
}, null);
我会收拾这与未来的编辑,但是要得到你们开始了,这里是我的组件...
I will tidy this up with a future edit, but to get you guys started, here is my component...
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); ;
}
}
}
这篇关于如何实现Awesomium 1.7.4.2在Monogame项目呢?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!