| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192 |
- ' Author: uye (owner of the MaaAssistantArknights team)
- ' Original Source: MaaAssistantArknights project - https://github.com/MaaAssistantArknights/MaaAssistantArknights
- ' License: Apache License 2.0 (this file only)
- '
- ' This file is originally developed for MaaAssistantArknights and licensed under AGPL v3.0.
- ' As the original author and copyright holder,
- ' I hereby re-license this file under the Apache License 2.0 for use in the Plain Craft Launcher project.
- '
- ' This file is contributed under the spirit of good faith and open cooperation.
- ' It does not implement any core launcher functions of PCL.
- '
- ' Description:
- ' Provides a WPF clipboard handling fix to avoid OpenClipboard exceptions
- ' in TextBox, RichTextBox, and DataGrid under Windows focus issues or clipboard hooks.
- '
- ' Date: 2025-07-03
- Imports System.Windows
- Imports System.Windows.Controls
- Imports System.Windows.Input
- Imports System.Windows.Documents
- Imports System.Linq
- Namespace Controls.Behaviors
- Public NotInheritable Class ClipboardInterceptor
- Private Sub New()
- End Sub
- Public Shared ReadOnly EnableSafeClipboardProperty As DependencyProperty =
- DependencyProperty.RegisterAttached("EnableSafeClipboard", GetType(Boolean), GetType(ClipboardInterceptor),
- New PropertyMetadata(False, AddressOf OnEnableSafeClipboardChanged))
- Public Shared Sub SetEnableSafeClipboard(element As DependencyObject, value As Boolean)
- element.SetValue(EnableSafeClipboardProperty, value)
- End Sub
- Public Shared Function GetEnableSafeClipboard(element As DependencyObject) As Boolean
- Return element.GetValue(EnableSafeClipboardProperty)
- End Function
- Private Shared Sub OnEnableSafeClipboardChanged(d As DependencyObject, e As DependencyPropertyChangedEventArgs)
- If TypeOf d Is TextBox AndAlso CBool(e.NewValue) Then
- AddCommandBindingsToTextBox(DirectCast(d, TextBox))
- ElseIf TypeOf d Is RichTextBox AndAlso CBool(e.NewValue) Then
- AddCommandBindingsToRichTextBox(DirectCast(d, RichTextBox))
- ElseIf TypeOf d Is DataGrid AndAlso CBool(e.NewValue) Then
- AddCommandBindingsToDataGrid(DirectCast(d, DataGrid))
- End If
- End Sub
- Private Shared Sub AddCommandBindingsToTextBox(tb As TextBox)
- tb.CommandBindings.Add(New CommandBinding(ApplicationCommands.Copy, AddressOf OnCopyTextBox))
- tb.CommandBindings.Add(New CommandBinding(ApplicationCommands.Cut, AddressOf OnCutTextBox))
- tb.CommandBindings.Add(New CommandBinding(ApplicationCommands.Paste, AddressOf OnPasteTextBox))
- End Sub
- Private Shared Sub AddCommandBindingsToRichTextBox(rtb As RichTextBox)
- rtb.CommandBindings.Add(New CommandBinding(ApplicationCommands.Copy, AddressOf OnCopyRichTextBox))
- rtb.CommandBindings.Add(New CommandBinding(ApplicationCommands.Cut, AddressOf OnCutRichTextBox))
- rtb.CommandBindings.Add(New CommandBinding(ApplicationCommands.Paste, AddressOf OnPasteRichTextBox))
- End Sub
- Private Shared Sub AddCommandBindingsToDataGrid(dg As DataGrid)
- dg.CommandBindings.Add(New CommandBinding(ApplicationCommands.Copy, AddressOf OnCopyDataGrid))
- End Sub
- Private Shared Sub OnCopyTextBox(sender As Object, e As ExecutedRoutedEventArgs)
- Dim tb = TryCast(sender, TextBox)
- If tb Is Nothing OrElse tb.SelectionLength <= 0 Then Return
- Try
- Forms.Clipboard.Clear()
- Forms.Clipboard.SetDataObject(tb.SelectedText, True)
- Catch
- End Try
- e.Handled = True
- End Sub
- Private Shared Sub OnCutTextBox(sender As Object, e As ExecutedRoutedEventArgs)
- Dim tb = TryCast(sender, TextBox)
- If tb Is Nothing OrElse tb.SelectionLength <= 0 Then Return
- Try
- Forms.Clipboard.Clear()
- Forms.Clipboard.SetDataObject(tb.SelectedText, True)
- Catch
- End Try
- tb.SelectedText = String.Empty
- e.Handled = True
- End Sub
- Private Shared Sub OnPasteTextBox(sender As Object, e As ExecutedRoutedEventArgs)
- Dim tb = TryCast(sender, TextBox)
- If tb Is Nothing Then Return
- If Forms.Clipboard.ContainsText() Then
- Dim pasteText = Forms.Clipboard.GetText()
- '将换行符替换为空格(#7825)
- If Not tb.AcceptsReturn Then pasteText = pasteText.Replace(vbCrLf, " ").Replace(vbCr, " ").Replace(vbLf, " ")
- Dim start = tb.SelectionStart
- tb.SelectedText = pasteText
- tb.CaretIndex = start + pasteText.Length
- tb.SelectionLength = 0
- End If
- e.Handled = True
- End Sub
- Private Shared Sub OnCopyRichTextBox(sender As Object, e As ExecutedRoutedEventArgs)
- Dim rtb = TryCast(sender, RichTextBox)
- If rtb Is Nothing Then Return
- Dim textRange = New TextRange(rtb.Selection.Start, rtb.Selection.End)
- If String.IsNullOrEmpty(textRange.Text) Then Return
- Try
- Forms.Clipboard.Clear()
- Forms.Clipboard.SetDataObject(textRange.Text, True)
- Catch
- End Try
- e.Handled = True
- End Sub
- Private Shared Sub OnCutRichTextBox(sender As Object, e As ExecutedRoutedEventArgs)
- Dim rtb = TryCast(sender, RichTextBox)
- If rtb Is Nothing Then Return
- Dim selection = New TextRange(rtb.Selection.Start, rtb.Selection.End)
- If String.IsNullOrEmpty(selection.Text) Then Return
- Try
- Forms.Clipboard.Clear()
- Forms.Clipboard.SetDataObject(selection.Text, True)
- Catch
- End Try
- selection.Text = String.Empty
- e.Handled = True
- End Sub
- Private Shared Sub OnPasteRichTextBox(sender As Object, e As ExecutedRoutedEventArgs)
- Dim rtb = TryCast(sender, RichTextBox)
- If rtb Is Nothing Then Return
- If Not Forms.Clipboard.ContainsText() Then Return
- Dim pasteText = Forms.Clipboard.GetText()
- Dim selection = rtb.Selection
- selection.Text = pasteText
- Dim caretPos = selection.End
- rtb.CaretPosition = caretPos
- rtb.Selection.Select(caretPos, caretPos)
- e.Handled = True
- End Sub
- Private Shared Sub OnCopyDataGrid(sender As Object, e As ExecutedRoutedEventArgs)
- Dim dg = TryCast(sender, DataGrid)
- If dg Is Nothing OrElse dg.SelectedCells Is Nothing OrElse dg.SelectedCells.Count = 0 Then Return
- Dim sb = New StringBuilder
- Dim rowGroups = dg.SelectedCells.GroupBy(Function(c) c.Item)
- For Each row In rowGroups
- Dim rowText = String.Join(vbTab, row.Select(
- Function(cell)
- Dim tb = TryCast(cell.Column.GetCellContent(cell.Item), TextBlock)
- Return If(tb IsNot Nothing, tb.Text, "")
- End Function))
- sb.AppendLine(rowText)
- Next
- Dim sbStr = sb.ToString().TrimEnd(ControlChars.Cr, ControlChars.Lf)
- Try
- Forms.Clipboard.Clear()
- Forms.Clipboard.SetDataObject(sbStr, True)
- Catch
- End Try
- e.Handled = True
- End Sub
- End Class
- End Namespace
|