The following code copies the actua PNG image to the clipboard with transparency. This varies from the other answer in that it actual stores the entire image instead of a reference to the file. This code will likely work with more applications then the one above. It currently uses the Ctrl
+Shift
+C
to copy with transparency. The code takes a while to run currently because the program gets recompiled and rerun each time you hit the keyboard shortcut. Please suggest any modifications to help make it more portable or faster
To test that it is working run.
WriteToClipboard["PNG", ExportString[
Rasterize[
Graphics[{Circle[]}]
, "Image", Background -> None], {"Base64", "PNG"}]]
The following prints a Button
that copy the selected Graphic as a PNG, and sets the keyboard shortcut Ctrl
+ Shift
+ C
.

(* Construct Button *)
Print[Button["Copy Image",
If[
Head[NotebookRead[EvaluationNotebook[]]] === GraphicsBox,Null,
MessageDialog["You must select a Graphic."];
Return[];
];
MessageDialog[AbsoluteTiming[
WriteToClipboard["PNG",
ExportString[
Rasterize[NotebookRead[EvaluationNotebook[]], "Image",
Background -> None], {"Base64", "PNG"}]];
]]
]
]
(* Set up keyboard shortcut *)
FrontEndExecute[
FrontEnd`AddMenuCommands["ClipboardWithPNG", {
MenuItem["ClipboardWithPNG", FrontEnd`KernelExecute[Function[
WriteToClipboard["PNG", ExportString[
Rasterize[
NotebookRead[InputNotebook[]]
, "Image", Background -> None], {"Base64", "PNG"}]]
][]
], MenuKey["c", Modifiers -> {"Control", "Shift"}],
System`MenuEvaluator -> Automatic]}]]
And the needed code and functions.
Module[{temp, t2, CopyFileOverwrite, csfile, exefile, file, NRun},
temp = FileNameJoin[{$TemporaryDirectory,
"ClipboardTransparency314241234"}];
NRun[s_] := (str = OpenWrite[FileNameJoin[{temp, "temp.bat"}]];
WriteString[str, s];
Import["!" <> Close[str], "Text"];);
If[DirectoryQ[temp],
t2 = Directory[];
SetDirectory[temp];
Map[Function[DeleteFile[#]], FileNames[]];
SetDirectory[t2];
DeleteDirectory[temp, DeleteContents -> True];
, Null
];
CreateDirectory[temp];
CopyFile[
FileNameJoin[{$InstallationDirectory, "SystemFiles", "Links",
"NETLink", "Wolfram.NETLink.dll"}],
FileNameJoin[{temp, "Wolfram.NETLink.dll"}]
];
csfile = FileNameJoin[{temp, "File.cs"}];
exefile = FileNameJoin[{temp, "File.exe"}];
file = OpenWrite[csfile];
WriteString[file, "using System;
using Wolfram.NETLink;
using System.IO;
using System.Drawing;
using System.Windows.Forms;
public class File{
[STAThread]
public static void Main(String[] args) {
string input = System.Console.In.ReadToEnd();
byte[] bytes = Convert.FromBase64String(input);
Stream stream = new MemoryStream(bytes);
IDataObject dataObject = new DataObject();
dataObject.SetData(args[0], stream);
Clipboard.SetDataObject(dataObject, true);
}
}"];
Close[file];
NRun ["cd " <> temp "
C:\\Windows\\Microsoft.NET\\Framework\\v4.0.30319\\csc.exe \
/reference:Wolfram.NETLink.dll File.cs"];
WriteToClipboard[type_, data_] := (
dataloc = FileNameJoin[{temp, "data.txt"}];
datafile = OpenWrite[dataloc];
WriteString[datafile, data];
Close[datafile];
NRun["type " <> dataloc <> " | " <> exefile <> " " <> type];
);
]
To help measure timing I have been using this modified code with this function.
Time[code_] := (
absolute = AbsoluteTiming[ReleaseHold[code]];
(* Print[ToString[absolute[[1]]]<>" | "<>ToString[code] ]; *)
absolute[[2]]
)
Time[HoldForm[Print["test"]]]
Old Code: To help users understand the evolution of the code, here is the old technique. It re compiles the program each time WriteToCliboard
is run, therefore it will likely much slower.