Files
xyou f70b061d1a
CI / Go Backend (push) Canceled after 0s
feat: 项目初始化 + 3D方块世界原型 + AI助搭系统
初始化 monorepo: Go后端(7微服务) + Unity客户端(9模块) + 启动器

HTML5原型: Three.js 3D体素世界, Perlin噪声地形, 原版材质, 22种方块

Minecraft创造模式背包: 双栏布局, 拖拽移动物品, 方向性元件引脚

AI助搭策划文档 + 客户端/服务端骨架 + Docker Compose + CI
2026-08-08 14:07:56 +08:00

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;
}
}
}