CI / Go Backend (push) Canceled after 0s
初始化 monorepo: Go后端(7微服务) + Unity客户端(9模块) + 启动器 HTML5原型: Three.js 3D体素世界, Perlin噪声地形, 原版材质, 22种方块 Minecraft创造模式背包: 双栏布局, 拖拽移动物品, 方向性元件引脚 AI助搭策划文档 + 客户端/服务端骨架 + Docker Compose + CI
218 lines
6.5 KiB
C#
218 lines
6.5 KiB
C#
using System.Text;
|
|
using System.Windows;
|
|
using System.Windows.Controls;
|
|
using System.Windows.Documents;
|
|
using System.Windows.Input;
|
|
using Clipboard = System.Windows.Forms.Clipboard;
|
|
|
|
// 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 based on work originally developed in the MaaAssistantArknights project,
|
|
// which is licensed under the GNU AGPL v3.0 only.
|
|
//
|
|
// As the original author of this code, I am re-licensing this specific file under
|
|
// the Apache License 2.0 for use in PCL2-CE.
|
|
//
|
|
// Description:
|
|
// Implements a WPF clipboard fix to handle OpenClipboard failures in TextBox,
|
|
// RichTextBox, and DataGrid, typically caused by focus issues or external hooks.
|
|
//
|
|
// Date: 2025-07-03
|
|
|
|
namespace PCL.Controls.Behaviors;
|
|
|
|
public sealed class ClipboardInterceptor
|
|
{
|
|
public static readonly DependencyProperty EnableSafeClipboardProperty =
|
|
DependencyProperty.RegisterAttached("EnableSafeClipboard", typeof(bool), typeof(ClipboardInterceptor),
|
|
new PropertyMetadata(false, OnEnableSafeClipboardChanged));
|
|
|
|
private ClipboardInterceptor()
|
|
{
|
|
}
|
|
|
|
public static void SetEnableSafeClipboard(DependencyObject element, bool value)
|
|
{
|
|
element.SetValue(EnableSafeClipboardProperty, value);
|
|
}
|
|
|
|
public static bool GetEnableSafeClipboard(DependencyObject element)
|
|
{
|
|
return (bool)element.GetValue(EnableSafeClipboardProperty);
|
|
}
|
|
|
|
private static void OnEnableSafeClipboardChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
|
|
{
|
|
if (!(bool)e.NewValue)
|
|
return;
|
|
|
|
switch (d)
|
|
{
|
|
case TextBox box:
|
|
AddCommandBindingsToTextBox(box);
|
|
break;
|
|
case RichTextBox box:
|
|
AddCommandBindingsToRichTextBox(box);
|
|
break;
|
|
case DataGrid grid:
|
|
AddCommandBindingsToDataGrid(grid);
|
|
break;
|
|
}
|
|
}
|
|
|
|
private static void AddCommandBindingsToTextBox(TextBox tb)
|
|
{
|
|
tb.CommandBindings.Add(new CommandBinding(ApplicationCommands.Copy, OnCopyTextBox));
|
|
tb.CommandBindings.Add(new CommandBinding(ApplicationCommands.Cut, OnCutTextBox));
|
|
tb.CommandBindings.Add(new CommandBinding(ApplicationCommands.Paste, OnPasteTextBox));
|
|
}
|
|
|
|
private static void AddCommandBindingsToRichTextBox(RichTextBox rtb)
|
|
{
|
|
rtb.CommandBindings.Add(new CommandBinding(ApplicationCommands.Copy, OnCopyRichTextBox));
|
|
rtb.CommandBindings.Add(new CommandBinding(ApplicationCommands.Cut, OnCutRichTextBox));
|
|
rtb.CommandBindings.Add(new CommandBinding(ApplicationCommands.Paste, OnPasteRichTextBox));
|
|
}
|
|
|
|
private static void AddCommandBindingsToDataGrid(DataGrid dg)
|
|
{
|
|
dg.CommandBindings.Add(new CommandBinding(ApplicationCommands.Copy, OnCopyDataGrid));
|
|
}
|
|
|
|
private static void OnCopyTextBox(object sender, ExecutedRoutedEventArgs e)
|
|
{
|
|
var tb = sender as TextBox;
|
|
if (tb is null || tb.SelectionLength <= 0)
|
|
return;
|
|
|
|
TrySetClipboardText(tb.SelectedText);
|
|
e.Handled = true;
|
|
}
|
|
|
|
private static void OnCutTextBox(object sender, ExecutedRoutedEventArgs e)
|
|
{
|
|
var tb = sender as TextBox;
|
|
if (tb is null || tb.SelectionLength <= 0)
|
|
return;
|
|
|
|
TrySetClipboardText(tb.SelectedText);
|
|
|
|
tb.SelectedText = string.Empty;
|
|
e.Handled = true;
|
|
}
|
|
|
|
private static void OnPasteTextBox(object sender, ExecutedRoutedEventArgs e)
|
|
{
|
|
var tb = sender as TextBox;
|
|
if (tb is null)
|
|
return;
|
|
|
|
if (Clipboard.ContainsText())
|
|
{
|
|
var pasteText = Clipboard.GetText();
|
|
|
|
if (!tb.AcceptsReturn)
|
|
pasteText = pasteText.Replace("\r\n", " ").Replace("\r", " ")
|
|
.Replace("\n", " ");
|
|
|
|
var start = tb.SelectionStart;
|
|
|
|
tb.SelectedText = pasteText;
|
|
tb.CaretIndex = start + pasteText.Length;
|
|
tb.SelectionLength = 0;
|
|
}
|
|
|
|
e.Handled = true;
|
|
}
|
|
|
|
private static void OnCopyRichTextBox(object sender, ExecutedRoutedEventArgs e)
|
|
{
|
|
var rtb = sender as RichTextBox;
|
|
if (rtb is null)
|
|
return;
|
|
|
|
var textRange = new TextRange(rtb.Selection.Start, rtb.Selection.End);
|
|
if (string.IsNullOrEmpty(textRange.Text))
|
|
return;
|
|
|
|
TrySetClipboardText(textRange.Text);
|
|
e.Handled = true;
|
|
}
|
|
|
|
private static void OnCutRichTextBox(object sender, ExecutedRoutedEventArgs e)
|
|
{
|
|
var rtb = sender as RichTextBox;
|
|
if (rtb is null)
|
|
return;
|
|
|
|
var selection = new TextRange(rtb.Selection.Start, rtb.Selection.End);
|
|
if (string.IsNullOrEmpty(selection.Text))
|
|
return;
|
|
|
|
TrySetClipboardText(selection.Text);
|
|
|
|
selection.Text = string.Empty;
|
|
e.Handled = true;
|
|
}
|
|
|
|
private static void OnPasteRichTextBox(object sender, ExecutedRoutedEventArgs e)
|
|
{
|
|
var rtb = sender as RichTextBox;
|
|
if (rtb is null)
|
|
return;
|
|
|
|
if (!Clipboard.ContainsText())
|
|
return;
|
|
|
|
var pasteText = Clipboard.GetText();
|
|
var selection = rtb.Selection;
|
|
|
|
selection.Text = pasteText;
|
|
|
|
var caretPos = selection.End;
|
|
rtb.CaretPosition = caretPos;
|
|
rtb.Selection.Select(caretPos, caretPos);
|
|
|
|
e.Handled = true;
|
|
}
|
|
|
|
private static void OnCopyDataGrid(object sender, ExecutedRoutedEventArgs e)
|
|
{
|
|
var dg = sender as DataGrid;
|
|
if (dg is null || dg.SelectedCells is null || dg.SelectedCells.Count == 0)
|
|
return;
|
|
|
|
var sb = new StringBuilder();
|
|
var rowGroups = dg.SelectedCells.GroupBy(c => c.Item);
|
|
|
|
foreach (var row in rowGroups)
|
|
{
|
|
var rowText = string.Join("\t", row.Select(cell =>
|
|
{
|
|
var tb = cell.Column.GetCellContent(cell.Item) as TextBlock;
|
|
return tb is not null ? tb.Text : "";
|
|
}));
|
|
sb.AppendLine(rowText);
|
|
}
|
|
|
|
TrySetClipboardText(sb.ToString().TrimEnd('\r', '\n'));
|
|
e.Handled = true;
|
|
}
|
|
|
|
private static bool TrySetClipboardText(string text)
|
|
{
|
|
try
|
|
{
|
|
Clipboard.Clear();
|
|
Clipboard.SetDataObject(text, true);
|
|
return true;
|
|
}
|
|
catch
|
|
{
|
|
return false;
|
|
}
|
|
}
|
|
}
|