public Boolean LoadPictureFromClipBoard() { if (Win32Api.OpenClipboard(IntPtr.Zero) == true) // 以当前的任务或者说是进程来打开剪贴板。返回值不为0则表示打开成功 { Win32Structure.BITMAPINFOHEADER BmpInfo = new Win32Structure.BITMAPINFOHEADER(); IntPtr MemPointer, Buffer; if (Win32Api.IsClipboardFormatAvailable(Win32Const.CF_DIB) != 0) // 剪贴板中有DIB图像数据 { Buffer = Win32Api.GetClipboardData(Win32Const.CF_DIB); // 得到DIB数据的起始地址 MemPointer = Win32Api.GlobalLock(Buffer); BmpInfo = (Win32Structure.BITMAPINFOHEADER)Marshal.PtrToStructure(MemPointer, typeof(Win32Structure.BITMAPINFOHEADER)); // 复制数据带结构体 AllocateBitmap(BmpInfo.Width, Math.Abs(BmpInfo.Height), (ushort)BmpInfo.BitCount); if (BmpInfo.BitCount <= 8) { m_PaletteSize = BmpInfo.ClrUsed == 0 ? (1 << (BmpInfo.BitCount)) : (int)BmpInfo.ClrUsed; // 得到实际的调色板的数量 Win32Api.CopyMemory(m_PaletteAddress, MemPointer + 40, m_PaletteSize * 4); // 复制剪贴板数据 if (BmpInfo.Height < 0) // FastBitmap的图像复制容许这个值为负值 { Win32Api.CopyMemory(m_Pointer, MemPointer + 40 + m_PaletteSize * 4, m_Stride * m_Height); // 复制图像数据 } else { for (int Y = 0; Y < m_Height; Y++) // 调整行序 { Win32Api.CopyMemory(m_Pointer + Y * m_Stride, MemPointer + 40 + m_PaletteSize * 4 + (m_Height - 1 - Y) * m_Stride, m_Stride); } } Win32Api.SetDIBColorTable(m_Hdc, 0, m_PaletteSize, m_PaletteAddress); // 设置DC的调色板 } else { if (BmpInfo.Height < 0) { Win32Api.CopyMemory(m_Pointer, MemPointer + 40, m_Stride * m_Height); // 24/32位图像无调色板,直接复制数据 } else { for (int Y = 0; Y < m_Height; Y++) { Win32Api.CopyMemory(m_Pointer + Y * m_Stride, MemPointer + 40 + (m_Height - 1 - Y) * m_Stride, m_Stride); } } } Win32Api.GlobalUnlock(Buffer); } Win32Api.CloseClipboard(); } return(true); }
public Boolean CopyToClipBoard(Boolean CompatibleWithPhotoShop = true) { if (m_Handle == IntPtr.Zero) { return(false); } Win32Structure.BITMAPINFOHEADER BmpInfo = new Win32Structure.BITMAPINFOHEADER(); IntPtr MemPointer, Buffer; int BufferSize = 0; // FastBitmap本身的数据顶点数据位于屏幕的左上角,因此设置为负值则后面的图像数据无需单独行拷贝 // 但是PhotoShop不支持这种格式。 BmpInfo.Height = (CompatibleWithPhotoShop == true ? m_Height : -m_Height); BmpInfo.Width = m_Width; BmpInfo.Compression = Win32Const.BI_RGB; BmpInfo.Planes = 1; BmpInfo.Size = 40; BmpInfo.BitCount = m_BitCount; BmpInfo.ClrUsed = (uint)m_PaletteSize; // 增加这一句,否则从剪贴板获取数据就错位(mspaint的黏贴也不对) switch (m_BitCount) { case 1: case 4: case 8: BufferSize = 40 + m_PaletteSize * 4 + m_Stride * m_Height; // 文件头+调色板+图像数据 break; case 24: case 32: BufferSize = 40 + m_Stride * m_Height; // 文件头+图像数据 break; default: return(false); } Buffer = Win32Api.GlobalAlloc(Win32Const.GMEM_MOVEABLE, BufferSize); // 给全局内存对象分配全局内存 ,必须使用GMEM_MOVEABLE标志 http://topic.csdn.net/u/20070122/10/cde3555b-c4da-40ca-8fd9-a5c05fcf75df.html if (Buffer == IntPtr.Zero) { return(false); } MemPointer = Win32Api.GlobalLock(Buffer); // 通过给全局内存对象加锁获得对全局内存块的引用 Marshal.StructureToPtr(BmpInfo, MemPointer, true); // 封送结构体到非托管内存中 switch (m_BitCount) { case 1: case 4: case 8: Win32Api.CopyMemory(MemPointer + 40, m_PaletteAddress, m_PaletteSize * 4); // 拷贝调色板数据 if (CompatibleWithPhotoShop == true) { for (int Y = 0; Y < Height; Y++) { Win32Api.CopyMemory(MemPointer + m_PaletteSize * 4 + 40 + Y * Stride, m_Pointer + Stride * (Height - 1 - Y), Stride); } } else { Win32Api.CopyMemory(MemPointer + m_PaletteSize * 4 + 40, m_Pointer, m_Stride * m_Height); // 拷贝图像数据 } break; case 24: case 32: if (CompatibleWithPhotoShop == true) { for (int Y = 0; Y < Height; Y++) { Win32Api.CopyMemory(MemPointer + 40 + Stride * Y, Pointer + Stride * (Height - 1 - Y), Stride); } } else { Win32Api.CopyMemory(MemPointer + 40, m_Pointer, m_Stride * m_Height); // 拷贝图像数据 } break; default: return(false); } Win32Api.GlobalUnlock(Buffer); // 使用完全局内存块后需要对全局内存块解锁 if (Win32Api.OpenClipboard(IntPtr.Zero) == true) // 以当前的任务或者说是进程来打开剪贴板。返回值不为0则表示打开成功 { Win32Api.EmptyClipboard(); // 这个函数将清空剪贴板,并释放剪贴板中数据的句柄,然后将剪贴板的所有权分配给当前打开剪贴板的窗口 Win32Api.SetClipboardData(Win32Const.CF_DIB, Buffer); Win32Api.CloseClipboard(); //GlobalFree Buffer 这个释放就交给系统去释放了,千万不要在这里释放,否则会造成一些莫名其妙的错误 return(true); } else { Win32Api.CloseClipboard(); return(false); } }