António R. António R. - 20 days ago 6
C# Question

How to limit dragging an image inside a Panel?

Good evening. I'm currently working on an interactive map editor. I'm trying to keep the map image from being dragged out of view by using this code

if (currentPosition.X > 0)
currentPosition.X = 0;
else if (currentPosition.X < -mapSize.Width + Size.Width )
currentPosition.X = -mapSize.Width + Size.Width ;
if (currentPosition.Y > 0)
currentPosition.Y = 0;
else if (currentPosition.Y < -mapSize.Height + Size.Height)
currentPosition.Y = -mapSize.Height + Size.Height;


However I can't drag it to the limits Size-mapSize.
The currentPosition corresponds to the upper left location of the image. Here's the full code of the class

namespace GameMaps
{
public class MapPanel : Panel
{
private Bitmap shownMap = null;
private Point mapLocation;
private Size mapSize;
private bool dragging;
private Point currentPosition;
//private Point newPosition;
private Point initialPosition;
private Point initialMousePosition;
private Form1 parentForm;

public MapPanel(Form1 parentForm) : base()
{
this.DoubleBuffered = true;


this.parentForm = parentForm;

}
public MapPanel(Panel targetPanel) : this(new Form1())
{

}

public void ShowMap(Map map)
{
if (map == null) return;
shownMap = map.MapTexture;
mapLocation = new Point(0, 0);
mapSize = shownMap.Size;
currentPosition = new Point();
initialPosition = new Point();
initialMousePosition = new Point(); //mapLocation;

}
protected override void OnPaint(PaintEventArgs e)
{
e.Graphics.PageUnit = GraphicsUnit.Pixel;
e.Graphics.PageScale = 1.0F;
// base.OnPaint(e);
if (shownMap == null)
{
base.OnPaint(e);
return;
}
e.Graphics.DrawImage(shownMap, currentPosition.X, currentPosition.Y);

}
protected override void OnMouseDown(MouseEventArgs e)
{
// base.OnMouseDown(e);
if (shownMap == null)
{
base.OnMouseDown(e);
return;
}
if (dragging)
{
dragging = false;
return;
}
else dragging = true;
initialPosition.X = currentPosition.X;
initialPosition.Y = currentPosition.Y;

initialMousePosition = e.Location;
}
protected override void OnMouseMove(MouseEventArgs e)
{
/*parentForm.label7.Text = currentPosition.X.ToString();
parentForm.label8.Text = currentPosition.Y.ToString();
parentForm.label9.Text = mapSize.Width.ToString();
parentForm.label10.Text = mapSize.Height.ToString();
parentForm.label11.Text = Size.Width.ToString();
parentForm.label12.Text = Size.Width.ToString();*/

//base.OnMouseMove(e);
if (!dragging) return;

currentPosition.X = e.X - initialMousePosition.X + initialPosition.X;
currentPosition.Y = e.Y - initialMousePosition.Y + initialPosition.Y;

if (currentPosition.X > 0)
currentPosition.X = 0;
else if (currentPosition.X < -mapSize.Width + Size.Width )
currentPosition.X = -mapSize.Width + Size.Width ;
if (currentPosition.Y > 0)
currentPosition.Y = 0;
else if (currentPosition.Y < -mapSize.Height + Size.Height)
currentPosition.Y = -mapSize.Height + Size.Height;

//if (currentPosition.X + mapSize.Width < this.Size.Width)
// currentPosition.X = this.Size.Width - mapSize.Width;


Invalidate();

// (e.X - initialPosition.X + xinit, e.Y - init_loc.Y + yinit);
}
protected override void OnMouseLeave(EventArgs e)
{
// base.OnMouseLeave(e);
dragging = false;
// F*! if I hold the mouse down this does not work
}

protected override void OnMouseUp(MouseEventArgs e)
{
//base.OnMouseUp(e);
dragging = false;
}
}


}

Answer

Well, it seems there was no bad logic except for the fact that I was using the Panel's Size instead of its DisplayRectangle (Size.Width == DisplayRectangle.Width-2). The whole problem was that the images I was using had been exported from Photoshop and had a resolution of 72dpi instead of 96dpi: Same Size, but on using DrawImage they were scaled up. Here's my solution. There are still this to correct but this is the solution regarding my original question. Also some variable names were changed.

namespace GameMaps
{
public class MapPanel : Panel
{
    private Map sourceMap;

    private Bitmap mapTexture;
    private Size mapSize;
    private Point mapPosition;
    private float dpiX, dpiY;

    private Point initialPosition;
    private Point initialMousePosition;

    private bool dragging;

    /* Constructors */
    public MapPanel() : base()
    {
        this.DoubleBuffered = true;

        this.sourceMap = null;
        this.dpiX = 96.0F; this.dpiY = 96.0F; // For now, this Application won't be DPI aware
    }

    public MapPanel(Panel targetPanel) : this()
    {
        // TO DO
    }

    /* Show a Map */
    public void ShowMap(Map map)
    {
        if (map == null)
            return;
        sourceMap = map;

        mapTexture = new Bitmap(map.MapTexture);
        mapTexture.SetResolution(dpiX, dpiY);
        mapSize = mapTexture.Size; // ?
        mapPosition = new Point(0, 0);
    }

    protected override void OnPaint(PaintEventArgs e)
    {
        // base.OnPaint(e);

        e.Graphics.PageUnit = GraphicsUnit.Pixel; // ?
        e.Graphics.PageScale = 1.0F; // ?

        if (sourceMap == null)
        {
            base.OnPaint(e);
            return;
        }
        e.Graphics.DrawImage(mapTexture, mapPosition.X, mapPosition.Y);
    }

    protected override void OnMouseDown(MouseEventArgs e)
    {
        // base.OnMouseDown(e);

        if (sourceMap == null)
        {
            base.OnMouseDown(e);
            return;
        }

        if (dragging)
        {
            dragging = false;
            return;
        }
        else dragging = true;

        initialPosition.X = mapPosition.X;
        initialPosition.Y = mapPosition.Y;

        initialMousePosition.X = e.Location.X;
        initialMousePosition.Y = e.Location.Y;
    }

    protected override void OnMouseMove(MouseEventArgs e)
    {
        //base.OnMouseMove(e);

        if (!dragging) return;

        mapPosition.X = e.X - initialMousePosition.X + initialPosition.X;
        mapPosition.Y = e.Y - initialMousePosition.Y + initialPosition.Y;

        if (mapPosition.X > 0)
            mapPosition.X = 0;
        else if (mapPosition.X < DisplayRectangle.Width - mapSize.Width)
            mapPosition.X = DisplayRectangle.Width - mapSize.Width;

        if (mapPosition.Y > 0)
            mapPosition.Y = 0;
        else if (mapPosition.Y < DisplayRectangle.Height - mapSize.Height)
            mapPosition.Y =  DisplayRectangle.Height - mapSize.Height;

        Invalidate(); // Force Repaint
    }

    protected override void OnMouseLeave(EventArgs e)
    {
        // base.OnMouseLeave(e);

        dragging = false;
        // TO DO: Correct this
    }

    protected override void OnMouseUp(MouseEventArgs e)
    {
        //base.OnMouseUp(e);

        dragging = false;
    }
}
}
Comments