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. Android ExpandableGridView的实现

    近期在做项目的时候碰到了这样一个布局 在android中有种实现折叠list方式是ExpandableListView  但是官方没有ExpandableGridView 那么怎么样用Expandab ...

  2. Android消息处理

    基本概念: Message:消息,其中包含了消息ID.what,消息处理对象.obj以及处理的数据.arg1.arg2等,由MessageQueue统一列队,终由Handler处理. Handler: ...

  3. JS学习:第二周——NO.3盒子模型

    1.CSS盒子模型包括四个部分组成:设定的宽高+padding+border+margin: 2.JS盒子模型:通过系统提供的属性和方法,来获取当前元素的样式值   JS提供的属性和方法: clien ...

  4. linux 安装nexus

    1.下载nexus 的包,加压缩. 2.启动neuxs export RUN_AS_USER=root     ./nexus start

  5. xampp 下安装mysql-python

    pip install mysql-python修改路径PATH="$PATH":(/mysql/bin 路径)brew install mysql-connector-c

  6. dex文件格式三

    先来看看整体的结构,结构体定义在DexFile.h里面   在dexFileSetupBasicPointers中设置各个子结构体,当然是在解析DexHeader之后 源码在DexFile.c文件中 ...

  7. JAVA基础学习——1.2 环境搭建 之eclipse安装及中文化

    安装好jdk,配置好环境变量以后,下面就可以进行安装eclipse了. 闲话少说,eclipse下载地址:http://www.eclipse.org/downloads/ 不大用关注checksum ...

  8. tcp_tw_reuse、tcp_tw_recycle 使用场景及注意事项

    linux TIME_WAIT 相关参数: net.ipv4.tcp_tw_reuse = 表示开启重用.允许将TIME-WAIT sockets重新用于新的TCP连接,默认为0,表示关闭 net.i ...

  9. 【bb平台刷课记】wireshark结合实例学抓包

    [bb平台刷课记]wireshark结合实例学抓包 背景:本校形势与政策课程课需要在网上观看视频的方式来修得学分,视频网页自带"播放器不可快进+离开窗口自动暂停+看完一集解锁下一集(即不能同 ...

  10. Unity3D 接完GVR SDk后如何插入自己的java代码

    1.用Eclipse创建一个Android Application Project 2.用压缩软件打开gvr_android_common.aar和unitygvractivity.aar,分别把里面 ...