Minecraft Forge 1.12.2でのコードになりますが、たぶん他のバージョンでも問題ない。たぶん。
また、Windows 10 64bit でしか動作検証していません。もし他のOSで動かなかったらゴメンよ。
まずスクリーンショットが撮影されたことを検知しないといけない。
Forgeでは
一つは
もう一つは
また、このイベントはキャンセルできる。キャンセルするとスクリーンショットは保存されない。
次に、クリップボードに保存するには。
まず、
そして、
でも、この
(コダワリの強いやつだ
ですが、またDataFlavorという未知のクラスが出てきてしまった。
またまたドキュメントより、
画像ならMIMEタイプは
で、結局のところどう実装すればいいのかというと、
このようにすればJavaがうまいことやってくれて動く。(よくわかってない
あとは、
こんな感じ。
これにて一件落着(?)
スクリーンショットが
また、Windows 10 64bit でしか動作検証していません。もし他のOSで動かなかったらゴメンよ。
まずスクリーンショットが撮影されたことを検知しないといけない。
Forgeでは
ScreenshotEvent
が用意されてる。これはスクリーンショットが保存される直前に発火される。ScreenshotEvent
には二つのデータが与えられる。一つは
java.awt.image.BufferedImage
で、スクリーンショットの画像情報。もう一つは
java.io.File
で、スクリーンショットの保存先を決める情報。これはあとから変更できる。また、このイベントはキャンセルできる。キャンセルするとスクリーンショットは保存されない。
次に、クリップボードに保存するには。
まず、
Toolkit.getDefaultToolkit().getSystemClipboard
でクリップボードを取得する。そして、
Clipboard#setContents()
を呼び出すことでクリップボードにデータを書き込む訳だ。でも、この
Clipboard#setContents()
の受け取る引数が少し厄介で java.awt.datatransfer.Transferable
を実装したクラスでないとダメらしい。(コダワリの強いやつだ
Transferable
とはドキュメントより、転送操作のためのデータを提供するために使用されるクラスのインタフェースを定義します。
BufferedImage
は Transferable
の実装ではないのでラッパーを自前で用意せにゃならん。
Java:
public interface Transferable {
public DataFlavor[] getTransferDataFlavors();
public boolean isDataFlavorSupported(DataFlavor flavor);
public Object getTransferData(DataFlavor flavor) throws UnsupportedFlavorException, IOException;
}
Transferable
はこの3つのメソッドを実装すればよいので苦ではない。ですが、またDataFlavorという未知のクラスが出てきてしまった。
またまたドキュメントより、
とは言われてもクリップボードの詳しい仕組みは知らないのであまりピンと来ない。MIMEタイプや表現クラスが格納されるらしい。DataFlavor は、データに関するメタ情報を提供します。DataFlavor は通常、クリップボード上のデータにアクセスしたり、ドラッグ&ドロップ操作中にデータにアクセスしたりするために使用されます。
画像ならMIMEタイプは
image/x-java-image
、表現クラスは java.awt.Image
となる。で、結局のところどう実装すればいいのかというと、
Java:
static class ImageWrapper implements Transferable {
//転送したい画像
private BufferedImage image;
//データの種類(配列なのは複数指定するため。一つしか使用しないので特に気にしない)
private DataFlavor[] flavor;
public ImageWrapper(BufferedImage image) {
this.image = image;
//DataFlavor.imageFlavorはその名の通り画像データ用。
this.flavor = new DataFlavor[] { DataFlavor.imageFlavor };
}
@Override
public DataFlavor[] getTransferDataFlavors() {
return flavor;
}
//DataFlavor#equalsではMIMEタイプや表現クラスが同じかどうか調べてる
@Override
public boolean isDataFlavorSupported(DataFlavor flavor) {
return this.flavor[0].equals(flavor);
}
@Override
public Object getTransferData(DataFlavor flavor) throws UnsupportedFlavorException, IOException {
if (!this.isDataFlavorSupported(flavor))
throw new UnsupportedFlavorException(flavor);
return image;
}
}
このようにすればJavaがうまいことやってくれて動く。(よくわかってない
あとは、
new ImageWrapper(image);
で生成したインスタンスを Clipboard#setContents()
の引数に与えるだけ。こんな感じ。
Java:
@SubscribeEvent
public void onScreenshot(ScreenshotEvent event) {
Clipboard clipboard = Toolkit.getDefaultTookit().getSystemClipboard();
ImageWrapper wrapper = new ImageWrapper(event.getImage());
clipboard.setContents(wrapper, null); //ClipboardOwnerはnullでも大丈夫
}
これにて一件落着(?)
スクリーンショットが
Ctrl + V
でTwitterや画像編集ソフトに一発でペーストできるようになった!