我有一个适用于Enhanced Metafiles的应用程序。
我能够创建它们,将它们作为 .emf 保存到磁盘并再次加载它们没问题。
我通过使用 gdi32.dll 方法和DLLImport 属性来做到这一点。
但是,为了启用版本容错序列化,我想将元文件与其他数据一起保存在对象中。
这实质上意味着我需要将元文件数据序列化为字节数组,然后再次反序列化以重建元文件。
我遇到的问题是反序列化数据似乎以某种方式损坏,因为我用来重建元文件的方法引发了“参数无效异常”。
至少像素格式和分辨率已经改变。
代码使用如下。
[DllImport("gdi32.dll")]
public static extern uint GetEnhMetaFileBits(IntPtr hemf, uint cbBuffer, byte[] lpbBuffer);
[DllImport("gdi32.dll")]
public static extern IntPtr SetEnhMetaFileBits(uint cbBuffer, byte[] lpBuffer);
[DllImport("gdi32.dll")]
public static extern bool DeleteEnhMetaFile(IntPtr hemf);
应用程序创建一个元文件图像并将其传递给下面的方法。
private byte[] ConvertMetaFileToByteArray(Image image)
{
byte[] dataArray = null;
Metafile mf = (Metafile)image;
IntPtr enhMetafileHandle = mf.GetHenhmetafile();
uint bufferSize = GetEnhMetaFileBits(enhMetafileHandle, 0, null);
if (enhMetafileHandle != IntPtr.Zero)
{
dataArray = new byte[bufferSize];
GetEnhMetaFileBits(enhMetafileHandle, bufferSize, dataArray);
}
DeleteEnhMetaFile(enhMetafileHandle);
return dataArray;
}
此时,dataArray 被插入到对象中并使用 BinaryFormatter 进行序列化。
然后使用 BinaryFormatter 和从对象中检索的 dataArray 再次反序列化保存的文件。
然后使用以下方法使用 dataArray 重建原始 Metafile。
public static Image ConvertByteArrayToMetafile(byte[] data)
{
Metafile mf = null;
try
{
IntPtr hemf = SetEnhMetaFileBits((uint)data.Length, data);
mf = new Metafile(hemf, true);
}
catch (Exception ex)
{
System.Windows.Forms.MessageBox.Show(ex.Message);
}
return (Image)mf;
}
然后将重建的元文件作为 .emf(模型)保存到磁盘,此时 Presenter 可以访问它以进行显示。
private static void SaveFile(Image image, String filepath)
{
try
{
byte[] buffer = ConvertMetafileToByteArray(image);
File.WriteAllBytes(filepath, buffer); //will overwrite file if it exists
}
catch (Exception ex)
{
System.Windows.Forms.MessageBox.Show(ex.Message);
}
}
问题是保存到磁盘失败。如果在序列化之前使用相同的方法保存原始元文件,则一切正常。所以在序列化/反序列化期间数据发生了一些事情。
事实上,如果我在调试器中检查 Metafile 属性,我可以看到 ImageFlags、PropertyID、分辨率和像素格式发生了变化。
原始 Format32bppRgb 更改为 Format32bppArgb
原始分辨率 81 更改为 96
我已经通过谷歌和 SO 进行了搜索,这帮助我走到了这一步,但我现在卡住了。
有没有人有足够的元文件/序列化经验来帮助..?
编辑:如果我直接序列化/反序列化字节数组(不嵌入另一个对象),我会遇到同样的问题。