Working with the Clipboard in VB.NET and C#

CodeGuru content and product recommendations are editorially independent. We may make money when you click on links to our partners. Learn More.

Introduction

Through the years. Access to the Clipboard object has become easier and easier. You might find it strange to have an entire article dedicated to the Clipboard object but the sad fact of the matter is it’s obvious properties and methods got lost in translation. Better said, people still do not know what the Clipboard object is, how to differentiate between copied information, and how to use it. I hope with this article I will demonstrate its proper use, and eliminate confusion.

Logic

With the advent of .NET, accessing the Clipboard from text fields has become so easy. Many a programmer does not realize this, especially if they come from a VB 6 background. The Textboxes come with built in Clipboard methods (Copy, Cut, Paste ) built in. We will make use of these methods, as well as make use of the Clipboard object to do the text manipulation.

With Pictureboxes we will make use of the Clipboard methods, as well as the BitBlt API. The reason for this is so that you can see which one of these two methods are better. The BitBlt API is much more capable of handling various picture types, as well as transparancy.

Design

Fire up Visual Studio 2012 and create a Windows Forms project with either VB.NET or C#. Give your form an appropriate name, or use mine, and add the following controls to it:

Control Property Setting
Form1 Name frmEasyClipBoard
  Size 474, 311
  Text Copying Cutting & Pasting
TextBox Name txtSource
  Location 0, 0
TextBox Name txtDest
  Location 0, 58
Button Name btnCopyTXT
  Location 126, 0
  Text Copy With Textbox
Button Name btnCutTXT
  Location 126, 29
  Text Cut With Textbox
Button Name btnPasteTXT
  Location 126, 58
  Text Paste With TextBox
Button Name btnClear
  Location 244, 29
  Text Clear
Button Name btnClipCopy
  Location 304, 0
  Text Clipboard Copy
Button Name btnClipCut
  Location 304, 29
  Text Clipboard Cut
Button Name btnClipPaste
  Location 304, 58
  Text Clipboard Paste
PictureBox Name picSource
  Image Any picture, or use mine which is supplied in the download
  Location 34, 107
PictureBox Name picDest
  Location 226, 87
Button Name btnClipCopyPic
  Location 12, 242
  Text Clipboard Copy
Button Name btnClipPastePic
  Location 120, 242
  Text Clipboard Paste
Button Name btnBBCopy
  Location 235, 242
  Text BitBlt Copy
Button Name btnBBPaste
  Location 316, 242
  Text BitBlt Paste

Coding

Text

As usual, let us start with the Modular declarations.

VB.NET

    Private strSelectedText As String 'Selected text

C#

This will keep the Selected text inside the textbox(es) that we want to copy. Now, let us Copy, Cut and Paste via the TextBoxes’ built-in methods. Add the following code.

VB.NET

    Private Sub btnCopyTXT_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnCopyTXT.Click
        If txtSource.Text <> "" Then 'If something typed in box
            If txtSource.SelectionLength > 0 Then 'if something selected
                strSelectedText = txtSource.SelectedText 'store selection
                txtSource.Copy() 'copy
            Else
                txtSource.SelectAll() 'nothing selected, take everything
                txtSource.Copy() 'copy
            End If
        End If
    End Sub

    Private Sub btnCutTXT_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnCutTXT.Click
        If txtSource.Text <> "" Then
            If txtSource.SelectionLength > 0 Then
                strSelectedText = txtSource.SelectedText
                txtSource.Cut()
            Else
                txtSource.SelectAll()
                txtSource.Cut()
            End If
        End If

    End Sub

    Private Sub btnPasteTXT_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnPasteTXT.Click
        Dim OldText As String 'previous text in textbox
        OldText = txtDest.Text 'store previous text
        txtDest.SelectionStart = OldText.Length ' set cursor at end to paste at back of text
        txtDest.Paste() 'paste

    End Sub

C#

        private void btnCopyTXT_Click(object sender, EventArgs e)
        {
            //If something typed in box
            if (!string.IsNullOrEmpty(txtSource.Text))
            {
                //if something selected
                if (txtSource.SelectionLength > 0)
                {
                    strSelectedText = txtSource.SelectedText;
                    //store selection
                    txtSource.Copy();
                    //copy
                }
                else
                {
                    txtSource.SelectAll();
                    //nothing selected, take everything
                    txtSource.Copy();
                    //copy
                }
            }
        }

        private void btnCutTXT_Click(object sender, EventArgs e)
        {
            if (!string.IsNullOrEmpty(txtSource.Text))
            {
                if (txtSource.SelectionLength > 0)
                {
                    strSelectedText = txtSource.SelectedText;
                    txtSource.Cut();
                }
                else
                {
                    txtSource.SelectAll();
                    txtSource.Cut();
                }
            }
        }

        private void btnPasteTXT_Click(object sender, EventArgs e)
        {
            string OldText = null;
            //previous text in textbox
            OldText = txtDest.Text;
            //store previous text
            txtDest.SelectionStart = OldText.Length;
            // set cursor at end to paste at back of text
            //paste
            txtDest.Paste();
        }

This is quite straightforward, as you probably expected. See how simple it is to use the TextBox properties for copy and paste operations?

Now, let us have a look at how it is done through the Clipboard object alone. Add the next code.

VB.NET

    Private Sub btnClipCopy_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnClipCopy.Click
        If txtSource.Text <> "" Then
            If txtSource.SelectionLength > 0 Then
                strSelectedText = txtSource.SelectedText
                Clipboard.SetText(strSelectedText) 'put selection on clipboard
            Else
                txtSource.SelectAll()
                Clipboard.SetText(txtSource.Text) 'put all text on clipboard
            End If
        End If
    End Sub

    Private Sub btnClipCut_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnClipCut.Click

        If txtSource.Text <> "" Then
            If txtSource.SelectionLength > 0 Then
                strSelectedText = txtSource.SelectedText
                Clipboard.SetText(strSelectedText)
                txtSource.SelectedText = "" 'clear text, for cutting - otherwise it's same as copy
            Else
                txtSource.SelectAll()
                Clipboard.SetText(txtSource.Text)
                txtSource.Text = ""
            End If
        End If
    End Sub

    Private Sub btnClipPaste_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnClipPaste.Click
        Dim ClipText As String 'store text from clipboard
        Dim OldText As String 'previous text in textbox
        OldText = txtDest.Text 'store previous text
        ClipText = Clipboard.GetText 'get the clipboard contents
        txtDest.Text = OldText & ClipText 'to paste at back of text, otherwise just say textbox2.text = cliptext
    End Sub

C#

        private void btnClipCopy_Click(object sender, EventArgs e)
        {
            if (!string.IsNullOrEmpty(txtSource.Text))
            {
                if (txtSource.SelectionLength > 0)
                {
                    strSelectedText = txtSource.SelectedText;
                    Clipboard.SetText(strSelectedText);
                    //put selection on clipboard
                }
                else
                {
                    txtSource.SelectAll();
                    Clipboard.SetText(txtSource.Text);
                    //put all text on clipboard
                }
            }
        }

        private void btnClipCut_Click(object sender, EventArgs e)
        {
            if (!string.IsNullOrEmpty(txtSource.Text))
            {
                if (txtSource.SelectionLength > 0)
                {
                    strSelectedText = txtSource.SelectedText;
                    Clipboard.SetText(strSelectedText);
                    txtSource.SelectedText = "";
                    //clear text, for cutting - otherwise it's same as copy
                }
                else
                {
                    txtSource.SelectAll();
                    Clipboard.SetText(txtSource.Text);
                    txtSource.Text = "";
                }
            }
        }

        private void btnClipPaste_Click(object sender, EventArgs e)
        {
            string ClipText = null;
            //store text from clipboard
            string OldText = null;
            //previous text in textbox
            OldText = txtDest.Text;
            //store previous text
            ClipText = Clipboard.GetText();
            //get the clipboard contents
            //to paste at back of text, otherwise just say textbox2.text = cliptext
            txtDest.Text = OldText + ClipText;
        }

As you can see, using only the Clipboard to copy and paste items is a bit more code, but the gist of the logic remains the same.

Now, for the fun part.

Pictures

Copying pictures is also quite straightforward. The Pictureboxes do not have clipboard methods built in, but we still have two options for copying and pasting. Option 1 is to use the Clipboard object, and option 2 is to use the BitBlt API. Let us have a look at how the Clipboard handles Image content.

VB.NET

    Private Sub btnClipCopyPic_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnClipCopyPic.Click
        Clipboard.SetImage(picSource.Image) 'copy picture onto clipboard
    End Sub

        Private Sub btnClipPastePic_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnClipPastePic.Click
        picDest.Image = Clipboard.GetImage() 'paste the image
    End Sub

C#:

        private void btnClipCopyPic_Click(object sender, EventArgs e)
        {
            	//copy picture onto clipboard
            Clipboard.SetImage(picSource.Image);
        }

        private void btnClipCutPic_Click(object sender, EventArgs e)
        {
            picDest.Image = Clipboard.GetImage(); //paste the image
        }

snake.gifAs easy easy as that! You might have noticed after pasting the picture (if you have used my picture that I have supplied – snake.gif ) that there was some sort of greyish area surrounding our picture. That area is actually transparent, so there should be no shading whatsoever. How do we fix this? The answer is BitBlt.

BitBlt

Bit Block Image Transfer copies pixels from a source rectangle to a destination rectangle object based on the Raster Operation Code.

Whoa! That is a mouthful! What it does in laymans terms is to copy a whole picture or a part of a picture to a destination. This destination can be an empty picturebox, or a picturebox with an image. The sky is the limit. We need to add this functionality to our program.

Add a new class to your project and name it EC_BitBlt.

Add the following namespace to the EC_BitBlt class to handle API calls.

VB.NET

Imports System.Runtime.InteropServices

C#

using System.Runtime.InteropServices;

Add the BitBlt API :

VB.NET

    <DllImport("gdi32.dll", EntryPoint:="BitBlt", SetLastError:=True, CharSet:=CharSet.Auto)> _
    Private Shared Function BitBlt( _
            ByVal hdcDest As IntPtr, _
            ByVal nXDest As Integer, _
            ByVal nYDest As Integer, _
            ByVal nWidth As Integer, _
            ByVal nHeight As Integer, _
            ByVal hdcSrc As IntPtr, _
            ByVal nXSrc As Integer, _
            ByVal nYSrc As Integer, _
            ByVal dwRop As Int32) As Boolean
    End Function

C#

        [DllImport("gdi32.dll", EntryPoint = "BitBlt", SetLastError = true, CharSet = CharSet.Auto)]
        private static extern bool BitBlt(IntPtr hdcDest, int nXDest, int nYDest, int nWidth, int nHeight, IntPtr hdcSrc, int nXSrc, int nYSrc, Int32 dwRop);

Add the following fields to the class.

VB.NET

    Private grpMem As Graphics 'Memory Graphic
    Private iptMem As IntPtr 'Pointer Handle

    Private szLastSize As Size 'get previous size

    Private blnCopied As Boolean 'copied?

    Const SRCCOPY As Integer = &HCC0020 'to copy, also get SRCINVERT to invert the colours as well

C#

        //Memory Graphic
        private Graphics grpMem;
        //Pointer Handle
        private IntPtr iptMem;

        //get previous size
        private Size szLastSize;

        //copied?
        private bool blnCopied;

        //to copy, also get SRCINVERT to invert the colours as well
        const int SRCCOPY = 0xcc0020;

Add the next code to copy the picture into memory.

VB.NET

    Public Sub EC_Copy(ByVal grpSource As Graphics, ByVal szSize As Size)
        szLastSize = szSize 'Store size

        'Copied already?
        If blnCopied Then DisposeObjects() 'Dispose old objects

        'Create temp Bitmap to create objects from
        Dim srcBmp As New Bitmap(szSize.Width, szSize.Height, grpSource)

        grpMem = Graphics.FromImage(srcBmp) 'Create Graphics object
        iptMem = grpMem.GetHdc 'Get Device Context

        'Get the picture
        DoBitBlt(grpSource, iptMem, szSize.Width, szSize.Height)

        'Dispose
        srcBmp.Dispose()

        blnCopied = True 'We have copied

    End Sub

C#

        public void EC_Copy(Graphics grpSource, Size szSize)
        {
            szLastSize = szSize; //Store size

            if (blnCopied)
                DisposeObjects(); //Dispose old objects

            Bitmap srcBmp = new Bitmap(szSize.Width, szSize.Height, grpSource); //Create temp Bitmap to create objects from

            grpMem = Graphics.FromImage(srcBmp); //Create Graphics object

            iptMem = grpMem.GetHdc(); //Get Device Context

            DoBitBlt(grpSource, iptMem, szSize.Width, szSize.Height); //Get the picture

            srcBmp.Dispose(); //Dispose

            blnCopied = true; //We have copied
        }

Add the code to paste the picture(s).

VB.NET

    Public Sub EC_Paste(ByVal grpDest As Graphics, ByVal intX As Integer, ByVal intY As Integer)
        Dim TargetHdc As IntPtr = grpDest.GetHdc 'Get target object

        DoBitBlt(iptMem, TargetHdc, szLastSize.Width, szLastSize.Height, intX, intY) 'Source, Dest, Width, Height, X, Y

        grpDest.ReleaseHdc(TargetHdc) 'Release memory reference
    End Sub

C#

        public void EC_Paste(Graphics grpDest, int intX, int intY)
        {
            IntPtr TargetHdc = grpDest.GetHdc(); //Get target object

            DoBitBlt(iptMem, TargetHdc, szLastSize.Width, szLastSize.Height, intX, intY); //Source, Dest, Width, Height, X, Y

            grpDest.ReleaseHdc(TargetHdc); //Release memory reference
        }

You will have noticed that we made reference to the DoBitBlt functions inside both copy and paste. Why? Well, we first have to copy the source into memory, then copy the memory graphic into the picturebox. The two steps are necessary because we might want to do other manipulation to the in-memory graphic before pasting. Let us add the DoBitBlt functions. One is for copying the image into memory, and the other one is for copying the picture from memory into a destination.

VB.NET

    Private Sub DoBitBlt(ByVal grpSource As Graphics, ByVal iptDest As IntPtr, ByVal intWidth As Integer, ByVal intHeight As Integer)
        'Create DeviceContext to capture from
        Dim SourceHDC As IntPtr = grpSource.GetHdc
        ' Blit (Copy) the data
        BitBlt(iptDest, 0, 0, intWidth, intHeight, SourceHDC, 0, 0, SRCCOPY)
        ' Release Device context
        grpSource.ReleaseHdc(SourceHDC)
    End Sub

    Private Sub DoBitBlt(ByVal iptSource As IntPtr, ByVal iptDest As IntPtr, ByVal intWidth As Integer, ByVal intHeight As Integer, ByVal intXPos As Integer, ByVal intYPos As Integer)
        ' Copy data to a specific position on target Device Context
        BitBlt(iptDest, intXPos, intYPos, intWidth, intHeight, iptSource, 0, 0, SRCCOPY)
    End Sub

C#

        private void DoBitBlt(Graphics grpSource, IntPtr iptDest, int intWidth, int intHeight)
        {
            //Create DeviceContext to capture from
            IntPtr SourceHDC = grpSource.GetHdc();
            // Blit (Copy) the data
            BitBlt(iptDest, 0, 0, intWidth, intHeight, SourceHDC, 0, 0, SRCCOPY);
            // Release Device context
            grpSource.ReleaseHdc(SourceHDC);
        }

        private void DoBitBlt(IntPtr iptSource, IntPtr iptDest, int intWidth, int intHeight, int intXPos, int intYPos)
        {
            // Copy data to a specific position on target Device Context
            BitBlt(iptDest, intXPos, intYPos, intWidth, intHeight, iptSource, 0, 0, SRCCOPY);
        }

All we need to do now is to make sure all objects have been Disposed properly out of memory. Add the next procedures.

VB.NET

    Protected Overrides Sub Finalize()
        DisposeObjects() 'make sure all memory is released
        MyBase.Finalize()
    End Sub

    Private Sub DisposeObjects()
        grpMem.ReleaseHdc(iptMem) ' Release Device Context
        grpMem.Dispose() ' Disposing of Graphics object
    End Sub

C#

        private void DisposeObjects()
        {
            grpMem.ReleaseHdc(iptMem);
            // Release Device Context
            grpMem.Dispose();
            // Disposing of Graphics object
        }

Add the next code to your frmEasyClipboard class to access the EC_BitBlt class’ methods

VB.NET

    Private Sub btnBBCopy_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnBBCopy.Click
        ' Create a Graphics object to work with
        Dim SourceGrp As Graphics = picSource.CreateGraphics
        ' Copy the surface
        BBBlits.EC_Copy(SourceGrp, New Size(picSource.Width, picSource.Height))
        ' Dispose of the Graphics object
        SourceGrp.Dispose()
    End Sub

    Private Sub btnBBPaste_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnBBPaste.Click
        'Create a Graphics object to paste to
        Dim targetGrp As Graphics = picDest.CreateGraphics
        ' BitBlt
        BBBlits.EC_Paste(targetGrp, 0, 0)

        targetGrp.Dispose()
    End Sub

C#

        private void btnBBCopy_Click(object sender, EventArgs e)
        {
            Graphics SourceGrp = picSource.CreateGraphics();
            // Copy the surface
            BBBlits.EC_Copy(SourceGrp, new Size(picSource.Width, picSource.Height));
            // Dispose of the Graphics object
            SourceGrp.Dispose();
        }

        private void btnBBPaste_Click(object sender, EventArgs e)
        {
            Graphics targetGrp = picDest.CreateGraphics();
            // BitBlt
            BBBlits.EC_Paste(targetGrp, 0, 0);

            targetGrp.Dispose();
        }
    }

Not too complicated now is it?

The source files are included with this article, so in case you have missed a step or two, you could have a look in there.

Conclusion

I hope you have enjoyed this article and that you have benefited from it. Until next time! Cheers!

More by Author

Get the Free Newsletter!

Subscribe to Developer Insider for top news, trends & analysis

Must Read