Take the 2-minute tour ×
Game Development Stack Exchange is a question and answer site for professional and independent game developers. It's 100% free, no registration required.

I'm working on a basic 2D tilemap editor in C#/XNA. Currently, it displays the map through a picturebox through which XNA's output is being routed, and editing is accomplished through simply checking mouse position (i.e., Is it within the picture box? If so, what tile is it on?).

The problem I'm having is that this results in the map being edited through other windows. For example, when trying to save a map, any clicks in the savefiledialog window will edit the map square beneath it, including the click on "Ok" or "cancel."

I believe this is the offending snippet of code from the Game1 class:

protected override void Update(GameTime gameTime)
    {

        Camera.Position = new Vector2(hscroll.Value, vscroll.Value);

        MouseState ms = Mouse.GetState();

        if ((ms.X > 0) && (ms.Y > 0) &&
            (ms.X < Camera.ViewPortWidth) &&
            (ms.Y < Camera.ViewPortHeight))
        {
            Vector2 mouseLoc = Camera.ScreenToWorld(
                new Vector2(ms.X, ms.Y));

            if (Camera.WorldRectangle.Contains(
                (int)mouseLoc.X, (int)mouseLoc.Y)) //<--right there
            {
                if (ms.LeftButton == ButtonState.Pressed)
                  //....

Two questions.

  1. Is this even a viable way to display the map in the map editor? I'd like to be able to pan, zoom, etc. in the future, as well as select multiple tiles at once and edit their properties.

  2. How do I stop the picturebox from registering clicks while other windows are in focus? I've tried adding && PictureBox.Focused to the if statement up there, but that stops it from accepting input at all, regardless of whether there's another window over it (apparently, "focus" doesn't mean what I thought it meant in this context).

Confession: this is my first attempt at Winform programming. Please excuse my lack of experience.

UPDATE: && pictureBox.Focused didn't work, but && pictureBox.Capture did. Still feels a little sloppy, but it works now. I have no confidence that this solution is correct, so I'm not closing the question just yet--something tells me there's a more correct way, and I'd like to know about it.

UPDATE2: Using Capture has introduced a new bug--right clicks don't register reliably (i.e., only around one in ten clicks) until minimizing and restoring the window, after which they register correctly. Rage.

share|improve this question
    
Are you creating your "save-dialog" as a modal dialog? A modal window shouldn't allow clicks anywhere else except the dialog itself. –  bummzack Jan 21 '13 at 8:08
add comment

2 Answers

up vote 1 down vote accepted

I reworked the code to use the Windows.Forms mouse event methods rather than XNA's input methods, and that solved the click-through problem. Just had to use PointToClient and set up offset values (i.e., int offset = myPictureBox.Location.X) to subtract from my mouse coordinates.

Here's the relevant code, for anyone who stumbles upon this problem in the future:

//constructor
public MapEditor()
    {
        InitializeComponent();
        this.pctSurface.MouseDown += new MouseEventHandler(pctSurface_Click);

        pctSurface_xOffset = pctSurface.Location.X; //private instance variables
        pctSurface_yOffset = pctSurface.Location.Y; 
    }

//on click
private void pctSurface_Click(object sender, EventArgs e)
    {
        //convert from screen coordinates to game world coordinates
        Vector2 mouseLoc = Camera.ScreenToWorld(
            new Vector2(PointToClient(MousePosition).X - pctSurface_xOffset,
                        PointToClient(MousePosition).Y - pctSurface_yOffset));

        switch (MouseButtons)
        {
            case System.Windows.Forms.MouseButtons.Left:
            //whatever you need left clicks to do
            break;
            //etc
share|improve this answer
add comment

This is an issue I was facing and its not directly built into XNA. One thing you can do is use win32 form controls to check which window is active. Another would be to centralize the dialogs and when one is opened, set a flag to disable input. (You can get the win32 form info by doing

var form = System.windows.Control.FromHandle(Window.Handle) as System.windows.Forms.Form;

)

share|improve this answer
add comment

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.