単純な検出
考えられる最初の解決策は、WM_PASTE
をオーバーライドするメッセージを検出することですWndProc
が、残念ながら、貼り付け操作を実行するときに、コントロールはそのメッセージを自分自身に送信しません。
キーボードイベントを検出し(OnKeyDown
関数をオーバーライドする必要があります)、キーの組み合わせ(CTRL + VおよびSHIFT + INS)がテキストを貼り付けるものであるかどうかを確認すると、これを解決できます。
Protected Sub OnKeyDown(ByVal e As KeyEventArgs)
Dim ctrlV As Boolean = e.Modifiers = Keys.Control && e.KeyCode = Keys.V
Dim shiftIns As Boolean = e.Modifiers = Keys.Shift && e.KeyCode = Keys.Insert
If ctrlV Or shiftIns Then
ProcessAllLines
End If
End Sub
うまく動作しますが、マウス (右クリックしてコンテキスト メニューを開く) を使用した貼り付け操作と、ドラッグ アンド ドロップによる貼り付け操作をキャッチできません。それらが必要ない場合は、このソリューションを使用できます (少なくとも単純明快です)。
より良い検出
仮定: ユーザーが内部に入力すると、RichTextBox
一度に 1 文字が挿入されます。これをどのように使用できますか?ユーザーが一度に複数の文字を入力できないため、より大きな変更を検出すると、貼り付け操作が検出されます (これは Unicode サロゲートのために常に当てはまるとは限りませんが、この場合は問題ではありません)。
すべての IME (極東の言語では試していません) や Unicode サロゲートではうまく機能しませんが、西洋の言語では問題ありません (とにかく、機能しない場合でも、すべての行を再処理するだけです)。 . また、この投稿とこの投稿を読んで、Unicode とC# バージョンのこの(ツイン) 回答の詳細を確認してください。
Dim _previousLength As Int32 = 0
Protected Sub richTextBox_TextChanged(ByVal sender As Object, ByVal e As EventArgs)
Dim currentLength As Int32 = richTextBox.Text.Length
If Math.Abs(currentLength - _previousLength) > 1 Then
ProcessAllLines
End If
_previousLength = currentLength
End Sub
完璧なソリューション
もちろん、完全な解決策が存在します (Windows 8 以降)。ネイティブのリッチ エディット コントロールがEN_CLIPFORMAT
通知メッセージを送信します。特定のクリップボード形式で貼り付けが行われたことを、リッチ エディット コントロールの親ウィンドウに通知することを目的としています。WndProc
次に、その親の をオーバーライドしてWM_NOTIFY
、この通知のメッセージを検出できます。とにかく、それは数行のコードではありません。詳細については、MSDN のこのリンクを確認してください: http://msdn.microsoft.com/en-us/library/windows/desktop/hh768385(v=vs.85).aspx。