Как я могу прочитать необработанные (CF_HTML) данные буфера обмена на веб-странице или С#?

Если я перетаскиваю выделенную веб-страницу из Firefox в HTML-Kit, HTML-Kit спрашивает меня, хочу ли я вставить текст или HTML. Если я выберу "текст", я получу следующее:

Version:0.9
StartHTML:00000147
EndHTML:00000516
StartFragment:00000181
EndFragment:00000480
SourceURL:http://en.wikipedia.org/wiki/Herodotus
<html><body>
<!--StartFragment-->Additional details have been garnered from the <i><a href="http://en.wikipedia.org/wiki/Suda" title="Suda">Suda</a></i>, an 11th-century encyclopaedia of the <a href="http://en.wikipedia.org/wiki/Byzantium" title="Byzantium">Byzantium</a> which likely took its information from traditional accounts.<!--EndFragment-->
</body>
</html>

Согласно MSDN, это "CF_HTML "отформатированные данные буфера обмена. Это то же самое в системах OS X и Linux?

Есть ли способ получить доступ к такой подробной информации (в отличие от простого фрагмента клипа) в операции перетаскивания с веб-страницы на веб-страницу? Как насчет настольного приложения C# WinForms?


person ine    schedule 26.09.2008    source источник


Ответы (3)


Для полноты картины вот код P/Invoke Win32 API для получения данных буфера обмена RAW.

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

//--------------------------------------------------------------------------------
http://metadataconsulting.blogspot.com/2019/06/How-to-get-HTML-from-the-Windows-system-clipboard-directly-using-PInvoke-Win32-Native-methods-avoiding-bad-funny-characters.html
//--------------------------------------------------------------------------------

public class ClipboardHelper
{
    #region Win32 Native PInvoke

    [DllImport("User32.dll", SetLastError = true)]
    private static extern uint RegisterClipboardFormat(string lpszFormat);
    //or specifically - private static extern uint RegisterClipboardFormatA(string lpszFormat);

    [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);

    #endregion

    public static string GetHTMLWin32Native()
    {

        string strHTMLUTF8 = string.Empty; 
        uint CF_HTML = RegisterClipboardFormatA("HTML Format");
        if (CF_HTML != null || CF_HTML == 0)
                return null;

        if (!IsClipboardFormatAvailable(CF_HTML))
            return null;

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

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

            IntPtr pointer = IntPtr.Zero;

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

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

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

            strHTMLUTF8 = System.Text.Encoding.UTF8.GetString(buff);
            }
            finally
            {
                if (pointer != IntPtr.Zero)
                    GlobalUnlock(handle);
            }
        }
        finally
        {
            CloseClipboard();
        }

        return strHTMLUTF8; 
    }
}
person Markus    schedule 27.08.2019
comment
Хотя есть некоторые ошибки компиляции (uint против int возвращаемого значения GlobalSize и отсутствие подписи RegisterClipboardFormatA pinvoke), это решение работает для меня очень хорошо. Спасибо ????. Я разместил здесь мою скомпилированную и немного улучшенную версию. - person Uwe Keim; 26.11.2019
comment
Спасибо Уве. Обновлено, у меня не было проблем с компиляцией uint для GlobalSize и получением длины (pinvoke.net/ default.aspx/user32/GetClipboardData.html) - person Markus; 02.12.2019

Это специфично для Microsoft, не ожидайте увидеть ту же информацию в других ОС.
Обратите внимание, что вы получаете тот же формат при копировании фрагмента из IE.

Я не уверен, что вы подразумеваете под «операцией перетаскивания веб-страницы на веб-страницу». Бросить куда? Текстовое поле?

Я не знаю C#, но в приложениях C/C++ для получения этой информации необходимо использовать OpenClipboard и связанные с ним API-интерфейсы Win32. В частности, GetClipboardData(CF_HTML) позволяет получить эту информацию (может быть получена и в виде обычного текста, например, или данные Unicode и т.п.).

person PhiLho    schedule 26.09.2008
comment
Под веб-страницей на веб-страницу я подразумеваю перетаскивание текста с одной страницы на другую, в текстовое поле или текстовую область. В идеале я хотел бы получить доступ к свойству SourceURL и выяснить, откуда взялись данные. - person ine; 27.09.2008

Приложение WinForms может использовать Clipboard.GetText для его получения. Однако я не думаю, что есть способ сделать это на веб-странице.

person Mark Brackett    schedule 26.09.2008