public class TextBlockSelect : TextBlock
{
private static bool Use全局选择管理 = false;
public TextPointer startpoz;
public TextPointer endpoz;
MenuItem copyMenu;
MenuItem selectAllMenu;
private static List<TextBlockSelect> listtextblock;
private static UIElement owner;
private static int DownIndex = -1;
private static TextPointer Downpoz;
private static Func<bool> func;
public static void 全局TextBlockSelect管理(List<TextBlockSelect> list, UIElement _owner, Func<bool> 全局管理时不被执行的条件)
{
Use全局选择管理 = true;
listtextblock = list;
owner = _owner;
func = 全局管理时不被执行的条件;
owner.PreviewMouseLeftButtonUp += Owner_PreviewMouseLeftButtonUp;
owner.PreviewMouseLeftButtonDown += Owner_PreviewMouseLeftButtonDown;
owner.PreviewMouseMove += Owner_PreviewMouseMove;
}
private static void Owner_PreviewMouseMove(object sender, MouseEventArgs e)
{
if (e.LeftButton == MouseButtonState.Pressed && DownIndex >= 0)
{
var index = listtextblock.FindIndex(x => x.IsMouseOver);
if (index >= 0)
{
foreach (var x in listtextblock.Where(x => x.HasSelection))
{
x.ClearSelection();
}
var endpz = listtextblock[index].GetPositionFromPoint(e.GetPosition(listtextblock[index]), true);
if (DownIndex == index)
{
listtextblock[index].Selection = new TextRange(Downpoz, endpz);
}
else
{
var bl = DownIndex <= index;
var min = Math.Min(DownIndex, index);
var max = Math.Max(DownIndex, index);
listtextblock[min].Selection = new TextRange(bl ? Downpoz : endpz, listtextblock[min].ContentEnd);
for (int i = min + 1; i <= max - 1; ++i)
{
listtextblock[i].Selection = new TextRange(listtextblock[i].ContentStart, listtextblock[i].ContentEnd);
}
listtextblock[max].Selection = new TextRange(listtextblock[max].ContentStart, bl ? endpz : Downpoz);
}
foreach (var x in listtextblock.Where(x => x.HasSelection))
{
x.Selection.ApplyPropertyValue(TextElement.BackgroundProperty, x.SelectionBrush);
}
CommandManager.InvalidateRequerySuggested();
}
}
}
private static void Owner_PreviewMouseLeftButtonDown(object sender, MouseButtonEventArgs e)
{
if (func())
return;
foreach (var x in listtextblock.Where(x => x.HasSelection))
{
x.ClearSelection();
}
var index = listtextblock.FindIndex(x => x.IsMouseOver);
if (index < 0)
return;
Downpoz = listtextblock[index].GetPositionFromPoint(e.GetPosition(listtextblock[index]), true);
if (Downpoz == null)
{
DownIndex = -1;
return;
}
DownIndex = index;
}
private static void Owner_PreviewMouseLeftButtonUp(object sender, MouseButtonEventArgs e)
{
DownIndex = -1;
}
public TextRange Selection { get; set; }
public bool HasSelection
{
get { return Selection != null && !Selection.IsEmpty; }
}
#region SelectionBrush
public static readonly DependencyProperty SelectionBrushProperty =
DependencyProperty.Register("SelectionBrush", typeof(Brush), typeof(TextBlockSelect),
new FrameworkPropertyMetadata(Brushes.Blue));
public Brush SelectionBrush
{
get { return (Brush)GetValue(SelectionBrushProperty); }
set { SetValue(SelectionBrushProperty, value); }
}
#endregion
public static readonly DependencyProperty Text2Property =
DependencyProperty.Register("Text2", typeof(string), typeof(TextBlockSelect),
new FrameworkPropertyMetadata(new PropertyChangedCallback(OnText2PropertyChanged)));
public string Text2
{
get { return (string)GetValue(Text2Property); }
set { SetValue(Text2Property, value); }
}
static void OnText2PropertyChanged(object sender, DependencyPropertyChangedEventArgs args)
{
if (sender != null && sender is TextBlockSelect)
{
TextBlockSelect view = (TextBlockSelect)sender;
if (args != null && args.NewValue != null)
{
string value = args.NewValue.ToString();
if (string.IsNullOrWhiteSpace(value))
{
view.Text = "";
view.Inlines.Clear();
}
else
{
view.AddInlines(value);
}
}
else
{
view.Text = "";
view.Inlines.Clear();
}
}
}
static void link_Click(object sender, RoutedEventArgs e)
{
Hyperlink link = sender as Hyperlink;
Process.Start(new ProcessStartInfo(link.NavigateUri.AbsoluteUri));
//throw new NotImplementedException();
}
public void AddInlines(string value)
{
//Regex urlregex = new Regex(@"((http|ftp|https)://)(([a-zA-Z0-9._-]+.[a-zA-Z]{2,6})|([0-9]{1,3}.[0-9]{1,3}.[0-9]{1,3}.[0-9]{1,3}))(:[0-9]{1,4})*(/[a-zA-Z0-9&%_./-~-]*)?", RegexOptions.IgnoreCase | RegexOptions.Compiled);
Regex urlregex = new Regex(@"^(http|https|ftp)\://[a-zA-Z0-9\-\.]+\.[a-zA-Z]{2,3}(:[a-zA-Z0-9]*)?/?([a-zA-Z0-9\-\._\?\,\'/\\\+&$%\$#\=~])*$", RegexOptions.IgnoreCase | RegexOptions.Compiled);
var ss = urlregex.Matches(value);
List<Tuple<int, int, string>> urlList = new List<Tuple<int, int, string>>();
foreach (Match item in ss)
{
Tuple<int, int, string> urlIndex = new Tuple<int, int, string>(value.IndexOf(item.Value), item.Value.Length, item.Value);
urlList.Add(urlIndex);
}
if (urlList.Count > 0)
{
//urlList.Sort();
for (int i = 0; i < urlList.Count; i++)
{
if (i == 0)
{
string startValue = value.Substring(0, urlList[0].Item1);
if (string.IsNullOrEmpty(startValue))
startValue = " ";
this.Inlines.Add(new Run() { Text = startValue });
AddHyperlink(urlList[0].Item3);
}
else
{
int stratIndex = urlList[i - 1].Item1 + urlList[i - 1].Item2;
this.Inlines.Add(new Run() { Text = value.Substring(stratIndex, urlList[i].Item1 - stratIndex) });
AddHyperlink(urlList[i].Item3);
}
if (i == urlList.Count - 1)
{
string endValue = value.Substring(urlList[i].Item1 + urlList[i].Item2);
if (string.IsNullOrEmpty(endValue))
endValue = " ";
this.Inlines.Add(new Run() { Text = endValue });
}
}
}
else
{
this.Inlines.Clear();
this.Text = value;
}
}
private void AddHyperlink(string value)
{
try
{
Hyperlink link = new Hyperlink();
link.NavigateUri = new Uri(value);
link.Click += link_Click;
link.Inlines.Add(new Run() { Text = value });
this.Inlines.Add(link);
}
catch
{
this.Inlines.Add(new Run() { Text = value });
}
}
public TextBlockSelect()
{
Focusable = true;
//InitMenu();
}
void InitMenu()
{
var contextMenu = new ContextMenu();
ContextMenu = contextMenu;
copyMenu = new MenuItem();
copyMenu.Header = "复制";
copyMenu.InputGestureText = "Ctrl + C";
copyMenu.Click += (ss, ee) =>
{
Copy();
};
contextMenu.Items.Add(copyMenu);
selectAllMenu = new MenuItem();
selectAllMenu.Header = "全选";
selectAllMenu.InputGestureText = "Ctrl + A";
selectAllMenu.Click += (ss, ee) =>
{
SelectAll();
};
contextMenu.Items.Add(selectAllMenu);
ContextMenuOpening += contextMenu_ContextMenuOpening;
}
void contextMenu_ContextMenuOpening(object sender, ContextMenuEventArgs e)
{
copyMenu.IsEnabled = HasSelection;
}
protected override void OnMouseLeftButtonUp(MouseButtonEventArgs e)
{
if (!Use全局选择管理)
{
Keyboard.Focus(this);
ReleaseMouseCapture();
}
base.OnMouseLeftButtonUp(e);
}
protected override void OnMouseLeftButtonDown(MouseButtonEventArgs e)
{
if (!Use全局选择管理)
{
var point = e.GetPosition(this);
startpoz = GetPositionFromPoint(point, true);
CaptureMouse();
}
base.OnMouseLeftButtonDown(e);
}
protected override void OnMouseMove(MouseEventArgs e)
{
//if (IsMouseCaptured)
if (!Use全局选择管理 && IsMouseCaptured && e.LeftButton == MouseButtonState.Pressed)
{
if (startpoz == null)
return;
var point = e.GetPosition(this);
endpoz = GetPositionFromPoint(point, true);
ClearSelection();
Selection = new TextRange(startpoz, endpoz);
Selection.ApplyPropertyValue(TextElement.BackgroundProperty, SelectionBrush);
CommandManager.InvalidateRequerySuggested();
OnSelectionChanged(EventArgs.Empty);
}
base.OnMouseMove(e);
}
protected override void OnKeyDown(KeyEventArgs e)
{
if (!Use全局选择管理)
{
if ((Keyboard.Modifiers & ModifierKeys.Control) == ModifierKeys.Control)
{
if (e.Key == Key.C)
Copy();
else if (e.Key == Key.A)
SelectAll();
}
}
base.OnKeyDown(e);
}
protected override void OnKeyUp(KeyEventArgs e)
{
//if ((Keyboard.Modifiers & ModifierKeys.Control) == ModifierKeys.Control)
//{
// if (e.Key == Key.C)
// Copy();
// else if (e.Key == Key.A)
// SelectAll();
//}
base.OnKeyUp(e);
}
protected override void OnLostFocus(RoutedEventArgs e)
{
if (!Use全局选择管理)
ClearSelection();
base.OnLostFocus(e);
}
public bool Copy()
{
if (!Use全局选择管理)
{
if (HasSelection)
{
Clipboard.SetDataObject(Selection.Text);
return true;
}
}
return false;
}
public void ClearSelection()
{
var contentRange = new TextRange(ContentStart, ContentEnd);
contentRange.ApplyPropertyValue(TextElement.BackgroundProperty, null);
Selection = null;
}
public void SelectAll()
{
Selection = new TextRange(ContentStart, ContentEnd);
Selection.ApplyPropertyValue(TextElement.BackgroundProperty, SelectionBrush);
}
public event EventHandler SelectionChanged;
protected virtual void OnSelectionChanged(EventArgs e)
{
var handler = this.SelectionChanged;
if (handler != null)
handler(this, e);
}
}
wpf,能够复制文字 及自动识别URL超链接的TextBlock
于 2022-12-05 11:42:18 首次发布