LoginSignup
1
1

ClipboardをNativeWindowでサブクラス化して楽したい

Posted at

目的

・AddClipboardFormatListener/RemoveClipboardFormatListenerをNativeWindowでサブクラス化したい
・WindowsFormに毎回書くのが面倒臭い、部品化して最低限に留めたい

環境

実施環境
・Windows 10 Professional
・Visual Studio 2022 Community(x64) Ver.17.7.0

実装

ClipboardListener.cs
using System.Runtime.InteropServices;
namespace CSClipboardListener
{
    public class ClipboardEventArgs : EventArgs
    {
        private string text;
        public string Text{get { return this.text; }}
        public ClipboardEventArgs(string str) => this.text = str;
    }

    public delegate void cbEventHandler(object sender, ClipboardEventArgs ev);

    public class ClipboardListener : NativeWindow
    {
        private Form Parent;                            //イベント通知先
        private const int WM_CLIPBOARDUPDATE = 0x031D;  //クリップボードの内容変更時に送信される
        public event cbEventHandler ClipboardHandler;   //
        
        //Win32API
        private static class NativeMethods
        {
            [DllImport("user32.dll", SetLastError = true)]
	        internal extern static void AddClipboardFormatListener(IntPtr hWnd);
	        [DllImport("user32.dll", SetLastError = true)]
	        internal extern static void RemoveClipboardFormatListener(IntPtr hWnd);
        }

#nullable disable warnings
        public ClipboardListener(Form f)
        {
            f.HandleCreated   += new EventHandler(OnHandleCreated);
            f.HandleDestroyed += new EventHandler(OnHandleDestroyed);
            this.Parent = f;
        }
#nullable restore warnings

        internal void OnHandleCreated(object sender, EventArgs e)
        {
            AssignHandle(((Form)sender).Handle);
            NativeMethods.AddClipboardFormatListener(this.Handle);
        }
        internal void OnHandleDestroyed(object sender, EventArgs e)
        {
            NativeMethods.RemoveClipboardFormatListener(this.Handle);
            this.ReleaseHandle();
        }

        protected override void WndProc(ref Message msg)
        {
            if((msg.Msg == WM_CLIPBOARDUPDATE) && Clipboard.ContainsText())
            {
                //if (ClipboardHandler != null) 
                //{   
                //    ClipboardHandler(this, new ClipboardEventArgs(Clipboard.GetText()));
                //}
                ClipboardHandler?.Invoke(this, new ClipboardEventArgs(Clipboard.GetText()));
            }
            base.WndProc(ref msg);
        }
    }
}

使用する側は以下の通り

FormClipListener.cs
namespace CSClipboardListener
{
    public partial class FormClipListener : Form
    {
        private readonly ClipboardListener clipListener;

        public FormClipListener()
        {
            clipListener = new ClipboardListener(this);
            clipListener.ClipboardHandler += this.OnClipBoardChanged;
            InitializeComponent();
        }

        private void OnClipBoardChanged(object sender, ClipboardEventArgs args)
        {
            this.textBox1.Text = args.Text;
        }

        private void FormClipListener_FormClosing(object sender, FormClosingEventArgs e)
        {
            clipListener.DestroyHandle();
        }
    }
}

参考及び改造元のページ

実装迄に探し回った物を雑多に列挙しているので注意

@IT

@Qiita内

@Microsoft公式

@外部サイト

クリップボードを監視してテキストボックスに追加していく感じの。

余談

思ったよりNativeWindowの情報が少なくて苦労した・・・探し方が下手なだけだろうか?

1
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
1