Showing posts with label .NET. Show all posts
Showing posts with label .NET. Show all posts

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();
        }
    }
}

Wednesday, August 12, 2020

C# .NET How to overload clipboard to handle multiple formats simultaneously




















Tip! Get ClipSpy - CodeProject to examine the clipboard overloads.  


The following console application is fully functional working code to demonstrate how to overload Windows system clipboard with multiple
formats

In below example source code specifically, we are overloading a image copy to append a caption.

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.

This is the overload in action, an additional text format has been added. 

Aside : See it in action with my tool - https://clipboardplaintextpowertool.blogspot.com/  which overloads images with following text metadata; 

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"

Update - Simplified further Aug 13, 2020.

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Text;
using System.Windows.Forms;
using System.Drawing.Imaging;
using System.Drawing;

namespace ClipboardOverloadExample
{
    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 does it contain data?
            System.Windows.Forms.IDataObject iData = Clipboard.GetDataObject();

            if (iData == null)
                return;
            
            //check if we have a standard Bitmap format on the clipboard
            //images are saved on the clipboard as raw bitmap "Memory Bitmap",but transparency maybe lost.
            if (!iData.GetDataPresent(DataFormats.Bitmap))
                return;

            //we have Bitmap format and thus we can perform cast safely
            Bitmap clipBMP = iData.GetData(DataFormats.Bitmap) as Bitmap;

            if (clipBMP == null)
                return;

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

            //Create an object that will contain multiple formats to paste - overload
            System.Windows.Forms.IDataObject objFormatstoPaste = new DataObject();

            //add formats to put on clipboard
            objFormatstoPaste.SetData(DataFormats.Text, imgInfo);
            objFormatstoPaste.SetData(DataFormats.Bitmap, clipBMP);

            //Copy to the clipboard, and the 2nd parameter indicates that the clipboard is not cleared when the program exits
            Clipboard.SetDataObject(objFormatstoPaste, true);
            
            Console.WriteLine("Success. You can exit program, but to test overload of clipboard, do the following:");
            Console.WriteLine("Open Notepad and paste (CTRL-V), you'll get text. Open MSPaint and you'll paste the image!");
            Console.ReadKey();

        }
    }
}