none
Adding an image with hyperlink to clipboard RRS feed

  • Question

  • Hi,

    Does anyone know how you go about creating a clipboard object in c# that has a hyperlink wrapped around an embedded image? I need to be able to paste it into word or OneNote. So far I've tried an HTML fragment with a base64 encoded image inside a link. This works fine if I load it as html , but doesn't work for pasting.

    I'm open to any suggestions!

    Rob

    Friday, December 6, 2019 12:02 PM

All replies

  • Clipboard copying requires agreement on both sides of the fence as to what the data means. For generic copy/paste like in Word you can only do things that it understands. Out of the box most apps support raw text but some apps, like Word, can do more advanced stuff if selected. In these apps you generally have the option of pasting raw text or something more.

    As for HTML it is a supported clipboard format so you must set the format as text and HTML. Pay particular attention to the required format. As noted in the documentation only text is allowed. Since only HTML is allowed it is up to each app to decide how to render it. Options I see:

    1) Use a regular `img` tag that grabs the image from a valid URL.

    2) Verify your base64 syntax. Browsers are forgiving, apps may not be. The comma at the end of the src is interesting.


    Michael Taylor http://www.michaeltaylorp3.net

    Friday, December 6, 2019 3:01 PM
    Moderator
  • Yes, you need to create a HTML fragment and doing that is much more complicated than it needs to be, or at least I really think so. I have tried doing it and it kind-of works but it is not the way thing should be done. I do not know how it should be done, there are pointers (offsets) and counts and many things that are supposed to be in agreement.

    As for base64 encoded image, you need to start with HTML that works in a browser. Does the HTML with base64 encoded image work in a browser? I do not know how to make it work, if it is possible.



    Sam Hobbs
    SimpleSamples.Info



    Saturday, December 7, 2019 5:03 AM
  • Adapted from KB274326 (VB) =>

    public partial class Form1 : Form
    {
        [DllImport("User32.dll", SetLastError = true )]
        public static extern IntPtr SetClipboardData(uint uFormat, IntPtr hMem);
    
        [DllImport("User32.dll", SetLastError = true )]
        public static extern bool OpenClipboard(IntPtr hWndNewOwner);
    
        [DllImport("User32.dll", SetLastError = true)]
        public static extern bool CloseClipboard();
    
        [DllImport("User32.dll", SetLastError = true)]
        public static extern bool EmptyClipboard();
    
        [DllImport("User32.dll", SetLastError = true, CharSet = CharSet.Unicode)]
        public static extern uint RegisterClipboardFormat(string lpszFormat);
        
    
        [DllImport("Kernel32.dll", SetLastError = true)]
        public static extern IntPtr GlobalAlloc(uint uFlags, int dwBytes);
    
        [DllImport("Kernel32.dll", SetLastError = true)]
        public static extern IntPtr GlobalLock(IntPtr handle);
    
        [DllImport("Kernel32.dll", SetLastError = true)]
        public static extern bool GlobalUnlock(IntPtr hMem);
    
        [DllImport("Kernel32.dll", SetLastError = true, EntryPoint = "RtlMoveMemory")]
        public static extern void CopyMemory(IntPtr Destination, IntPtr Source, int Length);
    
        [DllImport("Kernel32.dll", SetLastError = true, EntryPoint = "RtlMoveMemory")]
        public static extern void CopyMemory(IntPtr Destination, string Source, int Length);
    
        public Form1()
        {
            InitializeComponent();
        }
    
        // Add a Button to test
        private void button1_Click(object sender, EventArgs e)
        {
            string sHTML = "<a href=\"http://www.microsoft.com\"><img src=\"https://i.ibb.co/JrNqW4N/hulk.png\" style=\"width:256; height:256\" title=\"Hulk\" alt=\"www.microsoft.com\"></a>";
            PutHTMLClipboard(sHTML);
        }
    
        // see KB274326
        private const string m_sDescription = "Version:1.0\r\n" + "StartHTML:00000000\r\n" + "EndHTML:00000000\r\n" + "StartFragment:00000000\r\n" + "EndFragment:00000000\r\n";
    
        static uint m_cfid = 0;
        public void PutHTMLClipboard(string sHtmlFragment)
        {
            string sData;
            string sContextStart = "<HTML><BODY>";
            string sContextEnd = "</BODY></HTML>";
    
            if (m_cfid == 0)
                m_cfid = RegisterClipboardFormat("HTML Format");           
    
            sContextStart = sContextStart + "<!--StartFragment -->";
            sContextEnd = "<!--EndFragment -->" + sContextEnd;
            sData = m_sDescription + sContextStart + sHtmlFragment + sContextEnd;
    
            if (OpenClipboard(IntPtr.Zero))
            {
                IntPtr hMemHandle = IntPtr.Zero;
                IntPtr lpData;
    
                hMemHandle = GlobalAlloc(0, sData.Length + 10);
                if (hMemHandle != IntPtr.Zero)
                {
                    lpData = GlobalLock(hMemHandle);
                    if (lpData != IntPtr.Zero)
                    {
                        CopyMemory(lpData, sData, sData.Length);
                        GlobalUnlock(hMemHandle);
                        EmptyClipboard();
                        SetClipboardData(m_cfid, hMemHandle);
                    }
                }
                CloseClipboard();
            }
        }
    }

    Test Copy-Paste into Winword (2016)



    Saturday, December 7, 2019 11:53 AM