using System; using System.ComponentModel; using System.IO; using System.Runtime.InteropServices; using System.Runtime.Versioning; using Avalonia.Media.Imaging; namespace StabilityMatrix.Avalonia.Helpers; [SupportedOSPlatform("windows")] public static class WindowsClipboard { public static void SetBitmap(Bitmap bitmap) { if (bitmap == null) throw new ArgumentNullException(nameof(bitmap)); // Convert from Avalonia Bitmap to System Bitmap var memoryStream = new MemoryStream(); bitmap.Save(memoryStream); // this returns a png from Skia (we could save/load it from the system bitmap to convert it to a bmp first, but this seems to work well already) var systemBitmap = new System.Drawing.Bitmap(memoryStream); var hBitmap = systemBitmap.GetHbitmap(); var screenDC = GetDC(IntPtr.Zero); var sourceDC = CreateCompatibleDC(screenDC); var sourceBitmapSelection = SelectObject(sourceDC, hBitmap); var destDC = CreateCompatibleDC(screenDC); var compatibleBitmap = CreateCompatibleBitmap( screenDC, systemBitmap.Width, systemBitmap.Height ); var destinationBitmapSelection = SelectObject(destDC, compatibleBitmap); BitBlt(destDC, 0, 0, systemBitmap.Width, systemBitmap.Height, sourceDC, 0, 0, 0x00CC0020); // SRCCOPY try { OpenClipboard(IntPtr.Zero); EmptyClipboard(); var result = SetClipboardData( (uint) Win32ClipboardFormat.CF_BITMAP, compatibleBitmap ); if (result == IntPtr.Zero) { var errno = Marshal.GetLastWin32Error(); throw new Win32Exception(errno, $"SetClipboardData failed"); } } finally { CloseClipboard(); } } [DllImport("user32.dll", SetLastError = true)] static extern bool OpenClipboard(IntPtr hWndNewOwner); [DllImport("user32.dll", SetLastError = true)] private static extern bool CloseClipboard(); [DllImport("user32.dll")] static extern IntPtr SetClipboardData(uint uFormat, IntPtr hMem); [DllImport("user32.dll", SetLastError = true)] private static extern bool EmptyClipboard(); [DllImport("user32.dll", ExactSpelling = true)] public static extern IntPtr GetDC(IntPtr hWnd); [DllImport("gdi32.dll", ExactSpelling = true)] public static extern IntPtr CreateCompatibleDC(IntPtr hDC); [DllImport("gdi32.dll", ExactSpelling = true)] public static extern IntPtr CreateCompatibleBitmap(IntPtr hdc, int cx, int cy); [DllImport("gdi32.dll", SetLastError = true, ExactSpelling = true)] public static extern IntPtr SelectObject(IntPtr hdc, IntPtr h); [DllImport("gdi32.dll", SetLastError = true, ExactSpelling = true)] public static extern bool BitBlt( IntPtr hdc, int x, int y, int cx, int cy, IntPtr hdcSrc, int x1, int y1, uint rop ); }