Click here to Skip to main content
65,938 articles
CodeProject is changing. Read more.
Articles
(untagged)

Creating a Simple scratch card Control in WinForms

0.00/5 (No votes)
21 Oct 2015 3  
A simple scratch card like control for Winforms, where the user can reveal the image by scratching off a cover

Introduction

We all know how a scratch card works - even if we don't buy them - you take a coin, and you scrape off a coving to reveal a symbol beneath - if you have the right set of symbols, you win! But the covering means you can't tell before you start scraping.

This provides a control where the user can do the same thing with his mouse.

Background

This was an answer I posted to a question (How do you create a windows form application that works like a lottery scratch-and-win[^] - but someone decided that wasn't answerable, despite my answer being posted... :sigh: ) 

So I tidied up the code a little, made it a bit more flexible, and posted it here.

Using the Code

Add the User Control "ScratchImage" to your project (change the namespace, probably) and compile.

Drag and drop an instance onto your form, and set the Image property to a suitable image.

Run your app, and press the mouse button down on the cover surface, and drag to scratch the cover away.

How It Works

What it does is simple: the control has a couple of internal variables:

/// <summary>
/// The image we cover the "real" image with
/// </summary>
private Bitmap cover;
/// <summary>
/// When true, mouse movement removes the "cover" image
/// </summary>
private bool scratching = false;
/// <summary>
/// Last point the user scratched to
/// </summary>
private Point last = new Point(0, 0);

With a few simple property bases:

/// <summary>
/// Image to reveal as the top is "scratched off"
/// </summary>
private Image _Image = null;
/// <summary>
/// Pen to scratch with - wider reveals more at a time.
/// </summary>
/// <remarks>
/// The colour of this pen *MUST* match the colour used in the Paint event
/// to set the Transparency for the "cover" image.
/// </remarks>
private Pen _ScratchPen = new Pen(Brushes.Red, 5.0F);
/// <summary>
/// Brush to fill the cover image with
/// </summary>
private Brush _CoverBrush = Brushes.LightGray;

And handles a couple of mouse events:

/// <summary>
/// Mouse down - so start "scratching" from this point.
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void ScratchImage_MouseDown(object sender, MouseEventArgs e)
    {
    scratching = true;
    last = e.Location;
    }
/// <summary>
/// Mouse up - so stop "scratching"
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void ScratchImage_MouseUp(object sender, MouseEventArgs e)
    {
    scratching = false;
    }
/// <summary>
/// If we are scratching, draw on the cover so that the transparency layer lets
/// the real image show through.
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void ScratchImage_MouseMove(object sender, MouseEventArgs e)
    {
    if (scratching)
        {
        using (Graphics g = Graphics.FromImage(cover))
            {
            g.DrawLine(_ScratchPen, last, e.Location);
            }
        last = e.Location;
        Invalidate();
        }
    }

It also fills the "cover" with a solid colour:

/// <summary>
/// Creates an cover big enough to hide the "real" image
/// </summary>
private void MakeCover()
    {
    if (cover != null) cover.Dispose();
    cover = new Bitmap(Width, Height);
    using (Graphics g = Graphics.FromImage(cover))
        {
        g.FillRegion(_CoverBrush, new Region(new Rectangle(0, 0, Width, Height)));
        }
    }

Then, all it has to do is draw the two images via the Paint event:

/// <summary>
/// Paint the image and it's cover.
/// </summary>
/// <remarks>
/// We draw the "real image",
/// then we cover it with an image which contains a transparency layer.
/// The "scratched off" colour goes transparent,
/// and the real image can be seen through it.
/// </remarks>
/// <param name="sender"></param>
/// <param name="e"></param>
private void ScratchImage_Paint(object sender, PaintEventArgs e)
    {
    if (Image != null)
        {
        e.Graphics.DrawImage(Image, 0, 0, Width, Height);
        cover.MakeTransparent(_ScratchPen.Color);
        e.Graphics.DrawImage(cover, 0, 0, Width, Height);
        }
    }

That's it! There are a couple of other properties to make it more flexible, it has DoubleBuffered set to make it work properly, and it recreates the cover image on resize, but that's about all.

While the user is "scratching" with the mouse, that draws onto the "cover" image in a specific color of pen - which defaults to Red - which is treated as the Transparency colour when the cover is drawn over the base image. So everything drawn in Red on the cover becomes see-though and the image below becomes visible through the cover where the user held the mouse down to "scratch".

History

  • 2015-10-21 First version

License

This article has no explicit license attached to it but may contain usage terms in the article text or the download files themselves. If in doubt please contact the author via the discussion board below.

A list of licenses authors might use can be found here