WPF开发者QQ群: 340500857 | 微信群 -> 进入公众号主页 加入组织
欢迎转发、分享、点赞、在看,谢谢~。
前言
有小伙伴需要在软件反馈窗体增加截图功能需求,所以今天来实现一个仿微信的截图。
01
—
效果预览
效果预览(更多效果请下载源码体验):
02
—
代码如下
一、ScreenCut.cs 代码如下
using Microsoft.Win32;
using System;
using System.Collections.Generic;
using System.Drawing.Drawing2D;
using System.Drawing.Text;
using System.Linq;
using System.Text;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Shapes;namespace WPFDevelopers.Controls
{[TemplatePart(Name = CanvasTemplateName, Type = typeof(Canvas))][TemplatePart(Name = RectangleLeftTemplateName, Type = typeof(Rectangle))][TemplatePart(Name = RectangleTopTemplateName, Type = typeof(Rectangle))][TemplatePart(Name = RectangleRightTemplateName, Type = typeof(Rectangle))][TemplatePart(Name = RectangleBottomTemplateName, Type = typeof(Rectangle))][TemplatePart(Name = BorderTemplateName, Type = typeof(Border))][TemplatePart(Name = WrapPanelTemplateName, Type = typeof(WrapPanel))][TemplatePart(Name = ButtonSaveTemplateName, Type = typeof(Button))][TemplatePart(Name = ButtonCancelTemplateName, Type = typeof(Button))][TemplatePart(Name = ButtonCompleteTemplateName, Type = typeof(Button))]public class ScreenCut : Window{private const string CanvasTemplateName = "PART_Canvas";private const string RectangleLeftTemplateName = "PART_RectangleLeft";private const string RectangleTopTemplateName = "PART_RectangleTop";private const string RectangleRightTemplateName = "PART_RectangleRight";private const string RectangleBottomTemplateName = "PART_RectangleBottom";private const string BorderTemplateName = "PART_Border";private const string WrapPanelTemplateName = "PART_WrapPanel";private const string ButtonSaveTemplateName = "PART_ButtonSave";private const string ButtonCancelTemplateName = "PART_ButtonCancel";private const string ButtonCompleteTemplateName = "PART_ButtonComplete";private Canvas _canvas;private Rectangle _rectangleLeft, _rectangleTop, _rectangleRight, _rectangleBottom;private Border _border;private WrapPanel _wrapPanel;private Button _buttonSave,_buttonCancel, _buttonComplete;private Rect rect;private Point pointStart, pointEnd;private bool isMouseUp = false;static ScreenCut(){DefaultStyleKeyProperty.OverrideMetadata(typeof(ScreenCut), new FrameworkPropertyMetadata(typeof(ScreenCut)));}public override void OnApplyTemplate(){base.OnApplyTemplate();_canvas = GetTemplateChild(CanvasTemplateName) as Canvas;_rectangleLeft = GetTemplateChild(RectangleLeftTemplateName) as Rectangle;_rectangleTop = GetTemplateChild(RectangleTopTemplateName) as Rectangle;_rectangleRight = GetTemplateChild(RectangleRightTemplateName) as Rectangle;_rectangleBottom = GetTemplateChild(RectangleBottomTemplateName) as Rectangle;_border = GetTemplateChild(BorderTemplateName) as Border;_wrapPanel = GetTemplateChild(WrapPanelTemplateName) as WrapPanel;_buttonSave = GetTemplateChild(ButtonSaveTemplateName) as Button;if (_buttonSave != null)_buttonSave.Click += _buttonSave_Click;_buttonCancel = GetTemplateChild(ButtonCancelTemplateName) as Button;if (_buttonCancel != null)_buttonCancel.Click += _buttonCancel_Click;_buttonComplete = GetTemplateChild(ButtonCompleteTemplateName) as Button;if (_buttonComplete != null)_buttonComplete.Click += _buttonComplete_Click;this._canvas.Background = new ImageBrush(ChangeBitmapToImageSource(CaptureScreen()));_rectangleLeft.Width = _canvas.Width;_rectangleLeft.Height = _canvas.Height;}private void _buttonSave_Click(object sender, RoutedEventArgs e){SaveFileDialog dlg = new SaveFileDialog();dlg.FileName = $"WPFDevelopers{DateTime.Now.ToString("yyyyMMddHHmmss")}.jpg";dlg.DefaultExt = ".jpg";dlg.Filter = "image file|*.jpg";if (dlg.ShowDialog() == true){BitmapEncoder pngEncoder = new PngBitmapEncoder();pngEncoder.Frames.Add(BitmapFrame.Create(CutBitmap()));using (var fs = System.IO.File.OpenWrite(dlg.FileName)){pngEncoder.Save(fs);fs.Dispose();fs.Close();}}Close();}private void _buttonComplete_Click(object sender, RoutedEventArgs e){Clipboard.SetImage(CutBitmap());Close();}CroppedBitmap CutBitmap(){var renderTargetBitmap = new RenderTargetBitmap((int)_canvas.Width,(int)_canvas.Height, 96d, 96d, System.Windows.Media.PixelFormats.Default);renderTargetBitmap.Render(_canvas);return new CroppedBitmap(renderTargetBitmap, new Int32Rect((int)rect.X, (int)rect.Y, (int)rect.Width, (int)rect.Height));}private void _buttonCancel_Click(object sender, RoutedEventArgs e){Close();}protected override void OnPreviewKeyDown(KeyEventArgs e){if (e.Key == Key.Escape)Close();}protected override void OnPreviewMouseLeftButtonDown(MouseButtonEventArgs e){if (!isMouseUp){_wrapPanel.Visibility = Visibility.Hidden;pointStart = e.GetPosition(_canvas);pointEnd = pointStart;rect = new Rect(pointStart, pointEnd);}}protected override void OnPreviewMouseMove(MouseEventArgs e){if (e.LeftButton == MouseButtonState.Pressed && !isMouseUp){var current = e.GetPosition(_canvas);MoveAllRectangle(current);}}protected override void OnPreviewMouseLeftButtonUp(MouseButtonEventArgs e){if (!isMouseUp){_wrapPanel.Visibility = Visibility.Visible;Canvas.SetLeft(this._wrapPanel, rect.X + rect.Width - this._wrapPanel.ActualWidth);Canvas.SetTop(this._wrapPanel, rect.Y + rect.Height + 4);isMouseUp = true;}}void MoveAllRectangle(Point current){pointEnd = current;rect = new Rect(pointStart, pointEnd);this._rectangleLeft.Width = rect.X;this._rectangleLeft.Height = _canvas.Height;Canvas.SetLeft(this._rectangleTop, this._rectangleLeft.Width);this._rectangleTop.Width = rect.Width;double h = 0.0;if (current.Y < pointStart.Y)h = current.Y;elseh = current.Y - rect.Height;this._rectangleTop.Height = h;Canvas.SetLeft(this._rectangleRight, this._rectangleLeft.Width + rect.Width);this._rectangleRight.Width = _canvas.Width - (rect.Width + this._rectangleLeft.Width);this._rectangleRight.Height = _canvas.Height;Canvas.SetLeft(this._rectangleBottom, this._rectangleLeft.Width);Canvas.SetTop(this._rectangleBottom, rect.Height + this._rectangleTop.Height);this._rectangleBottom.Width = rect.Width;this._rectangleBottom.Height = _canvas.Height - (rect.Height + this._rectangleTop.Height);this._border.Height = rect.Height;this._border.Width = rect.Width;Canvas.SetLeft(this._border, rect.X);Canvas.SetTop(this._border, rect.Y);}System.Drawing.Bitmap CaptureScreen(){var bmpCaptured = new System.Drawing.Bitmap((int)SystemParameters.PrimaryScreenWidth, (int)SystemParameters.PrimaryScreenHeight, System.Drawing.Imaging.PixelFormat.Format24bppRgb);using (System.Drawing.Graphics g = System.Drawing.Graphics.FromImage(bmpCaptured)){g.SmoothingMode = SmoothingMode.AntiAlias;g.CompositingQuality = CompositingQuality.HighQuality;g.InterpolationMode = InterpolationMode.HighQualityBicubic;g.TextRenderingHint = TextRenderingHint.ClearTypeGridFit;g.PixelOffsetMode = PixelOffsetMode.HighQuality;g.CopyFromScreen(0, 0, 0, 0, bmpCaptured.Size, System.Drawing.CopyPixelOperation.SourceCopy);}return bmpCaptured;}[System.Runtime.InteropServices.DllImport("gdi32.dll")]public static extern bool DeleteObject(IntPtr hObject);ImageSource ChangeBitmapToImageSource(System.Drawing.Bitmap bitmap){IntPtr hBitmap = bitmap.GetHbitmap();ImageSource wpfBitmap = System.Windows.Interop.Imaging.CreateBitmapSourceFromHBitmap(hBitmap,IntPtr.Zero,Int32Rect.Empty,BitmapSizeOptions.FromEmptyOptions());if (!DeleteObject(hBitmap)){throw new System.ComponentModel.Win32Exception();}return wpfBitmap;}}
}
二、ScreenCut.xaml 代码如下
<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"xmlns:controls="clr-namespace:WPFDevelopers.Controls"><ResourceDictionary.MergedDictionaries><ResourceDictionary Source="Basic/ControlBasic.xaml"/><ResourceDictionary Source="../Styles/Styles.Buttons.xaml"/></ResourceDictionary.MergedDictionaries><Style x:Key="RectangleStyle" TargetType="{x:Type Rectangle}"><Setter Property="Fill" Value="{StaticResource BlackSolidColorBrush}"/><Setter Property="Opacity" Value=".5"/>
</Style><Style TargetType="{x:Type controls:ScreenCut}" BasedOn="{StaticResource ControlBasicStyle}"><Setter Property="WindowState" Value="Maximized"/><Setter Property="WindowStyle" Value="None"/><Setter Property="Template"><Setter.Value><ControlTemplate TargetType="{x:Type controls:ScreenCut}"><Canvas x:Name="PART_Canvas"Width="{Binding Source={x:Static SystemParameters.PrimaryScreenWidth}}"Height="{Binding Source={x:Static SystemParameters.PrimaryScreenHeight}}"><Rectangle x:Name="PART_RectangleLeft" Style="{StaticResource RectangleStyle}"/><Rectangle x:Name="PART_RectangleTop" Style="{StaticResource RectangleStyle}"/><Rectangle x:Name="PART_RectangleRight" Style="{StaticResource RectangleStyle}"/><Rectangle x:Name="PART_RectangleBottom" Style="{StaticResource RectangleStyle}"/><Border x:Name="PART_Border" BorderBrush="{StaticResource SuccessPressedSolidColorBrush}" BorderThickness="1"/><WrapPanel x:Name="PART_WrapPanel" Visibility="Hidden" Panel.ZIndex="99"Height="38" Background="{StaticResource WhiteSolidColorBrush}"VerticalAlignment="Center"><Button x:Name="PART_ButtonSave" Style="{StaticResource PathButton}"ToolTip="保存" Margin="10,0,0,0"><Button.Content><Path Fill="{StaticResource InfoPressedSolidColorBrush}" Width="18" Height="18" Stretch="Fill" Data="{StaticResource PathSave}"/></Button.Content></Button><Button x:Name="PART_ButtonCancel" Style="{StaticResource PathButton}"ToolTip="取消"><Button.Content><Path Fill="{StaticResource DangerPressedSolidColorBrush}" Width="14" Height="14" Stretch="Fill" Data="{StaticResource PathCancel}"/></Button.Content></Button><Button x:Name="PART_ButtonComplete" Style="{StaticResource PathButton}"ToolTip="完成" Margin="0,0,10,0"><Button.Content><Path Fill="{StaticResource SuccessPressedSolidColorBrush}" Width="20" Height="15" Stretch="Fill" Data="{StaticResource PathComplete}"/></Button.Content></Button></WrapPanel></Canvas></ControlTemplate></Setter.Value></Setter>
</Style>
</ResourceDictionary>
三、ScreenCutExample.xaml 代码如下
var screenCut = new ScreenCut();screenCut.ShowDialog();
源码地址
github:https://github.com/yanjinhuagood/WPFDevelopers.git
gitee:https://gitee.com/yanjinhua/WPFDevelopers.git
WPF开发者QQ群: 340500857
blogs: https://www.cnblogs.com/yanjinhua
Github:https://github.com/yanjinhuagood
出处:https://www.cnblogs.com/yanjinhua
版权:本作品采用「署名-非商业性使用-相同方式共享 4.0 国际」许可协议进行许可。
转载请著名作者 出处 https://github.com/yanjinhuagood