EMFファイルをクリップボードにコピー

いつか理想のドローソフトを作りたいっと思いつつ、意思の弱さゆえに開発を進められていないのですが、仕事の書類などでMS Officeで図形を駆使して図を描くたびに、作りたいと言う思いが再燃します。
そのたびに関連することを調べ始めまして、今回もその一環です。

 

理想のドローソフトに無くてはならない機能が、ベクタ形式のまま簡単にMS Office Word等に図を貼り付ける機能。すなわち、EMF(拡張メタファイル)形式でクリップボードにコピーする機能です。

追記:2006年以降のMS OfficeもOpen Officeもsvgのコピーに対応してるんだって。EMFはオワコンって事か。。。

ソフトはPythonで作る予定なので、Pythonでの方法を考えます。といってもWindowsのAPIをバインドするだけなんですけど。

 

書いたソースがこちら。結果エラーを吐きます。

ソース(Python):結果→エラー

import win32clipboard

f = open('test.emf','rb')
data = f.read()
f.close()

clip_type = win32clipboard.CF_ENHMETAFILE

win32clipboard.OpenClipboard()
win32clipboard.EmptyClipboard()
win32clipboard.SetClipboardData(clip_type, data)
win32clipboard.CloseClipboard()

エラー
pywintypes.error: (6, ‘SetClipboardData’, ‘The handle is invalid.’)

 

SetClipboardDataの第2引数は、ハンドルまたはバッファオブジェクトで、bytesオブジェクトは大丈夫だと思うんだけど、型が違うのかな?

 

EMF形式でしかもクリップボードの方にセットすることに関する情報が凄く少なくて途方にくれましたが、同じエラーで悩む記事は結構ありました。なかにはバグじゃないかと言う書き込みもチラホラ。

 

CF_ENHMETAFILE SetClipboardData ‘The handle is invalid’
https://mail.python.org/pipermail/python-win32/2011-August/011723.html

Pythonでクリップボードの画像をファイルに保存する
http://d.hatena.ne.jp/himazublog/20080629/1214703203

C#からClipboardを操作する
http://krdlab.hatenablog.com/entry/20070311/1173603960

 

まぁ、なんかクリップボードの仕様は複雑なところがあるみたく、Pythonだとはまりそうな感じがしたので、EMFをクリップボードにコピーするところだけは、C#でやってみようと思いました。Windowsに依存するところは.NETが最も相性が良いはずだ。

 

結果、色々な情報に翻弄されて、えらい時間かかったのですが、EMF形式をクリップボードにセットすることができました。

 

ソース(C#)

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

public class Program
{
    private const int CF_ENHMETAFILE = 14;
    [DllImport("user32.dll")]
    private static extern bool OpenClipboard(IntPtr hWndNewOwner);
    [DllImport("user32.dll")]
    private static extern bool EmptyClipboard();
    [DllImport("user32.dll")]
    private static extern IntPtr SetClipboardData(int uFormat, IntPtr hWnd);
    [DllImport("user32.dll")]
    private static extern int CloseClipboard();
    
    private static void Main()
    {
        Metafile metaFile = new Metafile("test.emf");
        IntPtr hMetaFile = metaFile.GetHenhmetafile();
        
        OpenClipboard(IntPtr.Zero);
        EmptyClipboard();
        SetClipboardData(CF_ENHMETAFILE,hMetaFile);
        CloseClipboard();
      
        Console.WriteLine("Set test.emf to clipboard!");
    }
}

終わってみれば、なんとシンプル。最初に下記のサイトに行き着いていれば・・・orz。

 

メタファイルの生成について
http://bbs.wankuma.com/index.cgi?mode=al2&namber=24261&KLOG=45

 

pyemfで出力したemfをWordに貼り付けられるのを確認。どうせWindowsに依存するんだし、C#で作成したexeを使うことで目的は果たせそうだな、っと掴んだところで今回は満足しました。いや、満足せずにソフト作れよ。

Updated: 2019年1月30日 — 08:29

コメントを残す

メールアドレスが公開されることはありません。 が付いている欄は必須項目です