空談録

http://artfulplace.net/blogs/ からひっこしつつ

Windows Store Appsでクリップボードから画像を取得したい

ブログ書く機会が減っているのはプログラミングをしていないからです!(きっぱり)

なんとなく気になったところもあったのでストアアプリでクリップボードから画像を取得するコードについて調べていきます
そして叫ばれるオッフィース先生へのもげもげ

とりあえずコードから見ていきましょう

クリップボードからの取得

これはとても簡単で、
Clipboard class - Windows app development (Windows.ApplicationModel.DataTransfer Namespace) のGetContent()メソッドを呼ぶと
DataPackageView class - Windows app development
(Windows.ApplicationModel.DataTransfer Namespace) が取れます。
このDataPackageViewの各メソッドを呼ぶことでクリップボードのデータを取得できます

たとえばクリップボード内の文章であればDataPackageView.GetTextAsync()でとれます
今回の目的の画像であればDataPackageView.GetBitmapAsync()です

適当に書くとこんな感じ

var b = await Clipboard.GetContent().GetBitmapAsync();

これで画像のStreamにアクセスできるRandomAccessStreamReferenceが取れます
ただし画像が含まれていない場合例外が出てしまいます

クリップボード内のデータといっても相当な種類があるわけなのでそれを判別する必要が先にあります
そこでDataPackageView.AvailableFormatsプロパティを使用します

DataPackageView.AvailableFormats

これはクリップボード内のデータの対応するすべてのフォーマットをIReadOnlyListで返してくれるプロパティです
たとえばVisual Studioからテキストをコピーした状態でプロパティを出すとこんな感じです

AnsiText, Rich Text Format, HTML Format, Text

IReadOnlyListのままだとどうにもできないので各要素を", "で結合しています
もうちょっと見てみましょう。メモ帳からだとこんな感じです

Text, Locale, AnsiText, OEMText

AnsiTextとTextが両方に含まれています。とりあえず文字列がほしい時はTextが含まれてるときに取得しとけばいいと思います

そしたら本題の画像に行きましょう。とりあえずPrintScreenで取得するとこんなんです

Bitmap, DeviceIndependentBitmap, DeviceIndependentBitmapV5

よくわからないフォーマットが並んでますがBitmapは一番わかりやすいし判定に使えそうですね
次にFirefoxで画像コピー

text/html, HTML Format, text/_moz_htmlinfo, text/_moz_htmlcontext, application/x-moz-nativeimage, DeviceIndependentBitmapV5, Bitmap, DeviceIndependentBitmap

また変なのが随分と混じってますがとりあえずBitmapでよさそうです

これで画像のときはAvailableFormatsにBitmapがあるとき画像として取得してTextがあるときは文字列として取得すればよさそうですね、めでたしめでたし

BitmapとTextを含むパターンの場合

これで終わらないのが素晴らしい点です

いくつかのアプリケーションはコピーした内容によるのかは知りませんがTextとBitmapを含むパターンが存在します
とても幅広く活用できるというか迷惑というかはお任せします

Internet Explorerで画像をコピーした場合こんな感じです

UntrustedDragDrop, msSourceUrl, FileDrop, Shell IDList Array, UniformResourceLocatorW, DeviceIndependentBitmap, Bitmap, HTML Format, Text, AnsiText

なんとも素晴らしいですね、検証用に作ったテスト用アプリでみるとこんな感じです
https://portalvhdsrp3qt9v47nzbn.blob.core.windows.net/publicphoto/fspic140806-5.png

URLもついでに入れるだけの素晴らしさ
っていうよりはHTML Formatでタグ切ってるだけでしょうけども…

IEはまだいいほうでmsResourceUrlで判定可能です
たぶんテキストでほしい人はいないと思うのでmsResourceUrlを含んでたらBitmapにするのがよさげ
ここからは呪われている気すらしますが頑張りましょう

続いてExcelです。一個だけセルを選択してコピーします

EnhancedMetafile, Bitmap, Biff12, Biff8, Biff5, SymbolicLink, DataInterchangeFormat, XML Spreadsheet, HTML Format, Text, AnsiText, Csv, Hyperlink, Rich Text Format, Embed Source, Object, Descriptor, Link Source Descriptor, Link, DspText

どんだけ利用可能にしてるんですかね……
とりあえずXML Spreadsheetで切る…?のがいいんでしょうか
ここでは結論付けないで先に進みましょう

PowerPointのテキストを選択してコピー

Preferred DropEffect, InShellDragLoop, Art::Text ClipFormat, HTML Format, Rich Text Format, Text, PNG, JFIF, GIF, Bitmap, EnhancedMetafile, PowerPoint 12.0 Internal Theme, PowerPoint 12.0 Internal Color Scheme

テキストですよね…ねえ…テキストですよね

ちなみにテキストじゃないものをコピーするとTextは混じりません(スライドをコピーしたとき)

Preferred DropEffect, InShellDragLoop, PowerPoint 12.0 Internal Slides, ActiveClipBoard, PowerPoint 14.0 Slides Package, Embedded Object, Link Source, Object Descriptor, Link Source Descriptor, PNG, JFIF, GIF, Bitmap, EnhancedMetafile, PowerPoint 12.0 Internal Theme, PowerPoint 12.0 Internal Color Scheme

Excelのと見比べるとEnhancedMetafileが切る対象としてはよさそうです
EnhancedMetafileの使用用途的には何か違う気もしますが一つ一つ切るのはさすがに…

OneNoteのテキストを選択してコピーがこれ

OneNote 2010 Internal, HTML Format, Text, AnsiText, EnhancedMetafile, DeviceIndependentBitmap, Bitmap

これもEnhancedMetafileがあるのでたぶんこれでOffice系は切れるはずですね

ちなみにWordはBitmapが混じらないです

あとこれ以外のOffice製品使わないのであとはご自分で確認していただけると…


ということでうちのClipboardから画像取得する仕組みがOffice検知しまくる原因も突き止めたかっただけの記事でした
同時に入れる系はかなりテロに近いので扱いには注意が必要ですね

他にもBitmapとTextが両方入ってるのありそうですがまあそうそうないでしょうし平和にいきましょう

ブログ書くような事柄が最近ないので次いつ書くのやら…
暇だったら謎言語についてでも書きたい

この辺で