小隐的博客

人生在世,笑饮一生
随笔 - 304, 文章 - 0, 评论 - 349, 阅读 - 50万
  博客园  :: 首页  :: 新随笔  :: 联系 :: 订阅 订阅  :: 管理
< 2025年3月 >
23 24 25 26 27 28 1
2 3 4 5 6 7 8
9 10 11 12 13 14 15
16 17 18 19 20 21 22
23 24 25 26 27 28 29
30 31 1 2 3 4 5

操作clipboard

Posted on   隐客  阅读(414)  评论(0编辑  收藏  举报
using System;
using System.Diagnostics;
 
using System.Windows.Forms;
using System.Text.RegularExpressions;
 
using System.Collections.Generic;
using System.Text;
using System.IO;
 
/// <summary>
/// Helper class to decode HTML from the clipboard.
/// See http://blogs.msdn.com/jmstall/archive/2007/01/21/html-clipboard.aspx for details.
/// </summary>
class HtmlFragment
{
    #region Read and decode from clipboard
    /// <summary>
    /// Get a HTML fragment from the clipboard.
    /// </summary>   
    /// <example>
    ///    string html = "<b>Hello!</b>";
    ///    HtmlFragment.CopyToClipboard(html);
    ///    HtmlFragment html2 = HtmlFragment.FromClipboard();
    ///    Debug.Assert(html2.Fragment == html);
    /// </example>
    static public HtmlFragment FromClipboard()
    {
        if (Clipboard.ContainsText(TextDataFormat.Html))
        {
            MemoryStream ms = (MemoryStream)Clipboard.GetData("Html Format");
            ms.Position = 0;
            byte[] vBytes = new byte[ms.Length];
            ms.Read(vBytes, 0, (int)ms.Length);
            string rawClipboardText = Encoding.UTF8.GetString(vBytes);
            //string rawClipboardText = Clipboard.GetText(TextDataFormat.Html );
            HtmlFragment h = new HtmlFragment(rawClipboardText);
            return h;
        }
        else
        {
            return null;
        }
    }
 
    /// <summary>
    /// Create an HTML fragment decoder around raw HTML text from the clipboard.
    /// This text should have the header.
    /// </summary>
    /// <param name="rawClipboardText">raw html text, with header.</param>
    public HtmlFragment(string rawClipboardText)
    {
        // This decodes CF_HTML, which is an entirely text format using UTF-8.
        // Format of this header is described at:
        // http://msdn.microsoft.com/library/default.asp?url=/workshop/networking/clipboard/htmlclipboard.asp
 
        // Note the counters are byte counts in the original string, which may be Ansi. So byte counts
        // may be the same as character counts (since sizeof(char) == 1).
        // But System.String is unicode, and so byte couns are no longer the same as character counts,
        // (since sizeof(wchar) == 2).
        int startHMTL = 0;
        int endHTML = 0;
 
        int startFragment = 0;
        int endFragment = 0;
 
        Regex r;
        Match m;
 
        r = new Regex("([a-zA-Z]+):(.+?)[\r\n]",
            RegexOptions.IgnoreCase | RegexOptions.Compiled);
 
        for (m = r.Match(rawClipboardText); m.Success; m = m.NextMatch())
        {
            string key = m.Groups[1].Value.ToLower();
            string val = m.Groups[2].Value;
 
            switch (key)
            {
                // Version number of the clipboard. Starting version is 0.9.
                case "version":
                    m_version = val;
                    break;
 
                // Byte count from the beginning of the clipboard to the start of the context, or -1 if no context
                case "starthtml":
                    if (startHMTL != 0) throw new FormatException("StartHtml is already declared");
                    startHMTL = int.Parse(val);
                    break;
 
                // Byte count from the beginning of the clipboard to the end of the context, or -1 if no context.
                case "endhtml":
                    if (startHMTL == 0) throw new FormatException("StartHTML must be declared before endHTML");
                    endHTML = int.Parse(val);
 
                    //m_fullText = rawClipboardText.Substring(startHMTL, 3);
                    m_fullText = rawClipboardText.Substring(startHMTL);
                    //Console.WriteLine(m_fullText.Length );
                    //m_fullText = rawClipboardText.Substring(startHMTL, endHTML - startHMTL);
                    break;
 
                //  Byte count from the beginning of the clipboard to the start of the fragment.
                case "startfragment":
                    if (startFragment != 0) throw new FormatException("StartFragment is already declared");
                    startFragment = int.Parse(val);
                    break;
 
                // Byte count from the beginning of the clipboard to the end of the fragment.
                case "endfragment":
                    if (startFragment == 0) throw new FormatException("StartFragment must be declared before EndFragment");
                    endFragment = int.Parse(val);
                    m_fragment = rawClipboardText.Substring(startFragment, endFragment - startFragment);
                    break;
 
                // Optional Source URL, used for resolving relative links.
                case "sourceurl":
                    m_source = new System.Uri(val);
                    break;
            }
        } // end for
 
        if (m_fullText == null && m_fragment == null)
        {
            throw new FormatException("No data specified");
        }
    }
 
 
    // Data. See properties for descriptions.
    string m_version;
    string m_fullText;
    string m_fragment;
    System.Uri m_source;
 
    /// <summary>
    /// Get the Version of the html. Usually something like "1.0".
    /// </summary>
    public string Version
    {
        get { return m_version; }
    }
 
 
    /// <summary>
    /// Get the full text (context) of the HTML fragment. This includes tags that the HTML is enclosed in.
    /// May be null if context is not specified.
    /// </summary>
    public string Context
    {
        get { return m_fullText; }
    }
 
 
    /// <summary>
    /// Get just the fragment of HTML text.
    /// </summary>
    public string Fragment
    {
        get { return m_fragment; }
    }
 
 
    /// <summary>
    /// Get the Source URL of the HTML. May be null if no SourceUrl is specified. This is useful for resolving relative urls.
    /// </summary>
    public System.Uri SourceUrl
    {
        get { return m_source; }
    }
 
    #endregion // Read and decode from clipboard
 
    #region Write to Clipboard
    // Helper to convert an integer into an 8 digit string.
    // String must be 8 characters, because it will be used to replace an 8 character string within a larger string.   
    static string To8DigitString(int x)
    {
        //return String.Format("{0,8}", x);
        return x.ToString().PadLeft(8, '0');
    }
 
    /// <summary>
    /// Clears clipboard and copy a HTML fragment to the clipboard. This generates the header.
    /// </summary>
    /// <param name="htmlFragment">A html fragment.</param>
    /// <example>
    ///    HtmlFragment.CopyToClipboard("<b>Hello!</b>");
    /// </example>
     
 
 
    /// <summary>
    /// Clears clipboard and copy a HTML fragment to the clipboard, providing additional meta-information.
    /// </summary>
    /// <param name="htmlFragment">a html fragment</param>
    /// <param name="title">optional title of the HTML document (can be null)</param>
    /// <param name="sourceUrl">optional Source URL of the HTML document, for resolving relative links (can be null)</param>
    public static void CopyToClipboard(string htmlFragment)
    {
 
 
        System.Text.StringBuilder sb = new System.Text.StringBuilder();
 
        // Builds the CF_HTML header. See format specification here:
        // http://msdn.microsoft.com/library/default.asp?url=/workshop/networking/clipboard/htmlclipboard.asp
 
        // The string contains index references to other spots in the string, so we need placeholders so we can compute the offsets.
        // The <<<<<<<_ strings are just placeholders. We'll backpatch them actual values afterwards.
        // The string layout (<<<) also ensures that it can't appear in the body of the html because the <
        // character must be escaped.
        string header =
@"Version:0.9
StartHTML:<<<<<<<1
EndHTML:<<<<<<<2
StartFragment:<<<<<<<3
EndFragment:<<<<<<<4
";
 
        string pre =
@"<!doctype html><html><BODY><!--StartFragment-->";
 
        string post = @"<!--EndFragment--></BODY></HTML>";
 
        sb.Append(header);
 
 
        int startHTML = sb.Length;
 
        sb.Append(pre);
        int fragmentStart = sb.Length;
 
         
        sb.Append(htmlFragment);
        int fragmentEnd = sb.Length;
 
        sb.Append(post);
        int endHTML = sb.Length;
 
        // Backpatch offsets
        sb.Replace("<<<<<<<1", To8DigitString(startHTML));
        sb.Replace("<<<<<<<2", To8DigitString(endHTML));
        sb.Replace("<<<<<<<3", To8DigitString(fragmentStart));
        sb.Replace("<<<<<<<4", To8DigitString(fragmentEnd));
 
 
        // Finally copy to clipboard.
        string data = sb.ToString();
        Clipboard.Clear();
        byte[] b = Encoding.Default.GetBytes(data);
        MemoryStream ms = new MemoryStream();
        ms.Write(b, 0, b.Length);
        Clipboard.SetData("Html Format", b);
        //Clipboard.SetText(data, TextDataFormat.Html);
    }
    public static void CopyHtmlToClipBoard(string html)
    {
        Encoding enc = Encoding.UTF8;
 
        string begin = "Version:0.9\r\nStartHTML:{0:000000}\r\nEndHTML:{1:000000}\r\nStartFragment:{2:000000}\r\nEndFragment:{3:000000}\r\n";
 
        string html_begin = "<html>\r\n<body>\r\n"
           + "<!--StartFragment-->";
 
        string html_end = "<!--EndFragment-->\r\n</body>\r\n</html>\r\n";
 
        string begin_sample = String.Format(begin, 0, 0, 0, 0);
 
        int count_begin = enc.GetByteCount(begin_sample);
        int count_html_begin = enc.GetByteCount(html_begin);
        int count_html = enc.GetByteCount(html);
        int count_html_end = enc.GetByteCount(html_end);
 
        string html_total = String.Format(
           begin
           , count_begin
           , count_begin + count_html_begin + count_html + count_html_end
           , count_begin + count_html_begin
           , count_begin + count_html_begin + count_html
           ) + html_begin + html + html_end;
 
        DataObject obj = new DataObject();
        obj.SetData(DataFormats.Html, new System.IO.MemoryStream(
           enc.GetBytes(html_total)));
        Clipboard.SetDataObject(obj, true);
    }
    #endregion // Write to Clipboard
} // end of class

HtmlFragment h = HtmlFragment.FromClipboard();
Console.WriteLine(h.Context );

//string htmlFragment = Encoding.UTF8.GetString(Encoding.Default.GetBytes("呵呵,测试一下"));
//HtmlFragment.CopyHtmlToClipBoard("<DIV>好像可以了</br>oh,mygod<IMG src=\"file:///C:\\b.jpg\"></DIV>");

  原文见

http://blogs.msdn.com/b/jmstall/archive/2007/01/21/sample-code-html-clipboard.aspx

http://blog.tcx.be/2005/08/copying-html-fragment-to-clipboard.html

编辑推荐:
· go语言实现终端里的倒计时
· 如何编写易于单元测试的代码
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
阅读排行:
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· ollama系列01:轻松3步本地部署deepseek,普通电脑可用
· 25岁的心里话
· 按钮权限的设计及实现
历史上的今天:
2010-12-15 集装箱货柜号码 公式算法
2007-12-15 VB6中判断用户是否按下了InputBox的取消按钮
2007-12-15 无锡之行
QQ交流
点击右上角即可分享
微信分享提示