采用WPF开发截图程序,so easy!

  • 2019 年 10 月 19 日
  • 筆記

前言  QQ、微信截图功能已很强大了,似乎没必要在开发一个截图程序了。但是有时QQ热键就是被占用,不能快速的开启截屏;有时,天天挂着QQ,领导也不乐意。既然是程序员,就要自己开发截屏工具,功能随心所欲,岂不快哉。

再强调一点:工具就是生产力!没有掌握WPF之前,我是不会开发这么一个程序的,如果采用MFC、winform框架,工作量太大,开发出来的效果肯定也比较low。本人用WPF,花了一天的功夫,开发了这个小程序。程序的定位就功能简单,平时工作不碍事,用着的时候,一键截图!

 界面  执行程序下载 一键截图

 程序就一个按钮,点击开始截屏,就是这么简单。看似简单,对开发技巧要求很高。内行看门道!

开发思虑

  常言道:看到的不一定是真实的。开发也要这样。程序叫截屏,你不要一股劲想着怎么截取别的窗口图案,肯定很费劲!思虑就是掩人耳目:先将整个屏幕复制,放到自己程序窗体中,窗体最大化,覆盖整个屏幕!用户看到还是整个屏幕,但是整个屏幕已被偷梁换柱!此后,你所有的操作都是在自己窗体上处理,当然可以随心所欲了!

截取整个屏幕

       public Bitmap GetScreenSnapshot()          {              System.Drawing.Rectangle rc = SystemInformation.VirtualScreen;              var bitmap = new Bitmap(rc.Width, rc.Height, System.Drawing.Imaging.PixelFormat.Format32bppArgb);                using (Graphics memoryGrahics = Graphics.FromImage(bitmap))              {                  memoryGrahics.CopyFromScreen(rc.X, rc.Y, 0, 0, rc.Size, CopyPixelOperation.SourceCopy);              }                return bitmap;          }

创建全屏窗体

 注意窗体属性,这样才能全面覆盖整个屏幕。

图层布局

这个很有技巧!为了实现非截图区域阴影效果,费了一番心机!即使这样,感觉也比winform用起来得心应手!

注:我不是一直贬低winform,但是要承认,这两个东西不是一个时代产物。wpf设计思路比winform先进很多。只是wpf新概念多,用的人少,开发起来常常蒙圈!经过一段迷茫期,前途就会光明了!

窗口的布局,不多说了!直接上代码。我对代码做了注释!

    <Grid>          <!-- 整个屏幕图像 -->          <Image x:Name="imgScreen"                 MouseDown="ImgScreen_MouseDown"                 MouseUp="ImgScreen_MouseUp"                 Stretch="None"                 MouseMove="ImgScreen_MouseMove">          </Image>            <!-- 覆盖一层黑色,半透明状 -->          <Grid x:Name="gridCover" Visibility="Collapsed" Background="Black" Opacity="0.5">          </Grid>            <Grid>              <Grid.RowDefinitions>                  <RowDefinition Height="*"></RowDefinition>                  <RowDefinition Height="auto"></RowDefinition>              </Grid.RowDefinitions>              <!-- 前面覆盖了一层黑色,但是截取的图像不能覆盖,只能在这里再显示截取图像 -->              <Image x:Name="imgCut" Grid.RowSpan="3" Stretch="None"                     HorizontalAlignment="Left" VerticalAlignment="Top"></Image>              <!--显示提示信息-->              <TextBlock HorizontalAlignment="Center" VerticalAlignment="Center"                             FontSize="22" Foreground="Yellow"                            Opacity="0.8" >滑动鼠标开始截屏 按ESC键退出</TextBlock>                <StackPanel  Grid.RowSpan="3">                  <!--截图指示框-->                  <Border x:Name="borderSelect"                  HorizontalAlignment="Left" VerticalAlignment="Top"                  BorderThickness="1" BorderBrush="Red"></Border>                  <!--宽和高指示-->                  <StackPanel Orientation="Horizontal">                      <TextBlock x:Name="txtCutInfo" Background="Black" Padding="3"                                 HorizontalAlignment="Left"                                 Foreground="White"></TextBlock>                  </StackPanel>                </StackPanel>            </Grid>      </Grid>

当鼠标移动时,不断的计算选中区域,设置borderSelect属性。

 private void ImgScreen_MouseMove(object sender, MouseEventArgs e)          {              if (!_isMouseDown)                  return;                gridCover.Visibility = Visibility.Visible;                //计算鼠标选中区域              Point currentPoint = e.GetPosition(imgScreen);              Point borderPoint = e.GetPosition(borderSelect);                double xDelta = xDelta_BoderToImgScreen;              double yDelta = yDelta_BoderToImgScreen;                _rectImgCut = ImageHelper.ToRect(currentPoint, _startPoint);                Rect rectBoderCut = ImageHelper.ToRect(new Point(currentPoint.X + xDelta, currentPoint.Y + yDelta),                  new Point(_startPoint.X + xDelta, _startPoint.Y + yDelta));                //设置方框位置和大小              Thickness thickness = new Thickness(rectBoderCut.Left, rectBoderCut.Top, 0, 0);              borderSelect.SetValue(FrameworkElement.MarginProperty, thickness);              imgCut.SetValue(FrameworkElement.MarginProperty, thickness);                thickness = new Thickness(rectBoderCut.Left, 3, 0, 0);              txtCutInfo.SetValue(FrameworkElement.MarginProperty, thickness);                borderSelect.Width = Math.Abs(_startPoint.X - currentPoint.X);              borderSelect.Height = Math.Abs(_startPoint.Y - currentPoint.Y);              borderSelect.Visibility = Visibility.Visible;                //为了防止整个图 变暗,鼠标选中区域图像抠图,再在上层图像上显示              imgCut.Source = GetBitmapCut();                Int32Rect imgDestRect = GetCutRect();              txtCutInfo.Text = string.Format($"宽:{imgDestRect.Width} 高:{imgDestRect.Height}");          }

到此,程序主要逻辑处理完毕!麻雀虽小五脏俱全!这里用到不少wpf布局技巧。这些技巧与winform处理思虑差别还是很大的!wpf虽然苦涩难懂,感觉一入候门深似海!如果坚持下来,就会感到豁然开朗,也理解了微软的一片苦心!

程序运行效果与QQ截图很类似了。顺着这个思虑往前走,完全可以开发出与QQ截图一样的效果!