single.php

C# Windowsのクリップボードが更新されたイベントを取得する方法

C#でクリップボードにテキストなどが転送された時のイベントを取得したい場合の方法を備忘録的に投稿します。

Win32 APIでクリップボードの更新を取得

C#のアセンブリでは取得は難しいので、Win32で[WM_CLIPBOARDUPDATE]メッセージで更新を取得できます。

他のメッセージ取得と同じで、こんな感じで取得が可能でした。

private const int WM_CLIPBOARDUPDATE = 0x031D;

protected override void WndProc(ref Message m)
{
    if (m.Msg == WM_CLIPBOARDUPDATE)
    {
        // クリップボードが更新された
    }

    base.WndProc(ref m);
}

クリップボードのテキストを取得

[WndProc]でメッセージを受信する構造なので、フォームを持つクラスが必要ですが、フォームを持たない[NativeWindow]クラスから派生させても取得ができます。

また、EventHandler<string>でイベントを公開すると、他のクラスから使いやすいクラスになります。

using System;
using System.Collections.Generic;
using System.Runtime.InteropServices;
using System.Text;
using System.Diagnostics;

namespace Sample
{
    internal class WinClipboard : NativeWindow, IDisposable
    {
        private const int WM_CLIPBOARDUPDATE = 0x031D;

        [DllImport("user32.dll", SetLastError = true)]
        private static extern bool AddClipboardFormatListener(IntPtr hwnd);

        [DllImport("user32.dll", SetLastError = true)]
        private static extern bool RemoveClipboardFormatListener(IntPtr hwnd);

        private readonly List<string> _lines = new List<string>();

        public event EventHandler<string>? ClipboardTextChanged;

        public WinClipboard()
        {
            CreateHandle(new CreateParams()); // ウィンドウハンドル作成
            AddClipboardFormatListener(this.Handle);
        }

        protected override void WndProc(ref Message m)
        {
            if (m.Msg == WM_CLIPBOARDUPDATE)
            {
                TryCaptureClipboardText();
            }

            base.WndProc(ref m);
        }

        private void TryCaptureClipboardText()
        {
            try
            {
                if (Clipboard.ContainsText())
                {
                    string text = Clipboard.GetText();

                    if (!string.IsNullOrWhiteSpace(text))
                    {
                        ClipboardTextChanged?.Invoke(this, text);
                    }
                }
            }
            catch
            {
                // クリップボード競合時は無視(必要ならリトライ)
            }
        }

        public void Dispose()
        {
            RemoveClipboardFormatListener(this.Handle);
            this.DestroyHandle();
        }
    }
}

使う場合はインスタンス化したクラス変数で公開されているイベントから取得できます。

private readonly WinClipboard _winclipboard = new WinClipboard();

_winclipboard.ClipboardTextChanged += (s, text) =>
{
    Debug.WriteLine(text);
};

まとめ

今回は短い記事ですが、クリップボードにテキストなどが転送された時のイベントを取得したい場合の方法について書きました。

C#には直接クリップボードの更新を取得するイベントは用意されていませんが、Win32 の “WM_CLIPBOARDUPDATE” メッセージを取得で可能でした。

C#でWindowsのクリップボードの更新を取得した人の参考になれば幸いです。

スポンサーリンク

最後までご覧いただき、ありがとうございます。

コメントを残す

メールアドレスが公開されることはありません。 が付いている欄は必須項目です