Working on adding text selection and copy-paste to HTML Renderer I wanted to add rich text copy capability.
My first thought was to use Clipboard.SetText method with TextDataFormat.Html but to my surprise it just didn’t work. Turning to Google I finally found this post, harder to find than what I expected, that explained what needs to be done.
Apparently when setting html text you need to provide a header with additional information to what fragment of the html you actually want to paste while being able to provide additional styling around it:
Version:1.0 StartHTML:000125 EndHTML:000260 StartFragment:000209 EndFragment:000222 <HTML> <head> <title>HTML clipboard</title> </head> <body> <!--StartFragment--><b>Hello!</b><!--EndFragment--> </body> </html>
Worked like a charm to paste rich html text!
But then when I tried to paste to non rich editor like Notepad I got nothing, it actually what I excepted.
To handle html and plain text paste you can’t use Clipboard.SetText method as it clears the clipboard each time called, you need to create DataObject instance, call its SetData method once with html format and once with text format, and then set the object to clipboard using Clipboard.SetDataObject.
The complete code I come up with based on Mike’s code:
Update
Although basically works, I have made a few mistakes in this code, see: Setting HTML/Text to Clipboard revisited for better clipboard handling.
Code (deprecated)
public static void CopyToClipboard(string html, string plainText) { var data = GetHtmlData(html); var dataObject = new DataObject(); dataObject.SetData(DataFormats.Html, data); dataObject.SetData(DataFormats.Text, plainText); Clipboard.SetDataObject(dataObject); } private static string GetHtmlData(string html) { var sb = new StringBuilder(); const string header = @"Format:HTML Format Version:1.0 StartHTML:<<<<<<<1 EndHTML:<<<<<<<2 StartFragment:<<<<<<<3 EndFragment:<<<<<<<4 StartSelection:<<<<<<<3 EndSelection:<<<<<<<3"; sb.Append(header); int startHtml = sb.Length; sb.Append(@"<!DOCTYPE HTML PUBLIC ""-//W3C//DTD HTML 4.0 Transitional//EN""><!--StartFragment-->"); int fragmentStart = sb.Length; sb.Append(html); int fragmentEnd = sb.Length; sb.Append(@"<!--EndFragment-->"); int endHtml = sb.Length; // Backpatch offsets sb.Replace("<<<<<<<1", String.Format("{0,8}", startHtml)); sb.Replace("<<<<<<<2", String.Format("{0,8}", endHtml)); sb.Replace("<<<<<<<3", String.Format("{0,8}", fragmentStart)); sb.Replace("<<<<<<<4", String.Format("{0,8}", fragmentEnd)); return sb.ToString(); }
[…] Copy selected rich html text. […]
This works very well! Thanks for your CopyToClipboard method!
nice post solve my problem perfectly
[…] getting feedback that my original clipboard code doesn’t handle all scenarios, especially with Chrome, I went back to the code to get a […]
[…] Copy selected rich html text . […]