!!!クリップボードチェインの仕組み 思うところあって、昨日ちょろっと調べたので適当に解説。 !!前提:どんなときに使うものか 至極簡単に言えば、クリップボードを監視したいときに使います。 これを使えば、クリップボードの内容が変更されたことを検知できるようになります。 !!仕組み1:いかにして検知するのか 例えば、ここにクリップボードを監視するソフト「CB VIEWER I」というソフトがあったとします。(以下便宜のためCB1) {{ref_image cbview1.png}} クリップボードのデータはAPIで取得できますが、その中身に変化が起こったかどうかを調べるためには クリップボードのデータを取得し続けなくてはいけなくなります。 それは不便。 そこで、この機能です。 具体的には、SetClipboardViewer()を呼びます。そうすることでOSに 「私はクリップボードビューアです。ですから、中身が変更されたら教えてくださいね。」 ということになります。 すると、'''OSはクリップボードのデータが変更(あるいは削除)されるたびに、ウィンドウメッセージのWM_DRAWCLIPBOARDを送ってくる'''ようになります。 {{ref_image cbview2.png}} あとは、WM_DRAWCLIPBOARDが来たときにデータを適切に処理すればいいわけです。 !!仕組み2:問題点 ところが、この仕組みには一つ困った点がありました。 例えば、先ほどの状態のところに、新たなクリップボード監視ソフト「CB VIEWER II」を導入したとします。(同じくCB2) {{ref_image cbview3.png}} このソフトがSetClipboardViewer()を呼ぶと、OSは'''そのソフトだけにWM_DRAWCLIPBOARDを送るようになります'''。 {{ref_image cbview4.png}} これではCB1は2度とクリップボードの変更を検知できなくなってしまいます。 !!仕組み3:解決策 そこで、CB2がCB1にWM_DRAWCLIPBOARDを送るようにします。 実は、SetClipboardViewer()を呼ぶとき、戻り値として'''OSが今までWM_DRAWCLIPBOARDを送っていたウィンドウハンドルが得られます'''。 要はそのハンドルに向かってWM_DRAWCLIPBOARDを送ればいいということになります。 {{ref_image cbview5.png}} 次々に鎖が連なっているかのような動作なので、クリップボードチェインと言うそうです。 !!仕組み4:終了 チェインの途中が抜けてしまう場合はどうでしょう。 そういう時は、ChangeClipboardChain()を使って、「私はチェインから抜けますよ」と宣言します。 すると、OSはチェインの一番最初のウィンドウにWM_CHANGECBCHAINというメッセージを送ります。 これには、たった今チェインを抜けたウィンドウのハンドルと、そのウィンドウが今までメッセージを 送信していたウィンドウのハンドルが含まれています。 これを見て、自分の次のウィンドウが抜けたと判断できるときは自身の送信先のデータを更新し、 そうで無い場合はWM_DRAWCLIPBOARDのときと同様、次のウィンドウにWM_CHANGECBCHAINを送ります。 !!まとめ *クリップボードチェインに参加するウィンドウは、次の二つのメッセージを'''必ず'''適切に処理せねばならない。 **WM_DRAWCLIPBOARD ***(あれば)次のウィンドウにメッセージを「伝言」する。 **WM_CHANGECBCHAIN ***終了したウィンドウが自分の次のものであれば、自分のデータを更新 ***そうで無い場合、(あれば)次のウィンドウにメッセージを「伝言」する。 **これらを怠ると、他のクリップボード監視ソフトに多大な迷惑がかかる。当然、それを使うユーザーに迷惑がかかる。 *クリップボードチェインに参加したウィンドウは、終了する前に適切に「脱退」の処理をせねばならない。 **これも怠れば、他のクリップボード監視ソフトに多大な迷惑がかかる。当然、それを使うユーザーに迷惑がかかる。 !!!余談:スーパーチラシの裏ブラザーズ(謎 なんで21世紀にもなって、「伝言ゲーム」などという仕組みなのか、まずそこら辺を2〜3時間問い詰めたい。 しかも、その仕組みは他のソフトを信頼しろ、という意味でしかない。このセキュリティの時代に(以下略