当前位置:   article > 正文

WPF实现截屏(仿微信)

wpf微信截图自动粘贴到对话框

 WPF开发者QQ群: 340500857  | 微信群 -> 进入公众号主页 加入组织

欢迎转发、分享、点赞、在看,谢谢~。0cdabee0d251d8e0f7ef85d0447f6d4c.png  

前言

      有小伙伴需要在软件反馈窗体增加截图功能需求,所以今天来实现一个仿微信的截图。

01

效果预览

效果预览(更多效果请下载源码体验):

02


代码如下

一、ScreenCut.cs 代码如下

  1. using Microsoft.Win32;
  2. using System;
  3. using System.Collections.Generic;
  4. using System.Drawing.Drawing2D;
  5. using System.Drawing.Text;
  6. using System.Linq;
  7. using System.Text;
  8. using System.Windows;
  9. using System.Windows.Controls;
  10. using System.Windows.Input;
  11. using System.Windows.Media;
  12. using System.Windows.Media.Imaging;
  13. using System.Windows.Shapes;
  14. namespace WPFDevelopers.Controls
  15. {
  16. [TemplatePart(Name = CanvasTemplateName, Type = typeof(Canvas))]
  17. [TemplatePart(Name = RectangleLeftTemplateName, Type = typeof(Rectangle))]
  18. [TemplatePart(Name = RectangleTopTemplateName, Type = typeof(Rectangle))]
  19. [TemplatePart(Name = RectangleRightTemplateName, Type = typeof(Rectangle))]
  20. [TemplatePart(Name = RectangleBottomTemplateName, Type = typeof(Rectangle))]
  21. [TemplatePart(Name = BorderTemplateName, Type = typeof(Border))]
  22. [TemplatePart(Name = WrapPanelTemplateName, Type = typeof(WrapPanel))]
  23. [TemplatePart(Name = ButtonSaveTemplateName, Type = typeof(Button))]
  24. [TemplatePart(Name = ButtonCancelTemplateName, Type = typeof(Button))]
  25. [TemplatePart(Name = ButtonCompleteTemplateName, Type = typeof(Button))]
  26. public class ScreenCut : Window
  27. {
  28. private const string CanvasTemplateName = "PART_Canvas";
  29. private const string RectangleLeftTemplateName = "PART_RectangleLeft";
  30. private const string RectangleTopTemplateName = "PART_RectangleTop";
  31. private const string RectangleRightTemplateName = "PART_RectangleRight";
  32. private const string RectangleBottomTemplateName = "PART_RectangleBottom";
  33. private const string BorderTemplateName = "PART_Border";
  34. private const string WrapPanelTemplateName = "PART_WrapPanel";
  35. private const string ButtonSaveTemplateName = "PART_ButtonSave";
  36. private const string ButtonCancelTemplateName = "PART_ButtonCancel";
  37. private const string ButtonCompleteTemplateName = "PART_ButtonComplete";
  38. private Canvas _canvas;
  39. private Rectangle _rectangleLeft, _rectangleTop, _rectangleRight, _rectangleBottom;
  40. private Border _border;
  41. private WrapPanel _wrapPanel;
  42. private Button _buttonSave,_buttonCancel, _buttonComplete;
  43. private Rect rect;
  44. private Point pointStart, pointEnd;
  45. private bool isMouseUp = false;
  46. static ScreenCut()
  47. {
  48. DefaultStyleKeyProperty.OverrideMetadata(typeof(ScreenCut), new FrameworkPropertyMetadata(typeof(ScreenCut)));
  49. }
  50. public override void OnApplyTemplate()
  51. {
  52. base.OnApplyTemplate();
  53. _canvas = GetTemplateChild(CanvasTemplateName) as Canvas;
  54. _rectangleLeft = GetTemplateChild(RectangleLeftTemplateName) as Rectangle;
  55. _rectangleTop = GetTemplateChild(RectangleTopTemplateName) as Rectangle;
  56. _rectangleRight = GetTemplateChild(RectangleRightTemplateName) as Rectangle;
  57. _rectangleBottom = GetTemplateChild(RectangleBottomTemplateName) as Rectangle;
  58. _border = GetTemplateChild(BorderTemplateName) as Border;
  59. _wrapPanel = GetTemplateChild(WrapPanelTemplateName) as WrapPanel;
  60. _buttonSave = GetTemplateChild(ButtonSaveTemplateName) as Button;
  61. if (_buttonSave != null)
  62. _buttonSave.Click += _buttonSave_Click;
  63. _buttonCancel = GetTemplateChild(ButtonCancelTemplateName) as Button;
  64. if (_buttonCancel != null)
  65. _buttonCancel.Click += _buttonCancel_Click;
  66. _buttonComplete = GetTemplateChild(ButtonCompleteTemplateName) as Button;
  67. if (_buttonComplete != null)
  68. _buttonComplete.Click += _buttonComplete_Click;
  69. this._canvas.Background = new ImageBrush(ChangeBitmapToImageSource(CaptureScreen()));
  70. _rectangleLeft.Width = _canvas.Width;
  71. _rectangleLeft.Height = _canvas.Height;
  72. }
  73. private void _buttonSave_Click(object sender, RoutedEventArgs e)
  74. {
  75. SaveFileDialog dlg = new SaveFileDialog();
  76. dlg.FileName = $"WPFDevelopers{DateTime.Now.ToString("yyyyMMddHHmmss")}.jpg";
  77. dlg.DefaultExt = ".jpg";
  78. dlg.Filter = "image file|*.jpg";
  79. if (dlg.ShowDialog() == true)
  80. {
  81. BitmapEncoder pngEncoder = new PngBitmapEncoder();
  82. pngEncoder.Frames.Add(BitmapFrame.Create(CutBitmap()));
  83. using (var fs = System.IO.File.OpenWrite(dlg.FileName))
  84. {
  85. pngEncoder.Save(fs);
  86. fs.Dispose();
  87. fs.Close();
  88. }
  89. }
  90. Close();
  91. }
  92. private void _buttonComplete_Click(object sender, RoutedEventArgs e)
  93. {
  94. Clipboard.SetImage(CutBitmap());
  95. Close();
  96. }
  97. CroppedBitmap CutBitmap()
  98. {
  99. var renderTargetBitmap = new RenderTargetBitmap((int)_canvas.Width,
  100. (int)_canvas.Height, 96d, 96d, System.Windows.Media.PixelFormats.Default);
  101. renderTargetBitmap.Render(_canvas);
  102. return new CroppedBitmap(renderTargetBitmap, new Int32Rect((int)rect.X, (int)rect.Y, (int)rect.Width, (int)rect.Height));
  103. }
  104. private void _buttonCancel_Click(object sender, RoutedEventArgs e)
  105. {
  106. Close();
  107. }
  108. protected override void OnPreviewKeyDown(KeyEventArgs e)
  109. {
  110. if (e.Key == Key.Escape)
  111. Close();
  112. }
  113. protected override void OnPreviewMouseLeftButtonDown(MouseButtonEventArgs e)
  114. {
  115. if (!isMouseUp)
  116. {
  117. _wrapPanel.Visibility = Visibility.Hidden;
  118. pointStart = e.GetPosition(_canvas);
  119. pointEnd = pointStart;
  120. rect = new Rect(pointStart, pointEnd);
  121. }
  122. }
  123. protected override void OnPreviewMouseMove(MouseEventArgs e)
  124. {
  125. if (e.LeftButton == MouseButtonState.Pressed && !isMouseUp)
  126. {
  127. var current = e.GetPosition(_canvas);
  128. MoveAllRectangle(current);
  129. }
  130. }
  131. protected override void OnPreviewMouseLeftButtonUp(MouseButtonEventArgs e)
  132. {
  133. if (!isMouseUp)
  134. {
  135. _wrapPanel.Visibility = Visibility.Visible;
  136. Canvas.SetLeft(this._wrapPanel, rect.X + rect.Width - this._wrapPanel.ActualWidth);
  137. Canvas.SetTop(this._wrapPanel, rect.Y + rect.Height + 4);
  138. isMouseUp = true;
  139. }
  140. }
  141. void MoveAllRectangle(Point current)
  142. {
  143. pointEnd = current;
  144. rect = new Rect(pointStart, pointEnd);
  145. this._rectangleLeft.Width = rect.X;
  146. this._rectangleLeft.Height = _canvas.Height;
  147. Canvas.SetLeft(this._rectangleTop, this._rectangleLeft.Width);
  148. this._rectangleTop.Width = rect.Width;
  149. double h = 0.0;
  150. if (current.Y < pointStart.Y)
  151. h = current.Y;
  152. else
  153. h = current.Y - rect.Height;
  154. this._rectangleTop.Height = h;
  155. Canvas.SetLeft(this._rectangleRight, this._rectangleLeft.Width + rect.Width);
  156. this._rectangleRight.Width = _canvas.Width - (rect.Width + this._rectangleLeft.Width);
  157. this._rectangleRight.Height = _canvas.Height;
  158. Canvas.SetLeft(this._rectangleBottom, this._rectangleLeft.Width);
  159. Canvas.SetTop(this._rectangleBottom, rect.Height + this._rectangleTop.Height);
  160. this._rectangleBottom.Width = rect.Width;
  161. this._rectangleBottom.Height = _canvas.Height - (rect.Height + this._rectangleTop.Height);
  162. this._border.Height = rect.Height;
  163. this._border.Width = rect.Width;
  164. Canvas.SetLeft(this._border, rect.X);
  165. Canvas.SetTop(this._border, rect.Y);
  166. }
  167. System.Drawing.Bitmap CaptureScreen()
  168. {
  169. var bmpCaptured = new System.Drawing.Bitmap((int)SystemParameters.PrimaryScreenWidth, (int)SystemParameters.PrimaryScreenHeight, System.Drawing.Imaging.PixelFormat.Format24bppRgb);
  170. using (System.Drawing.Graphics g = System.Drawing.Graphics.FromImage(bmpCaptured))
  171. {
  172. g.SmoothingMode = SmoothingMode.AntiAlias;
  173. g.CompositingQuality = CompositingQuality.HighQuality;
  174. g.InterpolationMode = InterpolationMode.HighQualityBicubic;
  175. g.TextRenderingHint = TextRenderingHint.ClearTypeGridFit;
  176. g.PixelOffsetMode = PixelOffsetMode.HighQuality;
  177. g.CopyFromScreen(0, 0, 0, 0, bmpCaptured.Size, System.Drawing.CopyPixelOperation.SourceCopy);
  178. }
  179. return bmpCaptured;
  180. }
  181. [System.Runtime.InteropServices.DllImport("gdi32.dll")]
  182. public static extern bool DeleteObject(IntPtr hObject);
  183. ImageSource ChangeBitmapToImageSource(System.Drawing.Bitmap bitmap)
  184. {
  185. IntPtr hBitmap = bitmap.GetHbitmap();
  186. ImageSource wpfBitmap = System.Windows.Interop.Imaging.CreateBitmapSourceFromHBitmap(
  187. hBitmap,
  188. IntPtr.Zero,
  189. Int32Rect.Empty,
  190. BitmapSizeOptions.FromEmptyOptions());
  191. if (!DeleteObject(hBitmap))
  192. {
  193. throw new System.ComponentModel.Win32Exception();
  194. }
  195. return wpfBitmap;
  196. }
  197. }
  198. }


二、ScreenCut.xaml 代码如下 

  1. <ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
  2. xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
  3. xmlns:controls="clr-namespace:WPFDevelopers.Controls">
  4. <ResourceDictionary.MergedDictionaries>
  5. <ResourceDictionary Source="Basic/ControlBasic.xaml"/>
  6. <ResourceDictionary Source="../Styles/Styles.Buttons.xaml"/>
  7. </ResourceDictionary.MergedDictionaries>
  8. <Style x:Key="RectangleStyle" TargetType="{x:Type Rectangle}">
  9. <Setter Property="Fill" Value="{StaticResource BlackSolidColorBrush}"/>
  10. <Setter Property="Opacity" Value=".5"/>
  11. </Style>
  12. <Style TargetType="{x:Type controls:ScreenCut}" BasedOn="{StaticResource ControlBasicStyle}">
  13. <Setter Property="WindowState" Value="Maximized"/>
  14. <Setter Property="WindowStyle" Value="None"/>
  15. <Setter Property="Template">
  16. <Setter.Value>
  17. <ControlTemplate TargetType="{x:Type controls:ScreenCut}">
  18. <Canvas x:Name="PART_Canvas"
  19. Width="{Binding Source={x:Static SystemParameters.PrimaryScreenWidth}}"
  20. Height="{Binding Source={x:Static SystemParameters.PrimaryScreenHeight}}">
  21. <Rectangle x:Name="PART_RectangleLeft" Style="{StaticResource RectangleStyle}"/>
  22. <Rectangle x:Name="PART_RectangleTop" Style="{StaticResource RectangleStyle}"/>
  23. <Rectangle x:Name="PART_RectangleRight" Style="{StaticResource RectangleStyle}"/>
  24. <Rectangle x:Name="PART_RectangleBottom" Style="{StaticResource RectangleStyle}"/>
  25. <Border x:Name="PART_Border" BorderBrush="{StaticResource SuccessPressedSolidColorBrush}"
  26. BorderThickness="1"/>
  27. <WrapPanel x:Name="PART_WrapPanel"
  28. Visibility="Hidden" Panel.ZIndex="99"
  29. Height="38" Background="{StaticResource WhiteSolidColorBrush}"
  30. VerticalAlignment="Center">
  31. <Button x:Name="PART_ButtonSave" Style="{StaticResource PathButton}"
  32. ToolTip="保存" Margin="10,0,0,0">
  33. <Button.Content>
  34. <Path Fill="{StaticResource InfoPressedSolidColorBrush}"
  35. Width="18" Height="18" Stretch="Fill"
  36. Data="{StaticResource PathSave}"/>
  37. </Button.Content>
  38. </Button>
  39. <Button x:Name="PART_ButtonCancel" Style="{StaticResource PathButton}"
  40. ToolTip="取消">
  41. <Button.Content>
  42. <Path Fill="{StaticResource DangerPressedSolidColorBrush}"
  43. Width="14" Height="14" Stretch="Fill"
  44. Data="{StaticResource PathCancel}"/>
  45. </Button.Content>
  46. </Button>
  47. <Button x:Name="PART_ButtonComplete" Style="{StaticResource PathButton}"
  48. ToolTip="完成" Margin="0,0,10,0">
  49. <Button.Content>
  50. <Path Fill="{StaticResource SuccessPressedSolidColorBrush}"
  51. Width="20" Height="15" Stretch="Fill"
  52. Data="{StaticResource PathComplete}"/>
  53. </Button.Content>
  54. </Button>
  55. </WrapPanel>
  56. </Canvas>
  57. </ControlTemplate>
  58. </Setter.Value>
  59. </Setter>
  60. </Style>
  61. </ResourceDictionary>


三、ScreenCutExample.xaml 代码如下

  1. var screenCut = new ScreenCut();
  2. 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

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/不正经/article/detail/139303
推荐阅读
相关标签
  

闽ICP备14008679号