1. 程式人生 > >採用WPF開發截圖程式,so easy!

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

前言  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截圖一樣的效