クリップボードの中身の文字列を条件に基づいて変更したい

実現したいこと

前提

クリップボードを監視する機能がある、タスクトレイ常駐型アプリが良いと考え、以下のページを参考にして(と言ってもほぼそのままです)作ってみたのですが、末尾の文字が「\\\」と3回繰り返されてしまいます。文字が増える以外は、ほぼ意図通りに動いています。

C#のタスクトレイ常駐アプリの作り方のご紹介!
https://www.fenet.jp/dotnet/column/environment/4527/
C#|クリップボードの変更を監視する
https://anis774.net/codevault/clipboardwatcher.html

発生している問題・エラーメッセージ

コード内のClipboard.SetTextで中身を変更したときに処理が再度行われているのかと思い、Debug.WriteLineで中身を見てみたのですが、

D:\test\\ D:\test\\\ D:\test\

となっており、この状態でペーストするとD:\test\\\になるのでわからなくなってしまいました。(処理が再度行われているなら無限ループを起こす気もします)
何故こうなってしまうのでしょうか。希望通りの動作にするにはどうしたら良いですか。

該当のソースコード

Form1.cs

c#

1using System.Diagnostics;2using System.Drawing;3using System.Runtime.InteropServices;4using System.Windows.Forms;5 6namespace WinFormsApp1 7{8 public partial class Form1 : Form 9 {10 NotifyIcon notifyIcon;11 ClipBoardWatcher cbw;12 13 public Form1()14 {15 this.ShowInTaskbar = false; //タスクバーに表示しない16 this.setComponents();17 }18 19 private void setComponents()20 {21 notifyIcon = new NotifyIcon();22 //アイコン23 notifyIcon.Icon = new Icon(@"Icon1.ico");24 //アイコン表示25 notifyIcon.Visible = true;26 //マウスポインタ合わせると出るテキスト27 notifyIcon.Text = "てすと";28 29 //コンテキストメニュー30 ContextMenuStrip contextMenuStrip = new ContextMenuStrip();31 ToolStripMenuItem toolStripMenuItem = new ToolStripMenuItem();32 toolStripMenuItem.Text = "&終了";33 toolStripMenuItem.Click += ToolStripMenuItem_Click;34 contextMenuStrip.Items.Add(toolStripMenuItem);35 notifyIcon.ContextMenuStrip = contextMenuStrip;36 37 //クリップボード監視開始38 cbw = new ClipBoardWatcher();39 cbw.DrawClipBoard += (sender2, e2) =>40 {41 //テキストが入ってたら42 if (Clipboard.ContainsText())43 {44 string str = Clipboard.GetText();45 //\\か:\が入ってたら46 if (str.Contains("\\\\") | str.Contains(":\\"))47 {48 str += "\\";49 Clipboard.SetText(str);50 Debug.WriteLine(str);51 }52 53 }54 };55 }56 57 private void ToolStripMenuItem_Click(object sender, EventArgs e)58 {59 cbw.Dispose();60 61 //アプリ終了62 Application.Exit();63 }64 65 /// <summary>66 /// クリップボードを監視するクラス。67 /// 使用後は必ずDispose()メソッドを呼び出して下さい。68 /// </summary>69 public class ClipBoardWatcher : IDisposable 70 {71 ClipBoardWatcherForm form;72 73 /// <summary>74 /// クリップボードに内容に変更があると発生します。75 /// DrawClipBoardというイベントの宣言76 /// </summary>77 public event EventHandler DrawClipBoard;78 79 /// <summary>80 /// ClipBoardWatcherクラスを初期化して81 /// クリップボードビューアチェインに登録します。82 /// 使用後は必ずDispose()メソッドを呼び出して下さい。83 /// </summary>84 public ClipBoardWatcher()85 {86 form = new ClipBoardWatcherForm();87 form.StartWatch(raiseDrawClipBoard);88 }89 90 private void raiseDrawClipBoard()91 {92 //DrawClipBoardイベント発生93 if (DrawClipBoard != null)94 {95 DrawClipBoard(this, EventArgs.Empty);96 }97 }98 99 /// <summary>100 /// ClipBoardWatcherクラスを101 /// クリップボードビューアチェインから削除します。102 /// </summary>103 public void Dispose()104 {105 form.Dispose();106 }107 108 private class ClipBoardWatcherForm : Form 109 {110 [DllImport("user32.dll")]111 private static extern IntPtr SetClipboardViewer(IntPtr hwnd);112 [DllImport("user32.dll")]113 private static extern int SendMessage(IntPtr hwnd, int wMsg, IntPtr wParam, IntPtr lParam);114 [DllImport("user32.dll")]115 private static extern bool ChangeClipboardChain(IntPtr hwnd, IntPtr hWndNext);116 117 const int WM_DRAWCLIPBOARD = 0x0308;118 const int WM_CHANGECBCHAIN = 0x030D;119 120 IntPtr nextHandle;121 System.Threading.ThreadStart proc;122 123 public void StartWatch(System.Threading.ThreadStart proc)124 {125 this.proc = proc;126 nextHandle = SetClipboardViewer(this.Handle);127 }128 129 protected override void WndProc(ref Message m)130 {131 if (m.Msg == WM_DRAWCLIPBOARD)132 {133 SendMessage(nextHandle, m.Msg, m.WParam, m.LParam);134 proc();135 }136 else if (m.Msg == WM_CHANGECBCHAIN)137 {138 if (m.WParam == nextHandle)139 {140 nextHandle = m.LParam;141 }142 else143 {144 SendMessage(nextHandle, m.Msg, m.WParam, m.LParam);145 }146 }147 base.WndProc(ref m);148 }149 150 protected override void Dispose(bool disposing)151 {152 ChangeClipboardChain(this.Handle, nextHandle);153 base.Dispose(disposing);154 }155 }156 }157 }158}

program.cs

c#

1namespace WinFormsApp1 2{3 internal static class Program 4 {5 /// <summary>6 /// The main entry point for the application.7 /// </summary>8 [STAThread]9 static void Main()10 {11 // To customize application configuration such as set high DPI settings or default font,12 // see https://aka.ms/applicationconfiguration.13 Application.EnableVisualStyles();14 Application.SetCompatibleTextRenderingDefault(false);15 //Application.Run(new Form1()); //非表示16 17 //formなしで実行する18 new Form1();19 Application.Run();20 }21 }22}

補足情報(FW/ツールのバージョンなど)

Windows10
Visual Studio2022で作成
Windowsフォームアプリ
フレームワーク:.NET6.0

コメントを投稿

0 コメント