Microsoft Office Word、Excel、Power Pointなどで作成した図をクリップボードにコピーした時、このデータを拡張メタファイル形式として以下のような方法でデータを取得しようとしてもうまくいきません。
'Imports System.Drawing 'Imports System.Windows.Forms Dim data As IDataObject = Clipboard.GetDataObject() 'クリップボードにデータがあるか調べる If Not data Is Nothing Then '拡張メタファイル形式でデータを取得する PictureBox1.Image = DirectCast(data.GetData(DataFormats.EnhancedMetafile), Image) End If
//using System.Drawing; //using System.Windows.Forms; IDataObject data = Clipboard.GetDataObject(); //クリップボードにデータがあるか調べる if (data != null) { //拡張メタファイル形式でデータを取得する PictureBox1.Image = (Image)data.GetData(DataFormats.EnhancedMetafile); }
.NET Frameworkの機能だけでは残念ながらクリップボードのメタファイルデータは取得できません(.NET Framework 1.1現在)。
しかし、Microsoft Officeからクリップボードにコピーされたデータは、EnhancedMetafile形式の他に様々な形式に関連付けられており、それらの形式で取得することはできます。
Microsoft Office 2007以降であれば、Bitmap形式で取得できますので、「クリップボードの画像を表示する」で紹介している方法で可能です。
Microsoft Office 2003以前ではこの方法は無理です。例えばOffice 2003のクリップボードのデータは、Office Drawing Shape Format、MetaFilePict、PNG+Office Art、JFIF+Office Art、GIF+Office Art、PNG、JFIF、GIF、ActiveClipboard、HTML Format形式に関連付けられています。このうち、HTML Format以外はMemoryStreamオブジェクトとしてデータを取得できますので、Microsoft Officeでコピーした図を、PNG形式等でデータを取得することが可能です。
次のサンプルでは、フォームにピクチャボックス"PictureBox1"があり、このPictureBox1にクリップボードにコピーされた図を表示しています。
'Imports System.Drawing 'Imports System.Windows.Forms Dim data As IDataObject = Clipboard.GetDataObject() 'クリップボードにデータがあるか調べる If data IsNot Nothing Then 'PNG形式でデータをMemoryStreamとして取得する Dim ms As System.IO.MemoryStream = _ DirectCast(data.GetData("PNG"), System.IO.MemoryStream) If Not ms Is Nothing Then 'Imageオブジェクトに変換する PictureBox1.Image = Image.FromStream(ms) End If End If
//using System.Drawing; //using System.Windows.Forms; IDataObject data = Clipboard.GetDataObject(); //クリップボードにデータがあるか調べる if (data != null) { //PNG形式でデータをMemoryStreamとして取得する System.IO.MemoryStream ms = (System.IO.MemoryStream)data.GetData("PNG"); if (ms != null) { //Imageオブジェクトに変換する PictureBox1.Image = Image.FromStream(ms); } }
"PNG"以外の形式を試してみたところ、上記のコードで"PNG"の部分を以下の文字列に変更した場合にのみ成功するようです。
"PNG+Office Art"
"JFIF+Office Art"
"GIF+Office Art"
"JFIF"
"GIF"
クリップボードのメタファイルデータをメタファイルとして取得するには、Win32 APIを使うしかないようです(.NET Framework 1.1現在)。この方法は、「Windows Forms FAQ - 37.5 How can I programmatically create a bitmap?」で紹介されています。
以下にWin32 APIを使用してクリップボードのメタファイルデータを取得するコードを紹介します。
'Imports System.Runtime.InteropServices Const CF_ENHMETAFILE As Integer = 14 <DllImport("user32.dll")> _ Private Shared Function OpenClipboard( _ ByVal hWndNewOwner As IntPtr) As Boolean End Function <DllImport("user32.dll")> _ Private Shared Function IsClipboardFormatAvailable( _ ByVal wFormat As Integer) As Integer End Function <DllImport("user32.dll")> _ Private Shared Function GetClipboardData( _ ByVal wFormat As Integer) As IntPtr End Function <DllImport("user32.dll")> _ Private Shared Function CloseClipboard() As Integer End Function ''' <summary> ''' クリップボードのメタファイル形式のデータを取得する ''' </summary> ''' <param name="hWnd">ウィンドウのハンドル</param> ''' <returns>取得したデータ</returns> Public Shared Function GetEnhMetafileOnClipboard( _ ByVal hWnd As IntPtr) As System.Drawing.Imaging.Metafile Dim meta As System.Drawing.Imaging.Metafile = Nothing If OpenClipboard(hWnd) Then Try If IsClipboardFormatAvailable(CF_ENHMETAFILE) <> 0 Then Dim hmeta As IntPtr = GetClipboardData(CF_ENHMETAFILE) meta = New System.Drawing.Imaging.Metafile(hmeta, True) End If Finally CloseClipboard() End Try End If Return meta End Function
//using System.Runtime.InteropServices; private const int CF_ENHMETAFILE = 14; [DllImport("user32.dll")] private static extern bool OpenClipboard(IntPtr hWndNewOwner); [DllImport("user32.dll")] private static extern int IsClipboardFormatAvailable(int wFormat); [DllImport("user32.dll")] private static extern IntPtr GetClipboardData(int wFormat); [DllImport("user32.dll")] private static extern int CloseClipboard(); /// <summary> /// クリップボードのメタファイル形式のデータを取得する /// </summary> /// <param name="hWnd">ウィンドウのハンドル</param> /// <returns>取得したデータ</returns> public static System.Drawing.Imaging.Metafile GetEnhMetafileOnClipboard(IntPtr hWnd) { System.Drawing.Imaging.Metafile meta = null; if (OpenClipboard(hWnd)) { try { if (IsClipboardFormatAvailable(CF_ENHMETAFILE) != 0) { IntPtr hmeta = GetClipboardData(CF_ENHMETAFILE); meta = new System.Drawing.Imaging.Metafile(hmeta, true); } } finally { CloseClipboard(); } } return meta; }
このGetEnhMetafileOnClipboardメソッドを使うには、C#では
PictureBox1.Image = GetEnhMetafileOnClipboard(this.Handle);
VB.NETでは
PictureBox1.Image = GetEnhMetafileOnClipboard(Me.Handle)
のようにします。
(この記事は、「.NETプログラミング研究 第38号」で紹介したものを基にしています。)