У меня есть приложение Silverlight 5, в котором работает браузер с повышенным доверием. Это позволяет нам делать то, что обычно невозможно в Silverlight, например иметь больший доступ к буферу обмена через P/Invoke.
Что мне нужно сделать, так это скопировать элементы управления в буфер обмена, чтобы их можно было вставить в Word или Outlook. Я могу преобразовать элементы управления в изображение с помощью WriteableBitmap, но у меня проблемы с копированием данных в буфер обмена.
Код вызова:
WriteableBitmap bmp = new WriteableBitmap(elements[0], new ScaleTransform() { ScaleX = 1.0, ScaleY = 1.0 });
int[] p = bmp.Pixels;
int len = p.Length * 4;
byte[] result = new byte[len];
Buffer.BlockCopy(p, 0, result, 0, len);
CopyToClipboardViaPInvoke(result, ClipboardFormat.CF_BITMAP);
Функция копирования:
private void CopyToClipboardViaPInvoke(byte[] data, ClipboardFormat format)
{
IntPtr p = IntPtr.Zero;
if (Native.OpenClipboard(p))
{
GCHandle pinnedArray = GCHandle.Alloc(data, GCHandleType.Pinned);
IntPtr pointer = pinnedArray.AddrOfPinnedObject();
try
{
Native.EmptyClipboard();
IntPtr result = Native.SetClipboardData(format, pointer);
}
finally
{
Native.CloseClipboard();
pinnedArray.Free();
}
}
}
Результат говорит об успешном завершении, но вставка ничего не делает. IsClipboardFormatAvailable
также указывает, что формат доступен в буфере обмена. Я также безуспешно пробовал различные входные данные ClipboardFormat и другие методы преобразования элемента управления в изображение.
Обновление 1
Благодаря предложениям пользователя 629926 у меня есть то, что я думаю, немного ближе, но я все еще что-то упускаю.
Native.EmptyClipboard();
IntPtr bmp = IntPtr.Zero;
GCHandle pinnedArray = GCHandle.Alloc(bytes, GCHandleType.Pinned);
IntPtr bmpPointer = pinnedArray.AddrOfPinnedObject();
Native.StartupInput sin = new Native.StartupInput() { GdiplusVersion = 1 };
Native.StartupOutput sout = new Native.StartupOutput();
IntPtr gdip = IntPtr.Zero;
int startup = Native.GdiplusStartup(out gdip, ref sin, out sout);
int created = Native.GdipCreateBitmapFromScan0(width, height, width * 4, 0x0026200A, bmpPointer, out bmp);
IntPtr result = Native.SetClipboardData(format, bmp);
Native.DeleteObject(bmp);
Native.GdiplusShutdown(ref gdip);