先上效果图
源码下载地址:http://download.youkuaiyun.com/detail/candyvoice/9788099
描述:启动程序,点击窗口button,开始截图,鼠标左键按下拖动,选中任意区域,拖动过程中,左上角实时显示选中区域大小,拖动结束,鼠标左键抬起,出现右下角保存、取消、ok三个button。右键点击,取消当前选中,可以继续拖动鼠标左键进行截图。双击右键,退出截图功能。按键盘ESC键,可退出截图。
原理:说的通俗一些,就是在原有的界面上盖上一层Canvas,就是画布,然后在这个画布上画矩形,也就是填充矩形的四周,空出来的地方就变成矩形了,如下图。边框线,线上可拖动的小方框、顶角可拖动的小圆球,都是自定义的样式,可在代码的generic.xaml文件中看到具体的设计。
参考资料:http://www.cnblogs.com/zhouyinhui/archive/2010/08/20/1804762.html
这个楼主原理的细节方面已经说的很详细,大家可以仔细看看。
根据上述楼主的代码,主要修改了以下两个类。
MaskCanvas.cs就是操作画布的类,MaskWindow.cs就是截图窗口的类。左上角大小显示框,是一label;右下角的三个按钮是一个自定义的toolbar。
1 MaskCanvas.cs
using System;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Input;
using System.Windows.Media;
namespace RisCaptureLib
{
internal class MaskCanvas : Canvas
{
public delegate void FrameDrawEventHander(Rect rect);
public event FrameDrawEventHander OnMove;
public MaskCanvas()
{
Loaded += OnLoaded;
}
private void OnLoaded(object sender, RoutedEventArgs e)
{
//make the render effect same as SnapsToDevicePixels
//"SnapsToDevicePixels = true;" doesn't work on "OnRender"
//however, this maybe make some offset form the render target's origin location
//SetValue(RenderOptions.EdgeModeProperty, EdgeMode.Aliased);
//ini this
Cursor = BitmapCursor.CreateCrossCursor();
Background = Brushes.Transparent;
//ini mask rect
maskRectLeft.Fill = maskRectRight.Fill = maskRectTop.Fill = maskRectBottom.Fill = Config.MaskWindowBackground;
//these propeties(x, y...) will not changed
SetLeft(maskRectLeft, 0);
SetTop(maskRectLeft, 0);
SetRight(maskRectRight, 0);
SetTop(maskRectRight, 0);
SetTop(maskRectTop, 0);
SetBottom(maskRectBottom, 0);
maskRectLeft.Height = ActualHeight;
Children.Add(maskRectLeft);
Children.Add(maskRectRight);
Children.Add(maskRectTop);
Children.Add(maskRectBottom);
//ini selection border
selectionBorder.Stroke = Config.SelectionBorderBrush;
selectionBorder.StrokeThickness = Config.SelectionBorderThickness.Left;
Children.Add(selectionBorder);
//ini indicator
indicator = new IndicatorObject(this);
Children.Add(indicator);
CompositionTarget.Rendering += OnCompositionTargetRendering;
}
private void UpdateSelectionBorderLayout()
{
if (!selectionRegion.IsEmpty)
{
SetLeft(selectionBorder, selectionRegion.Left);
SetTop(selectionBorder, selectionRegion.Top);
selectionBorder.Width = selectionRegion.Width;
selectionBorder.Height = selectionRegion.Height;
}
}
private void UpdateMaskRectanglesLayout()
{
var actualHeight = ActualHeight;
var actualWidth = ActualWidth;
if (selectionRegion.IsEmpty)
{
SetLeft(maskRectLeft, 0);
SetTop(maskRectLeft, 0);
maskRectLeft.Width = actualWidth;
maskRectLeft.Height = actualHeight;
maskRectRight.Width = maskRectRight.Height = maskRectTop.Width = maskRectTop.Height = maskRectBottom.Width = maskRectBottom.Height = 0;
}
else
{
var temp = selectionRegion.Left;
if (maskRectLeft.Width != temp)
{
maskRectLeft.Width = temp < 0 ? 0 : temp; //Math.Max(0, selectionRegion.Left);
}
temp = ActualWidth - selectionRegion.Right;
if (maskRectRight.Width != temp)
{
maskRectRight.Width = temp < 0 ? 0 : temp; //Math.Max(0, ActualWidth - selectionRegion.Right);
}
if (maskRectRight.Height != actualHeight)
{
maskRectRight.Height = actualH