using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Text;
using System.Text.RegularExpressions;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media; namespace SelectableTextBlock
{
public class TextBlockSelect : TextBlock
{
TextPointer startpoz;
TextPointer endpoz;
MenuItem copyMenu;
MenuItem selectAllMenu; public TextRange Selection { get; private 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.Orange)); 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);
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 > )
{
//urlList.Sort();
for (int i = ; i < urlList.Count; i++)
{
if (i == )
{
string startValue = value.Substring(, urlList[].Item1);
if (string.IsNullOrEmpty(startValue))
startValue = " ";
this.Inlines.Add(new Run() { Text = startValue }); AddHyperlink(urlList[].Item3);
}
else
{
int stratIndex = urlList[i - ].Item1 + urlList[i - ].Item2;
this.Inlines.Add(new Run() { Text = value.Substring(stratIndex, urlList[i].Item1 - stratIndex) }); AddHyperlink(urlList[i].Item3);
} if (i == urlList.Count - )
{
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)
{
Keyboard.Focus(this);
ReleaseMouseCapture();
base.OnMouseLeftButtonUp(e);
} protected override void OnMouseLeftButtonDown(MouseButtonEventArgs e)
{
var point = e.GetPosition(this);
startpoz = GetPositionFromPoint(point, true);
CaptureMouse();
base.OnMouseLeftButtonDown(e);
} protected override void OnMouseMove(MouseEventArgs e)
{
if (IsMouseCaptured)
{
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 OnKeyUp(KeyEventArgs e)
{
if (Keyboard.Modifiers == ModifierKeys.Control)
{
if (e.Key == Key.C)
Copy();
else if (e.Key == Key.A)
SelectAll();
} base.OnKeyUp(e);
} protected override void OnLostFocus(RoutedEventArgs e)
{
ClearSelection();
//base.OnLostFocus(e);
} public bool Copy()
{
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: 可以点击选择和复制文本的TextBlock 的基础上添加了对Url的识别。

wpf,能够复制文字 及自动识别URL超链接的TextBlock的更多相关文章

  1. WPF模拟探照灯文字

    原文:WPF模拟探照灯文字 版权声明:本文为博主原创文章,未经博主允许不得转载. https://blog.csdn.net/yangyisen0713/article/details/1835936 ...

  2. js复制文字

    一.原理分析 浏览器提供了 copy 命令 ,可以复制选中的内容 document.execCommand("copy") 如果是输入框,可以通过 select() 方法,选中输入 ...

  3. js 复制文字、 复制链接到粘贴板

    <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8&quo ...

  4. WPF中的文字修饰——上划线,中划线,基线与下划线

    原文:WPF中的文字修饰——上划线,中划线,基线与下划线 我们知道,文字的修饰包括:空心字.立体字.划线字.阴影字.加粗.倾斜等.这里只说划线字的修饰方式,按划线的位置,我们可将之分为:上划线.中划线 ...

  5. wpf 深度复制控件,打印控件

    原文:wpf 深度复制控件,打印控件 <Window x:Class="WpfApp2.MainWindow" xmlns="http://schemas.micr ...

  6. 点击复制文字到剪贴板兼容性安卓ios

    一般那种活动H5分享可能会用到点击复制文字到剪贴板,很简单的功能 于是搜了一搜:js复制文字到剪贴板,可用结果大致分为两类: 一类是js原生方法,这种方法兼容性不好,不兼容ios: https://d ...

  7. HTML 禁止复制文字

    因为本人平时喜欢看网络小说,但是喜欢看的文通过正经网站或者app都需要收费,让人很是不爽,所以...总之,百度网盘上资源很多.但是问题来了,这些资源肯定不会是作者自己流出的,也不应该是网站或app流出 ...

  8. [WPF] 玩玩彩虹文字及动画

    1. 前言 兴致来了玩玩 WPF 的彩虹文字.不是用 LinearGradientBrush 制作渐变色那种,是指每个文字独立颜色那种彩虹文字.虽然没什么实用价值,但希望这篇文章里用 ItemsCon ...

  9. WPF RichTextBox 自定义文字转超链接

    搬运自StackOverflow private void AddHyperlinkText(string linkURL, string linkName, string TextBeforeLin ...

随机推荐

  1. Hibernate之缓存的原理

    一.关于缓存: 其实对于缓存而言,它其实就是一块内存空间,在这个空间中存放了相互关联的持久化对象, 也就是存在于Session缓存内的对象,那么Session负责根据持久化对象的状态变化来同步的更新数 ...

  2. Mysql安装及主从复制配置

    1.下载 mysql数据库 wget http://dev.mysql.com/get/Downloads/MySQL-5.7/mysql-5.7.9-linux-glibc2.5-x86_64.ta ...

  3. 排序算法总结------选择排序 ---javascript描述

    每当面试时避不可少谈论的话题是排序算法,上次面试时被问到写排序算法,然后脑袋一懵不会写,狠狠的被面试官鄙视了一番,问我是不是第一次参加面试,怎么可以连排序算法都不会呢?不过当时确实是第一次去面试,以此 ...

  4. 报错注入分析之Extractvalue分析

    Extractvalue(这单词略长,拆分记忆法extract:提取物 value:值) 上一篇说的是updatexml.updatexml是修改的.而evtractvalue是查询的. 用法与upd ...

  5. python模块引用问题(比较杂乱,懒得整理)

    1 在stackoverflows摘抄 If the import module in the same dir, use e.g: from . import core If the import ...

  6. Android手机刷recovery

    以前觉得android刷机是件很麻烦的事,现在倒不觉得了.  只要手机刷入第三方的recovery,一切都好办了,无论是root还是刷google play.  recovery开源的有两大阵营,tw ...

  7. linux Mint18 backspace怎么不能连续删除

    打开菜单--->首选项--->键盘,如下图所示: 打开启用重复按键即可,就可以随心所欲的连续删除,连续移动光标了

  8. php mysqli mysqli_query() mysqli_real_query()

    2016年11月26日 15:22:27 星期六 场景: PHP从mysql中读取数据 1. 一次性读取所有数据返给PHP 2. 每次循环只读取一掉记录 数据量小的时候可以使用第一种方法, 数据量很大 ...

  9. MAC OS PHP

    Apache与PHP的配置 OSX自带了apache和php,但默认情况下没有开启,打开终端 sudo apachectl start 这时在浏览器中输入localhost应该就会出现apache标准 ...

  10. java 持久框架mybatis的初步学习

    什么是 MyBatis? MyBatis 是支持普通 SQL 查询,存储过程和高级映射的优秀持久层框架.MyBatis 消除 了几乎所有的 JDBC 代码和参数的手工设置以及结果集的检索.MyBati ...