Friday, August 14, 2020

C# .NET How to create a custom clipboard format to copy and paste

The following console application is fully functional working code to demonstrate how to create a custom clipboard format, when these standard formats will not suffice. 

In below example source code specifically, we are creating a custom class Infopic to paste onto the clipboard. 

Result: 

When you copy an image from a browser, and paste into MSPaint, you'll get the expected image.
When you paste into Notepad, you'll get a text message. 

See it in action with my tool - https://clipboardplaintextpowertool.blogspot.com/. When you copy an image, you also to get metadata for images like this; 

Clip iss063e070805.jpg [1041w✕585h] "NASA Image of the Day | NASA - Microsoft​ Edge", img src="https://www.nasa.gov/sites/default/files/styles/full_width_feature/public/thumbnails/image/iss063e070805.jpg"
using System;
using System.Collections.Generic;
using System.Data;
using System.Text;
using System.Windows.Forms;
using System.Drawing.Imaging;
using System.Drawing;
using System.Diagnostics;

namespace ClipboardCustomFormatEx
{
    class InfoPic
    {
        public System.Drawing.Image imgctnr { get; set; } //image container
        public string info { get; set; } //image caption
    }

    class Program
    {
        [STAThread] //TIP! Set this to get clipboard handle from a console app
        public static void Main(string[] args)
        {

            Console.WriteLine("Right-click COPY a image from your open brower. Press any key to start...");
            Console.ReadKey();

            //Let's grab clipboard - Do we have access and is there data 
            System.Windows.Forms.IDataObject iData = Clipboard.GetDataObject();

            if (iData == null)
                return;

            //check is we have standard Bitmap format available 
            if (!iData.GetDataPresent(DataFormats.Bitmap))
                return;

            Bitmap clipBMP = iData.GetData(DataFormats.Bitmap) as Bitmap;

            if (clipBMP == null)
                return;

            string imgInfo = "This image is a Bitmap " + clipBMP.PixelFormat.ToString();

            //Create on custom object to place on clibpoard. 
            InfoPic obj = new InfoPic();

            //Load object 
            obj.imgctnr = clipBMP;
            obj.info = imgInfo;

            //Some suggests we should serialize the object before placeing onto clipboard but not required

            //Set and use a custom format that represents our object with clipboard. It can be any name, using "AssemblyName"."ClassName", in this case. No need to "register" foramt ahead of time, any longer as in C using RegisterClipboardFormatA
            string myCustomFormat = "ClipboardCustomFormatEx.InfoPic";
            Clipboard.SetData(myCustomFormat, obj);

            Console.WriteLine("Success. ClipboardCustomFormatEx.InfoPic is pasted on clipboard. Press any key to continue...");
            Console.ReadKey();
            Console.WriteLine("Okay. Let's get grab the ClipboardCustomFormatEx.InfoPic object from the clipboard.");
            
            //Let's get all data ojbects to check if clipboard is accessible and initialize object
            IDataObject clipobj = Clipboard.GetDataObject();
            if (iData == null)
                return;

            //Does custom format live on clipboard 
            if (Clipboard.ContainsData(myCustomFormat) == false)
                return;

            InfoPic myPaste = clipobj.GetData(myCustomFormat) as InfoPic; //cast is safe

            Console.WriteLine("ClipboardCustomFormatEx.info = " + myPaste.info);
            Console.WriteLine("ClipboardCustomFormatEx.imgctnr size = " + myPaste.imgctnr.Size);
            Console.WriteLine("Success. Got ClipboardCustomFormatEx.InfoPic. Press any key to repaste to overload regular formats.");
            Console.ReadKey();

            Clipboard.Clear();

            //re-paste to test using standard formats acceptable to most programs
            System.Windows.Forms.IDataObject objFormatstoPaste = new DataObject();
            objFormatstoPaste.SetData(DataFormats.Text, "Repasted Image");
            Bitmap repasteBMP = (Bitmap)myPaste.imgctnr;
            repasteBMP.RotateFlip(RotateFlipType.RotateNoneFlipY); //upside down

            objFormatstoPaste.SetData(DataFormats.Bitmap, repasteBMP);

            Clipboard.SetDataObject(objFormatstoPaste, true);

            Console.WriteLine("Success. ClipboardCustomFormatEx.InfoPic is pasted on clipboard.");
            Console.WriteLine("Open Notepad and paste (CTRL-V), you'll get text. Open MSPaint and you'll paste the image!");
            Console.ReadKey();
        }
    }
}

No comments:

Post a Comment