当前位置:   article > 正文

.NET6 WPF 实现截图功能以及快捷键截图_wpf 截图

wpf 截图

1.需要添加引用

        System.Drawing.Common

2.主界面中添加一个按钮用于出发截图,按钮事件如下:

  1. 【MainWindow.xaml.cs】
  2. //截图按钮
  3. private void BTCut_Click(object sender, RoutedEventArgs e)
  4. {
  5. //截图时隐藏主窗体
  6. this.Hide();
  7. //截取屏幕的一帧,并打开一个窗体显示出来
  8. ScreenWindow snapWin = new ScreenWindow(CaptureCurrentScreen())
  9. {
  10. //ScreenWindow处理完成后回调的处理事件
  11. sendMessage = GetImageHandler
  12. };
  13. snapWin.ShowDialog();
  14. }
  15. private void GetImageHandler(Bitmap bitmap)
  16. {
  17. //此处写处理截图的逻辑
  18. }
  19. /// <summary>
  20. /// 截取屏幕
  21. /// </summary>
  22. /// <returns></returns>
  23. public static Bitmap CaptureCurrentScreen()
  24. {
  25. //创建与屏幕大小相同的位图对象
  26. var bmpScreen = new Bitmap((int)ScreenUtils.GetScreenWidth(), (int)ScreenUtils.GetScreenHeight(), System.Drawing.Imaging.PixelFormat.Format24bppRgb);
  27. //使用位图对象来创建Graphics的对象
  28. using (Graphics g = Graphics.FromImage(bmpScreen))
  29. {
  30. g.SmoothingMode = SmoothingMode.AntiAlias; //设置平滑模式,抗锯齿
  31. g.CompositingQuality = CompositingQuality.HighQuality; //设置合成质量
  32. g.InterpolationMode = InterpolationMode.HighQualityBicubic; //设置插值模式
  33. g.TextRenderingHint = TextRenderingHint.ClearTypeGridFit; //设置文本呈现的质量
  34. g.PixelOffsetMode = PixelOffsetMode.HighQuality; //设置呈现期间,像素偏移的方式
  35. //利用CopyFromScreen将当前屏幕截图并将内容存储在bmpScreen的位图中
  36. g.CopyFromScreen(0, 0, 0, 0, bmpScreen.Size, CopyPixelOperation.SourceCopy);
  37. }
  38. return bmpScreen;
  39. }

3.截屏后显示的窗体ScreenWindow代码如下

前台样式:

  1. <Window x:Class="myTestApp.Views.ScreenWindow"
  2. xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
  3. xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
  4. xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
  5. xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
  6. xmlns:local="clr-namespace:myTestApp.Views"
  7. mc:Ignorable="d"
  8. WindowState="Maximized" WindowStyle="None" AllowsTransparency="True" Background="Transparent"
  9. Title="ScreenWindow" Height="450" Width="800">
  10. <Grid>
  11. <InkCanvas Margin="0,0,0,0" Name="Ink" Visibility="Visible" EditingModeInverted="Select" EditingMode="Select" Cursor="Cross" MouseDown="Ink_MouseDown" MouseMove="Ink_MouseMove" MouseUp="Ink_MouseUp" MouseRightButtonDown="Ink_MouseRightButtonDown">
  12. </InkCanvas>
  13. <Border Name="Bord" Visibility="Collapsed" BorderThickness="2" HorizontalAlignment="Left" VerticalAlignment="Top" Cursor="Cross" BorderBrush="#FF09646D"/>
  14. <Button Name="Cancel" Visibility="Collapsed" Content="✘" FontSize="16" HorizontalAlignment="Left" Height="40" Margin="527,347,0,0" VerticalAlignment="Top" Width="40" BorderBrush="Red" Background="Red" Foreground="White" Click="Cancel_Click"/>
  15. <Button Name="Conf" Visibility="Collapsed" Content="✔" FontSize="16" HorizontalAlignment="Left" Height="40" Margin="527,347,0,0" VerticalAlignment="Top" Width="40" BorderBrush="#FF32510C" Background="#66C4EF3C" Foreground="White" Click="Conf_Click"/>
  16. </Grid>
  17. </Window>

后台代码:

  1. /// <summary>
  2. /// ScreenWindow.xaml 的交互逻辑
  3. /// </summary>
  4. public partial class ScreenWindow : Window
  5. {
  6. public delegate void SendMessage(Bitmap bitmap);
  7. public SendMessage sendMessage;
  8. #region Win32 API
  9. [DllImport("user32.dll")]
  10. static extern IntPtr GetDC(IntPtr ptr);
  11. [DllImport("gdi32.dll")]
  12. static extern int GetDeviceCaps(
  13. IntPtr hdc, // handle to DC
  14. int nIndex // index of capability
  15. );
  16. [DllImport("user32.dll", EntryPoint = "ReleaseDC")]
  17. static extern IntPtr ReleaseDC(IntPtr hWnd, IntPtr hDc);
  18. #endregion
  19. #region DeviceCaps常量
  20. const int HORZRES = 8;
  21. const int VERTRES = 10;
  22. const int LOGPIXELSX = 88;
  23. const int LOGPIXELSY = 90;
  24. const int DESKTOPVERTRES = 117;
  25. const int DESKTOPHORZRES = 118;
  26. #endregion
  27. private bool IsSnap = false;
  28. private Bitmap ScreenShot;
  29. public ScreenWindow(Bitmap bitmap)
  30. {
  31. InitializeComponent();
  32. this.Topmost = true;
  33. ScreenShot = bitmap;
  34. MouseDown += Ink_MouseDown;
  35. MouseUp += Ink_MouseUp;
  36. MouseMove += Ink_MouseMove;
  37. MouseRightButtonDown += Ink_MouseRightButtonDown;
  38. BitmapSource source;
  39. IsSnap = true;
  40. try
  41. {
  42. source = Imaging.CreateBitmapSourceFromHBitmap(ScreenShot.GetHbitmap(), IntPtr.Zero, Int32Rect.Empty, BitmapSizeOptions.FromEmptyOptions());
  43. }
  44. catch
  45. {
  46. source = null;
  47. }
  48. ImageBrush b = new ImageBrush();
  49. b.ImageSource = source;
  50. b.Stretch = Stretch.Fill;
  51. Ink.Background = b;
  52. Ink.EditingMode = InkCanvasEditingMode.None;
  53. this.WindowStartupLocation = WindowStartupLocation.Manual;
  54. this.Visibility = Visibility.Visible;
  55. this.Left = 0;
  56. this.Top = 0;
  57. this.Height = SystemParameters.VirtualScreenHeight;
  58. this.Width = SystemParameters.VirtualScreenWidth;
  59. }
  60. private bool ISDown = false; // 判断是否鼠标左键按下
  61. System.Windows.Point Startpoint = new System.Windows.Point();
  62. private void Ink_MouseDown(object sender, MouseButtonEventArgs e)
  63. {
  64. ISDown = true;
  65. Conf.Visibility = Visibility.Collapsed;
  66. Cancel.Visibility = Visibility.Collapsed;
  67. Startpoint = Mouse.GetPosition(this);
  68. }
  69. Rect rect;
  70. /// <summary>
  71. /// 根据鼠标移动画出矩形标识区域
  72. /// </summary>
  73. /// <param name="sender"></param>
  74. /// <param name="e"></param>
  75. private void Ink_MouseMove(object sender, MouseEventArgs e)
  76. {
  77. if (IsSnap)
  78. {
  79. if (ISDown == true)
  80. {
  81. System.Windows.Point point = Mouse.GetPosition(this);
  82. rect = new Rect(Startpoint, point);
  83. Bord.Visibility = Visibility.Visible;
  84. Bord.Margin = new Thickness(rect.Left, rect.Top, 0, 0);
  85. Bord.Height = rect.Height;
  86. Bord.Width = rect.Width;
  87. }
  88. }
  89. }
  90. Rect snapArea = new Rect();
  91. private void Ink_MouseUp(object sender, MouseButtonEventArgs e)
  92. {
  93. if (IsSnap)
  94. {
  95. ISDown = false;
  96. if (Bord.Visibility == Visibility.Collapsed)
  97. {
  98. Conf.Visibility = Visibility.Collapsed;
  99. Cancel.Visibility = Visibility.Collapsed;
  100. }
  101. else
  102. {
  103. Conf.Visibility = Visibility.Visible;
  104. Cancel.Visibility = Visibility.Visible;
  105. }
  106. if (rect.Width >= 10 && rect.Height >= 10)
  107. {
  108. if (System.Windows.Forms.SystemInformation.VirtualScreen.Height - rect.Bottom >= 0)
  109. {
  110. snapArea = rect;
  111. Conf.Margin = new Thickness(rect.Right - 40, rect.Bottom, 0, 0);
  112. Cancel.Margin = new Thickness(rect.Right - 80, rect.Bottom, 0, 0);
  113. }
  114. else
  115. {
  116. snapArea = rect;
  117. Conf.Margin = new Thickness(rect.Left + 10, rect.Top + 22, 0, 0);
  118. Cancel.Margin = new Thickness(rect.Left + 50, rect.Top + 22, 0, 0);
  119. }
  120. }
  121. }
  122. }
  123. private void Ink_MouseRightButtonDown(object sender, MouseButtonEventArgs e)
  124. {
  125. ISDown = false;
  126. Conf.Visibility = Visibility.Collapsed;
  127. Cancel.Visibility = Visibility.Collapsed;
  128. Bord.Visibility = Visibility.Collapsed;
  129. }
  130. private void Window_KeyDown(object sender, System.Windows.Input.KeyEventArgs e)
  131. {
  132. if (e.KeyStates == Keyboard.GetKeyStates(Key.Escape))
  133. {
  134. ISDown = false;
  135. Conf.Visibility = Visibility.Collapsed;
  136. Cancel.Visibility = Visibility.Collapsed;
  137. Bord.Visibility = Visibility.Collapsed;
  138. this.Close();
  139. }
  140. }
  141. /// <summary>
  142. /// 确认区域
  143. /// </summary>
  144. /// <param name="sender"></param>
  145. /// <param name="e"></param>
  146. private void Conf_Click(object sender, RoutedEventArgs e)
  147. {
  148. if (IsSnap)
  149. {
  150. double dpi = getDpi();
  151. System.Drawing.Rectangle rectangle = new System.Drawing.Rectangle((int)((snapArea.X + 2) * dpi), (int)((snapArea.Y + 2) * dpi), (int)((snapArea.Width - 4) * dpi), (int)((snapArea.Height - 4) * dpi));
  152. var bitmap1 = new Bitmap((int)(snapArea.Width * dpi), (int)(snapArea.Height * dpi), System.Drawing.Imaging.PixelFormat.Format32bppArgb);
  153. using (Graphics g = Graphics.FromImage(bitmap1))
  154. {
  155. g.CopyFromScreen(rectangle.X, rectangle.Y, 0, 0, rectangle.Size, CopyPixelOperation.SourceCopy);
  156. }
  157. this.Cursor = Cursors.Wait;
  158. sendMessage(bitmap1);
  159. this.Close();
  160. }
  161. }
  162. private void Cancel_Click(object sender, RoutedEventArgs e)
  163. {
  164. sendMessage(null);
  165. this.Close();
  166. }
  167. /// <summary>
  168. /// 获取系统dpi,这一步很重要
  169. /// </summary>
  170. /// <returns></returns>
  171. double getDpi()
  172. {
  173. double dDpi = 1;
  174. IntPtr desktopDc = GetDC(IntPtr.Zero);
  175. float horizontalDPI = GetDeviceCaps(desktopDc, LOGPIXELSX);
  176. float verticalDPI = GetDeviceCaps(desktopDc, LOGPIXELSY);
  177. int dpi = (int)(horizontalDPI + verticalDPI) / 2;
  178. dDpi = 1 + ((dpi - 96) / 24) * 0.25;
  179. if (dDpi < 1)
  180. {
  181. dDpi = 1;
  182. }
  183. ReleaseDC(IntPtr.Zero, desktopDc);
  184. return dDpi;
  185. }
  186. }

4.附:ScreenUtils.cs

  1. public class ScreenUtils
  2. {
  3. /// <summary>
  4. /// 获取DPI百分比
  5. /// </summary>
  6. /// <param name="window"></param>
  7. /// <returns></returns>
  8. public static double GetDpiRatio(Window window)
  9. {
  10. var currentGraphics = Graphics.FromHwnd(new WindowInteropHelper(window).Handle);
  11. return currentGraphics.DpiX / 96;
  12. }
  13. public static double GetDpiRatio()
  14. {
  15. return GetDpiRatio(Application.Current.MainWindow);
  16. }
  17. public static double GetScreenHeight()
  18. {
  19. return SystemParameters.PrimaryScreenHeight * GetDpiRatio();
  20. }
  21. public static double GetScreenActualHeight()
  22. {
  23. return SystemParameters.PrimaryScreenHeight;
  24. }
  25. public static double GetScreenWidth()
  26. {
  27. return SystemParameters.PrimaryScreenWidth * GetDpiRatio();
  28. }
  29. public static double GetScreenActualWidth()
  30. {
  31. return SystemParameters.PrimaryScreenWidth;
  32. }
  33. }

以上是实现截图功能的核心代码,接下来添加快捷键截图功能,通过Ctrl+Alt+A快捷截图

5.引用WindowsApi,用于注册全局快捷键,这样即使主窗体不在前台显示也能使用快捷键截图

添加HotKey.cs

  1. public class HotKey
  2. {
  3. [DllImport("user32.dll", SetLastError = true)]
  4. public static extern bool RegisterHotKey(
  5. IntPtr hWnd, // handle to window
  6. int id, // hot key identifier
  7. KeyModifiers fsModifiers, // key-modifier options
  8. System.Windows.Forms.Keys vk // virtual-key code
  9. );
  10. [DllImport("user32.dll", SetLastError = true)]
  11. public static extern bool UnregisterHotKey(
  12. IntPtr hWnd, // handle to window
  13. int id // hot key identifier
  14. );
  15. [Flags]
  16. public enum KeyModifiers
  17. {
  18. None = 0,
  19. Alt = 1,
  20. Control = 2,
  21. Shift = 4,
  22. Windows = 8
  23. }
  24. }

6.在主窗体完成初始化时注册全局快捷键

  1. 【MainWindow.xaml.cs】
  2. protected override void OnSourceInitialized(EventArgs e)
  3. {
  4. base.OnSourceInitialized(e);
  5. this.myHandle = new WindowInteropHelper(this).Handle;
  6. //组合键
  7. ctrHotKey = (uint)(KeyModifiers.Alt | KeyModifiers.Control);
  8. //注册
  9. bool f = RegisterHotKey(this.myHandle, 100, (KeyModifiers)ctrHotKey, Keys.A);//这时热键为Alt+CTRL+A
  10. HwndSource source = PresentationSource.FromVisual(this) as HwndSource;
  11. source.AddHook(WndProc);
  12. }
  13. //快捷键响应事件
  14. IntPtr WndProc(IntPtr hwnd, int msg, IntPtr wParam, IntPtr lParam, ref bool handle)
  15. {
  16. //Debug.WriteLine("hwnd:{0},msg:{1},wParam:{2},lParam{3}:,handle:{4}"
  17. // ,hwnd,msg,wParam,lParam,handle);
  18. string sid = wParam.ToString();
  19. switch (sid)
  20. {
  21. case "100":
  22. BTCut_Click(null, null);
  23. break;
  24. default:
  25. break;
  26. }
  27. return IntPtr.Zero;
  28. }

7.窗体程序退出时要注销掉全局快捷键

  1. 【MainWindow.xaml.cs】
  2. private void Window_Closing(object sender, System.ComponentModel.CancelEventArgs e)
  3. {
  4. UnregisterHotKey(this.myHandle, 100);//卸载快捷键
  5. }

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

闽ICP备14008679号