2018年6月6日水曜日

VB 今更 クリップボード

普段から 大変 お世話になっている クリップボード!。
でも、 自分のプログラムに その機能を盛り込むケースは少ない気もします。
勿論、フレームワークが標準でサポートしてくれる機能は 有益! ですが ね。
そして、この機能は 送り手 受け手 共に、その考え方が滲んでしまう のです。


ソフト間でデータを通信する有効な手段が、ドラッグドロップと並ぶ クリップボード ですね。
大活躍です。  有効活用しないのは 損 です。

でも、正直な処、色々なソフトを使えば使う程、
その 実装内容 に 違いがある事に気付きます。
クリップボードに送り出してくれる その内容 です。

文字や画像での利用が一般的とは思いますが、
そこでも、
画像で透明を扱えるか否か、 とか、
装飾加工した文字列を、 とか、
ファイル文字列が欲しい!、 とか、
ファイルそのものを複製したいのに、 とか、
要求は尽きません。

でも、 ソフトやアプリの考え方ひとつで、 それは 儚い望み に蹴落とされてしまいます。
そんな機能は うちのソフトには 要求されていないから ... そんな提供側の 吐き台詞 が聞こえて来そうです。

ドラッグドロップと同じ様に、クリップボードが扱う 形式 には 様々なもの があります。
更に、独自の実装を加える事も可能になっています。


先に上げた例の 透明画像 もそうです。

クリップボードの機能は、大昔からあって、高機能化が進んだソフトの提供する全ての内容をコピー出来る訳ではありません。
その原則は、 画面上で表示されている 基本的な内容 を扱う なのでしょう。
高機能が必要なら、そのファイル自体をコピーして、加工すれば良い訳ですからね。

ですから、送り出しても、受け側の大抵のソフトがサポートしないかも知れない部分は扱わない! のです。
文字の加飾も 画像の透明度も その様な位置付けが一般的なのだと思います。
汎用的なソフト間での 遣り取り になるのが 普通 です。

そして、多くの実装では、何がしかのものを クリップボードに送れば、其処は、そのデータで置き換わります。
上書きモードですね。
勿論、 履歴的に扱えるソフトもありますし、種類別に管理するものもあります。



前置きはこれ位にして ... 。   (何時も長いねぇ~。 X( 。).

まぁ、一様、普通の書き方で、画像をクリップボードに転送するものを書いて見ました。

透明部分を含む .png を用意してこれをクリップボードに入れたり出したりしましょう。
どんな変化が現れるか!。


透明背景に 60% 不透明の Test の文字 と 普通の png の文字からなる .png ファイル を、
Content として Project に持たせ、それを使います。
画面右下の PictureBox の 後部背景画像 桝目 の中の 文字 が 実際のファイルの内容 です。
これを、右上側のボタンで クリップボードに送り、
左側のボタンで取り出します。  その結果が、左下側の PictureBox に表示されています。
ふたつの画面の、 左が ごく普通の 方法、 右が 今回ご説明する 方法 、です。

普通に ファイルから image を生成し、クリップボードに送ると、
透明背景は 自分(プログラム)の 背景と重ねられ、結局、透明部分の無いデータしか、呼び戻せません。
これに対して、
特殊な方法で、データを定義した上で、クリップボードに送ると、 元を再現します。
そう、 透明部分を活かす PNG 形式 で 転送したのです。

透明度を情報に持つ画像を クリップボード 経由すると、
この様な事が起こります。

また、普通に、 SetData すると、 置換 になって、 データ種類を問わず、書き換えられてしまいます。
複数混在の為には、 ひと纏めにしたデータを 1回で転送する 必要があります。

画像2種類とファイル名とファイルそのもの をパックして 送る 事も 可能 です。
その結果は、
System.String
UnicodeText
Text
FileDrop
FileNameW
FileName
PNG
System.Drawing.Bitmap
Bitmap
これだけの種類のものにアクセスが可能になる訳です。
勿論、 取り出す側がどれを選択するかは、 それ(取り出す側)に委ねられている訳ですが ... 。


では、このコードの一部分を。

先ずは、PNG での 送り込み。
        Dim ms As New System.IO.MemoryStream
        Dim img As Image = Image.FromFile(strFile)
        Dim dataobject As IDataObject = New DataObject()
        img.Save(ms, System.Drawing.Imaging.ImageFormat.Png)
        dataobject.SetData("PNG", False, ms)
        'dataobject.SetData("PNG", True, ms)     'Can Not Get Both
        Clipboard.SetDataObject(dataobject)

次は、PNG での受け取り。  Form 前提で PictureBox1 へ。.
        Me.PictureBox1.Image = Nothing

        Dim png_Object As Object = Nothing
        Dim ms As New System.IO.MemoryStream

        If Clipboard.ContainsData("PNG") Then
            png_Object = Clipboard.GetData("PNG")
            If TypeName(png_Object) = "MemoryStream" Then
                ms = png_Object
                Me.PictureBox1.Image = Image.FromStream(ms) '
            End If
        End If

そして、現在のクリップボードに格納してあるデータの種類取得。  改行区切りの文字列として。.
         Dim sb As New System.Text.StringBuilder
        sb.Append("Existing Data Types  On Clipboard")
        sb.Append(vbCrLf)

        Dim data As IDataObject = Clipboard.GetDataObject()
        ' Note
        '        ten times in 100-millisecond intervals, and throws an ExternalException
        '
        If Not data Is Nothing Then
            For Each fmt As String In data.GetFormats()
                sb.Append(vbCrLf)
                sb.Append(fmt)
            Next
        End If

        Dim sbText As String = sb.ToString    'Reaults : Data Types In Clipboard

最後に、複合形式での 送り込み 例 。
        Dim data As IDataObject = New DataObject()
        'Bitmap
        Dim bmp As New Bitmap(strFile)
        data.SetData(DataFormats.Bitmap, bmp)
        'PNG
        Dim ms As New System.IO.MemoryStream
        Dim img As Image = Image.FromFile(strFile)
        img.Save(ms, System.Drawing.Imaging.ImageFormat.Png)
        data.SetData("PNG", False, ms)
        'Text
        data.SetData(DataFormats.Text, strFile)
        'FileDrop
         Dim fileFullPath As String = IO.Path.GetFullPath(strFile)       'Need Full Path
         data.SetData(DataFormats.FileDrop, New String() {fileFullPath})
         'Set
         Clipboard.SetDataObject(data)


尚、 クリップボード転送時に定義した 文字列 "PNG" は 大文字小文字を識別しない様です。
"PNG" で送り出して、"png" で受けても、正常動作します。

また、単に、クリップボードから データを取り出しているだけですから、
作業途中に、他のソフトから クリップボード転送(コピー) を行えば、
その結果に応じた結末になります。



0 件のコメント:

コメントを投稿