Home
Search
 
What's New
Index
Books
Links
Q & A
Newsletter
Banners
 
Feedback
Tip Jar
 
C# Helper...
 
XML RSS Feed
Follow VBHelper on Twitter
 
 
 
MSDN Visual Basic Community
 
 
 
 
TitleLet the user select an irregular area and copy it to and from the clipboard in VB .NET
Keywordsregion, path, area, select, overlay, copy, VB.NET, transparent, clipboard
CategoriesGraphics, VB.NET
 
This program uses a PictureBox's MouseDown, MouseMove, and MouseUp event handlers to let the user scribble to select an area. It saves the points drawn by the user in the m_Points array.

The MouseUp event handler adds a point to close the area if necessary. It then uses the points to create a graphics Path object. It makes a Bitmap containing a copy of a background picture and then makes a Graphics object attached to the Bitmap.

Next the protgram fills the new bitmap with transparent color (alpha = 0). It uses the Graphics object's SetClip method to restrict drawing to the Path and then uses DrawImage to copy the original picture onto the background (in the restricted area). The result is a picture that is transparent everywhere except where the picture inside the Path was copied.

 
Private m_Points() As Point
Private m_MaxPoint As Integer

' Start selecting a region.
Private Sub picVisible_MouseDown(ByVal sender As Object, _
    ByVal e As System.Windows.Forms.MouseEventArgs) Handles _
    picVisible.MouseDown
    ' Erase any previous drawing.
    picVisible.Image = DirectCast(picOriginal.Image.Clone, _
        Bitmap)

    ' Save the starting point.
    m_MaxPoint = 0
    ReDim m_Points(m_MaxPoint)
    m_Points(m_MaxPoint).X = e.X
    m_Points(m_MaxPoint).Y = e.Y
End Sub

' Continue selecting a region.
Private Sub picVisible_MouseMove(ByVal sender As Object, _
    ByVal e As System.Windows.Forms.MouseEventArgs) Handles _
    picVisible.MouseMove
    ' Do nothing if we're not selecting a region.
    If m_Points Is Nothing Then Exit Sub

    ' Save the new point.
    m_MaxPoint += 1
    ReDim Preserve m_Points(m_MaxPoint)
    m_Points(m_MaxPoint).X = e.X
    m_Points(m_MaxPoint).Y = e.Y

    ' Draw the latest line.
    Dim gr As Graphics = picVisible.CreateGraphics
    gr.DrawLine(Pens.Yellow, _
        m_Points(m_MaxPoint).X, _
        m_Points(m_MaxPoint).Y, _
        m_Points(m_MaxPoint - 1).X, _
        m_Points(m_MaxPoint - 1).Y)
End Sub

' Finish selecting a region.
Private Sub picVisible_MouseUp(ByVal sender As Object, _
    ByVal e As System.Windows.Forms.MouseEventArgs) Handles _
    picVisible.MouseUp
    ' Do nothing if we're not selecting a region.
    If m_Points Is Nothing Then Exit Sub

    ' Close the region.
    If (m_Points(0).X <> m_Points(m_MaxPoint).X) Or _
       (m_Points(0).Y <> m_Points(m_MaxPoint).Y) _
    Then
        ' Save the new point.
        m_MaxPoint += 1
        ReDim Preserve m_Points(m_MaxPoint)
        m_Points(m_MaxPoint).X = m_Points(0).X
        m_Points(m_MaxPoint).Y = m_Points(0).Y
    End If

    ' Make the points into a Path.
    Dim selected_path As New _
        System.Drawing.Drawing2D.GraphicsPath(Drawing2D.FillMode.Winding)
    selected_path.AddLines(m_Points)

    ' Make the drawing permanent.
    Dim bm_visible As Bitmap = _
        DirectCast(picOriginal.Image.Clone, Bitmap)
    Dim gr_visible As Graphics = _
        Graphics.FromImage(bm_visible)
    gr_visible.DrawPath(Pens.Orange, selected_path)
    picVisible.Image = bm_visible

    ' Copy the picture into picHidden 
    ' with a transparent background and
    ' restricting it to the selected region.
    Dim bm_copy As New Bitmap(bm_visible.Width, _
        bm_visible.Height)
    Dim gr_copy As Graphics = Graphics.FromImage(bm_copy)
    ' Fill with a transparent background.
    gr_copy.Clear(Color.FromArgb(0, 0, 0, 0))
    ' Clip to the path.
    gr_copy.SetClip(selected_path)
    ' Copy the image.
    gr_copy.DrawImage(picOriginal.Image, 0, 0)
    ' Display the result.
    picCopy.Image = bm_copy

    ' We're no longer selecting a region.
    m_Points = Nothing
    btnCopy.Enabled = True
End Sub
 
When you click the Copy button, the program copies the result image (with transparent background) to the clipboard.
 
' Save the intermediate image to the clipboard.
Private Sub btnCopy_Click(ByVal sender As System.Object, _
    ByVal e As System.EventArgs) Handles btnCopy.Click
    Clipboard.SetDataObject( _
        DirectCast(picCopy.Image.Clone, Bitmap), _
        True)
    Beep()
End Sub
 
When you click the Paste button, the program gets the clipboard's data object and uses that object's GetDataPresent method to see if the clipboard contains bitmap data. If bitmap data is present, the program makes a new bitmap holding a background image and draws the picture in the clipboard onto it. If the clipboard's picture has a transparent background (as it will if you just put it there using the Copy button), the transparent areas will not cover the background image.
 
' Paste the clipboard image onto the result picture.
Private Sub btnPaste_Click(ByVal sender As System.Object, _
    ByVal e As System.EventArgs) Handles btnPaste.Click
    ' See if the clipboard contains bitmap data.
    Dim clipboard_data As IDataObject = _
        Clipboard.GetDataObject()
    If clipboard_data.GetDataPresent(GetType(Bitmap)) Then
        ' Copy the clipboard bitmap onto the background.
        Dim bm_result As Bitmap = _
            DirectCast(picBackground.Image.Clone, Bitmap)
        Dim gr_result As Graphics = _
            Graphics.FromImage(bm_result)
        gr_result.DrawImage( _
            DirectCast(clipboard_data.GetData(GetType(Bitmap)), _
                Bitmap), _
            0, 0)
        picResult.Image = bm_result
    End If
End Sub
 
You could use a similar method to copy and paste partially transparent images to and from other applications that understand transparency. Unfortunately MSPaint does not understand transparency.

For more information on graphics programming in Visual Basic (not VB .NET), see my book Visual Basic Graphics Programming.

 
 
Copyright © 1997-2010 Rocky Mountain Computer Consulting, Inc.   All rights reserved.
  Updated