Let the user drag an image with transparent pixels over a background image in C#

drag an image

This example shows how you can let the user drag an image on a PictureBox. The PictureBox‘s Image property is set to a background image. The user can press the mouse down on any of the image’s non-transparent pixels to drag the image.

When it starts, the program uses the following code to get ready to drag the image.

// The smiley image.
private Bitmap Smiley;

// The smiley image's location.
private Rectangle SmileyLocation;

private void Form1_Load(object sender, EventArgs e)
{
    // Make the white pixels in the smiley transparent.
    Smiley = new Bitmap(Properties.Resources.smile);
    Smiley.MakeTransparent(Color.White);

    // Set the smiley's initial location.
    SmileyLocation = new Rectangle(10, 10,
        Smiley.Width, Smiley.Height);
}

The program first gets the image from the smile resource and uses it to make a Bitmap. It uses the Bitmap‘s MakeTransparent method to make the image’s white pixels transparent.

The program stores the image’s location in a Rectangle named SmileyLocation. After it loads the smiley image, the program initializes SmileyLocation to the position (10, 10).

The following code shows the PictureBox‘s Paint event handler.

// Draw the picture over the background.
private void picBackground_Paint(object sender, PaintEventArgs e)
{
    e.Graphics.DrawImage(Smiley, SmileyLocation);
}

This code simply draws the picture above the background.

When the user presses the mouse down on the PictureBox, the following code starts dragging the smiley image.

// True when we are dragging.
private bool Dragging = false;

// The offset from the mouse's down position
// and the picture's upper left corner.
private int OffsetX, OffsetY;

// Start dragging the picture.
private void picBackground_MouseDown(
    object sender, MouseEventArgs e)
{
    // See if we're over the picture.
    if (PointIsOverPicture(e.X, e.Y))
    {
        // Start dragging.
        Dragging = true;

        // Save the offset from the mouse to the picture's origin.
        OffsetX = SmileyLocation.X - e.X;
        OffsetY = SmileyLocation.Y - e.Y;
    }
}

The variable Dragging records whether the program is currently dragging the smiley. The variables OffsetX and OffsetY record the distance between the smiley image’s upper left corner and the mouse’s location.

The MouseDown event handler calls the PointIsOverPicture method described later to see if the mouse is over a non-transparent pixel in the smiley image. It if is over such a pixel, the program sets Dragging = true and stores the difference between the smiley image’s location and the mouse’s position.

When the mouse moves, the following MouseMove event handler continues the drag.

// Continue dragging the picture.
private void picBackground_MouseMove(
    object sender, MouseEventArgs e)
{
    // See if we're dragging.
    if (Dragging)
    {
        // We're dragging the image. Move it.
        SmileyLocation.X = e.X + OffsetX;
        SmileyLocation.Y = e.Y + OffsetY;

        // Redraw.
        picBackground.Invalidate();
    }
    else
    {
        // We're not dragging the image. See if we're over it.
        Cursor new_cursor = Cursors.Default;
        if (PointIsOverPicture(e.X, e.Y))
        {
            new_cursor = Cursors.Hand;
        }
        if (picBackground.Cursor != new_cursor)
            picBackground.Cursor = new_cursor;
    }
}

This code checks Dragging to see if a drag is in progress. If Dragging is true, the code updates the smiley image’s location so it remains the same distance from the mouse’s current position as it had when the user pressed the mouse down. It then invalidates the PictureBox to make it’s Paint event handler draw the smiley at its new location.

If Dragging is false, the code calls the PointIsOverPicture method to see if the mouse is over a non-transparent pixel. If it is, the program displays the Hand cursor. Otherwise it displays the default cursor.

When the user releases the mouse, the following code ends the drag.

// Stop dragging the picture.
private void picBackground_MouseUp(
    object sender, MouseEventArgs e)
{
    Dragging = false;
}

The following code shows the PointIsOverPicture method, which returns true if the indicated position is over a non-transparent pixel on the smiley image.

// Return true if the point is over the picture's current location.
private bool PointIsOverPicture(int x, int y)
{
    // See if it's over the picture's bounding rectangle.
    if ((x < SmileyLocation.Left) || (x >= SmileyLocation.Right) ||
        (y < SmileyLocation.Top) || (y >= SmileyLocation.Bottom))
        return false;

    // See if the point is above a non-transparent pixel.
    int i = x - SmileyLocation.X;
    int j = y - SmileyLocation.Y;
    return (Smiley.GetPixel(i, j).A > 0);
}

First the code determines whether the point is over the smiley image’s bounding rectangle. If it is not, the method returns false.

If the position is over the smiley image’s bounding rectangle, the method calculates the pixel position relative to the image’s upper left corner. It then uses the smiley bitmap’s GetPixel method to get the color of the pixel at that position. It returns true if that pixel’s alpha (opacity) component is greater than 0, indicating that it is not transparent.


Download Example   Follow me on Twitter   RSS feed




This entry was posted in graphics, image processing and tagged , . Bookmark the permalink.

Leave a Reply

Your email address will not be published. Required fields are marked *