PRB: Metarchivos en el Portapapeles no son visibles para todas las aplicaciones

En este artículo se refiere a los siguientes espacios de nombres de biblioteca de clases de Microsoft.NET Framework:
  • System.Drawing.Imaging
  • System.Runtime.InteropServices

Síntomas

Metarchivos de aplicaciones .NET agregan al Portapapeles no son visibles para otras aplicaciones.

Causa

Este problema se produce porque el.NET Framework utiliza un nuevo formato de Portapapeles cuando agrega metarchivos en el Portapapeles. Otras aplicaciones, como Microsoft Word o el sistema operativo no son conscientes de este nuevo formato y, por tanto, no pueden pegar o mostrar la imagen.

Solución

Para agregar un metarchivo en el Portapapeles para que sea visible para otras aplicaciones, debe utilizar el formato CF_ENHMETAFILE. Soporte para este formato se proporciona a través de la clase del objeto DataObject con el método DataFormats.EnhancedMetafile . Desgraciadamente, las limitaciones en la implementación actual de la de.NET Framework impedir esto una solución viable. Por tanto, debe obtener interoperabilidad con Win32 Portapapeles interfaces application programming interfaces (API) para resolver este problema.

Los ejemplos de código siguientes muestran cómo agregar un metarchivo en el Portapapeles para que sea visible para otras aplicaciones.

Ejemplo de Microsoft Visual Basic .NET

Imports System.Drawing.ImagingImports System.Runtime.InteropServices

Public Class ClipboardMetafileHelper
<DllImport("user32.dll", EntryPoint:="OpenClipboard", _
SetLastError:=True, ExactSpelling:=True, CallingConvention:=CallingConvention.StdCall)> _
Public Shared Function OpenClipboard(ByVal hWnd As IntPtr) As Boolean
End Function
<DllImport("user32.dll", EntryPoint:="EmptyClipboard", _
SetLastError:=True, ExactSpelling:=True, CallingConvention:=CallingConvention.StdCall)> _
Public Shared Function EmptyClipboard() As Boolean
End Function
<DllImport("user32.dll", EntryPoint:="SetClipboardData", _
SetLastError:=True, ExactSpelling:=True, CallingConvention:=CallingConvention.StdCall)> _
Public Shared Function SetClipboardData(ByVal uFormat As Integer, ByVal hWnd As IntPtr) As IntPtr
End Function
<DllImport("user32.dll", EntryPoint:="CloseClipboard", _
SetLastError:=True, ExactSpelling:=True, CallingConvention:=CallingConvention.StdCall)> _
Public Shared Function CloseClipboard() As Boolean
End Function
<DllImport("gdi32.dll", EntryPoint:="CopyEnhMetaFileA", _
SetLastError:=True, ExactSpelling:=True, CallingConvention:=CallingConvention.StdCall)> _
Public Shared Function CopyEnhMetaFile(ByVal hemfSrc As IntPtr, ByVal hNULL As IntPtr) As IntPtr
End Function
<DllImport("gdi32.dll", EntryPoint:="DeleteEnhMetaFile", _
SetLastError:=True, ExactSpelling:=True, CallingConvention:=CallingConvention.StdCall)> _
Public Shared Function DeleteEnhMetaFile(ByVal hemfSrc As IntPtr) As Boolean
End Function

' Metafile mf is set to a state that is not valid inside this function.
Public Shared Function PutEnhMetafileOnClipboard(ByVal hWnd As IntPtr, ByVal mf As Metafile) As Boolean
Dim bResult As New Boolean()
bResult = False
Dim hEMF, hEMF2 As IntPtr
hEMF = mf.GetHenhmetafile() ' invalidates mf
If Not hEMF.Equals(New IntPtr(0)) Then
hEMF2 = CopyEnhMetaFile(hEMF, New IntPtr(0))
If Not hEMF2.Equals(New IntPtr(0)) Then
If OpenClipboard(hWnd) Then
If EmptyClipboard() Then
Dim hRes As IntPtr
hRes = SetClipboardData(14, hEMF2) ' 14 == CF_ENHMETAFILE
bResult = hRes.Equals(hEMF2)
CloseClipboard()
End If
End If
End If
DeleteEnhMetaFile(hEMF)
End If
Return bResult
End Function

End Class


'You can call this function with code that is similar to the following code:
Dim mf As New Metafile("filename.emf")
ClipboardMetafileHelper.PutEnhMetafileOnClipboard(me.Handle,mf)

Ejemplo de Microsoft Visual C#.

using System.Drawing.Imaging;using System.Runtime.InteropServices;

public 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, IntPtr hNULL);
[DllImport("gdi32.dll")]
static extern bool DeleteEnhMetaFile(IntPtr hemf);

// Metafile mf is set to a state that is not valid inside this function.
static public bool PutEnhMetafileOnClipboard( IntPtr hWnd, Metafile mf )
{
bool bResult = false;
IntPtr hEMF, hEMF2;
hEMF = mf.GetHenhmetafile(); // invalidates mf
if( ! hEMF.Equals( new IntPtr(0) ) )
{
hEMF2 = CopyEnhMetaFile( hEMF, new IntPtr(0) );
if( ! hEMF2.Equals( new IntPtr(0) ) )
{
if( OpenClipboard( hWnd ) )
{
if( EmptyClipboard() )
{
IntPtr hRes = SetClipboardData( 14 /*CF_ENHMETAFILE*/, hEMF2 );
bResult = hRes.Equals( hEMF2 );
CloseClipboard();
}
}
}
DeleteEnhMetaFile( hEMF );
}
return bResult;
}
}

//You can call this function with code that is similar to the following code:
Metafile mf = new Metafile( "filename.emf" );
ClipboardMetafileHelper.PutEnhMetafileOnClipboard(this.Handle, mf );

Propiedades

Id. de artículo: 323530 - Última revisión: 17 ene. 2017 - Revisión: 1

Comentarios