C# と VB.NET の質問掲示板

ASP.NET、C++/CLI、Java 何でもどうぞ

C# と VB.NET の入門サイト

クリップボードの内容をリアルタイムに取得する方法

[トピック内 5 記事 (1 - 5 表示)]  << 0 >>

■103004 / inTopicNo.1)  クリップボードの内容をリアルタイムに取得する方法
  
□投稿者/ こここ (1回)-(2024/03/12(Tue) 20:22:54)

分類:[.NET 全般] 

Win11でVB.NET2015の環境で
プログラム開発を行っております。


プログラムを起動した状態で
テキストデータをCtrl+Cキーでコピーすると
自動でプログラムがコピーしたテキストの内容を処理して
クリップボードのテキストデータを別の内容に書き換えるプログラムを作っています。

リアルタイムでクリップボードを取得する方法に関しては
https://atmarkit.itmedia.co.jp/fdotnet/dotnettips/848cbviewer/cbviewer.html
このページのコードでうまくいきました。


しかし、10〜20回に1回くらいの頻度で
テキストデータが取得できなかったり、
取得するのに10秒以上かかったりするなど
不思議な挙動をしています。

一体、なぜタイミングによってうまくいったり
うまくいかなかったりするのでしょうか?




引用返信 編集キー/
■103005 / inTopicNo.2)  Re[1]: クリップボードの内容をリアルタイムに取得する方法
□投稿者/ KOZ (438回)-(2024/03/13(Wed) 00:21:33)
> リアルタイムでクリップボードを取得する方法に関しては
> https://atmarkit.itmedia.co.jp/fdotnet/dotnettips/848cbviewer/cbviewer.html
> このページのコードでうまくいきました。


これは少し古いやり方です。
Windows Vista 以降であれば AddClipboardFormatListener/RemoveClipboardFormatListener を使って、もっと楽に制御できます。

「AddClipboardFormatListener 関数」
https://learn.microsoft.com/ja-jp/windows/win32/api/winuser/nf-winuser-addclipboardformatlistener

「RemoveClipboardFormatListener 関数」
https://learn.microsoft.com/ja-jp/windows/win32/api/winuser/nf-winuser-removeclipboardformatlistener


> しかし、10〜20回に1回くらいの頻度で
> テキストデータが取得できなかったり、
> 取得するのに10秒以上かかったりするなど
> 不思議な挙動をしています。


内容を書き換える部分はどのようにコーディングしているんでしょうか?
書き換えたことによりイベントが発生して無限ループに入ったりしていませんか?

引用返信 編集キー/
■103010 / inTopicNo.3)  Re[2]: クリップボードの内容をリアルタイムに取得する方法
□投稿者/ こここ (2回)-(2024/03/13(Wed) 16:09:11)
ありがとうございます。

まだ、新しいコードは試していないのですが、


Invoke(Sub()

GetClipboardText = Clipboard.GetText()

End Sub)


のコードでクリップボードの内容を取得した後に、


BeginInvoke(Sub()

Clipboard.SetText(" ")

End Sub)

のコードで、クリップボードの内容を書き換えています。

もしかして、書き換えたことで
再度クリップボードの取得プログラムが呼ばれているということがあり得るのでしょうか?

この場合、例えば、ブーリアン変数を宣言しておいて、
更新するまではリアルタイムでの取得を行わないようにするなどの
必要がありますか?


引用返信 編集キー/
■103012 / inTopicNo.4)  Re[3]: クリップボードの内容をリアルタイムに取得する方法
□投稿者/ KOZ (439回)-(2024/03/13(Wed) 19:11:54)
2024/03/13(Wed) 19:14:44 編集(投稿者)
No103010 (こここ さん) に返信

イベントはメッセージキューを介して通知されるので Invoke や BeginInvoke は必要ないです。

> もしかして、書き換えたことで
> 再度クリップボードの取得プログラムが呼ばれているということがあり得るのでしょうか?

呼ばれます。
書き換える前にフックを解除し、書き換えた後にフックを再開すればOKです。

下にサンプルを書きますが、クリップボードを他のプログラムが開いていると、Clipboard のメソッドは普通に失敗することがあるので、間隔を置いてリトライするなどしてください。


Imports System.Runtime.InteropServices

Public Class Form1

    Protected Overrides Sub OnHandleCreated(e As EventArgs)
        MyBase.OnHandleCreated(e)
        AddClipboardFormatListener(Handle)
    End Sub

    Protected Overrides Sub WndProc(ByRef m As Message)
        Select Case m.Msg
            Case WM_NCDESTROY
                MyBase.WndProc(m)
                RemoveClipboardFormatListener(Handle)

            Case WM_CLIPBOARDUPDATE
                RemoveClipboardFormatListener(Handle)
                If Clipboard.ContainsText() Then
                    Dim clipboardText As String = Clipboard.GetText()
                    Dim replaceString = YourTask(clipboardText)
                    If clipboardText <> replaceString Then
                        Clipboard.Clear()
                        Clipboard.SetText(replaceString)
                    End If
                End If
                AddClipboardFormatListener(Handle)

            Case Else
                MyBase.WndProc(m)
        End Select
    End Sub

    Private Function YourTask(clipboardText As String) As String
        Return clipboardText & "A"
    End Function

    Private Const WM_NCDESTROY As Integer = &H82
    Private Const WM_CLIPBOARDUPDATE As Integer = &H31D

    <DllImport("user32.dll", SetLastError:=True)>
    Private Shared Function AddClipboardFormatListener(hwnd As IntPtr) As Boolean
    End Function

    <DllImport("user32.dll", SetLastError:=True)>
    Private Shared Function RemoveClipboardFormatListener(hwnd As IntPtr) As Boolean
    End Function

End Class

引用返信 編集キー/
■103024 / inTopicNo.5)  Re[4]: クリップボードの内容をリアルタイムに取得する方法
□投稿者/ こここ (3回)-(2024/03/22(Fri) 11:58:06)
ありがとうございます。
こんな方法があったのですね
うまくいきました
解決済み
引用返信 編集キー/

このトピックをツリーで一括表示


トピック内ページ移動 / << 0 >>

このトピックに書きこむ