クリップボードの中身をバイナリレベルで書き換えるには?


すっぴ  2003-03-26 09:53:16  No: 106444

皆様始めまして。
とあるツールで固有のコマンドをテキストに書き換えるプログラムを作ろうと思っています。
コマンドの情報が特殊形式のようなので、クリップボード経由で書き換えることにしました。
例えば「実行」のコマンドをコピーしてバイナリエディタで覗くと
「05 00 00 00 D8 4C 00 00 00」(形式はFormat566(謎)で、FormatHandleは0x0236)
という数値が検出されます。
これがクリップボードのデータ内に含まれているときに「実行」という文字のコードに
書き換えてメモ帳等に落とせるようにしたいわけです。

1.クリップボード(IDateObject)からバイト配列を取り出す
2.特定の配列を対応したテキストコードに書き換える
3.書き換えが終わったらテキストデータとしてクリップボードに戻す

この処理の仕方を教えてください。
差し迫っては1.がどうしてもうまくいきません。
2.に関してはReplace関数に注目しています。テキストを置換する実験はうまくいきましたが、
バイト配列でも同じように置換できますか?
開発環境はVisual Basic.netです。よろしくお願いします。


Y2  2003-03-27 08:31:27  No: 106445

クリップボードからの読み込みと書き込みは、Clipboard.GetDataObjectから返されるIDataObjectのGetDataObjectメソッドとSetDataObjectメソッドでできますけど、問題は、データ形式が何なのか分からないことですね。
クリップボードから読み込もうとしているデータ形式によって処理が違うので、それを調べる必要があります。
データ形式はIDataObject.GetFormatsメソッドで調べることもできます。

データ形式がテキストであれば、
=Clipboard.GetDataObject(GetType(String))
でString型でテキストデータが獲得できます。
ちなみに、String型からバイト配列に変換するためのクラスもあります。

>例えば「実行」のコマンドをコピーしてバイナリエディタで覗くと
今の書き込み内容では、すっぴさんが何をコピーしようとしているのか分かりませんので、的確な答えが返せないです。(~Д~)「


すっぴ  2003-03-28 01:02:34  No: 106446

データ形式に関係なくバイト配列を取り出すにはファイルとして扱うしかないのでしょうか?
バイナリエディタ等でデータを取得して、表示するまでの処理の途中で
文字列操作をするような形にできればいいと思っているのですが。

テキスト変換したいのは「RPGツクール2000」というソフトのイベントコマンドです。
このソフトではイベントの流れをコードを書き出して説明したくてもVBとは違い
そのままコピーすることができないので、変換ツールを作ろうと思い立ちました。
こちらにソフトの体験版があります。
http://www.enterbrain.co.jp/digifami/products/rpg2000/taiken.html

データ形式ですが、以下のコードを利用したところFormat566と表示されました。
とはいえヘルプにあったものを改造しただけで、意味は理解していません。
Dim myDataObject As IDataObject = Clipboard.GetDataObject()
Dim myFormatsArray As [String]() = myDataObject.GetFormats(False)
Dim theResult As String = "The original format associated with the data is:" & vbCr
Dim i As Integer
For i = 0 To myFormatsArray.Length - 1
     theResult += myFormatsArray(i) + vbCr
Next i
myFormatsArray = myDataObject.GetFormats(True)
theResult += vbCr + "The data format(s) and conversion format(s) associated with " & _
 "the data are:" & vbCr
For i = 0 To myFormatsArray.Length - 1
    theResult += myFormatsArray(i) + vbCr
Next i
MessageBox.Show(theResult)


たかみちえ  URL  2003-03-28 01:40:35  No: 106447

IDateObjectは知りませんけど、
 下記のサイトを見てみてください。
http://tokyo.cool.ne.jp/masapico/

"関数別 Win32 サンプル集"の中に
"GetClipboardData"というAPIが紹介されています。
クリップボードの指定フォーマットのデータのハンドルを返すものだそうです。

  ハンドルさえわかれば、GlobalLockでバイナリデータを取り出すことができるようなので、
これならば大丈夫でしょう。
  ここで扱っているのはテキストですけど、GetClipboardDataの引数をかえれば、どうしようもできるはずです。
(ただ、VBでどういう風に扱うかはわかりません)

  フォーマットの識別には、CLCLというソフトがあるので、
それを使うといいかもしれません。
http://www.nakka.com/
(不明なデータ形式の場合、形式の名前をメニューに表示してくれるので)


すっぴ  2003-03-28 10:04:33  No: 106448

>たかみちえ氏
ご親切にありがとうございました。
残念ながら「CLCL」からは形式の取得はできませんでしたが、
これをヒントにして形式表示機能のあるクリップボードビューアを探してみました。

その結果としては「ClipboardCatcher」と「Clipboard Analyzer」から
共通して「0x0236」という情報が得られたに留まりました。
やはり特殊形式と見るしかなさそうです。

ただ、「CLCL」では形式が分からなくてもバイナリデータはしっかりと
表示されます。VBではGetDataObjectメソッドで形式を指定して抽出する
以外にバイト配列を取り出す方法はないのでしょうか。
公開されているソースコードはC言語のようですので使い方が分かりませんでした。


Y2  2003-03-28 18:35:53  No: 106449

>=Clipboard.GetDataObject(GetType(String))

>=Clipboard.GetDataObject.GetData(GetType(String))
間違えました。;~_~)

すっぴさんが投稿されたコードは、クリップボードの中に入っているデータのデータ形式を調べるという動作はしているのですが、肝心なデータを獲得する.GetDataメソッドがないようです。

VB.NETでクリップボードから獲得可能な形式一覧を調べるには、GetFormatsメソッドを使えば調べられます。
Dim F() As String = Clipboard.GetDataObject.GetFormats
ListBox1.Items.Clear()
Dim i As Integer = 0
Do While i < F.Length
    ListBox1.Items.Add(F(i))
    i += 1
Loop
F()には、通常、"Text"、"UnicodeText"、"OEMText"、"System.String"、"Locale"などが格納されるのですが、このリストに載ってない形式で獲得することはできないと思います。(クリップボードにデータが無いので)
例えば、リストに"UnicodeText"が入っているのが確認できれば、
= Clipboard.GetDataObject.GetData("UnicodeText")
でその形式のデータが獲得できます。
すっぴさんが扱っているデータは↑のようにすると、どのようなデータ形式が返ってくるのでしょうか?
"Format566"なのでしょうか?

--------------------------------------
バイト配列として読み込むには、
Dim rStream As System.IO.MemoryStream = Clipboard.GetDataObject.GetData("text")
If rStream Is Nothing OrElse rStream.Length = 0 Then Exit Sub
Dim B() As Byte = rStream.ToArray
ReDim Preserve B(B.Length - 2)
でOKでした。これでB()に配列として格納されます。

-----------------------------
バイト配列の中身を確認するには、
= BitConverter.ToString(B)
が手っ取り早いです。
例えば、バイトデータ「05 00 00 00 D8 4C 00 00 00」が格納されていたとすれば、
文字列"05-00-00-00-D8-4C-00-00-00"が返ります。
Hex(B(インデックス))
というやり方もあるでしょうけど、BitConverterを使うのが簡単だと思います。

---------------------------------
バイト配列をクリップボードに書き込むには、
= System.Text.Encoding.Default.GetString(B)
で文字列に変換できるので、
Clipboard.SetDataObject(System.Text.Encoding.Default.GetString(B), True)
でできます。Trueはアプリケーションが終了した後もクリップボードに書き込んだものが消えないという意味です。

ちなみに、書いた後であれなんですけど、クリップボードからバイト配列で取り込むよりは、文字列として取り込んだほうが簡単な気がします。
バイト配列の状態だと、Replace関数とか、文字列比較ができないので・・・、まあ、BitConverterなどで文字列に変換すれば良いのですけど。
ちょっと難しいプログラムになってしまいましたけど、何か分からないところがあったら追記しますので。(´Д`)/


Y2  2003-03-28 18:47:42  No: 106450

>共通して「0x0236」という情報が得られたに留まりました。
テキストのデータ形式を表すコードページのIDかもしれませんね。
コードページは、そのテキストがASCIIなのか、Unicodeなのか、UTF-8なのか、ANSIなのか、などを表すものです。


たかみちえ  URL  2003-03-29 01:48:26  No: 106451

> VBではGetDataObjectメソッドで形式を指定して抽出する
以外にバイト配列を取り出す方法はないのでしょうか。
  ですからAPIで…。

  VBにかぎらず、Windowsや、その下で動くソフトはAPIを何度も使って動いています。
VBの各関数は、ほとんどがそれを簡略化しているに過ぎません。
(たとえばフォームは、本来CreateWindow APIを使って、何度も処理をした末に作成されるものです、
VBでは、フォームの作成と破棄を全部VB側がやってくれています)
  上のGetDataObjectも、結局APIの呼び出しを簡略化しているだけではないか・・・と思います。

  簡略化された動作は、応用の利くようにできてはいるものの、
『RPGツクールのコピーしたクリップボードデータを取得する』という方法には対応していないのだと思います。

  ですから、そういうときには、"自分で1からAPIを使う必要がある"ということです。
  ただし、VBはAPIの呼び出しを基本的には想定していないようなので、
APIを使っている最中に、VBの関数を使うようなことは、あまりしないほうがいいです。

  ええと、0x0236(VBであらわすと&h0236)という情報が得られたのなら、
それを、GetClipboardData APIの引数に指定してみたらどうでしょう?
  もしうまくいけば、そのデータのハンドルが手に入り、結果、データを手に入れることができるはずです。
(何度もいいますけど、VBでポインタを扱う方法を、わたしはよく知りません、
できるとは思いますけど、もしできない場合は、他の言語でDLLを作って橋渡しするとか、
差し支えがなければDelphiやC言語でやったほうがいいです)


※返信する前に利用規約をご確認ください。

※Google reCAPTCHA認証からCloudflare Turnstile認証へ変更しました。






  このエントリーをはてなブックマークに追加