C# と VB.NET の質問掲示板

わんくま同盟

ASP.NET、C++/CLI、Java 何でもどうぞ

C# と VB.NET の入門サイト


(過去ログ 82 を表示中)
■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は要りませんよね。

返信 編集キー/


管理者用

- Child Tree -