リアルタイムにクリップボードの監視
リアルタイムにクリップボードの監視
(ソフトを起動してる間)リアルタイムにクリップボードを自動監視し、クリップボードの内容(ただの文字列)が変わる度にEditBox1に出力したいのですが、どうやったら良いのでしょう?
Re: リアルタイムにクリップボードの監視
> (ソフトを起動してる間)リアルタイムにクリップボードを自動監視し、クリップボードの内容(ただの文字列)が変わる度にEditBox1に出力したいのですが、どうやったら良いのでしょう?
これはActiveBasicのヘルプファイルを作る時にコードを書いたんですけど、情報を探すのがやたらと面倒くさかった記憶があります。
説明も面倒なのでコードをドカ載せします...でもコメントかなり飛ばしてます...。
詳しく知りたい場合は、
「ChangeClipboardChain」「SetClipboardViewer」「GetClipboardViewer」
「WM_DRAWCLIPBOARD」「WM_CHANGECBCHAIN」
と検索してみてください。
これはActiveBasicのヘルプファイルを作る時にコードを書いたんですけど、情報を探すのがやたらと面倒くさかった記憶があります。
説明も面倒なのでコードをドカ載せします...でもコメントかなり飛ばしてます...。
詳しく知りたい場合は、
「ChangeClipboardChain」「SetClipboardViewer」「GetClipboardViewer」
「WM_DRAWCLIPBOARD」「WM_CHANGECBCHAIN」
と検索してみてください。
[ここをクリックすると内容が表示されます]
コード: 全て選択
'クリップボードを監視します。
' TODO: この位置にグローバルな変数、構造体、定数、関数を定義します。
Declare Function ChangeClipboardChain Lib "user32" (
ByVal hWndRemove As HWND,
ByVal hWndNewNext As HWND) As BOOL
Declare Function SetClipboardViewer Lib "user32" (
ByVal hWndNewViewer As HWND) As HWND
Declare Function GetClipboardViewer Lib "user32" () As HWND
Dim hNextWnd As HWND
'-----------------------------------------------------------------------------
' ウィンドウメッセージを処理するためのコールバック関数
Function MainWndProc(hWnd As HWND, dwMsg As DWord, wParam As WPARAM, lParam As LPARAM) As DWord
' TODO: この位置にウィンドウメッセージを処理するためのコードを記述します。
Select Case dwMsg
Case WM_CREATE
hNextWnd=SetClipboardViewer(hWnd)
Case WM_DESTROY
ChangeClipboardChain(hWnd,hNextWnd)
Case WM_DRAWCLIPBOARD ' クリップボードの内容が変更された場合、実行される。
Dim hMem As HGLOBAL
Dim lpStr As BytePtr
' クリップボード内の文字列を取得
If OpenClipboard(hMainWnd) Then
hMem=GetClipboardData(CF_TEXT)
CloseClipboard()
If hMem Then
lpStr=GlobalLock(hMem)
' エディットボックスに文字列を設定
SetDlgItemText(hMainWnd,EditBox1,lpStr)
GlobalUnlock(hMem)
Else
SetDlgItemText(hMainWnd,EditBox1,"テキストデータがありません。")
End If
End If
If hNextWnd Then
SendMessage(hNextWnd,dwMsg,wParam,lParam)
End If
Case WM_CHANGECBCHAIN
If wParam=hNextWnd Then
hNextWnd=lParam As HWND
ElseIf hNextWnd Then
SendMessage(hNextWnd,dwMsg,wParam,lParam)
End If
End Select
' イベントプロシージャの呼び出しを行います。
MainWndProc=EventCall_MainWnd(hWnd,dwMsg,wParam,lParam)
End Function
クリップボードについて
定期的にクリップボードを監視する
指定したいデータ形式を保存しておく
新しいデータか判定する
以下、アクティブベーシックのヘルプから引用しました。
Win32API: GetClipboardData
クリップボードから指定したデータ形式のデータを取得します。
--------------------------------------------------------------------------------
定義
Declare Function GetClipboardData Lib "user32" _
(uFormat As DWord) As HANDLE
uFormat
取得するデータの形式を指定します。以下の定数を利用することができます。
定数 説明
CF_BITMAP ビットマップ データ(ビットマップ ハンドル)です。
CF_DIB BITMAPINFO構造体とビット配列からなるビットマップデータです。
CF_DIF Software Arts 社の DIF データ交換形式です。
CF_DSPBITMAP プライベートな形式のビットマップデータです。
CF_DSPENHMETAFILE プライベートな形式の拡張メタファイルデータです。
CF_DSPMETAFILEPICT プライベートな形式のメタファイル画像表示形式データです。
CF_DSPTEXT プライベートな形式のテキストデータです。
CF_ENHMETAFILE 拡張メタファイルのデータ(enhanced metafile ハンドル)です。
CF_GDIOBJFIRST(&H0300) ~ CF_GDIOBJLAST(&H03FF) GDI オブジェクトによって表現される、アプリケーション定義のクリップボード形式です。
CF_HDROP ファイルドロップ形式です。
CF_LOCALE テキストデータのロケール ID ハンドルです。
CF_METAFILEPICT METAFILEPICT 構造体のメモリオブジェクトです。メタファイル画像形式です。
CF_PALETTE カラーパレットのハンドルです。
CF_PENDATA Windows のペン拡張機能のためのデータです。
CF_PRIVATEFIRST(&H0200) ~ CF_PRIVATELAST(&H02FF) プライベートなクリップボード形式です。
CF_RIFF RIFF 形式の音声データです。
CF_SYLK Microsoft シンボリックリンク (SYLK) 形式のデータです。
CF_TEXT テキスト形式のデータです。各行は復帰改行 (CR-LF) コードで終わります。データの終端は NULL 文字です。この形式は、ANSI テキストに使います。
CF_WAVE WAVE 形式の音声データです。
CF_TIFF TIFF 形式の画像データです。
CF_UNICODETEXT Unicode のテキスト形式です。各行は復帰改行 (CR-LF) コードで終わります。データの終端は NULL 文字です(WindowsNT系OSのみ)。
戻り値
関数が成功すると、データが格納されているメモリ オブジェクトのハンドルが返ります。失敗すると、NULL が返ります。
解説
この関数を呼び出す前に、OpenClipboard関数を使用してクリップボードをオープンしておく必要があります。
取得したメモリ オブジェクトは、GlobalLock関数を使用して参照することができるようになります。
環境情報
インクルード ファイル: api_window.sbp 内で定義済み
DLLファイル: user32.dll
--------------------------------------------------------------------------------
OpenClipboard関数、SetClipboardData関数、GlobalLock関数
指定したいデータ形式を保存しておく
新しいデータか判定する
以下、アクティブベーシックのヘルプから引用しました。
Win32API: GetClipboardData
クリップボードから指定したデータ形式のデータを取得します。
--------------------------------------------------------------------------------
定義
Declare Function GetClipboardData Lib "user32" _
(uFormat As DWord) As HANDLE
uFormat
取得するデータの形式を指定します。以下の定数を利用することができます。
定数 説明
CF_BITMAP ビットマップ データ(ビットマップ ハンドル)です。
CF_DIB BITMAPINFO構造体とビット配列からなるビットマップデータです。
CF_DIF Software Arts 社の DIF データ交換形式です。
CF_DSPBITMAP プライベートな形式のビットマップデータです。
CF_DSPENHMETAFILE プライベートな形式の拡張メタファイルデータです。
CF_DSPMETAFILEPICT プライベートな形式のメタファイル画像表示形式データです。
CF_DSPTEXT プライベートな形式のテキストデータです。
CF_ENHMETAFILE 拡張メタファイルのデータ(enhanced metafile ハンドル)です。
CF_GDIOBJFIRST(&H0300) ~ CF_GDIOBJLAST(&H03FF) GDI オブジェクトによって表現される、アプリケーション定義のクリップボード形式です。
CF_HDROP ファイルドロップ形式です。
CF_LOCALE テキストデータのロケール ID ハンドルです。
CF_METAFILEPICT METAFILEPICT 構造体のメモリオブジェクトです。メタファイル画像形式です。
CF_PALETTE カラーパレットのハンドルです。
CF_PENDATA Windows のペン拡張機能のためのデータです。
CF_PRIVATEFIRST(&H0200) ~ CF_PRIVATELAST(&H02FF) プライベートなクリップボード形式です。
CF_RIFF RIFF 形式の音声データです。
CF_SYLK Microsoft シンボリックリンク (SYLK) 形式のデータです。
CF_TEXT テキスト形式のデータです。各行は復帰改行 (CR-LF) コードで終わります。データの終端は NULL 文字です。この形式は、ANSI テキストに使います。
CF_WAVE WAVE 形式の音声データです。
CF_TIFF TIFF 形式の画像データです。
CF_UNICODETEXT Unicode のテキスト形式です。各行は復帰改行 (CR-LF) コードで終わります。データの終端は NULL 文字です(WindowsNT系OSのみ)。
戻り値
関数が成功すると、データが格納されているメモリ オブジェクトのハンドルが返ります。失敗すると、NULL が返ります。
解説
この関数を呼び出す前に、OpenClipboard関数を使用してクリップボードをオープンしておく必要があります。
取得したメモリ オブジェクトは、GlobalLock関数を使用して参照することができるようになります。
環境情報
インクルード ファイル: api_window.sbp 内で定義済み
DLLファイル: user32.dll
--------------------------------------------------------------------------------
OpenClipboard関数、SetClipboardData関数、GlobalLock関数
Re: リアルタイムにクリップボードの監視
早速コードを実行してみました。
コピーを繰り返すと新たにコピーした文字列が上書きされてしまうのですが、"追加"でどんどんと言う風にはならないでしょうか?^^;
又、ボタン1を押せばクリップボード監視を停止としたい場合どうしたら良いのでしょうか?
後、7さんの書いて頂いたコード中の
If hMem Then ってどんな条件分岐なんですか?
もしもグローバルオブジェクトメモリ ハンドルが?!
何がどうなったら・・・と言うのが全くわからないので^^;
コピーを繰り返すと新たにコピーした文字列が上書きされてしまうのですが、"追加"でどんどんと言う風にはならないでしょうか?^^;
又、ボタン1を押せばクリップボード監視を停止としたい場合どうしたら良いのでしょうか?
後、7さんの書いて頂いたコード中の
If hMem Then ってどんな条件分岐なんですか?
もしもグローバルオブジェクトメモリ ハンドルが?!
何がどうなったら・・・と言うのが全くわからないので^^;
Re: リアルタイムにクリップボードの監視
> コピーを繰り返すと新たにコピーした文字列が上書きされてしまうのですが、"追加"でどんどんと言う風にはならないでしょうか?^^;
そうですね。文字列を設定してしまうので追加って感じじゃないですね。
文字列を設定せずに追加するような処理に替えます。
すいません。実装しようとしたら全体的にコードが変わってしまいました。新しく載せます。
ちなみに、クリップボードの監視を始めるには、SetClipboardViewer()関数、終了するには、ChangeClipboardChain()関数を使います。
> If hMem Then ってどんな条件分岐なんですか?
> もしもグローバルオブジェクトメモリ ハンドルが?!
言葉に直すなら「グローバルオブジェクトメモリハンドルが FALSE じゃないなら」って感じでしょうか。
「グローバルオブジェクトメモリハンドルが TRUE なら」とは違うので注意が必要です。
そういえば自分もプログラミングを始めた頃、同じように意味が分からなくて困ったことがありました!
そうですね。文字列を設定してしまうので追加って感じじゃないですね。
文字列を設定せずに追加するような処理に替えます。
関数の定義 [ここをクリックすると内容が表示されます]
コード: 全て選択
'----------------------------------------------------------------------
' エディットボックスに文字列を追加
' hWnd : エディットボックスのハンドル
' lpString : 追加したい文字列
' bUndo : UNDOを有効にするか(TRUE=する)
' 戻り値 : 成功した場合、1。失敗した場合、0。
'----------------------------------------------------------------------
Function EditBox_AddText(ByVal hWnd As HWND,ByVal lpString As BytePtr,ByVal bUndo As BOOL)
SendMessage(hWnd,EM_SETSEL,-1,-1)
EditBox_AddText=SendMessage(hWnd,EM_REPLACESEL,bUndo As WPARAM,lpString As LPARAM)
End Function
エディットボックスに文字列を設定を変更 [ここをクリックすると内容が表示されます]
> 又、ボタン1を押せばクリップボード監視を停止としたい場合どうしたら良いのでしょうか?コード: 全て選択
' エディットボックスに文字列を追加
EditBox_AddText(GetDlgItem(hMainWnd,EditBox1),MakeStr(lpStr)+Ex"\r\n",TRUE)
' エディットボックスに文字列を設定
' SetDlgItemText(hMainWnd,EditBox1,lpStr)
すいません。実装しようとしたら全体的にコードが変わってしまいました。新しく載せます。
ちなみに、クリップボードの監視を始めるには、SetClipboardViewer()関数、終了するには、ChangeClipboardChain()関数を使います。
[ここをクリックすると内容が表示されます]
別にクリップボードの監視に詳しい訳じゃないので、動いてるんですけどなんか問題あるかもしれません...。コード: 全て選択
'----------------------------------------------------------------------
' エディットボックスに文字列を追加
' hWnd : エディットボックスのハンドル
' lpString : 追加したい文字列
' bUndo : UNDOを有効にするか(TRUE=する)
' 戻り値 : 成功した場合、1。失敗した場合、0。
'----------------------------------------------------------------------
Function EditBox_AddText(ByVal hWnd As HWND,ByVal lpString As BytePtr,ByVal bUndo As BOOL)
SendMessage(hWnd,EM_SETSEL,-1,-1)
EditBox_AddText=SendMessage(hWnd,EM_REPLACESEL,bUndo As WPARAM,lpString As LPARAM)
End Function
Dim hNextWnd As HWND ' チェイン内の次のウィンドウハンドルを持つ
Dim isCBView As BOOL ' クリップボードの監視状態を持つ
'-----------------------------------------------------------------------------
' ウィンドウメッセージを処理するためのコールバック関数
Function MainWndProc(hWnd As HWND, dwMsg As DWord, wParam As WPARAM, lParam As LPARAM) As DWord
' TODO: この位置にウィンドウメッセージを処理するためのコードを記述します。
Select Case dwMsg
Case WM_DRAWCLIPBOARD ' クリップボードの内容が変更された場合、実行される。
Dim hMem As HGLOBAL
Dim lpStr As BytePtr
' クリップボード内の文字列を取得
If OpenClipboard(hMainWnd) Then
hMem=GetClipboardData(CF_TEXT)
CloseClipboard()
If hMem Then
lpStr=GlobalLock(hMem)
' エディットボックスに文字列を追加
EditBox_AddText(GetDlgItem(hMainWnd,EditBox1),MakeStr(lpStr)+Ex"\r\n",TRUE)
GlobalUnlock(hMem)
Else
SetDlgItemText(hMainWnd,EditBox1,"テキストデータがありません。")
End If
End If
If hNextWnd Then
SendMessage(hNextWnd,dwMsg,wParam,lParam)
End If
Case WM_CHANGECBCHAIN
If wParam=hNextWnd Then
hNextWnd=lParam As HWND
ElseIf hNextWnd Then
SendMessage(hNextWnd,dwMsg,wParam,lParam)
End If
End Select
' イベントプロシージャの呼び出しを行います。
MainWndProc=EventCall_MainWnd(hWnd,dwMsg,wParam,lParam)
End Function
' ウィンドウ破棄時
Sub MainWnd_Destroy()
ChangeClipboardChain(hMainWnd,hNextWnd)
CBView_DestroyObjects()
PostQuitMessage(0)
End Sub
' ウィンドウ作成時
Sub MainWnd_Create(ByRef CreateStruct As CREATESTRUCT)
hNextWnd=SetClipboardViewer(hMainWnd)
isCBView=TRUE
End Sub
' コマンドボタン1を押した時
Sub MainWnd_CommandButton1_Click()
' 監視していないなら
If isCBView=FALSE Then
hNextWnd=SetClipboardViewer(hMainWnd)
isCBView=TRUE
End If
End Sub
' コマンドボタン2を押した時
Sub MainWnd_CommandButton2_Click()
' 監視しているなら
If isCBView Then
ChangeClipboardChain(hMainWnd,hNextWnd)
isCBView=FALSE
End If
End Sub
> If hMem Then ってどんな条件分岐なんですか?
> もしもグローバルオブジェクトメモリ ハンドルが?!
言葉に直すなら「グローバルオブジェクトメモリハンドルが FALSE じゃないなら」って感じでしょうか。
「グローバルオブジェクトメモリハンドルが TRUE なら」とは違うので注意が必要です。
そういえば自分もプログラミングを始めた頃、同じように意味が分からなくて困ったことがありました!
Re: リアルタイムにクリップボードの監視
7さん、どうも有難う御座いますm(_ _)m
期待通りの動作で感激しました♪
文字列の追加方法を最初書いて頂いたソースに自分なりにあれこれと模索してたのですが、コンパイルでエラーが多発してしまってまして…
今回のソースを元に何とか工夫して自分の目指す物を作ってみたいと思います。
>言葉に直すなら「グローバルオブジェクトメモリハンドルが FALSE じゃないなら」って感じでしょうか。
>「グローバルオブジェクトメモリハンドルが TRUE なら」とは違うので注意が必要です。
折角説明して頂いてもイマイチ理解出来ないです^^;
自分で早く使える(理解する)様になりたいですね
(FALSEじゃないなら、TRUEじゃないの???と思ってみたり)
期待通りの動作で感激しました♪
文字列の追加方法を最初書いて頂いたソースに自分なりにあれこれと模索してたのですが、コンパイルでエラーが多発してしまってまして…
今回のソースを元に何とか工夫して自分の目指す物を作ってみたいと思います。
>言葉に直すなら「グローバルオブジェクトメモリハンドルが FALSE じゃないなら」って感じでしょうか。
>「グローバルオブジェクトメモリハンドルが TRUE なら」とは違うので注意が必要です。
折角説明して頂いてもイマイチ理解出来ないです^^;
自分で早く使える(理解する)様になりたいですね
(FALSEじゃないなら、TRUEじゃないの???と思ってみたり)
> TRUE/FALSEというよりもNULLかそうでないかという感じです。
> GetClipboardの戻り値の説明に「失敗すると、NULL が返ります」と書いてあります。
> If hMem ThenはIf hMem <> 0 Thenと等価です。(NULL = 0)
あ、成る程!!そう言う式が隠れてるんですね!!
> つまりGetClipboardDataが成功したかどうかを確かめる手段として
> 「hMemがデータを保持しているかどうか」をIfで問うているのです。
>
> ちなみにNULLとは空と言う意味です。
お陰様でやっとすっきりと出来ました。
イグトランスさん、わかり易い説明有難う御座いました。
> GetClipboardの戻り値の説明に「失敗すると、NULL が返ります」と書いてあります。
> If hMem ThenはIf hMem <> 0 Thenと等価です。(NULL = 0)
あ、成る程!!そう言う式が隠れてるんですね!!
> つまりGetClipboardDataが成功したかどうかを確かめる手段として
> 「hMemがデータを保持しているかどうか」をIfで問うているのです。
>
> ちなみにNULLとは空と言う意味です。
お陰様でやっとすっきりと出来ました。
イグトランスさん、わかり易い説明有難う御座いました。