wpf,能够复制文字 及自动识别URL超链接的TextBlock

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);
        }
    }
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值