■48403 / ) |
Re[11]: クリップボードのコピー・貼り付けが完了するタイミングは? |
□投稿者/ れい (888回)-(2010/04/05(Mon) 15:19:36)
|
■No48382 (ダッチ さん) に返信 > http://youryella.wankuma.com/Software/OneTouchKeyboard/Tips.aspx > このページの「コマンドを組み合わせる」の部分を見ていただければ、 > 何をしているのかがわかりやすいかと思います。
ああ。なるほど。 操作の自動化か…
> ただ、囚人さんにも指摘されましたが、クリップボードはあくまでも手段の一つです。
昔ならキーボードドライバとマウスドライバを書くんですが、 今はフックだけでがんばらないといけないので…つらいですね。
> 「文字列を貼り付け」コマンドというのがありまして、 > あらかじめ文字列を登録しておいてコマンドを実行すると、それを貼り付けるというものです。 > 他にもコマンドがあるのですが、それを好きなだけ組み合わせて > まとめて実行できるソフトを作成しています。
その条件なら、確かに私もクリップボードを使うと思います。 ですが、ダッチさんのような構成・構造にはしないと思います。
例えば。 「アプリケーションにクリップボードから貼り付ける」というと、クリップボードからみて能動的な作業に聞こえますが、 実際には「アプリケーションからクリップボードにデータ取得を要請される」ので、 クリップボードにとっては「貼り付け」は受動的な作業です。
Ctrl+Vでも条件によっては「貼り付け」ない場合もあるし。
また、クリップボードは非常に限られたリソースです。 ステーション(?)に一個しかありません。
私はクリップボードにいろいろ大切な物を残しておきます。 「文字列を貼り付け」で、クリップボードが消えたら、勝手に消えたと思うでしょう。 ブチ切れです。
なので、そんなコマンドは作りません。
プログラムはなんでもできますが、 何かの上に載ってるならその上でできることしかできません。 つまり。 Windowsには「文字列を貼りつける」という機能・概念はありません。 それを作ろうと思ったらOSに手を入れないといけないことになります。
.SHOさんが言うように、「貼り付け完了」という概念もないわけです。 あるのは、「クリップボードからデータを取得する」という概念だけ。 で、他のアプリができることは「クリップボードからデータを取得するよう指示する(Ctrl+V)」ことだけです。 いつ、どのように取得するかはアプリ次第なわけです。
私なら
「クリップボードに文字列を登録」 「クリップボードから貼り付けを指示(Ctrl+V)」 「クリップボードが読まれるか、xxx秒経つまで待機」
というコマンドにします。
また… > コード------------------------------------------ > Dim data As New Youryella.Windows.Forms.DataObjectEx > data.SetText("a") > Clipboard.SetDataObject(data, False) > SendPasteKey() > Application.DoEvents() > While (Not data.Pasted) > Application.DoEvents() > Thread.Sleep(10) > End While > ------------------------------------------------ > SetDataObject に copy:=False を渡すと GetData メソッドが呼び出されるまで、待つことができるようになりました。 > Ctrl+V を送信した後に GetData メソッドが呼ばれるまで待機します。 > なぜか Application.DoEvents を呼び出さないと無限ループになってしまいますが、 > 一応このコードで貼り付けが完了するまで待機することができました。 > (Application.DoEvents が気持ち悪い・・・)
(OLEでない)クリップボードは、Windowsのメッセージ機構を経由してデータをやりとりします。 つまり、「貼り付け」は「GUI層」の担当なわけです。 速度的にも、機構的にも、「GUI層」のやり方、 つまり「イベントドリブン」や「シングルスレッド」といった概念でやらねば うまくいかないということです。
ですので、
> 他にもコマンドがあるのですが、それを好きなだけ組み合わせて > まとめて実行できるソフトを作成しています。
まとめて実行するために、「スレッドを一つ立ててコマンドを順番に実行する」というのはダメで、 「一つのイベントで一つのコマンドだけを実行」し、 「コマンド完了毎に逐次イベントを立てる」というやり方が良い、ということになります。 コルーチン的に。
各コマンド毎に実行完了イベントを作り、実行完了イベントハンドラで次のコマンドを開始するわけです。 DataObjectではGetDataでイベントを上げて、「データ送信完了イベント」を作るわけです。
そうすればApplication.DoEventsは要りませんよね。
|
|