FC2ブログ

スポンサーサイト

上記の広告は1ヶ月以上更新のないブログに表示されています。
新しい記事を書く事で広告が消せます。

Rxを使ってクリップボードの監視を行う

 C#にはクリップボードの操作を行う為のClipboardクラスがありますが、残念ながらこのクラスにはクリップボードの変更を通知する機能はありません。
 そこで、Rx(Reactive Extensions)を使用してクリップボードの監視を行ってみます。
using System;
using System.Windows;
using System.Reactive.Linq;
using System.Reactive.Concurrency;

using Livet;

namespace ClipboardWatcher.ViewModels
{
    public class MainWindowViewModel : ViewModel
    {
        public MainWindowViewModel()
        {
            // 起動時にClipboardの値をクリアする
            Clipboard.Clear();

            var watcher = Observable
                .Timer(TimeSpan.FromMilliseconds(200))  // 200ms毎に               
                .Where(_ => Clipboard.ContainsText())   // クリップボードにテキストデータがあるかを確認
                .ObserveOnDispatcher()                  // 操作スレッドをUIスレッドに変更(これを忘れると例外発生)
                .Select(_ => Clipboard.GetText())       // クリップボードのテキストを取得               
                .ObserveOn(Scheduler.Default)           // 操作スレッドを規定スレッドに変更
                .Repeat()                               // 上記の監視を何度も繰り返す     
                .DistinctUntilChanged()                 // 以前の結果と違う場合のみ
                .Subscribe(x => ClipboardText = x);
            
            // Livetを使用するならCompositeDisposableに追加しておけば
            // ViewModelがDisposeされる際にクリップボードの監視も停止されます。
            // Livetを使用しないのであれば、しかるべき場所でwatcher.Dispose();を実行してください。
            CompositeDisposable.Add(watcher);
        }

        #region ClipboardText変更通知プロパティ
        private string _ClipboardText;
        /// <summary>
        /// クリップボードにコピーされたテキスト
        /// </summary>
        public string ClipboardText
        {
            get
            { return _ClipboardText; }
            set
            { 
                if (_ClipboardText == value)
                    return;
                _ClipboardText = value;
                RaisePropertyChanged();
            }
        }
        #endregion
    }
}
 大体コメントに書いてあるので、特に説明は必要ないと思いますが、要点のみ説明します。
 Clipboard.GetText()メソッドはSTAモードじゃないと例外が発生します。そのため、GetTextメソッドを呼ぶ前に処理スレッドをUIスレッドに切り替えています。
 その後、UIスレッドの負荷を下げるため再度別スレッドに処理を移し、DistinctUntilChanged() メソッドを使用することで前回の値と違う場合のみ値を通しています。
 Repeat()メソッドは、この一連の監視処理を何度も続けるために必須です。これを忘れるとうまく動きません。
 Subscribe()メソッドの戻り値はIDisposableインスタンスです。このインスタンスのDispose()メソッドを呼ぶと、クリップボードの監視は停止します。
 Livetを使用しているので、CompositeDisposableにwatcherを追加していますが、Livetを使用しない場合は、しかるべき場所でwatcher.Dispose()を実行し監視を停止させてください。
   あとはView側で適当にバインドするだけです。
    <Grid>
        <TextBlock Text="{Binding ClipboardText}" />
    </Grid>
 これで、コピー(Ctrl + C)した瞬間に、Viewにコピーしたテキストが表示されます。
スポンサーサイト

テーマ : プログラミング
ジャンル : コンピュータ

コメントの投稿

非公開コメント

カレンダー
11 | 2018/12 | 01
- - - - - - 1
2 3 4 5 6 7 8
9 10 11 12 13 14 15
16 17 18 19 20 21 22
23 24 25 26 27 28 29
30 31 - - - - -
全記事表示リンク

全ての記事を表示する

カテゴリ
タグリスト

月別アーカイブ
11  09  08  07  06  05  04  03  02  01  12  11  10  09  08  07  06  04  03  02  01  12  11  10  09  08  07  06  05  04  03  02  01  12  11  10  09 
最新記事
リンク
最新コメント
検索フォーム
Amazon
上記広告は1ヶ月以上更新のないブログに表示されています。新しい記事を書くことで広告を消せます。