|
using Microsoft.Xna.Framework; |
|
using Microsoft.Xna.Framework.Graphics; |
|
using Microsoft.Xna.Framework.Input; |
|
using YOURNAMESPACE.CefWrapper; |
|
using Xilium.CefGlue; |
|
|
|
namespace YOURNAMESPACE; |
|
|
|
public class MainGame : Game |
|
{ |
|
private GraphicsDeviceManager _graphics = null!; |
|
private SpriteBatch _spriteBatch = null!; |
|
private MonoGameRenderHandler _renderHandler = null!; |
|
private BrowserClient _client = null!; |
|
private CefBrowser? _browser; |
|
public MainGame() |
|
{ |
|
_graphics = new GraphicsDeviceManager(this); |
|
Content.RootDirectory = "Content"; |
|
IsMouseVisible = true; |
|
} |
|
|
|
public async Task RunAsync() |
|
{ |
|
await Task.Run(() => Run()); |
|
} |
|
|
|
protected override void Initialize() |
|
{ |
|
base.Initialize(); |
|
|
|
int width = Window.ClientBounds.Width; |
|
int height = Window.ClientBounds.Height; |
|
|
|
_renderHandler = new MonoGameRenderHandler(GraphicsDevice, width, height); |
|
_client = new BrowserClient(_renderHandler); |
|
|
|
var windowInfo = CefWindowInfo.Create(); |
|
windowInfo.SetAsWindowless(IntPtr.Zero, true); |
|
|
|
var browserSettings = new CefBrowserSettings() |
|
{ |
|
WindowlessFrameRate = 60, |
|
}; |
|
|
|
//CefBrowserHost.CreateBrowser( |
|
// windowInfo, |
|
// _client, |
|
// browserSettings, |
|
// "http://google.com"); |
|
|
|
CefRuntime.PostTask(CefThreadId.UI, new ActionTask(() => |
|
{ |
|
_browser = CefBrowserHost.CreateBrowserSync( |
|
windowInfo, |
|
_client, |
|
browserSettings, |
|
"http://localhost:61861"); |
|
})); |
|
} |
|
|
|
protected override void LoadContent() |
|
{ |
|
_spriteBatch = new SpriteBatch(GraphicsDevice); |
|
|
|
// TODO: use this.Content to load your game content here |
|
} |
|
|
|
private MouseState _cachedMouseState; |
|
private KeyboardState _cachedKeyboardState; |
|
protected override void Update(GameTime gameTime) |
|
{ |
|
if (GamePad.GetState(PlayerIndex.One).Buttons.Back == ButtonState.Pressed || Keyboard.GetState().IsKeyDown(Keys.Escape)) |
|
{ |
|
Exit(); |
|
} |
|
|
|
var mouseState = Mouse.GetState(); |
|
var keyboardState = Keyboard.GetState(); |
|
|
|
if (_browser != null) |
|
{ |
|
SendMouseEvent(mouseState, keyboardState); |
|
SendKeyEvent(keyboardState); |
|
} |
|
|
|
_cachedMouseState = mouseState; |
|
_cachedKeyboardState = keyboardState; |
|
|
|
base.Update(gameTime); |
|
} |
|
|
|
protected override void Draw(GameTime gameTime) |
|
{ |
|
GraphicsDevice.Clear(Color.CornflowerBlue); |
|
|
|
_spriteBatch.Begin(); |
|
if (_renderHandler?.Texture != null) |
|
{ |
|
_spriteBatch.Draw(_renderHandler.Texture, Vector2.Zero, Color.White); |
|
} |
|
_spriteBatch.End(); |
|
|
|
base.Draw(gameTime); |
|
} |
|
|
|
private void SendMouseEvent(MouseState mouseState, KeyboardState keyboardState) |
|
{ |
|
if (_browser == null) |
|
{ |
|
return; |
|
} |
|
|
|
var host = _browser.GetHost(); |
|
|
|
CefEventFlags buttonFlags = GetModifiersFromMouseState(mouseState); |
|
CefEventFlags keyboardFlags = GetModifiersFromKeyboardState(keyboardState); |
|
|
|
|
|
var evt = new CefMouseEvent |
|
{ |
|
X = mouseState.X, |
|
Y = mouseState.Y, |
|
Modifiers = buttonFlags | keyboardFlags |
|
}; |
|
|
|
host.SendMouseMoveEvent(evt, false); |
|
|
|
if (mouseState.LeftButton == ButtonState.Pressed) |
|
{ |
|
host.SendMouseClickEvent(evt, CefMouseButtonType.Left, false, 1); |
|
} |
|
else if (_cachedMouseState.LeftButton == ButtonState.Pressed && mouseState.LeftButton == ButtonState.Released) |
|
{ |
|
host.SendMouseClickEvent(evt, CefMouseButtonType.Left, true, 1); |
|
} |
|
|
|
if (mouseState.RightButton == ButtonState.Pressed) |
|
{ |
|
host.SendMouseClickEvent(evt, CefMouseButtonType.Right, false, 1); |
|
} |
|
else if (_cachedMouseState.RightButton == ButtonState.Pressed && mouseState.RightButton == ButtonState.Released) |
|
{ |
|
host.SendMouseClickEvent(evt, CefMouseButtonType.Right, true, 1); |
|
} |
|
|
|
if (mouseState.MiddleButton == ButtonState.Pressed) |
|
{ |
|
host.SendMouseClickEvent(evt, CefMouseButtonType.Middle, false, 1); |
|
} |
|
else if (_cachedMouseState.MiddleButton == ButtonState.Pressed && mouseState.MiddleButton == ButtonState.Released) |
|
{ |
|
host.SendMouseClickEvent(evt, CefMouseButtonType.Middle, true, 1); |
|
} |
|
} |
|
|
|
private void SendKeyEvent(KeyboardState keyboardState) |
|
{ |
|
if (_browser == null) return; |
|
|
|
var host = _browser.GetHost(); |
|
var pressedKeys = keyboardState.GetPressedKeys(); |
|
var cachedPressedKeys = _cachedKeyboardState.GetPressedKeys(); |
|
|
|
foreach (var key in pressedKeys) |
|
{ |
|
if (!cachedPressedKeys.Contains(key)) |
|
{ |
|
bool isSpecialKey = IsSpecialKey(key); |
|
|
|
var keyDownEvent = new CefKeyEvent |
|
{ |
|
EventType = CefKeyEventType.KeyDown, |
|
WindowsKeyCode = (int)key, |
|
Modifiers = GetModifiersFromKeyboardState(keyboardState) |
|
}; |
|
host.SendKeyEvent(keyDownEvent); |
|
|
|
if (!isSpecialKey) |
|
{ |
|
char character = GetCharFromKey(key, keyboardState); |
|
if (character != '\0') |
|
{ |
|
var charEvent = new CefKeyEvent |
|
{ |
|
EventType = CefKeyEventType.Char, |
|
WindowsKeyCode = character, |
|
Modifiers = GetModifiersFromKeyboardState(keyboardState) |
|
}; |
|
host.SendKeyEvent(charEvent); |
|
} |
|
} |
|
} |
|
} |
|
|
|
foreach (var key in cachedPressedKeys) |
|
{ |
|
if (!pressedKeys.Contains(key)) |
|
{ |
|
var keyUpEvent = new CefKeyEvent |
|
{ |
|
EventType = CefKeyEventType.KeyUp, |
|
WindowsKeyCode = (int)key, |
|
Modifiers = GetModifiersFromKeyboardState(keyboardState) |
|
}; |
|
host.SendKeyEvent(keyUpEvent); |
|
} |
|
} |
|
|
|
_cachedKeyboardState = keyboardState; |
|
} |
|
|
|
private bool IsSpecialKey(Keys key) |
|
{ |
|
switch (key) |
|
{ |
|
case Keys.Back: |
|
case Keys.Tab: |
|
case Keys.Enter: |
|
case Keys.Escape: |
|
case Keys.LeftShift: |
|
case Keys.RightShift: |
|
case Keys.LeftControl: |
|
case Keys.RightControl: |
|
case Keys.LeftAlt: |
|
case Keys.RightAlt: |
|
case Keys.Up: |
|
case Keys.Down: |
|
case Keys.Left: |
|
case Keys.Right: |
|
case Keys.Delete: |
|
case Keys.Home: |
|
case Keys.End: |
|
case Keys.PageUp: |
|
case Keys.PageDown: |
|
return true; |
|
default: |
|
return false; |
|
} |
|
} |
|
|
|
private char GetCharFromKey(Keys key, KeyboardState keyboardState) |
|
{ |
|
bool shift = keyboardState.IsKeyDown(Keys.LeftShift) || keyboardState.IsKeyDown(Keys.RightShift); |
|
|
|
if (key >= Keys.A && key <= Keys.Z) |
|
{ |
|
char c = (char)('a' + (key - Keys.A)); |
|
if (shift) c = char.ToUpper(c); |
|
return c; |
|
} |
|
|
|
if (key >= Keys.D0 && key <= Keys.D9) |
|
{ |
|
char c = (char)('0' + (key - Keys.D0)); |
|
if (shift) |
|
{ |
|
return key switch |
|
{ |
|
Keys.D1 => '!', |
|
Keys.D2 => '@', |
|
Keys.D3 => '#', |
|
Keys.D4 => '$', |
|
Keys.D5 => '%', |
|
Keys.D6 => '^', |
|
Keys.D7 => '&', |
|
Keys.D8 => '*', |
|
Keys.D9 => '(', |
|
Keys.D0 => ')', |
|
_ => c |
|
}; |
|
} |
|
return c; |
|
} |
|
|
|
if (key == Keys.Space) |
|
{ |
|
return ' '; |
|
} |
|
|
|
return '\0'; |
|
} |
|
private CefEventFlags GetModifiersFromKeyboardState(KeyboardState keyboardState) |
|
{ |
|
CefEventFlags modifiers = CefEventFlags.None; |
|
if (keyboardState.IsKeyDown(Keys.LeftShift) || keyboardState.IsKeyDown(Keys.RightShift)) |
|
{ |
|
modifiers |= CefEventFlags.ShiftDown; |
|
} |
|
if (keyboardState.IsKeyDown(Keys.LeftControl) || keyboardState.IsKeyDown(Keys.RightControl)) |
|
{ |
|
modifiers |= CefEventFlags.ControlDown; |
|
} |
|
if (keyboardState.IsKeyDown(Keys.LeftAlt) || keyboardState.IsKeyDown(Keys.RightAlt)) |
|
{ |
|
modifiers |= CefEventFlags.AltDown; |
|
} |
|
if (keyboardState.IsKeyDown(Keys.CapsLock)) |
|
{ |
|
modifiers |= CefEventFlags.CapsLockOn; |
|
} |
|
return modifiers; |
|
} |
|
private CefEventFlags GetModifiersFromMouseState(MouseState mouseState) |
|
{ |
|
CefEventFlags modifiers = CefEventFlags.None; |
|
if (mouseState.LeftButton == ButtonState.Pressed) |
|
{ |
|
modifiers |= CefEventFlags.LeftMouseButton; |
|
} |
|
if (mouseState.MiddleButton == ButtonState.Pressed) |
|
{ |
|
modifiers |= CefEventFlags.MiddleMouseButton; |
|
} |
|
if (mouseState.RightButton == ButtonState.Pressed) |
|
{ |
|
modifiers |= CefEventFlags.RightMouseButton; |
|
} |
|
return modifiers; |
|
} |
|
} |
https://github.com/Pieeer1/MonoBlazor
The above repository now contains a better full example. I recommend using it, as it does not require a locally run server to operate