[食譜好菜] C# 複製 HTML 格式的文字到剪貼薄中

部落格的文章我一直是用 Markdown Monster 寫完後,直接 Ctrl + Shift + C,Markdown Monster 會直接幫我將文章轉成 HTML 內容寫入到剪貼薄中,接著在點部落的編輯器上切換原始碼,再把 HTML 內容貼上去,但是最近點部落的編輯器改版了,沒辦法直接貼上 HTML 原始碼,可是 Markdown Monster 複製的 HTML 內容居然貼得上去,這其中必有緣故。

HTML 剪貼薄格式

一查之下才發現,原來我們寫入到剪貼薄的內容是有格式的,HTML 就是其中之一,但是也不是說將 HTML 原始碼寫入到剪貼薄中,就會被判斷是 HTML,我們必須將 HTML 原始碼照著一定的格式寫入到剪貼薄中,才會是真的 HTML 格式,不然就只是一般的純文字而已,而這個 HTML 格式看起來就像下面這樣。

Version:0.9
StartHTML:000000149
EndHTML:000000749
StartFragment:000000204
EndFragment:000000713
StartSelection:000000204
EndSelection:000000713
<!DOCTYPE html>
<html>
<body>
<!--StartFragment--><p>部落格的文章我一直是用 <a href="https://markdownmonster.west-wind.com/">Markdown Monster</a> 寫完後,直接 <code>Ctrl + Shift + C</code>,Markdown Monster 會直接幫我將文章轉成 HTML 內容,複製到剪貼薄中,然後我再直接把 HTML 內容貼到<a href="https://dotblogs.com.tw/">點部落</a>上,最近點部落的編輯器改版了,沒辦法直接貼上 HTML 原始碼,但是 Markdown Monster 複製的 HTML 內容居然貼得上去,這其中必有緣故。</p><!--EndFragment-->
</body>
</html>
  • Version:固定就填 0.9
  • StartHTML/EndHTML:HTML 內容開始及結束的 byte 索引位置,從上面的例子來看,開始就是 <!DOCTYPE html><,結束就是 </html>>
  • StartFragment/EndFragment:實際被複製的 HTML 內容開始及結束的 byte 索引位置,從上面的例子來看,就是 <p>部落格的文章<,以及 必有緣故。</p>>,而且實際被複製的 HTML 內容應該用 <!--StartFragment--><!--EndFragment--> 包起來。
  • StartSelection/EndSelection:額外包含的一些資訊,目前沒用到,填的值跟 StartFragment/EndFragment 一樣就行了。

Clipboard

在 C# 要寫入資料到剪貼薄中,用的是 Clipboard 類別,我們要寫入 HTML 格式的文字還需要 DataObject 類別,接著我們就照著格式把我們要的 HTML 內容兜好。

var html = @"<p>部落格的文章我一直是用 <a href=""https://markdownmonster.west-wind.com/"">Markdown Monster</a> 寫完後,直接 <code>Ctrl + Shift + C</code>,Markdown Monster 會直接幫我將文章轉成 HTML 內容,複製到剪貼薄中,然後我再直接把 HTML 內容貼到<a href=""https://dotblogs.com.tw/"">點部落</a>上,最近點部落的編輯器改版了,沒辦法直接貼上 HTML 原始碼,但是 Markdown Monster 複製的 HTML 內容居然貼得上去,這其中必有緣故。</p>";

var header = @"Version:0.9
StartHTML:<<<<<<<<1
EndHTML:<<<<<<<<2
StartFragment:<<<<<<<<3
EndFragment:<<<<<<<<4
StartSelection:<<<<<<<<3
EndSelection:<<<<<<<<4";

var stringBuilder = new StringBuilder();

stringBuilder.AppendLine(header);
stringBuilder.AppendLine("<!DOCTYPE html>");
stringBuilder.AppendLine("<html>");
stringBuilder.AppendLine("<body>");
stringBuilder.Append("<!--StartFragment-->");

var fragmentStart = stringBuilder.GetByteCount();

stringBuilder.Append(html);

var fragmentEnd = stringBuilder.GetByteCount();

stringBuilder.AppendLine("<!--EndFragment-->");
stringBuilder.AppendLine("</body>");
stringBuilder.Append("</html>");

stringBuilder.Replace("<<<<<<<<1", header.Length.ToString("D9"));
stringBuilder.Replace("<<<<<<<<2", stringBuilder.GetByteCount().ToString("D9"));
stringBuilder.Replace("<<<<<<<<3", fragmentStart.ToString("D9"));
stringBuilder.Replace("<<<<<<<<4", fragmentEnd.ToString("D9"));

var dataObject = new DataObject();
dataObject.SetData(DataFormats.Html, stringBuilder.ToString());
dataObject.SetData(DataFormats.Text, html);
dataObject.SetData(DataFormats.UnicodeText, html);

Clipboard.SetDataObject(dataObject, true);

其中 DataObject 需要再指定 TextUnicodeText 格式的內容,因為剪貼薄的貼上功能,其實是會根據要貼上去的地方,去判斷該貼上哪一種格式的內容,如果我們不指定這兩種格式的內容,像是貼上 Notepad(記事本)的時候就不會出現任何文字。

程式撰寫好之後,我們就來跑跑看,可以看到只是單純地複製 HTML 文字到點部落的編輯器,就只是純文字而已,但是透過指定的 HTML 格式寫入剪貼薄之後,貼上去之後就呈現 HTML 效果的內容。

參考資料

C# 指南ASP.NET 教學ASP.NET MVC 指引
Azure SQL Database 教學SQL Server 教學Xamarin.Forms 教學