为什么我的图元文件会“丢失”一个位图?

问题描述:

最近我发现了一个bug,同时用元文件绘制东西。现在我不确定我是否做错了什么或者图元文件本身有错误:为什么我的图元文件会“丢失”一个位图?

在通过PlayEnhMetafile在另一个元文件本身上绘制的元文件上绘制图像时,我失去了远处的图像或在右边。我猜它与屏幕坐标有关(我运行双屏幕1280 * 1024,所以2560 * 1024),导致图像开始消失的底部通道大约为500.

这是一些示例代码我创建了更具体地向您显示问题。 (你可以只使用此代码替换新创建的Windows C#项目的Form1.cs和其上放置一个按钮)

using System; 
using System.Drawing; 
using System.Windows.Forms; 
using System.Drawing.Imaging; 
using System.IO; 
using System.Runtime.InteropServices; 

namespace MetaFileDrawing 
{ 
public partial class Form1 
    : Form 
{ 
    [DllImport("gdi32.dll", SetLastError = true)] 
    private static extern bool PlayEnhMetaFile(IntPtr hdc, IntPtr hEmf, ref Rectangle rectangle); 

    [DllImport("gdi32.dll", SetLastError = true)] 
    public static extern bool DeleteObject(IntPtr hGdiObj); 

    public Form1() 
    { 
    InitializeComponent(); 
    } 

    /// <summary> 
    /// Creates the sub-metafile where the actual drawing is done (and the problems occur). 
    /// </summary> 
    private Metafile GetSubMetafile() 
    { 
    Metafile metafile = null; 
    using(Graphics controlGraphics = this.CreateGraphics()) 
    { 
    using(MemoryStream memoryStream = new MemoryStream()) 
    { 
    metafile = new Metafile(memoryStream, controlGraphics.GetHdc(), EmfType.EmfOnly, string.Empty); 

    using(Graphics metafileGraphics = Graphics.FromImage(metafile)) 
    { 
     Bitmap bitmap = new Bitmap("Fibonacci.png"); 
     // Draw the image 3 times... if pushed to far down, it wont show up? 
     metafileGraphics.DrawRectangle(Pens.Yellow, new Rectangle(0, 0, 40, 1200)); 
     metafileGraphics.DrawImage(bitmap, new Point(0, 0)); 
     metafileGraphics.DrawImage(bitmap, new Point(10, 950)); 
     metafileGraphics.DrawImage(bitmap, new Point(20, 1150)); 
    } 
    } 
    controlGraphics.ReleaseHdc(); 
    } 
    return metafile; 
    } 

    /// <summary> 
    /// Creates and draws the metafile. 
    /// </summary> 
    private void DrawMetafile() 
    { 
    using(Graphics controlGraphics = this.CreateGraphics()) 
    {  
    using(MemoryStream memoryStream = new MemoryStream()) 
    { 
    // EmfType.EmfOnly is a restriction defined by my project limitations 
    Metafile metafile = new Metafile(memoryStream, controlGraphics.GetHdc(), EmfType.EmfOnly, string.Empty); 

    using(Graphics metafileGraphics = Graphics.FromImage(metafile)) 
    { 
     // A large red rect for orientation 
     metafileGraphics.DrawRectangle(Pens.Red, new Rectangle(0, 0, 4000, 4000)); 

     // Create the sub metafile 
     Metafile subMetafile = GetSubMetafile(); 

     // To check, draw the subMetafile with DrawImage (works fine, the inlined image is drawn 3 times) 
     metafileGraphics.DrawImage(subMetafile, new Point(10, 0)); 

     // On the right side, draw the sub metafile using PlayEnhMetaFile (dont work correctly, only 2 images) 
     IntPtr hMetafile = subMetafile.GetHenhmetafile(); 
     Rectangle rectangle1 = new Rectangle(100, 0, 170, 1230); 
     PlayEnhMetaFile(metafileGraphics.GetHdc(), hMetafile, ref rectangle1); 
     metafileGraphics.ReleaseHdc(); 
     DeleteObject(hMetafile); 
    } 

    metafile.Save("Output.emf"); 
    } 
    controlGraphics.ReleaseHdc(); 
    } 
    } 

    private void button1_Click(object sender, EventArgs e) 
    { 
    DrawMetafile(); 
    } 
} 
} 

正如你所看到的,使用PlayEnhMetaFile功能使我失去了三选一图片。有任何想法吗?

我遇到了使用C++的相同问题,并找到了两种解决方法。我可以使用GDI +附加到图元文件并播放,但坐标稍微偏离。我目前使用的更复杂的替代方法是使用EnumEnhMetaFile,并手动执行bitblt/stretchblt/stretchdibits调用,这似乎工作。如果您找到了更好的解决方案,请告诉我。