Ответы с форумов MSDN

Работа с буфером обмена

Date: 29.01.2017 7:03:28

Используя класс Clipboard:

IDataObject myDataObject=Clipboard.GetDataObject();
String[] allFormats = myDataObject.GetFormats();

foreach(string s in allFormats)
{	
	if(s==DataFormats.UnicodeText)
	{		
		string text=myDataObject.GetData(DataFormats.UnicodeText);		
		MessageBox.Show("UnicodeText size: "+ ((text.Length+1) * 2).ToString());
	}
	else
	{
		object val=myDataObject.GetData(s);
		int size=System.Runtime.InteropServices.Marshal.SizeOf(val);
		MessageBox.Show(s+" size: " + (size).ToString());
	}
}

С размером не все так просто, он зависит от типа данных... Зная тип и формулу, можно размер посчитать (в примере размер Юникод-строки). Для произвольного объекта можно взять размер неуправляемой памяти (Marshal.SizeOf), но не факт что это сработает.

Добавлено: да, Marshal.SizeOf бесполезен в этом случае. См. ниже рабочий метод.



Message 970

Date: 29.01.2017 11:18:44

Вот нашел еще один способ получения размера произвольного формата в буфере обмена (работает в 80% случаев). Возвращает размер выделенной памяти, который больше или равен размеру самих данных, но для некоторых форматов возвращается слишком маленькое значение или 0:

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;
using System.Runtime.InteropServices;

namespace Test
{
    public partial class Form1 : Form
    {
        [DllImport("user32.dll", SetLastError = true)]
        static extern bool OpenClipboard(IntPtr hWndNewOwner);

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

        [DllImport("kernel32.dll")]
        static extern UIntPtr GlobalSize(IntPtr hMem);

        [DllImport("user32.dll", SetLastError = true)]
        static extern bool CloseClipboard();

        public uint GetClipboardDataSize(string fmt)//получение размера блока памяти в буфере обмена
        {
            DataFormats.Format myFormat;
            int id;
            IntPtr hMem;
            uint size;

            OpenClipboard(IntPtr.Zero);

            myFormat = DataFormats.GetFormat(fmt);
            id = myFormat.Id;
            hMem = GetClipboardData((uint)id);
            size = (uint)GlobalSize(hMem);

            CloseClipboard();

            return size;
        }

        public Form1()
        {
            InitializeComponent();
        }

        private void button1_Click(object sender, EventArgs e)
        { 
            IDataObject myDataObject = Clipboard.GetDataObject();
            String[] allFormats = myDataObject.GetFormats();//получение списка форматов
            
            StringBuilder sb=new StringBuilder(300);  
            
            foreach (string s in allFormats)
            {
                sb.AppendLine(s + ": " + GetClipboardDataSize(s) + " bytes");              
            }            

            MessageBox.Show(sb.ToString());
        }
    }
}
Тестирование показало, что Marshal.SizeOf не работает (в смысле, для объектов буфера обмена), а также что формула размера для Юникод-текста все-таки ((text.Length+1) * 2) а не ((text.Length+2) * 2)


Автор: VadimTagil

Главная страница - Список тем - Репозиторий на GitHub