こんにちはゲストさん。会員登録(無料)して質問・回答してみよう!

締切り済みの質問

クリップボードからの貼り付けのフック

VB.net、C#、.net framework2005で、
クリップボード拡張ソフトを開発しております。

クリップボードへの入出力が起こる直前にフックをかけたいです。
コピー・切り取り操作(ClipBoardへの入力)については
クリップボードチェーンに自分を加え、WM_DRAWCLIPBOARDをハンドルすることで解決できました。
貼り付け(ClipBoardからの出力)についてはどのようにすれば実現できますでしょうか?
貼り付けイベントが起こった時に、チェーン内のプログラムにそれを通知するようなWindowsメッセージがあるかと思い、それらしいものを探してみたのですが、利用できそうなものがありませんでした…

具体的には、
・入力時に、データを加工して仮想クリップボードに格納
・出力時に、仮想クリップボード内のデータを再度加工して出力(貼り付け)
という処理を実現したいです。

宜しくお願い致します。

投稿日時 - 2009-05-02 16:19:29

QNo.4925770

すぐに回答ほしいです

このQ&Aは役に立ちましたか?

2人が「このQ&Aが役に立った」と投票しています

回答(1)

ANo.1

 こんばんは。回答が付かないようですので。

 外部の誰かがクリップボードを変更した瞬間に受け取りたいと言う事でしょうか。
 クリップボードビューワに自分のウィンドウが登録されていれば、WM_DRAWCLIPBOARDで変更通知を受け取れる筈です。
 http://jo0ls-dotnet-stuff.blogspot.com/2008/12/setclipboardviewer-api-vbnet.html

 以下はクリップボードへビットマップが入る度にメッセージを出します。
 PrintScreenキーを押してスクリーンショットを取れば直に確認出来ます。

Public Class Form1

Declare Unicode Function SetClipboardViewer Lib "user32.dll" (ByVal hWnd As IntPtr) As IntPtr
Declare Unicode Function ChangeClipboardChain Lib "user32.dll" (ByVal hWnd As IntPtr, ByVal hWndNext As IntPtr) As Int32

Declare Unicode Function OpenClipboard Lib "user32.dll" (ByVal hWnd As IntPtr) As Int32
Declare Unicode Function CloseClipboard Lib "user32.dll" () As Int32
Declare Unicode Function GetClipboardData Lib "user32.dll" (ByVal uiFormat As UInt32) As IntPtr

Const WM_CHANGECBCHAIN = &H30D
Const WM_DRAWCLIPBOARD = &H308
Const CF_BITMAP = &H2

Private hWndNext As IntPtr

Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
'自分をクリップボードビューワーに登録
Me.hWndNext = SetClipboardViewer(Me.Handle)

End Sub
Private Sub Form1_FormClosed(ByVal sender As System.Object, ByVal e As System.Windows.Forms.FormClosedEventArgs) Handles MyBase.FormClosed
'自分をクリップボードビューワーから解除
ChangeClipboardChain(Me.Handle, Me.hWndNext)

End Sub

Protected Overrides Sub WndProc(ByRef m As Message)

Select Case m.Msg

Case WM_DRAWCLIPBOARD

'クリップボードの中を開いてビットマップだったらメッセージを出す
OpenClipboard(Me.Handle)

Dim hClipboard As IntPtr = GetClipboardData(CF_BITMAP)

CloseClipboard()

If hClipboard <> IntPtr.Zero Then

MsgBox("クリップボードにビットマップが来ました")

End If

m.HWnd = Me.hWndNext

Case WM_CHANGECBCHAIN

If Me.hWndNext = m.WParam.ToInt32() Then

Me.hWndNext = m.LParam.ToInt32()

ElseIf Me.hWndNext <> IntPtr.Zero Then

m.HWnd = Me.hWndNext

End If

End Select

MyBase.WndProc(m)

End Sub

End Class

投稿日時 - 2009-05-07 00:26:41

補足

御回答ありがとうございます。

質問の仕方が悪かったかもしれません。
それは上で言うクリップボードへの入力の際の話(クリップボードへの変更通知)ですよね?それに関しては仰るとおりWM_DRAWCLIPBOARDをハンドルすることで解決しております。
やりたいことは、システム全体での貼り付け行為(Ctrl+V)を監視して、その直前に処理を差し込むことです。具体的には、クリップボードのデータをその都度の任意のものに差し替えたいと思います。
キー(Ctrl+V)のグローバルフックでも出来ないことは無いのですが、キーの押しっぱなし等で連続して貼り付けが起こった場合、クリップボードのデータの同期タイミングにズレが生じます。
つまり、例えば貼り付けの度に連番(1,2,3...)を出力するような処理を差し込むとして、
 1.Ctrl+V検知
 2.クリップボードデータをn+1に差し替え(その後n++)
 3.CallNextHookExで処理を流す
 4.システムが貼り付け操作を実行
このフローにおいて、システムが4の操作を完了する前に新たなキーフックを検知してしまうと、貼り付け前にデータ差し替えが起こってしまい、実際の出力が1,2,4,5...等と歯抜けになってしまう問題に直面しています。
標題の質問に限らず、この問題を解決する何か良い方法をご存知の方、ご教示下さい。
宜しくお願い致します。

投稿日時 - 2009-05-07 03:34:27

あなたにオススメの質問