GDI+ / C#:如何将图像保存为 EMF?

发布于 2024-07-06 13:42:44 字数 233 浏览 5 评论 0原文

如果您使用 Image.Save 方法将图像保存到 EMF/WMF,则会出现异常 (http://msdn.microsoft.com/en-us/library/ktx83wah.aspx)

是否有其他方法将图像保存到 EMF/WMF? 有可用的编码器吗?

If you use Image.Save Method to save an image to a EMF/WMF, you get an exception (http://msdn.microsoft.com/en-us/library/ktx83wah.aspx)

Is there another way to save the image to an EMF/WMF?
Are there any encoders available?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(10

停顿的约定 2024-07-13 13:42:44

Image 是一个抽象类:您想要执行的操作取决于您处理的是 Metafile 还是 Bitmap

使用Metafile 使用 GDI+ 创建图像并将其保存为 EMF 非常简单。 根据 Mike 的帖子

var path = @"c:\foo.emf"
var g = CreateGraphics(); // get a graphics object from your form, or wherever
var img = new Metafile(path, g.GetHdc()); // file is created here
var ig = Graphics.FromImage(img);
// call drawing methods on ig, causing writes to the file
ig.Dispose(); img.Dispose(); g.ReleaseHdc(); g.Dispose();

这是大多数时候你想做的就是 EMF 的用途:以 GDI+ 绘图命令的形式保存矢量图像。

您可以使用上述方法并调用 ig.DrawImage(your_bitmap) 将位图保存到 EMF 文件,但请注意,这不会神奇地将光栅数据转换为矢量图像。

Image is an abstract class: what you want to do depends on whether you are dealing with a Metafile or a Bitmap.

Creating an image with GDI+ and saving it as an EMF is simple with Metafile. Per Mike's post:

var path = @"c:\foo.emf"
var g = CreateGraphics(); // get a graphics object from your form, or wherever
var img = new Metafile(path, g.GetHdc()); // file is created here
var ig = Graphics.FromImage(img);
// call drawing methods on ig, causing writes to the file
ig.Dispose(); img.Dispose(); g.ReleaseHdc(); g.Dispose();

This is what you want to do most of the time, since that is what EMF is for: saving vector images in the form of GDI+ drawing commands.

You can save a Bitmap to an EMF file by using the above method and calling ig.DrawImage(your_bitmap), but be aware that this does not magically covert your raster data into a vector image.

初见终念 2024-07-13 13:42:44

如果我没记错的话,它可以通过 Metafile.GetHenhmetafile()、API GetEnhMetaFileBits() 和 Stream.Write() 的组合来完成,就像

[DllImport("gdi32")] static extern uint GetEnhMetaFileBits(IntPtr hemf, uint cbBuffer, byte[] lpbBuffer);


IntPtr h = metafile.GetHenhMetafile();
int size = GetEnhMetaFileBits(h, 0, null);
byte[] data = new byte[size];
GetEnhMetaFileBits(h, size, data);
using (FileStream w = File.Create("out.emf")) {
    w.Write(data, 0, size);
}
// TODO: I don't remember whether the handle needs to be closed, but I guess not.

我认为这就是我解决问题时的方法。

If I remember correctly, it can be done with a combination of the Metafile.GetHenhmetafile(), the API GetEnhMetaFileBits() and Stream.Write(), something like

[DllImport("gdi32")] static extern uint GetEnhMetaFileBits(IntPtr hemf, uint cbBuffer, byte[] lpbBuffer);


IntPtr h = metafile.GetHenhMetafile();
int size = GetEnhMetaFileBits(h, 0, null);
byte[] data = new byte[size];
GetEnhMetaFileBits(h, size, data);
using (FileStream w = File.Create("out.emf")) {
    w.Write(data, 0, size);
}
// TODO: I don't remember whether the handle needs to be closed, but I guess not.

I think this is how I solved the problem when I had it.

土豪我们做朋友吧 2024-07-13 13:42:44

图元文件是记录 GDI 操作序列的文件。 它是可缩放的,因为生成图片的原始操作序列被捕获,因此可以缩放记录的坐标。

我认为,在 .NET 中,您应该创建一个 Metafile 对象,使用 Graphics.FromImage 创建一个 Graphics 对象,然后执行绘图步骤。 当您在文件上绘图时,该文件会自动更新。 您可以在图形文档中找到一个小示例。添加元文件注释

如果您确实想在图元文件中存储位图,请使用以下步骤,然后使用 Graphics.DrawImage 绘制位图。 但是,当缩放时,它将使用 StretchBlt 进行拉伸。

A metafile is a file which records a sequence of GDI operations. It is scalable because the original sequence of operations that generated the picture are captured, and therefore the co-ordinates that were recorded can be scaled.

I think, in .NET, that you should create a Metafile object, create a Graphics object using Graphics.FromImage, then perform your drawing steps. The file is automatically updated as you draw on it. You can find a small sample in the documentation for Graphics.AddMetafileComment.

If you really want to store a bitmap in a metafile, use these steps then use Graphics.DrawImage to paint the bitmap. However, when it is scaled it will be stretched using StretchBlt.

七禾 2024-07-13 13:42:44

问题是:“是否有其他方法将图像保存到 EMF/WMF?” 不是“什么是图元文件”或“如何创建图元文件”或“如何将图元文件与图形一起使用”。

我也在寻找这个问题的答案“如何保存 EMF/WMF”
事实上,如果您使用:

  Graphics grfx = CreateGraphics();
  MemoryStream ms = new MemoryStream();
  IntPtr ipHdc = grfx.GetHdc();

  Metafile mf = new Metafile(ms, ipHdc);

  grfx.ReleaseHdc(ipHdc);
  grfx.Dispose();
  grfx = Graphics.FromImage(mf);

  grfx.FillEllipse(Brushes.Gray, 0, 0, 100, 100);
  grfx.DrawEllipse(Pens.Black, 0, 0, 100, 100);
  grfx.DrawArc(new Pen(Color.Red, 10), 20, 20, 60, 60, 30, 120);
  grfx.Dispose();

  mf.Save(@"C:\file.emf", ImageFormat.Emf);
  mf.Save(@"C:\file.png", ImageFormat.Png);

在这两种情况下,图像都会保存为 png 格式。 这是我无法解决的问题:/

The question was: "Is there another way to save the image to an EMF/WMF?" Not "what is metafile" or "how to create metafile" or "how to use metafile with Graphics".

I also look for answer for this question "how to save EMF/WMF"
In fact if you use:

  Graphics grfx = CreateGraphics();
  MemoryStream ms = new MemoryStream();
  IntPtr ipHdc = grfx.GetHdc();

  Metafile mf = new Metafile(ms, ipHdc);

  grfx.ReleaseHdc(ipHdc);
  grfx.Dispose();
  grfx = Graphics.FromImage(mf);

  grfx.FillEllipse(Brushes.Gray, 0, 0, 100, 100);
  grfx.DrawEllipse(Pens.Black, 0, 0, 100, 100);
  grfx.DrawArc(new Pen(Color.Red, 10), 20, 20, 60, 60, 30, 120);
  grfx.Dispose();

  mf.Save(@"C:\file.emf", ImageFormat.Emf);
  mf.Save(@"C:\file.png", ImageFormat.Png);

In both cases image is saved as format png. And this is the problem which I cannot solve :/

吹梦到西洲 2024-07-13 13:42:44

erikkallen 的答案是正确的。 我在 VB.NET 中尝试过此操作,并且必须使用 2 个不同的 DllImports 才能使其正常工作:

<System.Runtime.InteropServices.DllImportAttribute("gdi32.dll", EntryPoint:="GetEnhMetaFileBits")> _
    Public Shared Function GetEnhMetaFileBits(<System.Runtime.InteropServices.InAttribute()> ByVal hEMF As System.IntPtr, ByVal nSize As UInteger, ByVal lpData As IntPtr) As UInteger
End Function

    <System.Runtime.InteropServices.DllImportAttribute("gdi32.dll", EntryPoint:="GetEnhMetaFileBits")> _
    Public Shared Function GetEnhMetaFileBits(<System.Runtime.InteropServices.InAttribute()> ByVal hEMF As System.IntPtr, ByVal nSize As UInteger, ByVal lpData() As Byte) As UInteger
End Function

第一个导入用于第一次调用以获取 emf 大小。 第二次导入以获取实际位。
或者,您可以使用:

Dim h As IntPtr = mf.GetHenhmetafile()
CopyEnhMetaFileW(h, FileName)

这会将 emf 位直接复制到指定文件中。

The answer by erikkallen is correct. I tried this from VB.NET, and had to use 2 different DllImports to get it to work:

<System.Runtime.InteropServices.DllImportAttribute("gdi32.dll", EntryPoint:="GetEnhMetaFileBits")> _
    Public Shared Function GetEnhMetaFileBits(<System.Runtime.InteropServices.InAttribute()> ByVal hEMF As System.IntPtr, ByVal nSize As UInteger, ByVal lpData As IntPtr) As UInteger
End Function

    <System.Runtime.InteropServices.DllImportAttribute("gdi32.dll", EntryPoint:="GetEnhMetaFileBits")> _
    Public Shared Function GetEnhMetaFileBits(<System.Runtime.InteropServices.InAttribute()> ByVal hEMF As System.IntPtr, ByVal nSize As UInteger, ByVal lpData() As Byte) As UInteger
End Function

The first import is used for the first call to get the emf size. The second import to get the actual bits.
Alternatively you could use:

Dim h As IntPtr = mf.GetHenhmetafile()
CopyEnhMetaFileW(h, FileName)

This copies the emf bits directly to the named file.

蛮可爱 2024-07-13 13:42:44

您还需要关闭 CopyEnhMetaFile 处理程序:

IntPtr ptr2 = CopyEnhMetaFile(iptrMetafileHandle, "image.emf");
DeleteEnhMetaFile(ptr2);

// Delete the metafile from memory
DeleteEnhMetaFile(iptrMetafileHandle);

否则,您无法删除该文件,因为该文件仍在被进程使用。

You also need to close the CopyEnhMetaFile handler:

IntPtr ptr2 = CopyEnhMetaFile(iptrMetafileHandle, "image.emf");
DeleteEnhMetaFile(ptr2);

// Delete the metafile from memory
DeleteEnhMetaFile(iptrMetafileHandle);

Otherwise, you cannot delete the file because it's still used by the process.

向地狱狂奔 2024-07-13 13:42:44

我正在寻找一种将图元文件对象中的 GDI 指令保存到 EMF 文件的方法。 韩老师的帖子帮我解决了这个问题。 这是我加入 SOF 之前的事。 谢谢你,韩。 这是我尝试过的

    [DllImport("gdi32.dll")]
    static extern IntPtr CopyEnhMetaFile(  // Copy EMF to file
        IntPtr hemfSrc,   // Handle to EMF
        String lpszFile // File
    );

    [DllImport("gdi32.dll")]
    static extern int DeleteEnhMetaFile(  // Delete EMF
        IntPtr hemf // Handle to EMF
    );

   // Code that creates the metafile 
   // Metafile metafile = ...

   // Get a handle to the metafile
   IntPtr iptrMetafileHandle = metafile.GetHenhmetafile();

   // Export metafile to an image file
   CopyEnhMetaFile(
         iptrMetafileHandle, 
          "image.emf");

   // Delete the metafile from memory
   DeleteEnhMetaFile(iptrMetafileHandle);

I was looking for a way to save the GDI instructions in a Metafile object to a EMF file. Han's post helped me solve the problem. This was before I joined SOF. Thank you, Han. Here is what I tried.

    [DllImport("gdi32.dll")]
    static extern IntPtr CopyEnhMetaFile(  // Copy EMF to file
        IntPtr hemfSrc,   // Handle to EMF
        String lpszFile // File
    );

    [DllImport("gdi32.dll")]
    static extern int DeleteEnhMetaFile(  // Delete EMF
        IntPtr hemf // Handle to EMF
    );

   // Code that creates the metafile 
   // Metafile metafile = ...

   // Get a handle to the metafile
   IntPtr iptrMetafileHandle = metafile.GetHenhmetafile();

   // Export metafile to an image file
   CopyEnhMetaFile(
         iptrMetafileHandle, 
          "image.emf");

   // Delete the metafile from memory
   DeleteEnhMetaFile(iptrMetafileHandle);

み零 2024-07-13 13:42:44

我建议避免在托管 .NET 应用程序中出现此类外部和非托管的问题。
相反,我建议更像此线程中给出的托管解决方案:

使用 .NET 将图像转换为 WMF?

PS 我正在回答这个旧线程,因为这是我找到的最佳答案,但最终开发了一个托管解决方案,然后引导我到上面的链接。 所以,为了节省其他人的时间,我想我应该把这个指向那个。

I would recommend avoiding such extern's and unmanaged cruft in a managed .NET app.
Instead, I'd recommend something a bit more like the managed solution given in this thread:

Convert an image into WMF with .NET?

P.S. I am answering this old thread because this was the best answer I had found, but then ended up developing a managed solution, which then lead me to the link above. So, to save others that time, I figured I'd point this one to that one.

心如狂蝶 2024-07-13 13:42:44

看来矢量与位图之间存在很多混淆。 该线程中的所有代码都会生成位图(非矢量)文件 - 它不保留矢量 GDI 调用。 要向自己证明这一点,请下载“EMF Parser”工具并检查输出文件:http: //downloads.z​​dnet.com/abstract.aspx?docid=749645

这个问题引起了很多开发者的苦恼。 如果微软能解决这个问题并正确支持他们自己的 EMF 格式,那就太好了。

It appears there is much confusion over vector vs. bitmap. All of the code in this thread generates bitmap (non-vector) files - it does not preserve the vector GDI calls. To prove this to yourself, download the "EMF Parser" tool and inspect the output files: http://downloads.zdnet.com/abstract.aspx?docid=749645.

This issue has caused many developers considering anguish. Sure would be nice if Microsoft would fix this and properly support their own EMF format.

仲春光 2024-07-13 13:42:44

这是一个公共 EMF 类,用于将位图保存为 EMF,但不幸的是,不起作用..返回错误。

Public Class EMF
' This routine demonstrates how to create an Enhanced Metafile (EMF) from a
' bitmap image, contained in a PictureBox.
' You must use a PictureBox control, since the Image control doesn't support
' the hDC property, needed to create the image file.
' Draw a PictureBox on a form, and insert a supported image like Bmp,
' Jpg or Gif. Don't use a WMF or EMF image. Useful for imaging apps that need
' to save images to different formats than Bitmap.


' ========== API DECLARATIONS ==========

'Bitmap properties structure

Private Structure BITMAP
    Dim bmType As Long
    Dim bmWidth As Long
    Dim bmHeight As Long
    Dim bmWidthBytes As Long
    Dim bmPlanes As Integer
    Dim bmBitsPixel As Integer
    Dim bmBits As Long
End Structure


'Rectagle structure, needed to "build" the EMF
Private Structure RECT
    Dim Left As Long
    Dim Top As Long
    Dim Right As Long
    Dim Bottom As Long
End Structure


'API Functions for drawing graphics
Private Declare Function CreateCompatibleDC Lib "gdi32" (ByVal hdc As Long) As _
  Long
Private Declare Function SelectObject Lib "gdi32" (ByVal hdc As Long,
  ByVal hObject As Long) As Long
Private Declare Function BitBlt Lib "gdi32" (ByVal hDestDC As Long,
  ByVal X As Long, ByVal Y As Long, ByVal nWidth As Long,
  ByVal nHeight As Long, ByVal hSrcDC As Long, ByVal xSrc As Long,
  ByVal ySrc As Long, ByVal dwRop As Long) As Long
Private Declare Function DeleteDC Lib "gdi32" (ByVal hdc As Long) As Long
Private Declare Function DeleteObject Lib "gdi32" (ByVal hObject As Long) As _
  Long
Private Declare Function GetObject Lib "gdi32" Alias "GetObjectA" (ByVal _
  hObject As Long, ByVal nCount As Long, lpObject As Object) As Long
Private Declare Function StretchBlt Lib "gdi32" (ByVal hdc As Long,
  ByVal X As Long, ByVal Y As Long, ByVal nWidth As Long,
  ByVal nHeight As Long, ByVal hSrcDC As Long, ByVal xSrc As Long,
  ByVal ySrc As Long, ByVal nSrcWidth As Long, ByVal nSrcHeight As Long,
  ByVal dwRop As Long) As Long

'API Functions for creating metafiles
Private Declare Function CreateEnhMetaFile Lib "gdi32" Alias _
  "CreateEnhMetaFileA" (ByVal hdcRef As Long, ByVal lpFileName As String,
  lpRect As RECT, ByVal lpDescription As String) As Long
Private Declare Function CloseEnhMetaFile Lib "gdi32" (ByVal hdc As Long) As _
  Long
Private Declare Function DeleteEnhMetaFile Lib "gdi32" (ByVal hEmf As Long) As _
  Long
Private Declare Function SetMapMode Lib "gdi32" (ByVal hdc As Long,
  ByVal nMapMode As Long) As Long


'This Enum is needed to set the "Mapping" property for EMF images
Public Enum MMETRIC
    MM_HIMETRIC = 3
    MM_LOMETRIC = 2
    MM_LOENGLISH = 4
    MM_ISOTROPIC = 7
    MM_HIENGLISH = 5
    MM_ANISOTROPIC = 8
    MM_ADLIB = 9
End Enum

'è una costante in decimale 13369370 
'https://www.tapatalk.com/groups/visualbasicexplorer/what-s-the-difference-vbsrccopy-or-t4443.html
Public Const vbSrcCopy = &HCC0020

' ==========================================

' This function creates an EMF image.
' Parameters:
'  SourceImage: Must be a picturebox
'  FileName: full pathname for Enhanced Metafile on disk
'  Metrics: a value from MMETRIC Enum
'  Comments (optional): You can add your own comments to an Enhanced Metafile
'
' Example:
'  Dim RetVal As Long
'  ' The best way for creating an EMF image is to use the MM_ADLIB mapping mode
'  RetVal = CreateEmf(Picture1, "image1.emf", MM_ADLIB,
' "Enhanced Metafile Demonstration Usage")

Public Function CreateEmf(ByRef SourceImage As Object, ByVal FileName As String,
  ByVal Metrics As MMETRIC, Optional ByVal Comments As String = Nothing) As Long
    'Variables and types
    Dim bm As BITMAP
    Dim hdcMem As Long   'Temporary Compatible Device Context


    Dim hdc As Long     'EMF Device Context
    Dim hEmf As Long    'Will get the returned value by CloseEnhMetafile API
    Dim R As RECT      'A rectangle that will enclose the EMF image
    Dim OldScale As Integer 'Used to maintain Picturebox ScaleMode property
    Dim HoldBitmap As Long 'Keeps the bitmap onto memory

    Comments = Comments & vbNullChar 'You can add comments to Metafiles. A NULL
    ' char is needed

    GetObject(SourceImage, Len(bm), bm) 'Reads image properties and puts them
    ' in a Bitmap structure

    R.Top = SourceImage.Top       'Creates a rectangle using bitmap
    ' properties
    R.Left = SourceImage.Left
    R.Right = SourceImage.Picture.Width
    R.Bottom = SourceImage.Picture.Height

    'Sets the Picturebox Scalemode properties to Pixels.
    OldScale = SourceImage.ScaleMode
    'SourceImage.ScaleMode = vbPixels   'commanetato perché è gia tutto in pixel

    'Creates the metafile to disk reading the picturebox device context thru
    ' the GetDC Api
    'FileName is a string containing the full pathname for the image
    'R is the rectangle structure as shown before
    'Some comments are added.
    hdc = CreateEnhMetaFile(SourceImage.hdc, FileName, R, Comments)

    '...sets the mapping property
    SetMapMode(hdc, Metrics)

    'Since Bitmap and Metafile are different, a new compatible device context
    ' must be created
    'with a reference to the EMF device context
    hdcMem = CreateCompatibleDC(hdc)

    'Takes the bitmap....
    HoldBitmap = SelectObject(hdcMem, SourceImage)

    '...and copies first to intermediate device context reading data from the
    ' bitmap
    BitBlt(hdcMem, 0, 0, SourceImage.ScaleWidth, SourceImage.ScaleHeight, SourceImage.hdc, 0, 0, vbSrcCopy)
    'and then to the EMF device context
    BitBlt(hdc, 0, 0, SourceImage.ScaleWidth, SourceImage.ScaleHeight, hdcMem, 0, 0, vbSrcCopy)

    'Reassigns bitmap previous value to DC before deleting
    SelectObject(hdcMem, HoldBitmap)
    'Next step is disposing objects
    DeleteDC(hdcMem)
    DeleteObject(SelectObject(hdcMem, SourceImage))

    'Closes the new metafile
    hEmf = CloseEnhMetaFile(hdc)

    If DeleteEnhMetaFile(hEmf) = 1 Then
        CreateEmf = 0  'No errors
    Else
        CreateEmf = 1  'If an error occurred,
        ' returns 1
    End If

    'sets the PictureBox Scalemode property to the previous mode
    SourceImage.ScaleMode = OldScale
    Return CreateEmf
End Function End Class

This is a public EMF class to save bitmap as EMF, but unfortunally, don't work .. return an error.

Public Class EMF
' This routine demonstrates how to create an Enhanced Metafile (EMF) from a
' bitmap image, contained in a PictureBox.
' You must use a PictureBox control, since the Image control doesn't support
' the hDC property, needed to create the image file.
' Draw a PictureBox on a form, and insert a supported image like Bmp,
' Jpg or Gif. Don't use a WMF or EMF image. Useful for imaging apps that need
' to save images to different formats than Bitmap.


' ========== API DECLARATIONS ==========

'Bitmap properties structure

Private Structure BITMAP
    Dim bmType As Long
    Dim bmWidth As Long
    Dim bmHeight As Long
    Dim bmWidthBytes As Long
    Dim bmPlanes As Integer
    Dim bmBitsPixel As Integer
    Dim bmBits As Long
End Structure


'Rectagle structure, needed to "build" the EMF
Private Structure RECT
    Dim Left As Long
    Dim Top As Long
    Dim Right As Long
    Dim Bottom As Long
End Structure


'API Functions for drawing graphics
Private Declare Function CreateCompatibleDC Lib "gdi32" (ByVal hdc As Long) As _
  Long
Private Declare Function SelectObject Lib "gdi32" (ByVal hdc As Long,
  ByVal hObject As Long) As Long
Private Declare Function BitBlt Lib "gdi32" (ByVal hDestDC As Long,
  ByVal X As Long, ByVal Y As Long, ByVal nWidth As Long,
  ByVal nHeight As Long, ByVal hSrcDC As Long, ByVal xSrc As Long,
  ByVal ySrc As Long, ByVal dwRop As Long) As Long
Private Declare Function DeleteDC Lib "gdi32" (ByVal hdc As Long) As Long
Private Declare Function DeleteObject Lib "gdi32" (ByVal hObject As Long) As _
  Long
Private Declare Function GetObject Lib "gdi32" Alias "GetObjectA" (ByVal _
  hObject As Long, ByVal nCount As Long, lpObject As Object) As Long
Private Declare Function StretchBlt Lib "gdi32" (ByVal hdc As Long,
  ByVal X As Long, ByVal Y As Long, ByVal nWidth As Long,
  ByVal nHeight As Long, ByVal hSrcDC As Long, ByVal xSrc As Long,
  ByVal ySrc As Long, ByVal nSrcWidth As Long, ByVal nSrcHeight As Long,
  ByVal dwRop As Long) As Long

'API Functions for creating metafiles
Private Declare Function CreateEnhMetaFile Lib "gdi32" Alias _
  "CreateEnhMetaFileA" (ByVal hdcRef As Long, ByVal lpFileName As String,
  lpRect As RECT, ByVal lpDescription As String) As Long
Private Declare Function CloseEnhMetaFile Lib "gdi32" (ByVal hdc As Long) As _
  Long
Private Declare Function DeleteEnhMetaFile Lib "gdi32" (ByVal hEmf As Long) As _
  Long
Private Declare Function SetMapMode Lib "gdi32" (ByVal hdc As Long,
  ByVal nMapMode As Long) As Long


'This Enum is needed to set the "Mapping" property for EMF images
Public Enum MMETRIC
    MM_HIMETRIC = 3
    MM_LOMETRIC = 2
    MM_LOENGLISH = 4
    MM_ISOTROPIC = 7
    MM_HIENGLISH = 5
    MM_ANISOTROPIC = 8
    MM_ADLIB = 9
End Enum

'è una costante in decimale 13369370 
'https://www.tapatalk.com/groups/visualbasicexplorer/what-s-the-difference-vbsrccopy-or-t4443.html
Public Const vbSrcCopy = &HCC0020

' ==========================================

' This function creates an EMF image.
' Parameters:
'  SourceImage: Must be a picturebox
'  FileName: full pathname for Enhanced Metafile on disk
'  Metrics: a value from MMETRIC Enum
'  Comments (optional): You can add your own comments to an Enhanced Metafile
'
' Example:
'  Dim RetVal As Long
'  ' The best way for creating an EMF image is to use the MM_ADLIB mapping mode
'  RetVal = CreateEmf(Picture1, "image1.emf", MM_ADLIB,
' "Enhanced Metafile Demonstration Usage")

Public Function CreateEmf(ByRef SourceImage As Object, ByVal FileName As String,
  ByVal Metrics As MMETRIC, Optional ByVal Comments As String = Nothing) As Long
    'Variables and types
    Dim bm As BITMAP
    Dim hdcMem As Long   'Temporary Compatible Device Context


    Dim hdc As Long     'EMF Device Context
    Dim hEmf As Long    'Will get the returned value by CloseEnhMetafile API
    Dim R As RECT      'A rectangle that will enclose the EMF image
    Dim OldScale As Integer 'Used to maintain Picturebox ScaleMode property
    Dim HoldBitmap As Long 'Keeps the bitmap onto memory

    Comments = Comments & vbNullChar 'You can add comments to Metafiles. A NULL
    ' char is needed

    GetObject(SourceImage, Len(bm), bm) 'Reads image properties and puts them
    ' in a Bitmap structure

    R.Top = SourceImage.Top       'Creates a rectangle using bitmap
    ' properties
    R.Left = SourceImage.Left
    R.Right = SourceImage.Picture.Width
    R.Bottom = SourceImage.Picture.Height

    'Sets the Picturebox Scalemode properties to Pixels.
    OldScale = SourceImage.ScaleMode
    'SourceImage.ScaleMode = vbPixels   'commanetato perché è gia tutto in pixel

    'Creates the metafile to disk reading the picturebox device context thru
    ' the GetDC Api
    'FileName is a string containing the full pathname for the image
    'R is the rectangle structure as shown before
    'Some comments are added.
    hdc = CreateEnhMetaFile(SourceImage.hdc, FileName, R, Comments)

    '...sets the mapping property
    SetMapMode(hdc, Metrics)

    'Since Bitmap and Metafile are different, a new compatible device context
    ' must be created
    'with a reference to the EMF device context
    hdcMem = CreateCompatibleDC(hdc)

    'Takes the bitmap....
    HoldBitmap = SelectObject(hdcMem, SourceImage)

    '...and copies first to intermediate device context reading data from the
    ' bitmap
    BitBlt(hdcMem, 0, 0, SourceImage.ScaleWidth, SourceImage.ScaleHeight, SourceImage.hdc, 0, 0, vbSrcCopy)
    'and then to the EMF device context
    BitBlt(hdc, 0, 0, SourceImage.ScaleWidth, SourceImage.ScaleHeight, hdcMem, 0, 0, vbSrcCopy)

    'Reassigns bitmap previous value to DC before deleting
    SelectObject(hdcMem, HoldBitmap)
    'Next step is disposing objects
    DeleteDC(hdcMem)
    DeleteObject(SelectObject(hdcMem, SourceImage))

    'Closes the new metafile
    hEmf = CloseEnhMetaFile(hdc)

    If DeleteEnhMetaFile(hEmf) = 1 Then
        CreateEmf = 0  'No errors
    Else
        CreateEmf = 1  'If an error occurred,
        ' returns 1
    End If

    'sets the PictureBox Scalemode property to the previous mode
    SourceImage.ScaleMode = OldScale
    Return CreateEmf
End Function End Class
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文