问题
I've embedded Monogame into a Windows Form using this code:
private IntPtr drawSurface;
private Control gameForm;
public MapEditor(MainWindow window)
{
graphics = new GraphicsDeviceManager(this);
Content.RootDirectory = "Content";
this.drawSurface = window.pcbViewport.Handle;
graphics.PreparingDeviceSettings += new EventHandler<PreparingDeviceSettingsEventArgs>(graphics_PreparingDeviceSettings);
Mouse.WindowHandle = drawSurface;
gameForm = Control.FromHandle(this.Window.Handle);
gameForm.VisibleChanged += new EventHandler(gameForm_VisibleChanged);
}
private void gameForm_VisibleChanged(object sender, EventArgs e)
{
if (gameForm.Visible)
{
gameForm.Visible = false;
}
}
private void graphics_PreparingDeviceSettings(object sender, PreparingDeviceSettingsEventArgs e)
{
e.GraphicsDeviceInformation.PresentationParameters.DeviceWindowHandle = drawSurface;
}
Now, this code used to work... I think. It's been a while and the code is on another computer with an older version so I seem to remember this working before now with Monogame. Anyway, the problem is that Mouse input doesn't work! Keyboard and Gamepad input work fine, but Mouse input doesn't register at all. I've experimented and found that if I take out the VisibleChanged event, it works but it also shows the GameWindow as well as the form (which it doesn't need to as it's being drawn in the PictureBox.
I'm aware that I can put the GameWindow in a Control, and if need be then I'll do that but I'm trying to see if there is a solution to making the existing code work again.
回答1:
The issue with your approach is that setting Mouse.WindowHandle
in MonoGame
does nothing (the setter for this property is empty, if you look at the source code).1
This means that your Game
is always bound to its default window (the one that you are hiding), and that all mouse input outside that window is ignored. If you don't hide it, you will see that clicking into the original window creates mouse events correctly. Draws, on the other hand, are done to the picture box correctly. Keyboard events are not filtered by screen area, so they work without issues.
My opinion is that this is not how you should be hosting XNA/MonoGame inside Windows Forms, but instead look into how to implement a GraphicsDeviceControl
class, which should inherit from System.Windows.Forms.Control
and provide the ability to draw itself by using an XNA Framework GraphicsDevice
. The approach is explained in this article (XNA 4, but can be easily ported to MonoGame).
If you do want to use the approach you are using right now, the only thing you can do is checkout MonoGame source code, and find the implementation of GameWindow
for windows forms (that is, WinFormsGameWindow
, which is an internal class). Since Mouse.GetState()
merely returns GameWindow.MouseState
, a possibility to instantiate your own GameWindow
would allow you to get the events filtered by your window.
Or, if you are changing MonoGame code anyway, then you might as well add a Game
constructor overload which would accept the Control
handle from the start.
1 Ironically, there is a comment inside that this setter was left "only for XNA compatibility", like throwing a compile-time error is a big deal compared to the time people will lose debugging this. :-D
来源:https://stackoverflow.com/questions/33812634/mouse-not-working-with-monogame-in-winforms