クリップボードの内容が変更されたときに、なにか処理を行うために、クリップボードを監視します。
手順 1
まず、クリップボードに変更があったら知らせてもらえるようにする。
クリップボード変更の通知を受けるウィンドウは、列になっていて、その列をクリップボードビューアチェインという。
とりあえず、その列(クリップボードビューアチェイン)に並ぶ(自ウィンドウを追加する)。
(並ぶというよりも、一番前に割り込むことになる)
これには、SetClipboardViewer
を使う。
手順 2
クリップボードに変更があると、列(クリップボードビューアチェイン)の先頭のウィンドウにのみ、メッセージ WM_DRAWCLIPBOARD
が渡される。
メッセージを、列の後ろに並んでいるウィンドウに渡していく処理は、各ウィンドウに任せてある。
つまり、このメッセージを受け取って、処理をしたウィンドウは、次のウィンドウに、メッセージを渡さなければならない。
そのために、自分(チェインに追加するウィンドウ)のすぐ後ろに並んでいるウィンドウのハンドルを保持しておく必要がある。
もし、メッセージを渡さなければ、列の後ろのウィンドウは、クリップボードの変更を知ることができなくなる。
メッセージを渡すには、SendMessage
を使う。
すぐ後ろのウィンドウのハンドルは、手順 1 で、SetClipboardViewer
の戻り値として渡される。
手順 3
列からどれかのウィンドウが抜けると(クリップボードビューアチェインに変更があると)、メッセージ WM_CHANGECBCHAIN
が、チェインの先頭のウィンドウに渡される。
このメッセージの引数として、列を抜ける(削除される)ウィンドウのハンドルと、そのウィンドウの次に並んでいるウィンドウのハンドルが渡される。
チェイン内の各ウィンドウは、すぐ後ろのウィンドウのハンドルを保持しておく必要があるので、
削除されるウィンドウが自分のすぐ後ろのウィンドウだった場合、削除されるウィンドウの次のウィンドウのハンドルを保持しなければならない。
また、削除されるウィンドウが自分のすぐ後ろのウィンドウでなかった場合は、例によって、後ろのウィンドウに、メッセージを渡す。
手順 4
アプリケーションを終了するときは、列から抜けなければならない。
列を抜ける(チェインから自ウィンドウを削除する)には、ChangeClipboardChain
を呼ぶだけでよい。
VB では
VB では、ウィンドウが受け取ったメッセージを直接調べるために、フォームをサブクラス化する。
SendMessage
の引数 lparam
は、As Any
となっているので、
手順 2、 手順 3 で、SendMessage
を呼び出すとき渡す lparam
に ByVal
キーワードをつける。
(WM_DRAWCLIPBOARD
には、引数がないので、手順 2 の場合は ByVal
がなくても問題ないようだが)