读取图片文件MetaFile放入Windows剪切板
前言
前段时间群里有个小伙在工作中遇到一个问题,透明的图片存入剪切板在粘贴到adobe PDF中出现不透明问题但是粘贴到Excel可以,还有就是从excel复制再粘贴到PDF也是可以。小伙在群里发了两天都没有解决,当时看到这个问题感觉很有趣我就去尝试了一下,当时我用的WPS,我试了一下可以粘贴到WPS 打开的PDF中,当时我感觉是PDF编辑器的问题,建议小伙换个,小伙说不能换客户要求必须是这个,好的嘛那就开始搞
号脉
我打开两个神级IDE VS 分别获取一下从excel复制之后和通过小伙程序复制之后存到剪切板中的数据,我对比了一下剪切板中的确有很多的不同,那就开始尝试是因啥不同导致的,我用程序把从Excel中复制获取的数据按照参数对象一个一个从新清空剪切板在重新放入剪切板,尝试是哪个参数对象导致的PDF无法呈现预想的结果。最后确定是因为剪切板中没有存储MetafilePict数据导致的
开药
下面获取图片文件的MetaFile数据
public Metafile GetGeometryMetafile(Bitmap bitmap)
{
Metafile metafile;
using (MemoryStream stream = new MemoryStream())
using (Graphics rtfBoxGraphics = Graphics.FromImage(bitmap))
{
IntPtr pDeviceContext = rtfBoxGraphics.GetHdc();
metafile = new Metafile(stream, pDeviceContext);
using (Graphics imageGraphics = Graphics.FromImage(metafile))
{
//imageGraphics.DrawImage(bitmap, new Drawing.Rectangle(0, 0, bitmap.Width, bitmap.Height));
imageGraphics.DrawImageUnscaled(bitmap, new Rectangle(0, 0, bitmap.Width, bitmap.Height));
}
rtfBoxGraphics.ReleaseHdc(pDeviceContext);
}
return metafile;
}
吃药
下面把获取的文件MetaFile放入剪切板
因为特殊原因,需要调用系统dll进行剪切板操作
internal static class ClipboardMetafileHelper
{
[DllImport("user32.dll")]
static extern bool OpenClipboard(IntPtr hWndNewOwner);
[DllImport("user32.dll")]
static extern bool EmptyClipboard();
[DllImport("user32.dll")]
static extern IntPtr SetClipboardData(uint uFormat, IntPtr hMem);
[DllImport("user32.dll")]
static extern bool CloseClipboard();
[DllImport("gdi32.dll")]
static extern IntPtr CopyEnhMetaFile(IntPtr hemfSrc, string fileName);
[DllImport("gdi32.dll")]
static extern bool DeleteEnhMetaFile(IntPtr hemf);
/// <summary>
/// Copies the given <see cref="T:System.Drawing.Imaging.MetaFile" /> to the clipboard.
/// The given <see cref="T:System.Drawing.Imaging.MetaFile" /> is set to an invalid state inside this function.
/// </summary>
static public bool PutEnhMetafileOnClipboard(IntPtr hWnd, Metafile metafile)
{
return PutEnhMetafileOnClipboard(hWnd, metafile, true);
}
/// <summary>
/// Copies the given <see cref="T:System.Drawing.Imaging.MetaFile" /> to the clipboard.
/// The given <see cref="T:System.Drawing.Imaging.MetaFile" /> is set to an invalid state inside this function.
/// </summary>
static public bool PutEnhMetafileOnClipboard(IntPtr hWnd, Metafile metafile, bool clearClipboard)
{
if (metafile == null) throw new ArgumentNullException("metafile");
bool bResult = false;
IntPtr hEMF, hEMF2;
hEMF = metafile.GetHenhmetafile(); // invalidates mf
if (!hEMF.Equals(IntPtr.Zero))
{
try
{
hEMF2 = CopyEnhMetaFile(hEMF, null);
if (!hEMF2.Equals(IntPtr.Zero))
{
if (OpenClipboard(hWnd))
{
try
{
if (clearClipboard)
{
if (!EmptyClipboard())
return false;
}
IntPtr hRes = SetClipboardData(14 /*CF_ENHMETAFILE*/, hEMF2);
bResult = hRes.Equals(hEMF2);
}
finally
{
CloseClipboard();
}
}
}
}
finally
{
DeleteEnhMetaFile(hEMF);
}
}
return bResult;
}
/// <summary>
/// Copies the given <see cref="T:System.Drawing.Imaging.MetaFile" /> to the specified file. If the file does not exist, it will be created.
/// The given <see cref="T:System.Drawing.Imaging.MetaFile" /> is set to an invalid state inside this function.
/// </summary>
static public bool SaveEnhMetaFile(string fileName, Metafile metafile)
{
if (metafile == null) throw new ArgumentNullException("metafile");
bool result = false;
IntPtr hEmf = metafile.GetHenhmetafile();
if (hEmf != IntPtr.Zero)
{
IntPtr resHEnh = CopyEnhMetaFile(hEmf, fileName);
if (resHEnh != IntPtr.Zero)
{
DeleteEnhMetaFile(resHEnh);
result = true;
}
DeleteEnhMetaFile(hEmf);
metafile.Dispose();
}
return result;
}
}
var path = AppDomain.CurrentDomain.BaseDirectory + "1.png";
Bitmap bm = new Bitmap(path, false);
var mf = GetGeometryMetafile(bm);
ClipboardMetafileHelper.PutEnhMetafileOnClipboard(IntPtr.Zero, mf);
总结
功能看着挺简单,其实内部有很多的坑(文件MetaFIle数据的获取,MetaFile怎么才能正确放到剪切板中),从网上找的资料也不是很全,没有现成的代码,这里做一下总结汇总,供大家使用。上述代码也有一定的问题(剪切板中的数据放到别的编辑器有的失效是因为剪切板中数据缺少对应编辑器所需的参数,可根据Clipboard.GetDataObject()获取缓存数据对象判断编辑器需要的对象然后利用下面方法进行后续代码优化。
public static void SetClipboardImage(Bitmap image, Bitmap imageNoTr, DataObject data)
{
Clipboard.Clear();
if (data == null)
data = new DataObject();
if (imageNoTr == null)
imageNoTr = image;
using (MemoryStream pngMemStream = new MemoryStream())
using (MemoryStream dibMemStream = new MemoryStream())
{
// As standard bitmap, without transparency support
data.SetData(DataFormats.Bitmap, imageNoTr);
// As PNG. Gimp will prefer this over the other two.
image.Save(pngMemStream, ImageFormat.Png);
data.SetData("PNG", pngMemStream);
// As DIB. This is (wrongly) accepted as ARGB by many applications.
Byte[] dibData = ConvertToDib(image);
dibMemStream.Write(dibData, 0, dibData.Length);
data.SetData(DataFormats.Dib, dibMemStream);
// The 'copy=true' argument means the MemoryStreams can be safely disposed after the operation.
Clipboard.SetDataObject(data, true);
}
}
读取图片文件MetaFile放入Windows剪切板的更多相关文章
- 监视 Windows 剪切板
一.先看代码 import win32con,win32gui import win32clipboard as cb class MyWindow(): def __init__(self): #注 ...
- Python实现图片转文字并翻译至剪切板
一.环境搭建: 1.PySimpleGUI: pip3 install pysimplegui 2.pytesseract需要有tesseract环境才行: 1. 先搭建tesseract: brew ...
- windows剪切板暂存
其实最初是因为在项目中使用了html网页编辑器,通过ie的com组件和javascript通讯完成一些事情,其中有一个功能是插入表格,我们原本使用的range.pasteHTML(HTMLstr);根 ...
- winform学习之----打开文件对话框并将文件内容放入文本框
OpenFileDialog ofg = new OpenFileDialog(); ofg.Title = "ddd";//设置对话框标题 ofg.Multiselect = t ...
- c# 读取图片文件
/// <summary> /// 通过FileStream 来打开文件,这样就可以实现不锁定Image文件,到时可以让多用户同时访问Image文件 /// </summary> ...
- 【DOS】取某目录下某类型文件信息放入文本
C:\Users\horn1\Desktop\新建文件夹>dir *.jar >1.txt 这样,所有扩展名为jar的文件信息就送到新建的文本文件1.txt中了.虽然简单,但也是个常用功能 ...
- Delphi的windows剪切板操作函数
1. Clipbrd函数 function Clipboard: TClipboard;:若应用程序从未使用过剪贴板,则调用该函数形成新的剪贴板:若之前使用过剪贴板则返回使用过的剪贴板. 属性: As ...
- 使用python读写windows剪切板
import win32clipboard as w import win32con base_addr = 0x8e00000 buffer_len = 0x123 def getText(): w ...
- java通过文件路径读取该路径下的所有文件并将其放入list中
java通过文件路径读取该路径下的所有文件并将其放入list中 java中可以通过递归的方式获取指定路径下的所有文件并将其放入List集合中.假设指定路径为path,目标集合为fileList,遍 ...
随机推荐
- Spring Ioc源码分析系列--自动注入循环依赖的处理
Spring Ioc源码分析系列--自动注入循环依赖的处理 前言 前面的文章Spring Ioc源码分析系列--Bean实例化过程(二)在讲解到Spring创建bean出现循环依赖的时候并没有深入去分 ...
- python中collections.OrderedDict()
import collections #from collections import OrderededDict my_orderDict=collections.OrderedDict(house ...
- 腾讯云数据库TDSQL-大咖论道 | 基础软件的过去、现在、未来
近十年来,中国基础软件发展势头迅猛,市场前景看高,越来越多的企业也正在进行基础软件升级.那中国基础软件行业目前在国际市场上有什么优势,面临哪些困境,以及未来基础软件行业会如何发展呢?腾讯云数据库邀请沙 ...
- Apache Shiro反序列化漏洞(Shiro550)
1.漏洞原理: Shiro 是 Java 的一个安全框架,执行身份验证.授权.密码.会话管理 shiro默认使用了CookieRememberMeManager,其处理cookie的流程是:得到rem ...
- SAP APO-部署选项
SAP SCM Server安装提供SAP APO功能模块的所有功能. 在SAP APO的附加部署模型中,以下组件可用作SAP APO工具的一部分- OTE-在附加部署模型中,无法通过SAP SCM服 ...
- NFS网络文件系统搭建
1. 简介 NFS, 就是network file system的简称. 可以通过NFS, 来共享不同主机的文件.目录. 2010年,NFS已经发展到v4.1版本. 2. 应用场景 在中小型企业中,N ...
- CANN算子:利用迭代器高效实现Tensor数据切割分块处理
摘要:本文以Diagonal算子为例,介绍并详细讲解如何利用迭代器对n维Tensor进行基于位置坐标的大批量数据读取工作. 本文分享自华为云社区<CANN算子:利用迭代器高效实现Tensor数据 ...
- P1189 SEARCH—搜索
将这题加进来的原因 因为他的优化令人眼前一新! 题目传送门() 相似的题目之 血色先锋队 ↑这一题也要用到标记数组 优化!!! 对于一个位置, 如果他在同样的深度再一次被访问,那他接下来所走的路径,所 ...
- Whats On Tap | Tapdata Cloud 如何助力大型家居连锁商城推进数字化经营?
Tapdata Cloud 的操作有多便捷,上手试一下就能充分了解了.--Tapdata Cloud 用户 | 报表实施 @某大型家居服务平台 一边是监管政策趋严,推动房地产回归本源,存量竞争时代开启 ...
- SVM简要介绍
SVM 支持向量机(SVM),是一个用于解决二分类问题的有监督机器学习模型. 1.SVM的两个优点 更高的速度 在有一定的样本数量支持下(成千上万张),具有比其他模型有更好的效果 2.SVM的工作过程 ...