採用WPF開發截圖程序,so easy!

摘自:https://www.cnblogs.com/yuanchenhui/p/screenshot-easy.htmlhtml

採用WPF開發截圖程序,so easy!

 

前言  QQ、微信截圖功能已很強大了,彷佛不必在開發一個截圖程序了。可是有時QQ熱鍵就是被佔用,不能快速的開啓截屏;有時,每天掛着QQ,領導也不樂意。既然是程序員,就要本身開發截屏工具,功能爲所欲爲,豈不快哉。前端

再強調一點:工具就是生產力!沒有掌握WPF以前,我是不會開發這麼一個程序的,若是採用MFC、winform框架,工做量是至關的大,開發出來的效果確定也比較low。本人用WPF,花了一天多的功夫,開發了這個小程序。程序的定位就功能簡單,平時工做不礙事,用着的時候,一鍵截圖!程序員

 界面  執行程序下載地址: 一鍵截圖,點我下載。canvas

爲了避免影響視覺, 程序主界面很是小。程序會在全部界面最前端展現。小程序

有兩個按鈕1)「快捷截圖」:截圖後,當即將截圖複製到剪切板。2)「截圖+編輯」:截圖後,能夠在圖上標註箭頭和文字。c#

正在截圖時,效果:微信

截圖後,可編輯:框架

 看似簡單,對開發技巧要求很高。內行看門道!工具

開發思路佈局

  常言道:看到的不必定是真實的。開發也要這樣。程序叫截屏,你不要一股勁想着怎麼截取別的窗口圖案,確定很費勁!思慮就是掩人耳目:先將整個屏幕複製,放到本身程序窗體中,窗體最大化,覆蓋整個屏幕!用戶看到仍是整個屏幕,可是整個屏幕已被偷樑換柱!此後,你全部的操做都是在本身窗體上處理,固然能夠爲所欲爲了!

截取整個屏幕

複製代碼
       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新概念多,用的人少,開發起來經常蒙圈!通過一段迷茫期,前途就會光明瞭!

窗口的佈局,很少說了!直接上代碼。我對代碼作了註釋!

複製代碼
<Window.Resources>
        <ControlTemplate x:Key="templatePushButton" TargetType="RadioButton">
            <Border x:Name="Part_Border" BorderThickness="1" BorderBrush="Gray" 
                                        Background="{TemplateBinding Background}"
                                        Margin="{TemplateBinding Margin}"
                                        Padding="{TemplateBinding Padding}">
                <ContentPresenter></ContentPresenter>
            </Border>

            <ControlTemplate.Triggers >
                <Trigger Property="IsChecked" Value="True">
                    <Setter  TargetName="Part_Border"  Property="BorderBrush" Value="Blue"></Setter>
                </Trigger>
                <Trigger Property="IsMouseOver" Value="True">
                    <Setter  TargetName="Part_Border"  Property="Background" Value="#FFb2dff9"></Setter>
                </Trigger>
            </ControlTemplate.Triggers>
        </ControlTemplate>

        <Style x:Key="stylePushButton" TargetType="RadioButton">
            <Setter Property="VerticalAlignment" Value="Center"></Setter>
            <Setter Property="Padding" Value="8,5,8,5"></Setter>
            <Setter Property="Template" Value="{StaticResource templatePushButton}"></Setter>
        </Style>

    </Window.Resources>
    <Grid Background="Green" >
        <!-- 整個屏幕圖像 -->
        <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>
            <!-- 前面覆蓋了一層黑色,可是截取的圖像不能覆蓋,只能在這裏再顯示截取圖像 -->
            <Grid x:Name="gridCutImg"  
                  MouseDown="ImgCut_MouseDown" 
                  MouseMove="ImgCut_MouseMove"
                   MouseUp="ImgCut_MouseUp">
                <Image x:Name="imgCut" Grid.RowSpan="3" Stretch="None"                                                                    
                   HorizontalAlignment="Left" VerticalAlignment="Top"></Image>
                <!--用來畫箭頭和文字-->
                <Canvas x:Name="canvasEdit"  HorizontalAlignment='Left'
                        VerticalAlignment="Top"  Background="Transparent">
                    
                </Canvas>
            </Grid>

            <!--顯示提示信息-->
            <TextBlock HorizontalAlignment="Center" VerticalAlignment="Center"
                           FontSize="22" Foreground="Yellow"
                          Opacity="0.8" >滑動鼠標開始截屏 截圖保存到剪切板 按ESC鍵退出</TextBlock>

            <StackPanel  Grid.RowSpan="3">
                <Grid >
                    <Grid.ColumnDefinitions>
                        <ColumnDefinition Width="auto"></ColumnDefinition>
                        <ColumnDefinition Width="*"></ColumnDefinition>
                    </Grid.ColumnDefinitions>
                </Grid>
                <!--截圖指示框-->
                <Border x:Name="borderSelect" 
                HorizontalAlignment="Left" VerticalAlignment="Top"
                BorderThickness="1" BorderBrush="Red"></Border>
                <!--寬和高指示-->
                <Grid  HorizontalAlignment="Stretch" >
                    <Grid.ColumnDefinitions>
                        <ColumnDefinition Width="auto"></ColumnDefinition>
                        <ColumnDefinition Width="auto"></ColumnDefinition>
                    </Grid.ColumnDefinitions>
                    <TextBlock x:Name="txtCutInfo"  Padding="8,5,8,5" 
                               HorizontalAlignment="Left"
                              Background="White" VerticalAlignment="Center">1</TextBlock>
                    <StackPanel x:Name="stackEdit" Orientation="Horizontal" HorizontalAlignment="Right" Grid.Column="1" Margin="2">
                        <RadioButton x:Name="radioArrow" GroupName="editType" Click="RadioArrow_Click" Foreground="Black" Padding="10,5,10,5" Style="{StaticResource stylePushButton}">↑</RadioButton>
                        <RadioButton  x:Name="radioText"  GroupName="editType" Click="RadioText_Click" Foreground="Black" Style="{StaticResource stylePushButton}">文</RadioButton>
                        <RadioButton  x:Name="radioClose" Click="RadioClose_Click" Foreground="Red" Style="{StaticResource stylePushButton}">X</RadioButton>
                    </StackPanel>
                </Grid>

            </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截圖同樣的效果!

專一.NET、VC++。擅長WPF、WinForm、Socket等技術。 技術交流QQ 13712486
 
分類:  c#wpf圖像
標籤:  WPFscreenc#
相關文章
相關標籤/搜索