【WPF】WPF截屏

引言

.NET的截图控件在网上流传得不多啊,难得发现一个精品截图控件( 传送门),但是无奈是winform的,无鄙视winform的意思,纯偏爱WPF罢了.后来又找到一个周银辉做的WPF截图(继续传送门),发现截屏是实现了,但是功能略少了点.So,打算自己用WPF去实现一个,无奈略渣,还是简单分享一下吧.

一个Window和一个Canvas

Window是截图的主界面,但是设置好WindowStyle和WindowState就基本没它什么事了,Window里面放个Canvas,Canvas主要承载当前的截屏和画板DrawingPannel以及工具控件.先看看Window和Canvas的代码吧,如下

<Window x:Class="WpfCapture.Window3"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:wpfCapture="clr-namespace:WpfCapture"
        Title="Window3" Height="300" Width="300" WindowStyle="None" WindowState="Maximized">
    <Canvas Name="xgrid"   >
    </Canvas>
</Window>

什么时候加载当前截屏,怎样加载,看代码

        public Window3()
        {
            InitializeComponent();
            screenSnapshot = GetScreenSnapshot();
            var bmp = ToBitmapSource(screenSnapshot);
            bmp.Freeze();
            this.xgrid.Background = new ImageBrush(bmp);
        } 

       public Bitmap GetScreenSnapshot()
        {
            try
            {
                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;
            }

            catch (Exception)
            {

            }
            return null;
        }

画板DrawingPannel

画板DrawingPannel是自定义的一个布局控件类,主要是用来显示DrawingVisual对象的,类定义如下:

 public class DrawingCanvas : Panel
    {
        private List<Visual> visuals = new List<Visual>();

        protected override Visual GetVisualChild(int index)
        {
            return visuals[index];
        }
        protected override int VisualChildrenCount
        {
            get
            {
                return visuals.Count;
            }
        }

        public void RemoveLastVisual()
        {
            if (visuals.Count > 0)
            {

               var item= visuals.FindLast(x => true);
               DeleteVisual(item);
            }

        }

        public void AddVisual(Visual visual)
        {
            visuals.Add(visual);

            base.AddVisualChild(visual);
            base.AddLogicalChild(visual);
            Console.WriteLine(visuals.Count);
        }

        public void DeleteVisual(Visual visual)
        {
            visuals.Remove(visual);

            base.RemoveVisualChild(visual);
            base.RemoveLogicalChild(visual);
        }
    }

既然画板有了,当然不能漏了画笔等操作工具,所以最终界面XAML描述如下

<Window x:Class="WpfCapture.Window3"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:wpfCapture="clr-namespace:WpfCapture"
        Title="Window3" Height="300" Width="300" WindowStyle="None" WindowState="Maximized">
    <Canvas Name="xgrid" >
        <wpfCapture:DrawingCanvas x:Name="grid" Background="AliceBlue"  Canvas.Top="0" Canvas.Left="0"  Width="{Binding ActualWidth,ElementName=xgrid}"
                                  Height="{Binding ActualHeight,ElementName=xgrid}"
                                  Opacity="0.8"  MouseLeftButtonDown="Grid_OnMouseLeftButtonDown" PreviewMouseMove="grid_PreviewMouseMove_1" MouseLeftButtonUp="Grid_OnMouseLeftButtonUp"
                                  MouseMove="grid_MouseMove_2" MouseRightButtonDown="grid_MouseRightButtonDown_1"
                                  >
        </wpfCapture:DrawingCanvas>

        <StackPanel Orientation="Horizontal" Name="toolpanel"  Visibility="Collapsed" Height="28" Width="160">
            <ToolBar>
                <RadioButton GroupName="tool" Name="Arrow" >
                    <Image Source="./icons/Arrow.ico"></Image>
                </RadioButton>
                <RadioButton GroupName="tool" Name="Rectangular">

                    <Image Source="./icons/Rectangular.ico"></Image>
                </RadioButton>
                <RadioButton GroupName="tool" Name="Line">
                    <Image Source="./icons/Line.ico"></Image>
                </RadioButton>

                <Button Click="Button_Click_2">
                    <Image Source="./icons/Redo.png"></Image>
                </Button>
                <Button>
                    <Image Source="./icons/Exit.ico"></Image>
                </Button>
                <Button Click="Button_Click_1">
                    <Image Source="./icons/Accept.ico"></Image>
                </Button>
            </ToolBar>
        </StackPanel>
    </Canvas>
</Window>

如何指定截图方框

如何画截图边框出来呢.其实上面已经有画板了,那么我们只需要在上面画个方框,再将工具栏显示出来,那么好像有点像样了.如何画?需要用到DrawingVisual类,画框的方法如下:

 private void DrawSquare1(DrawingVisual visual)
        {
            using (DrawingContext dc = visual.RenderOpen())
            {
                dc.DrawRectangle(drawingBrush, drawingPen,
                    new Rect(startPoint, endPoint));
            }
        }

在鼠标事件中利用上面那个方法轻松画出方框,然后接下来我就用笨方法了,在画出方框后,我new了一个新的DrawingCanvas替代方框,再从一开始截屏图片中截取相应的图片作为DrawingCanvas的背景,在这个过程中要注意DPI值的转换,我的电脑是120的DPI,所以从WPF的单位转换为真正分辨率单位时要乘以1.25.

            //得到DPI比例
            Graphics graphics = Graphics.FromHwnd(IntPtr.Zero);
            systemdpi = graphics.DpiX / 96;
//得到截图方框的背景
        private BitmapSource CopyFromScreenSnapshot()
        {
            var sourceRect = new System.Drawing.Rectangle((int)(Math.Min(startPoint.X, endPoint.X) * systemdpi), (int)(Math.Min(startPoint.Y, endPoint.Y) * systemdpi), (int)(Math.Abs(startPoint.X - endPoint.X) * systemdpi), (int)(Math.Abs(startPoint.Y - endPoint.Y) * systemdpi));
            var destRect = new System.Drawing.Rectangle(0, 0, (int)(sourceRect.Width * systemdpi), (int)(sourceRect.Height * systemdpi));
            if (screenSnapshot != null)
            {
                var bitmap = new Bitmap((int)(sourceRect.Width * systemdpi), (int)(sourceRect.Height * systemdpi), System.Drawing.Imaging.PixelFormat.Format32bppArgb);
                using (Graphics g = Graphics.FromImage(bitmap))
                {
                    g.DrawImage(screenSnapshot, destRect, sourceRect, GraphicsUnit.Pixel);
                }
                return ToBitmapSource(bitmap);
            }
            return null;
        }

画板工具

画板工具我只定义了几个一个线段,方框和钢笔,也有后退,退出和完成截图工具.直接看代码好了

//画方框
        private void DrawSquare(System.Windows.Point point1, System.Windows.Point point2)
        {
            using (DrawingContext dc = selectionSquare.RenderOpen())
            {
                dc.DrawRectangle(selectionSquareBrush, selectionSquarePen,
                    new Rect(point1, point2));
           }
        }
        //画箭头....好吧,是画直线
        private void DrawArrow(System.Windows.Point point1, System.Windows.Point point2)
        {
            using (DrawingContext dc = selectionSquare.RenderOpen())
            {
                dc.DrawLine(selectionSquarePen, point1, point2);
            }
        }

        PathGeometry pgGeometry = new PathGeometry();
        PathFigure pfFigure = new PathFigure();
        //画钢笔线
        private void DrawLine(System.Windows.Point point1, System.Windows.Point point2)
        {
            using (DrawingContext dc = selectionSquare.RenderOpen())
            {
                LineSegment lsLineSegment = new LineSegment(point2, true);

                pfFigure.Segments.Add(lsLineSegment);

                Console.WriteLine(point2.Y);

                pgGeometry.Figures.Add(pfFigure);

                dc.DrawGeometry(selectionSquareBrush, selectionSquarePen, pgGeometry);
            }
        }

各种鼠标方法我就不一一标出来了,最终效果如下:

小结

其实一句话可以说完整个实现的:将Canvas背景设置为当前屏幕,画个框放画板,在画板上涂涂画画,然后将画板转成图片.多简单,但是上面还有好多细节没有说到,也有比较多功能没有实现,例如拖拉边框等功能.因为是纯练习,代码注释和规则都懒了,还有画板功能也不怎么样,画起来会有延迟的...不能再说下去了....话说,做完这个后,在CodePreject发现一个好东西,也是一个画板来的,也是利用DrawingVisual ,但是比我这个画板强大多了,效率和功能都高一筹,放上传送门,让我们共同学习一下.最后,如果你有更好的做法,请不吝指教.

时间: 2024-12-31 18:09:02

【WPF】WPF截屏的相关文章

WPF Popup全屏 弹出方法。解决只显示75%的问题。

WPF Popup全屏 弹出方法.解决只显示75%的问题. WPF 中 Popup 有一个特点.当Popup的高度超过屏幕的75%的时候,只显示75%的高度. 如下代码: <Window x:Class="WpfApplication13.MainWindow" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.micro

[WPF]程序全屏

代码: 使用: [WPF]程序全屏

WPF 窗口全屏

this.WindowState = System.Windows.WindowState.Normal; this.WindowStyle = System.Windows.WindowStyle.None; this.ResizeMode = System.Windows.ResizeMode.NoResize; this.Topmost = true; this.Left = 0.0; this.Top = 0.0; this.Width = System.Windows.SystemPa

WPF技术触屏上的应用系列(二): 嵌入百度地图、API调用及结合本地数据库在地图上进行自定义标点的实现

原文:WPF技术触屏上的应用系列(二): 嵌入百度地图.API调用及结合本地数据库在地图上进行自定义标点的实现 去年某客户单位要做个大屏触屏应用,要对档案资源进行展示之用.客户端是Window7操作系统,54寸大屏电脑电视一体机.要求有很炫的展示效果,要有一定的视觉冲击力,可触控操作.当然满足客户的要求也可以有其它途径.但鉴于咱是搞 .NET技术的,首先其冲想到的微软WPF方面,之前对WPF的了解与学习也只是停留在比较浅的层面,没有进一步深入学习与应用.所以在项目接来以后,也就赶鸭子上架了,经过

WPF技术触屏上的应用系列(六): 视觉冲击、超炫系统主界面、系统入口效果实现

原文:WPF技术触屏上的应用系列(六): 视觉冲击.超炫系统主界面.系统入口效果实现 去年某客户单位要做个大屏触屏应用,要对档案资源进行展示之用.客户端是Window7操作系统,54寸大屏电脑电视一体机.要求有很炫的展示效果,要有一定的视觉冲击力,可触控操作.当然满足客户的要求也可以有其它途径.但鉴于咱是搞 .NET技术的,首先其冲想到的微软WPF方面,之前对WPF的了解与学习也只是停留在比较浅的层面,没有进一步深入学习与应用.所以在项目接来以后,也就赶鸭子上架了,经过努力奋斗最终还是搞定了.当

WPF技术触屏上的应用系列(五): 图片列表异步加载、手指进行缩小、放大、拖动 、惯性滑入滑出等效果

原文:WPF技术触屏上的应用系列(五): 图片列表异步加载.手指进行缩小.放大.拖动 .惯性滑入滑出等效果 去年某客户单位要做个大屏触屏应用,要对档案资源进行展示之用.客户端是Window7操作系统,54寸大屏电脑电视一体机.要求有很炫的展示效果,要有一定的视觉冲击力,可触控操作.当然满足客户的要求也可以有其它途径.但鉴于咱是搞 .NET技术的,首先其冲想到的微软WPF方面,之前对WPF的了解与学习也只是停留在比较浅的层面,没有进一步深入学习与应用.所以在项目接来以后,也就赶鸭子上架了,经过努力

WPF技术触屏上的应用系列(三): 视频播放器的使用及视频播放、播放、暂停、可拖动播放进度效果实现

原文:WPF技术触屏上的应用系列(三): 视频播放器的使用及视频播放.播放.暂停.可拖动播放进度效果实现 去年某客户单位要做个大屏触屏应用,要对档案资源进行展示之用.客户端是Window7操作系统,54寸大屏电脑电视一体机.要求有很炫的展示效果,要有一定的视觉冲击力,可触控操作.当然满足客户的要求也可以有其它途径.但鉴于咱是搞 .NET技术的,首先其冲想到的微软WPF方面,之前对WPF的了解与学习也只是停留在比较浅的层面,没有进一步深入学习与应用.所以在项目接来以后,也就赶鸭子上架了,经过努力奋

WPF技术触屏上的应用系列(四): 3D效果图片播放器(图片立体轮放、图片立体轮播、图片倒影立体滚动)效果实现

原文:WPF技术触屏上的应用系列(四): 3D效果图片播放器(图片立体轮放.图片立体轮播.图片倒影立体滚动)效果实现 去年某客户单位要做个大屏触屏应用,要对档案资源进行展示之用.客户端是Window7操作系统,54寸大屏电脑电视一体机.要求有很炫的展示效果,要有一定的视觉冲击力,可触控操作.当然满足客户的要求也可以有其它途径.但鉴于咱是搞 .NET技术的,首先其冲想到的微软WPF方面,之前对WPF的了解与学习也只是停留在比较浅的层面,没有进一步深入学习与应用.所以在项目接来以后,也就赶鸭子上架了

WPF技术触屏上的应用系列(一): 3D 图片(照片)墙、柱面墙(凹面墙或者叫远景墙、凸面墙或者叫近景墙)实现

原文:WPF技术触屏上的应用系列(一): 3D 图片(照片)墙.柱面墙(凹面墙或者叫远景墙.凸面墙或者叫近景墙)实现 去年某客户单位要做个大屏触屏应用,要对档案资源进行展示之用.客户端是Window7操作系统,54寸大屏电脑电视一体机.要求有很炫的展示效果,要有一定的视觉冲击力,可触控操作.当然满足客户的要求也可以有其它途径.但鉴于咱是搞 .NET技术的,首先其冲想到的微软WPF方面,之前对WPF的了解与学习也只是停留在比较浅的层面,没有进一步深入学习与应用.所以在项目接来以后,也就赶鸭子上架了