• 締切済み

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

VB.net、C#、.net framework2005で、 クリップボード拡張ソフトを開発しております。 クリップボードへの入出力が起こる直前にフックをかけたいです。 コピー・切り取り操作(ClipBoardへの入力)については クリップボードチェーンに自分を加え、WM_DRAWCLIPBOARDをハンドルすることで解決できました。 貼り付け(ClipBoardからの出力)についてはどのようにすれば実現できますでしょうか? 貼り付けイベントが起こった時に、チェーン内のプログラムにそれを通知するようなWindowsメッセージがあるかと思い、それらしいものを探してみたのですが、利用できそうなものがありませんでした… 具体的には、 ・入力時に、データを加工して仮想クリップボードに格納 ・出力時に、仮想クリップボード内のデータを再度加工して出力(貼り付け) という処理を実現したいです。 宜しくお願い致します。

みんなの回答

回答No.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

i_110
質問者

補足

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