【问题标题】:How do i implement Awesomium 1.7.4.2 in a Monogame project?如何在 Monogame 项目中实现 Awesomium 1.7.4.2?
【发布时间】:2014-04-12 12:12:30
【问题描述】:

我正在尝试在我的 monogame 项目中渲染一个浏览器,以绘制一些界面和东西。我过去曾使用旧版本的 awesomium 做到这一点,没有任何问题。但是我不知道如何在这个新版本中正确初始化 awesomium,无论我如何尝试都会出错。

据我了解,我需要调用一次 WebCore.Run(),而不是 WebCore.Update(),但我从该方法中得到了各种异常。

以下是我到目前为止所遵循的步骤:

  1. 安装 Awesomium 1.7.4.2
  2. 在我的项目中引用了\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() 并且永远不会完成该行。

如何设置?在任何地方都找不到任何示例。所有在线示例仍然告诉您使用已过时的更新。

【问题讨论】:

  • 我也在为同样的事情苦苦挣扎。
  • 是的,我从来没有解决它...我降级到版本 1.7.3.0 那个版本工作得很好。如果您对此有任何疑问,我很乐意提供帮助。

标签: c# monogame awesomium


【解决方案1】:

我刚刚完成了这项工作,您必须创建一个新线程,然后调用 Run,然后侦听 WebCore 引发的事件,届时 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); ;
        }
    }
}

【讨论】:

  • 太棒了!我永远也想不通。请问您是从哪里找到这些信息的?
  • 我阅读了有关 Run 方法的注释,并对其进行了修改,直到我让它工作为止。要查看注释,请在 Run 方法上执行 GoToDefinition,然后展开折叠的注释。
  • 干得好,院长。我希望我能给你 1000 票。
  • 我正在 XNA 中尝试你的实现(我认为应该是一样的),我发现了一些问题。 WebCore 线程从未停止,必须添加以下内容:protected override void UnloadContent() { WebCore.Shutdown();然后我有关于获取键事件的问题,我想它与线程有关,然后是另一个问题:你如何处理 CTRL+A 来选择所有(选定的字段),CTRL+C/X/V 来复制和粘贴?谢谢
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-03-05
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多