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常用组件之ListView

    使用ListAdapter是ListView的适配器. 使用ListView.setAdapter()方法来设置ListView的适配器. 简单的使用 adapter = new ArrayAdapt ...

  2. nyoj 473 A^B Problem

    A^B Problem 时间限制:1000 ms  |  内存限制:65535 KB 难度:2   描述 Give you two numbers a and b,how to know the a^ ...

  3. SVN部署和使用

    一.SVN介绍 svn(subversion)是近年来崛起的版本管理工具,是cvs的接班人.目前,绝大多数开源软件都使用svn作为代码版本管理软件. 二.服务器端和客户端 1.服务器端软件Subver ...

  4. Linq练习

    首先在Program.cs的Main()方法下添加如下代码: string[] names = { "heh", "haha", "huahua&qu ...

  5. Orchard 模块开发学习笔记 (1)

    创建模块 首先,打开Bin目录下的Orchard.exe 等到出现orchard>后, 看看命令列表中是否存在 codegen module 如果不存在,则需要先执行:feature enabl ...

  6. 功能实现:PLC对LPC的音量控制

    设计方案1: 在PLC上,当使用QDial调节音量时,触发QDial的SIGNAL:ValueChange(),对应SLOT向LPC发送自定义键码0x22; 在LPC上,当接收到0x22键码时,执行操 ...

  7. title换行

  8. WPF 主题切换(Z)

    using System; using System.Windows; using Assergs.Windows; namespace XMLSpy.WPF.Util{ /// <summar ...

  9. Camtasia 录屏说明

    准备好要录制的屏幕或网页,在即将播放的位置暂停住. 从开始菜单位置“TechSmith”启动Camtasia Recorder 8,其界面如下所示: 注意,要录制系统声音,须在Recorded inp ...

  10. Team Foundation Server源代码管理多人开发的使用心得

    问题1:多人使用TFS源代码管理器的时候,往往会造成同个文件内源代码不一致,覆盖别人的代码. 解决方案: 给多个人分配不同的开发任务,保证每个人修改的文件都不会重叠. 但有些情况无法避免多个人同时修改 ...