原文:利用Adorner制作用于图像裁切的选择框

前天,我写了一篇“使用Adorner显示WPF控件的边界点”的文章。这次,使用从Adorner继承来写一个用于图像裁切的选择框。

先看看效果:

C#代码:
// RubberbandAdorner.cs

#define VISUALCHILD

using System;
using System.IO;
using System.Windows;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Documents;

namespace PhotoDemo
{
#if VISUALCHILD
    public class RubberbandAdorner : Adorner
    {
        private Window1 _window;
        public Window1 Window { set { _window = value; } }

        private RectangleGeometry _geometry;
       
        private UIElement _adornedElement;

        private Rect _selectRect;
        public Rect SelectRect { get { return _selectRect; } }

        private System.Windows.Shapes.Path _rubberband;
        public System.Windows.Shapes.Path Rubberband { get { return _rubberband; } }

        protected override int VisualChildrenCount { get { return 1; } }
       
        private Point _anchorPoint;
               
        public RubberbandAdorner(UIElement adornedElement) : base(adornedElement)
        {
            _adornedElement = adornedElement;
            _selectRect = new Rect();
            _geometry = new RectangleGeometry();
            _rubberband = new System.Windows.Shapes.Path();
            _rubberband.Data = _geometry;
            _rubberband.StrokeThickness = 1;
            _rubberband.Stroke = Brushes.Yellow;
            _rubberband.Opacity = .6;
            _rubberband.Visibility = Visibility.Hidden;
            AddVisualChild(_rubberband);

            MouseMove += new MouseEventHandler(DrawSelection);
            MouseUp += new MouseButtonEventHandler(EndSelection);
        }

        protected override Size ArrangeOverride(Size size)
        {
            Size finalSize = base.ArrangeOverride(size);
            ((UIElement)GetVisualChild(0)).Arrange(new Rect(new Point(), finalSize));

            return finalSize;
        }

        public void StartSelection(Point anchorPoint)
        {
            _anchorPoint = anchorPoint;
            _selectRect.Size = new Size(10, 10);
            _selectRect.Location = _anchorPoint;
            _geometry.Rect = _selectRect;
            if (Visibility.Visible != _rubberband.Visibility)
                _rubberband.Visibility = Visibility.Visible;
        }

        private void DrawSelection(object sender, MouseEventArgs e)
        {
            if (e.LeftButton == MouseButtonState.Pressed)
            {
                Point mousePosition = e.GetPosition(_adornedElement);

                if (mousePosition.X < _anchorPoint.X)
                    _selectRect.X = mousePosition.X;
                else
                    _selectRect.X = _anchorPoint.X;

                if (mousePosition.Y < _anchorPoint.Y)
                    _selectRect.Y = mousePosition.Y;
                else
                    _selectRect.Y = _anchorPoint.Y;

                _selectRect.Width = Math.Abs(mousePosition.X - _anchorPoint.X);
                _selectRect.Height = Math.Abs(mousePosition.Y - _anchorPoint.Y);

                _geometry.Rect = _selectRect;
                AdornerLayer layer = AdornerLayer.GetAdornerLayer(_adornedElement);
                layer.InvalidateArrange();
            }
        }

        private void EndSelection(object sender, MouseButtonEventArgs e)
        {
            if (3 >= _selectRect.Width || 3 >= _selectRect.Height)
                _rubberband.Visibility = Visibility.Hidden;
            else
                _window.CropButton.IsEnabled = true;

            ReleaseMouseCapture();
        }
   
        protected override Visual GetVisualChild(int index)
        {
            return _rubberband;
        }
    }
#endif

#if NoVISUALCHILD

    public class RubberbandAdorner : Adorner
    {

        private UIElement _adornedElement;
        private bool _showRect;
        private Window1 _window;
        SolidColorBrush _brush;
        Pen _pen;
        private Rect _selectRect;
        public Rect SelectRect { get { return _selectRect; } set { _selectRect = value; } }
        public bool ShowRect { get { return _showRect; } set { _showRect = value; } }
        public Window1 Window { set { _window = value; } }

        public RubberbandAdorner(UIElement adornedElement)
            : base(adornedElement)
        {
            _adornedElement = adornedElement;
            _selectRect = new Rect();
            _brush = new SolidColorBrush();
            _brush.Color = Colors.Yellow;
            _brush.Opacity = .6;
            _pen = new Pen();
            _pen.Thickness = 2;
            _pen.Brush = _brush;
            _showRect = false;
            MouseMove += new MouseEventHandler(DrawSelection);
            MouseUp += new MouseButtonEventHandler(EndSelection);
        }

        public void StartSelection(Point anchorPoint)
        {
            _anchorPoint = anchorPoint;
            _selectRect.Size = new Size(0, 0);
            _selectRect.Location = _anchorPoint;
            if (!_showRect)
                _showRect = true;
        }

        private void DrawSelection(object sender, MouseEventArgs e)
        {
            if (e.LeftButton == MouseButtonState.Pressed)
            {
                Point mousePosition = e.GetPosition(_adornedElement);
                if (mousePosition.X < _anchorPoint.X)
                    _selectRect.X = mousePosition.X;
                else
                    _selectRect.X = _anchorPoint.X;
                if (mousePosition.Y < _anchorPoint.Y)
                    _selectRect.Y = mousePosition.Y;
                else
                    _selectRect.Y = _anchorPoint.Y;
                _selectRect.Width = Math.Abs(mousePosition.X - _anchorPoint.X);
                _selectRect.Height = Math.Abs(mousePosition.Y - _anchorPoint.Y);
                InvalidateArrange();
                AdornerLayer layer = AdornerLayer.GetAdornerLayer(_adornedElement);
                layer.InvalidateArrange();
            }
        }

        private void EndSelection(object sender, MouseButtonEventArgs e)
        {
            if (3 >= _selectRect.Width || 3 >= _selectRect.Height)
                ShowRect = false;
            else
                _window.CropButton.IsEnabled = true;
            ReleaseMouseCapture();
        }

        protected override void OnRender(DrawingContext drawingContext)
        {
            if (_showRect)
            {
                base.OnRender(drawingContext);
                drawingContext.DrawRectangle(Brushes.Transparent, _pen, _selectRect);
            }
            else
                return;
        }
    }
#endif

}

目前的代码是画一个实线框,而且是静止的。

有待改进的地方:
1. 如果需要制作类似Photoshop中的“蚂蚁行军”效果呢?如何写程序呢?
2. 如果需要制作类似Photoshop中已框选区域可移动,修改(比如:四周四角加方形手柄)呢? 

利用Adorner制作用于图像裁切的选择框的更多相关文章

  1. 类似 select 选择框效果及美化

    网上有各种各样的关于 select 选择框的美化,找了很多,并没有好的样式效果.所以就找了一个利用 ul li 做的类似 select 选择框的效果,不废话了,先上图,效果如下: 对于上图的箭头效果, ...

  2. Spinner列表选择框

    Spinner首先它是一个弹出式的列表选择框,由于间接继承了ViewGroup,所以它可以当做一个容器使用; 如果我们可以明确下拉列表中的列表项, 则可以不需要编写代码, 只需要为spinner指定a ...

  3. dreamweaver中的 map怎么调用?_制作热点图像区域

    我们浏览网页时,经常看到一些图片上会出现特别的超链接,即在一张图片上有多个局部区域和不同的网页链接,比如地图链接. 这就是映射图像(Image Map),它是指一幅根据链接对象不同而被人为划分为若干指 ...

  4. 【百度地图API】如何利用PhoneGap制作地图APP

    原文:[百度地图API]如何利用PhoneGap制作地图APP 摘要:百度地图API是一套由javascript编写的地图程序接口,按说它应该运行在浏览器上.现在,只要利用PhoneGap,我们就能开 ...

  5. 【203】利用UltraISO制作和刻录光盘映像的方法

    参考:利用UltraISO制作和刻录光盘映像的方法 软件:UltraISO注册版(制作镜像).rar 目录: 1.利用UltraISO制作光盘映像2.利用UltraISO刻录光盘映像文件 1.利用Ul ...

  6. SIFT算法总结:用于图像搜索

    原始文章链接:http://bubblexc.com/y2011/163/ 原文链接:http://blog.csdn.net/cserchen/article/details/5606859 关于三 ...

  7. 利用WIX制作安装包(2)

    原文 利用WIX制作安装包(2) 这一篇文章将为大家介绍如何使用WIX自定义UI.上一篇文章我们讲过WIX为我们提供了五种安装界面.每种安装界面都是由不同的Dialog组成.在这里我们挑选一种比较常用 ...

  8. 利用pil库处理图像

    1关于PIL PIL(Python Image Library)是python的第三方图像处理库,但是由于其强大的功能与众多的使用人数,几乎已经被认为是python官方图像处理库了. 2PIL的主要功 ...

  9. 利用Unity3D制作简易2D计算器

    利用Unity3D制作简易2D计算器 标签(空格分隔): uiniy3D 1. 操作流程 在unity3DD中创建一个新项目 注意选择是2D的(因为默认3D) 在Assets框右键新建C#脚本 在新建 ...

随机推荐

  1. [WASM] Create and Run a Native WebAssembly Function

    In this introduction, we show a simple WebAssembly function that returns the square root of a number ...

  2. Android中Activity切换时共享视图元素的切换动画(5.0以上)

    同一时候公布在我的博客 点此进入 背景 说来这个的背景很easy,常常在使用图片列表的时候就会想,假设"列表中的图片放大到整个屏幕"作为 Activity 的补间动画.就很完美了. ...

  3. hive SQL优化之distribute by和sort by

    近期在优化hiveSQL. 以下是一段排序,分组后取每组第一行记录的SQL INSERT OVERWRITE TABLE t_wa_funnel_distinct_temp PARTITION (pt ...

  4. 【t043】成绩查询

    Time Limit: 1 second Memory Limit: 128 MB [问题描述] 说起测试计算机的软件,排在第一位的就应当是SuperPi 了.它不但能良好的体现机器的整体水平,而且还 ...

  5. (十四)RabbitMQ消息队列-启用SSL安全通讯

    原文:(十四)RabbitMQ消息队列-启用SSL安全通讯 如果RabbitMQ服务在内网中,只有内网的应用连接,我们认为这些连接都是安全的,但是个别情况我们需要让RabbitMQ对外提供服务.这种情 ...

  6. solaris 11 stdio.h: No such file or directory

    http://www.zendo.name/solaris-11-stdio-h%EF%BC%9A-no-such-file-or-directory/ Posted on 2012 年 3 月 23 ...

  7. Windows 计算程序运行时间(高精度计时)

    首先,认识一下clock()和GetTickCount(): 一.clock()clock()是C/C++中的计时函数,而与其相关的数据类型是clock_t.在MSDN中,查得对clock函数定义如下 ...

  8. HTML中DOM对象的属性和方法的层级关系是怎样的?(目录即层次)

    HTML中DOM对象的属性和方法的层级关系是怎样的?(目录即层次) 一.总结 一句话总结:目录就是测试题 1.document取得元素(get element)的方式有哪几种? 解答:四种,分别是id ...

  9. 一入Python深似海--print

    先给大家来个干货^~^,学习Python的一个好站点,http://learnpythonthehardway.org/book/ 经典样例 以下是几个老经典的样例喽,刚接触Python的能够敲一敲, ...

  10. 通过手机其他iOS应用打开此文件

    根据所处理文档的格式,提供本地设备(InApp)能处理该格式文档的所有应用(App).比如,demo中所处理的是pdf格式的文档,那么可以打开该文档的本地app有邮件.打印等等.仅支持ARC. dem ...