Copiar um trecho de HTML para a Clipboard não é algo tão simples assim.Tente usar o método Clipboard.SetText() para copiar html. Você verá que não irá funcionar. Mas por que não funciona?
Bom, quando copiamos um trecho HTML para a Clipboard devemos enviar junto deste trecho um cabeçalho contendo algumas informações. Este é um exemplo de um html copiado para a área de transferência:
Version:1.0 StartHTML:0000000157 EndHTML:0000001207 StartFragment:0000000193 EndFragment:0000001171 SourceURL:https://herbertdotlausmann.wordpress.com/ <html> <body> <!--StartFragment--><h1 class="site-title">Herbert.Lausmann</a></h1><!--EndFragment--> </body> </html>
Percebeu agora porque simplesmente copiar um html usando o Clipboard.SetText() não funciona?
Mas vamos à solução. Eis o código que faz o trabalho de criar o cabeçalho e ainda permite que incluamos junto com o HTML a ser copiado uma versão em texto plano para ser colado onde não há suporte à html:
public void CopyToClipboard(string html, string plainText, bool isHtml5 = false) { string data = GetHtmlData(html, isHtml5); System.Windows.IDataObject iData = new System.Windows.DataObject(); iData.SetData(System.Windows.DataFormats.Html, data); iData.SetData(System.Windows.DataFormats.Text, plainText); System.Windows.Clipboard.SetDataObject(iData, true); } private string GetHtmlData(string html, bool isHtml5) { var sb = new StringBuilder(); const string header = @"Version:1.0 StartHTML:<<<<<<<<1 EndHTML:<<<<<<<<2 StartFragment:<<<<<<<<3 EndFragment:<<<<<<<<4 StartSelection:<<<<<<<<3 EndSelection:<<<<<<<<4"; sb.AppendLine(header); int startHtml = sb.Length; if (isHtml5) sb.AppendLine(@"<!DOCTYPE html>"); else sb.AppendLine(@"<!DOCTYPE HTML PUBLIC ""-//W3C//DTD HTML 4.01 Transitional//EN"" ""http://www.w3.org/TR/html4/loose.dtd"">"); sb.AppendLine("<html>"); sb.AppendLine("<head>"); sb.AppendLine("</head>"); sb.AppendLine("<body>"); sb.Append(@"<!--StartFragment-->"); int fragmentStart = sb.Length; sb.Append(html); int fragmentEnd = sb.Length; sb.AppendLine(@"<!--EndFragment-->"); sb.AppendLine("</body>"); sb.Append("</html>"); int endHtml = sb.Length; // Backpatch offsets sb.Replace("<<<<<<<<1", startHtml.ToString("000000000")); sb.Replace("<<<<<<<<2", endHtml.ToString("000000000")); sb.Replace("<<<<<<<<3", fragmentStart.ToString("000000000")); sb.Replace("<<<<<<<<4", fragmentEnd.ToString("000000000")); return sb.ToString(); }
Agora para poder copiar um trecho html chame o método CopyToClipboard(html, plaintext); informando o html que se deseja copiar, a sua versão em texto plano, e um valor booleano informado se o html está na versão 5 ou não.
É algo simples, mas que deu bastante trabalho para encontrar.
Este post foi baseado no artigo Setting HTML and plain text formatting to clipboard « The Art of Dev, porém o código do artigo não funcionou em meus testes. Contudo, eu o reescrevi. Testei no Mozilla Firefox 23, Internet Explorer 11 e Google Chrome 35 funcionando perfeitamente.
I don’t see where it says that html and body elements are required.
What application are you pasting into?
I’m pasting the copied html into a web page in Google Chrome. The app that copy the html segment, using my code, is a WPF application runnig in Windows 7 Home Basic…
OK… you got me curious so although the code runs in HTML Renderer project I retested it and it work perfect. Why do you think you need to provide html, head and body elements?
I’ve tested your original code, but it didn’t work for me. After some searching I read these articles on MSDN:
http://msdn.microsoft.com/en-us/library/aa767917(VS.85).aspx
http://blogs.msdn.com/b/jmstall/archive/2007/01/21/html-clipboard.aspx
In them is written that when we copy just one segment of HTML we should include the html, head(This’s optional) and body elements. After rewriting your code with the adaptations it worked perfectly!