0

I'm trying to get the Clipboard data using this native method with C#/.NET. The problem is I'm mangling the data. Here's my code:

IntPtr pointer = GetClipboardData(dataformat);
int size = Marshal.SizeOf(pointer);
byte[] buff = new byte[size];
Marshal.Copy(data, buff, 0, size);

Here's the pinvoke I'm using for the GetClipboardData method:

[DllImport("user32.dll")]
private static extern IntPtr GetClipboardData(uint uFormat);

Can anyone tell me where I'm going wrong?

CODe
  • 2,253
  • 6
  • 36
  • 65
  • Have you looked at the example provided here: https://msdn.microsoft.com/en-us/library/windows/desktop/ms649016(v=vs.85).aspx#_win32_Copying_Information_to_the_Clipboard – MikeH Oct 07 '15 at 23:26
  • 1
    @Roy It's a built in function, see the link provided by the OP – MikeH Oct 07 '15 at 23:28
  • @MikeH Ah I missed that first link. Still would have been nice to see the p-invoke specification just to be sure –  Oct 07 '15 at 23:30
  • @MikeH - I have seen that example. I'm not great with C++, but isn't this for copying TO the clipboard? I'm just trying to get the data off of it. I didn't see what I could try to convert to C# from this to work for my needs. – CODe Oct 07 '15 at 23:30
  • 1
    @Roy I'll provide the pinvoke for ya. See edit. – CODe Oct 07 '15 at 23:32
  • 3
    `data` is actually a _handle_ not a direct pointer to memory. You need to _lock it_ using `GlobalLock()` in order to get the memory block. [See this answer here](http://stackoverflow.com/questions/14762456/getclipboarddatacf-text). It's c++ but you get the idea. Any reason you are not just using the .NET [Clipboard](https://msdn.microsoft.com/en-us/library/system.windows.clipboard(v=vs.110).aspx) class? –  Oct 07 '15 at 23:36
  • 1
    There is a second example further on which shows retrieving info from the clipboard. – MikeH Oct 07 '15 at 23:39
  • @MikeH Ahh, I see it. Missed that, looks like it's reinforcing what Roy mentions. – CODe Oct 07 '15 at 23:46

1 Answers1

10

If you want to get byte array from clipboard, which represents unicode text for example, the code will be something like this:

using System;
using System.Runtime.InteropServices;
using System.Text;

public class ClipboardHelper
{
    #region Win32

    [DllImport("User32.dll", SetLastError = true)]
    [return: MarshalAs(UnmanagedType.Bool)]
    private static extern bool IsClipboardFormatAvailable(uint format);

    [DllImport("User32.dll", SetLastError = true)]
    private static extern IntPtr GetClipboardData(uint uFormat);

    [DllImport("User32.dll", SetLastError = true)]
    [return: MarshalAs(UnmanagedType.Bool)]
    private static extern bool OpenClipboard(IntPtr hWndNewOwner);

    [DllImport("User32.dll", SetLastError = true)]
    [return: MarshalAs(UnmanagedType.Bool)]
    private static extern bool CloseClipboard();

    [DllImport("Kernel32.dll", SetLastError = true)]
    private static extern IntPtr GlobalLock(IntPtr hMem);

    [DllImport("Kernel32.dll", SetLastError = true)]
    [return: MarshalAs(UnmanagedType.Bool)]
    private static extern bool GlobalUnlock(IntPtr hMem);

    [DllImport("Kernel32.dll", SetLastError = true)]
    private static extern int GlobalSize(IntPtr hMem);

    private const uint CF_UNICODETEXT = 13U;

    #endregion

    public static string GetText()
    {
        if (!IsClipboardFormatAvailable(CF_UNICODETEXT))
            return null;

        try
        {
            if (!OpenClipboard(IntPtr.Zero))
                return null;

            IntPtr handle = GetClipboardData(CF_UNICODETEXT);
            if (handle == IntPtr.Zero)
                return null;

            IntPtr pointer = IntPtr.Zero;

            try
            {
                pointer = GlobalLock(handle);
                if (pointer == IntPtr.Zero)
                    return null;

                int size = GlobalSize(handle);
                byte[] buff = new byte[size];

                Marshal.Copy(pointer, buff, 0, size);

                return Encoding.Unicode.GetString(buff).TrimEnd('\0');
            }
            finally
            {
                if (pointer != IntPtr.Zero)
                    GlobalUnlock(handle);
            }
        }
        finally
        {
            CloseClipboard();
        }
    }
}
emoacht
  • 2,764
  • 1
  • 13
  • 24
  • Thanks for spelling it out, while I had figured it out already from the comments above, I do appreciate your answer. – CODe Oct 11 '15 at 18:08
  • A little problem of this code: got extra character when getting clipboard text copied from Adobe acrobat. Better solution : https://stackoverflow.com/a/47346795/3335415 – cuiliang Mar 27 '22 at 06:01