ScreenToGif 代码分析

Stella981
• 阅读 674

ScreenToGif项目由四个文件夹组成:

  1. Files 存放协议文件
  2. GifRecorder 存放gif编码器代码
  3. ScreenToGif 存放主代码
  4. Other 存放Hooktest和Translator的代码

问题1:GifRecorder 和ScreenToGif、Hooktest、Translator 下面都有了一个Properties,里面有个AssemblyInfo.cs是什么东西?

.net工程的Properties文件夹下自动生成一个名为AssemblyInfo.cs的文件,一般情况下我们很少直接改动该文件。但我们实际上通过另一个形式操作该文件。那就是通过在鼠标右键点击项目的属性进入“应用程序”->“程序集信息”,然后修改信息。

程序集指的是DLL或者EXE等可执行文件。

问题2:启动界面分析

<Window x:Class="ScreenToGif.Windows.Other.Startup"

        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"

        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"

        xmlns:n="clr-namespace:ScreenToGif.Controls"

        xmlns:u="clr-namespace:ScreenToGif.Util"

        Title="{DynamicResource Title.StartUp}" Height="220" Width="500" Icon="/Resources/Logo.ico" WindowStartupLocation="CenterScreen"

        MinWidth="500" MinHeight="220" UseLayoutRounding="True" Loaded="Startup_OnLoaded">

    <Window.CommandBindings>

        

        

        

        

        

        

            

            

        </Grid.RowDefinitions>

        

            <Grid.ColumnDefinitions>   

                

                

                

                

            </Grid.ColumnDefinitions>

            

            <!--<n:ImageButton Grid.Column="1" x:Name="BoardButton2" Text="Test" Content="{StaticResource Vector.Info}"

                               Margin="5" Style="{StaticResource Style.Button.Horizontal}" Effect="{StaticResource Shadow.Foreground.Small}"

                               Padding="3" MaxSize="25" Click="TestButton_OnClick" Visibility="Collapsed"/>-->

            

                

                    

                

            

            <n:ImageButton Grid.Column="3" x:Name="OptionsButton" Text="{DynamicResource Options}" Content="{StaticResource Vector.Options}"

                           Margin="5" Style="{StaticResource Style.Button.Horizontal}" Effect="{StaticResource Shadow.Black.Small}"

                           Padding="2" MaxSize="25" Command="u:Commands.Options"/>

        

        

            <Grid.ColumnDefinitions>

                

                

                

                

            </Grid.ColumnDefinitions>

            <n:ImageButton Grid.Column="0" x:Name="RecordButton" Text="{DynamicResource Recorder}" Margin="5,0,5,5"

                           Effect="{StaticResource Shadow.Black.Tiny}" MaxSize="36" Content="{StaticResource Vector.Record.New}"

                           Command="u:Commands.NewRecording" Style="{StaticResource Style.Button.Vertical.Border}" FontSize="13">

                <n:ImageButton.ToolTip>

                    <n:HeaderedTooltip Header="{DynamicResource Recorder}" Text="{DynamicResource Tooltip.Recorder}"

                                              MaxWidth="250" Placement="Bottom" HorizontalOffset="-5"/>

                </n:ImageButton.ToolTip>

            

            <n:ImageButton Grid.Column="1" x:Name="WebcamButton" Text="{DynamicResource Webcam}" Margin="5,0,5,5"

                           Effect="{StaticResource Shadow.Black.Tiny}" MaxSize="36" Content="{StaticResource Vector.Camera.New}"

                           Command="u:Commands.NewWebcamRecording" Style="{StaticResource Style.Button.Vertical.Border}" FontSize="13">

                <n:ImageButton.ToolTip>

                    <n:HeaderedTooltip Header="{DynamicResource Webcam}" Text="{DynamicResource Tooltip.Webcam}" MaxWidth="250" Placement="Bottom" HorizontalOffset="-5"/>

                </n:ImageButton.ToolTip>

            

            <n:ImageButton Grid.Column="2" x:Name="BoardButton" Text="{DynamicResource Board}" Margin="5,0,5,5"

                           Effect="{StaticResource Shadow.Black.Tiny}" MaxSize="36" Content="{StaticResource Vector.Board.New}"

                           Command="u:Commands.NewBoardRecording" Style="{StaticResource Style.Button.Vertical.Border}" FontSize="13">

                <n:ImageButton.ToolTip>

                    <n:HeaderedTooltip Header="{DynamicResource Board}" Text="{DynamicResource Tooltip.Board}" MaxWidth="250" Placement="Bottom" HorizontalOffset="-5"/>

                </n:ImageButton.ToolTip>

            

            <n:ImageButton Grid.Column="3" x:Name="EditorButton" Text="{DynamicResource Editor}" Margin="5,0,5,5"

                           Effect="{StaticResource Shadow.Black.Tiny}" MaxSize="35" Content="{StaticResource Vector.Editor}"

                           Command="u:Commands.Editor" Style="{StaticResource Style.Button.Vertical.Border}" FontSize="13">

                <n:ImageButton.ToolTip>

                    <n:HeaderedTooltip Header="{DynamicResource Editor}" Text="{DynamicResource Tooltip.Editor}" MaxWidth="250" Placement="Bottom" HorizontalOffset="-5"/>   

                </n:ImageButton.ToolTip><!---这有一个浮动提示->

            

        

    

问题3:使用的静态资源和动态资源是怎么个原理?

静态资源指该资源只在程序载入内存时一次性使用,之后都不会改变。动态资源是相反的概念。

资源的四个层级?

  1. 数据库中的资源 ,相当于仓库
  2. 资源文件中的资源,相当于旅行箱
  3. Wpf 对象资源,相当于背包
  4. 变量中的数据,相当于手里

什么是wpf对象资源?

使用window.Rescources标签下的ResourceDictionary标签夹住的资源

<Window.Resources>

    

<sys:String x:Key=”str”>

   我是一个资源

  

</WIndow.Rescources>

<TextBlock Text=”{StaticResource ResourceKey=str}”  

这是在xaml中引用,如何在程序中引用呢?

string text = (string) this.FindResource(“str”)//资源中的文件要自己来进行格式转换

使用标签引用和程序中的FindResource引用会在当前控件的Resource属性中查找,如果找不到,就会找上一级的。

如果得知就是引用当前的,可以使用string text = (string) this.Resources[“str”]

将资源程序写到外部文件,如何在程序中引用?

<window.Resources>

</window.Resources>

静态资源和动态资源中的静态和动态不是描述资源的,描述控件行为的,也说明改资源项是否可以被外部改写(类似xml的改写),只载入一次,之后永远不变,还是可以动态的变化。

对于动态资源可以使用this.Resoures[“res2”]=new TextBlock(){text=”我要改变了”} ,静态资源不理会对资源的重新赋值

<window.Resources>

</window.Resources>

<Button  content=”{DynamicResources res2}”/>

问题4:一个界面文件,是如何调用另外一个界面文件的?

比如在ScreenToGif这个项目中,有个Windows文件夹,下面有个Other文件,里面有个ColorSelector.xaml,如何在其他界面文件中使用呢?

步骤:

  1. 添加对该目录的引用using ScreenToGif.Windows.Other;,不然你需要写完整目录
  2. 书写代码

            var colorPicker = new ColorSelector(UserSettings.All.BoardColor) { Owner = this };

            var result = colorPicker.ShowDialog();

问题5: style属性是什么东西?

http://blog.csdn.net/aoshilang2249/article/details/45129365

《深入浅出WPF》 深入浅出话模板

问题6:录制屏幕界面分析

<n:LightWindow x:Name="RecorderLightWindow" x:Class="ScreenToGif.Windows.Recorder"

               xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"

               xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"

               xmlns:n="clr-namespace:ScreenToGif.Controls"

               xmlns:u="clr-namespace:ScreenToGif.Util"

               xmlns:c="clr-namespace:ScreenToGif.Util.Converters"

               Title="ScreenToGif" SnapsToDevicePixels="True" UseLayoutRounding="True" AllowsTransparency="True" WindowStyle="None"

               Topmost="True" Icon="../Resources/Logo.ico" Child="{StaticResource Vector.Back}"

               IsThin="{Binding RecorderThinMode, Source={x:Static u:UserSettings.All}}"

               IsFullScreen="{Binding FullScreenMode, Source={x:Static u:UserSettings.All}}"

               Width="{Binding Source={x:Static u:UserSettings.All}, Path=RecorderWidth, Mode=TwoWay}"

               Height="{Binding Source={x:Static u:UserSettings.All}, Path=RecorderHeight, Mode=TwoWay}"

               Left="{Binding Source={x:Static u:UserSettings.All}, Path=RecorderLeft, Mode=TwoWay}"

               Top="{Binding Source={x:Static u:UserSettings.All}, Path=RecorderTop, Mode=TwoWay}"

               FocusManager.FocusedElement="{Binding RelativeSource={x:Static RelativeSource.Self}, Mode=OneTime}"

               Foreground="{Binding Source={x:Static u:UserSettings.All}, Path=RecorderForeground, Mode=TwoWay, Converter={StaticResource ColorToBrush}}"

               Background="{Binding Source={x:Static u:UserSettings.All}, Path=RecorderBackground, Mode=TwoWay, Converter={StaticResource ColorToBrush}}"

               SizeChanged="LightWindow_SizeChanged" Loaded="Recorder_Loaded" Closing="Window_Closing" LocationChanged="Window_LocationChanged">

    <Window.Resources>

        

            

                

            

            

                

            

            

                <DoubleAnimation.EasingFunction>

                    

                </DoubleAnimation.EasingFunction>

            

        

        

            

                

            

            

                

            

            <DoubleAnimation Storyboard.TargetName="DiscardButton" Storyboard.TargetProperty="(Button.Opacity)"

                             From="{Binding ElementName=DiscardButton,Path=Opacity}" To="0" Duration="0:0:1">

                <DoubleAnimation.EasingFunction>

                    

                </DoubleAnimation.EasingFunction>

            

        

        <c:StageToButtonString x:Key="StageToButtonStringConverter"/>

        <c:StageToCanvas x:Key="StageToCanvasConverter"/>

        <c:ShortcutKeys x:Key="ShortcutKeys"/>

        <c:InvertedBoolToVisibility x:Key="InvertedBoolToVisibility"/>

        <c:BoolOrToInvertedVisibility x:Key="BoolOrToInvertedVisibility"/>

        <c:IntToString x:Key="IntToStringConverter"/>

    </Window.Resources>

    <Window.CommandBindings>

        

        

        

        

        

    </Window.CommandBindings>

    

        <Grid.RowDefinitions>

            

            

        </Grid.RowDefinitions>

        

        

        

        <Grid Grid.Row="1" x:Name="LowerGrid" Height="31" VerticalAlignment="Bottom" Background="{Binding ElementName=RecorderLightWindow, Path=Background}"

              KeyboardNavigation.TabNavigation="Cycle" MouseLeftButtonDown="CommandGrid_MouseLeftButtonDown">

            <Grid.ColumnDefinitions>

                

                

            </Grid.ColumnDefinitions>

            

                <Grid.RowDefinitions>

                    

                    

                </Grid.RowDefinitions>

                <Grid.ColumnDefinitions>

                    

                    

                </Grid.ColumnDefinitions>

                <n:ImageButton Grid.Row="0" Grid.Column="0" x:Name="BackButton" Content="{StaticResource Vector.Back}" Style="{StaticResource Style.Button.NoText}"

                               ContentHeight="14" Padding="4,1" TabIndex="0" Click="BackButton_Click"/>

                <n:ImageButton Grid.Row="1" Grid.Column="0" x:Name="CloseButton" Content="{StaticResource Vector.Close}" Style="{StaticResource Style.Button.NoText}"

                               ContentHeight="10" Padding="4,1" TabIndex="1" Click="CloseButton_Click"/>

                <TextBlock Grid.Row="0" Grid.Column="1" x:Name="CaptionText" Text="{Binding Title, ElementName=RecorderLightWindow}" FontFamily="Segoe UI" FontSize="12"

                           FontWeight="Regular" Margin="5,0,0,0" Foreground="#FF6F5252" Effect="{DynamicResource Shadow.Foreground.Small}"/>

                <TextBlock Grid.Row="1" Grid.Column="1" x:Name="FrameCountTextBlock" Text="{Binding FrameCount, ElementName=RecorderLightWindow, Converter={StaticResource IntToStringConverter}}"

                           FontFamily="Segoe UI" FontSize="12" FontWeight="Regular" Margin="5,0,0,0" Foreground="#FF061E87" Effect="{DynamicResource Shadow.Foreground.Small}"/>

            

            <StackPanel Grid.Column="1" x:Name="ControlStackPanel" Height="31" Orientation="Horizontal" HorizontalAlignment="Right"

                        ScrollViewer.VerticalScrollBarVisibility="Disabled">

                <n:ImageButton x:Name="SnapButton" Content="{StaticResource Vector.Crosshair}" Margin="0" Style="{StaticResource Style.Button.NoText}"

                               HorizontalContentAlignment="Center" Effect="{StaticResource Shadow.Foreground.Small}" ContentHeight="20" ContentWidth="20"

                               Visibility="{Binding FullScreenMode, Source={x:Static u:UserSettings.All}, Converter={StaticResource InvertedBoolToVisibility}}"

                               Command="u:Commands.EnableSnapToWindow" Padding="3" TabIndex="2" PreviewMouseDown="SnapButton_PreviewMouseDown">

                    <n:ImageButton.ToolTip>

                        

                    </n:ImageButton.ToolTip>

                

                <n:ImageButton x:Name="OptionsButton" Content="{StaticResource Vector.Options}" Margin="0" Style="{StaticResource Style.Button.NoText}"

                               Effect="{StaticResource Shadow.Foreground.Small}" ContentHeight="20" ContentWidth="20" Command="u:Commands.Options" Padding="3" TabIndex="3">

                    <n:ImageButton.ToolTip>

                        

                    </n:ImageButton.ToolTip>

                

                

                

                    <Viewbox.Visibility>

                        

                            

                            

                        

                    </Viewbox.Visibility>

                    

                        <n:CircularProgressBar StrokeThickness="2" Percentage="100" SegmentColor="Gray" Radius="24" IsTabStop="False"/>

                        <n:CircularProgressBar StrokeThickness="22" Percentage="100" SegmentColor="#FFF0F1F1" Radius="10" IsTabStop="False"/>

                        <n:CircularProgressBar StrokeThickness="2" Value="{Binding ElementName=FpsIntegerUpDown, Path=Value, Mode=OneWay}"

                                               IsInverted="True" Minimum="1" Maximum="60" SegmentColor="#FFE28A73" Radius="24" IsTabStop="False"/>

                        <n:CircularProgressBar StrokeThickness="22" Value="{Binding ElementName=FpsIntegerUpDown, Path=Value, Mode=OneWay}"

                                               IsInverted="True" Minimum="1" Maximum="60" SegmentColor="#FFE28A73" Radius="10" IsTabStop="False"/>

                    

                    <Viewbox.ToolTip>

                        

                    </Viewbox.ToolTip>

                

                <n:IntegerUpDown x:Name="FpsIntegerUpDown" Margin="1,3" StepValue="1" Minimum="1" Maximum="60" MinWidth="45" TabIndex="4"

                                 Value="{Binding Source={x:Static u:UserSettings.All}, Path=LatestFps, Mode=TwoWay}"

                                 Visibility="{Binding SnapshotMode, Source={x:Static u:UserSettings.All}, Converter={StaticResource InvertedBoolToVisibility}}">

                    <n:IntegerUpDown.ToolTip>

                        

                    </n:IntegerUpDown.ToolTip>

                

                <Label Content="{StaticResource Recorder.Fps.Short}" FontSize="12" FontFamily="Segoe UI" Margin="1,0,0,0" VerticalContentAlignment="Center" Padding="0"

                       Foreground="{Binding ElementName=RecorderLightWindow, Path=Foreground}" Visibility="{Binding SnapshotMode, Source={x:Static u:UserSettings.All}, Converter={StaticResource InvertedBoolToVisibility}}"/>

                

                <!--<Viewbox Child="{StaticResource Vector.WidthHeight}" Stretch="UniformToFill" Margin="3,4" HorizontalAlignment="Right" FlowDirection="LeftToRight" SnapsToDevicePixels="True"

                             Visibility="{Binding RecorderThinMode, Converter={StaticResource InvertedBoolToVisibility}, Source={x:Static u:UserSettings.All}}"/>-->

                <n:IntegerBox x:Name="WidthIntegerBox" Value="{Binding Source={x:Static u:UserSettings.All}, Path=RecorderWidth, Mode=TwoWay}"

                              Offset="{x:Static u:Constants.HorizontalOffset}" Minimum="100" Maximum="3000" TabIndex="6" Height="Auto" Padding="4,0" Margin="1,3"

                              ToolTip="{DynamicResource Recorder.Width}" ToolTipService.Placement="Bottom" ToolTipService.HorizontalOffset="-5"

                              Visibility="{Binding FullScreenMode, Source={x:Static u:UserSettings.All}, Converter={StaticResource InvertedBoolToVisibility}}"/>

                <Label Content="×" FontSize="16" FontFamily="Segoe Script" Margin="1" VerticalContentAlignment="Center" Padding="0"

                       Foreground="{Binding ElementName=RecorderLightWindow, Path=Foreground}"

                       Visibility="{Binding FullScreenMode, Source={x:Static u:UserSettings.All}, Converter={StaticResource InvertedBoolToVisibility}}"/>

                <n:IntegerBox x:Name="HeightIntegerBox" Value="{Binding Source={x:Static u:UserSettings.All}, Path=RecorderHeight, Mode=TwoWay}"

                              Offset="{x:Static u:Constants.VerticalOffset}" Minimum="100" Maximum="3000" TabIndex="7" Height="Auto" Padding="4,0" Margin="1,3"

                              ToolTip="{DynamicResource Recorder.Height}" ToolTipService.Placement="Bottom" ToolTipService.HorizontalOffset="-5"

                              Visibility="{Binding FullScreenMode, Source={x:Static u:UserSettings.All}, Converter={StaticResource InvertedBoolToVisibility}}"/>

                <Label Content="px" FontSize="12" FontFamily="Segoe UI" Margin="1,0,0,0" VerticalContentAlignment="Center" Padding="0"

                       Foreground="{Binding ElementName=RecorderLightWindow, Path=Foreground}"

                       Visibility="{Binding FullScreenMode, Source={x:Static u:UserSettings.All}, Converter={StaticResource InvertedBoolToVisibility}}"/>

                

                <n:ImageButton x:Name="DiscardButton" Text="{DynamicResource Recorder.Discard}" Content="{StaticResource Vector.Remove}" Visibility="Collapsed"

                               Click="DiscardButton_Click" Style="{StaticResource Style.Button.Horizontal}"

                               Foreground="{Binding ElementName=RecorderLightWindow, Path=Foreground}"

                               UseLayoutRounding="True" MaxSize="16" ContentHeight="18" ContentWidth="18" TabIndex="8"

                               MinWidth="{Binding RelativeSource={RelativeSource Mode=Self}, Path=ActualHeight}"

                               KeyGesture="{Binding Converter={StaticResource ShortcutKeys}, ConverterParameter='3'}"/>

                

                <n:ImageButton x:Name="RecordPauseButton" UseLayoutRounding="True" MaxSize="16" ContentHeight="18" ContentWidth="18" TabIndex="9"

                               Text="{Binding Stage, ElementName=RecorderLightWindow, Converter={StaticResource StageToButtonStringConverter}, FallbackValue={StaticResource Recorder.Record}}"

                               Content="{Binding Stage, ElementName=RecorderLightWindow, Converter={StaticResource StageToCanvasConverter}, FallbackValue={StaticResource Vector.Record}}"

                               Click="RecordPauseButton_Click" Style="{StaticResource Style.Button.Horizontal}"

                               Foreground="{Binding ElementName=RecorderLightWindow, Path=Foreground}"

                               MinWidth="{Binding RelativeSource={RelativeSource Mode=Self}, Path=ActualHeight}"

                               KeyGesture="{Binding Converter={StaticResource ShortcutKeys}, ConverterParameter='1'}">

                    <n:ImageButton.ContextMenu>

                        

                            <n:ImageMenuItem Header="{DynamicResource Recorder.RecordingOptions}" IsHitTestVisible="False" Image="{StaticResource Vector.Record}" MaxSize="16"/>

                            

                            <n:ImageMenuItem Header="{DynamicResource Recorder.Snapshot}" IsCheckable="True" Image="{StaticResource Vector.Camera.Add}" MaxSize="16"

                                             IsChecked="{Binding SnapshotMode, Source={x:Static u:UserSettings.All}, Mode=TwoWay}" Command="u:Commands.EnableSnapshot"/>

                            <n:ImageMenuItem x:Name="ThinModeMenuItem" Header="{DynamicResource Recorder.ThinMode}" IsCheckable="True" Image="{StaticResource Vector.Application}" MaxSize="16"

                                             IsChecked="{Binding RecorderThinMode, Source={x:Static u:UserSettings.All}, Mode=TwoWay}" Command="u:Commands.EnableThinMode"

                                             Visibility="{Binding FullScreenMode, Source={x:Static u:UserSettings.All}, Converter={StaticResource InvertedBoolToVisibility}}"/>

                            <n:ImageMenuItem Header="{DynamicResource Recorder.Fullscreen}" IsCheckable="True" Image="{StaticResource Vector.WidthHeight}" MaxSize="16"

                                             IsChecked="{Binding FullScreenMode, Source={x:Static u:UserSettings.All}, Mode=TwoWay}" Command="u:Commands.EnableFullScreen"/>

                        

                    </n:ImageButton.ContextMenu>

                

                <n:ImageButton x:Name="StopButton" Text="{DynamicResource Recorder.Stop}" Content="{StaticResource Vector.Stop}"

                               Click="StopButton_Click" Style="{StaticResource Style.Button.Horizontal}"

                               Foreground="{Binding ElementName=RecorderLightWindow, Path=Foreground}"

                               UseLayoutRounding="True" MaxSize="16" ContentHeight="18" ContentWidth="18" Margin="0" TabIndex="10"

                               MinWidth="{Binding RelativeSource={RelativeSource Mode=Self}, Path=ActualHeight}"

                               KeyGesture="{Binding Converter={StaticResource ShortcutKeys}, ConverterParameter='2'}"/>

            

        

    

问题7:如果这个软件让你实现,你会怎么做?

启动界面,是4个选项,录制桌面、录制摄像头、录制绘图、视频帧编辑器

录制桌面、录制摄像头、录制绘图其实是一样的东西。

无非是设置一个定时器,定时的采集图像放到硬盘中。这部分的代码在呢?

C:\Users\laiqun\AppData\Local\Temp\   C:\Users\laiqun\AppData\Local\Temp\ScreenToGif\Recording\2018-02-03 14-18-53

                <n:ImageButton x:Name="RecordPauseButton" UseLayoutRounding="True" MaxSize="16" ContentHeight="18" ContentWidth="18" TabIndex="9" 

                               Text="{Binding Stage, ElementName=RecorderLightWindow, Converter={StaticResource StageToButtonStringConverter}, FallbackValue={StaticResource Recorder.Record}}" 

                               Content="{Binding Stage, ElementName=RecorderLightWindow, Converter={StaticResource StageToCanvasConverter}, FallbackValue={StaticResource Vector.Record}}" 

                               Click="RecordPauseButton_Click" Style="{StaticResource Style.Button.Horizontal}"

                               Foreground="{Binding ElementName=RecorderLightWindow, Path=Foreground}" 

                               MinWidth="{Binding RelativeSource={RelativeSource Mode=Self}, Path=ActualHeight}"

录制按钮点击

        private void RecordPauseButton_Click(object sender, RoutedEventArgs e)

        {

            if (!UserSettings.All.SnapshotMode)

                RecordPause();

            else

                Snap();

        }

RecordPause函数的实现:

        private async void RecordPause()

        {

            switch (Stage)  //Stage在哪儿改变?  

            {

                case Stage.Stopped:  //一开始肯定是从stopped 状态开始的,启动录制后,这里会将stopped状态改变为recording,表示正在录制。

录制其实在启动一个定时器,做各种记录性的操作。

从UnregisterEvents这个函数可以看出蛛丝马迹      

  private void UnregisterEvents()

        {

            _capture.Tick -= Normal_Elapsed;

            _capture.Tick -= NormalAsync_Elapsed;

            _capture.Tick -= Cursor_Elapsed;

            _capture.Tick -= CursorAsync_Elapsed;

            _capture.Tick -= FullCursor_Elapsed;

            _capture.Tick -= Full_Elapsed;

        }

        private void Normal_Elapsed(object sender, EventArgs e)

        {

            //Actual position on the screen.  获取要录制的区域

            var lefttop = Dispatcher.Invoke(() =>

            {

                var left = Math.Round((Math.Round(Left, MidpointRounding.AwayFromZero) + Constants.LeftOffset) * _scale);

                var top = Math.Round((Math.Round(Top, MidpointRounding.AwayFromZero) + Constants.TopOffset) * _scale);

                return new Point((int)left, (int)top);

            });

            //Take a screenshot of the area. 

            var bt = Native.Capture(_size, lefttop.X, lefttop.Y);

            if (bt == null || !IsLoaded)

                return;

            var fileName = $"{Project.FullPath}{FrameCount}.png";

//这里只是简单的更新一下图像文件信息,并没有实际创建图像文件

            Project.Frames.Add(new FrameInfo(fileName, FrameRate.GetMilliseconds(_snapDelay), new List(_keyList)));

            _keyList.Clear();

            //AddFrames创建图像文件

            ThreadPool.QueueUserWorkItem(delegate { AddFrames(fileName, new Bitmap(bt)); });//线程池

            FrameCount++;

        }

1.       System.Windows.Forms.Timer myTimer = new System.Windows.Forms.Timer();//实例化 

2.      myTimer.Tick += new EventHandler(函数名); //给timer挂起事件

3.      myTimer.Enabled = true;//使timer可用

4.       myTimer.Interval = n; //设置时间间隔,以毫秒为单位

5.       myTimer.Stop(); //如果要暂停计时则使用Stop()方法

6.       myTimer.Enabled = false;//若要停止使用timer,则使之不可用

设置项界面

是一个xml文件,用来读取和写入配置的。 程序的相关地方会读取这些配置,为了方便,最好把读取配置项的地方写在一起.这部分的代码在呢?UserSettings

namespace ScreenToGif.Util

{

    internal sealed class UserSettings : INotifyPropertyChanged

    {

        #region Variables

        private static ResourceDictionary _local;

        private static ResourceDictionary _appData;

        private static readonly ResourceDictionary Default;

        public event PropertyChangedEventHandler PropertyChanged;

        public static UserSettings All { get; } = new UserSettings();

视频帧编辑器负责把录制的一帧帧的图像载入,创建对应的缩略图。这部分的代码在呢?

我想在录制的时候顺势把鼠标和键盘录制进去,怎么实现?这部分的代码在呢?

Recorder构造函数

                _actHook = new UserActivityHook(true, true); //true for the mouse, true for the keyboard.

                _actHook.KeyDown += KeyHookTarget;

                _actHook.OnMouseActivity += MouseHookTarget;

点赞
收藏
评论区
推荐文章
blmius blmius
3年前
MySQL:[Err] 1292 - Incorrect datetime value: ‘0000-00-00 00:00:00‘ for column ‘CREATE_TIME‘ at row 1
文章目录问题用navicat导入数据时,报错:原因这是因为当前的MySQL不支持datetime为0的情况。解决修改sql\mode:sql\mode:SQLMode定义了MySQL应支持的SQL语法、数据校验等,这样可以更容易地在不同的环境中使用MySQL。全局s
Easter79 Easter79
3年前
swap空间的增减方法
(1)增大swap空间去激活swap交换区:swapoff v /dev/vg00/lvswap扩展交换lv:lvextend L 10G /dev/vg00/lvswap重新生成swap交换区:mkswap /dev/vg00/lvswap激活新生成的交换区:swapon v /dev/vg00/lvswap
待兔 待兔
4个月前
手写Java HashMap源码
HashMap的使用教程HashMap的使用教程HashMap的使用教程HashMap的使用教程HashMap的使用教程22
Jacquelyn38 Jacquelyn38
3年前
2020年前端实用代码段,为你的工作保驾护航
有空的时候,自己总结了几个代码段,在开发中也经常使用,谢谢。1、使用解构获取json数据let jsonData  id: 1,status: "OK",data: 'a', 'b';let  id, status, data: number   jsonData;console.log(id, status, number )
Java修道之路,问鼎巅峰,我辈代码修仙法力齐天
<center<fontcolor00FF7Fsize5face"黑体"代码尽头谁为峰,一见秃头道成空。</font<center<fontcolor00FF00size5face"黑体"编程修真路破折,一步一劫渡飞升。</font众所周知,编程修真有八大境界:1.Javase练气筑基2.数据库结丹3.web前端元婴4.Jav
Wesley13 Wesley13
3年前
FLV文件格式
1.        FLV文件对齐方式FLV文件以大端对齐方式存放多字节整型。如存放数字无符号16位的数字300(0x012C),那么在FLV文件中存放的顺序是:|0x01|0x2C|。如果是无符号32位数字300(0x0000012C),那么在FLV文件中的存放顺序是:|0x00|0x00|0x00|0x01|0x2C。2.  
Wesley13 Wesley13
3年前
00:Java简单了解
浅谈Java之概述Java是SUN(StanfordUniversityNetwork),斯坦福大学网络公司)1995年推出的一门高级编程语言。Java是一种面向Internet的编程语言。随着Java技术在web方面的不断成熟,已经成为Web应用程序的首选开发语言。Java是简单易学,完全面向对象,安全可靠,与平台无关的编程语言。
Wesley13 Wesley13
3年前
ES6 新增的数组的方法
给定一个数组letlist\//wu:武力zhi:智力{id:1,name:'张飞',wu:97,zhi:10},{id:2,name:'诸葛亮',wu:55,zhi:99},{id:3,name:'赵云',wu:97,zhi:66},{id:4,na
Wesley13 Wesley13
3年前
MySQL部分从库上面因为大量的临时表tmp_table造成慢查询
背景描述Time:20190124T00:08:14.70572408:00User@Host:@Id:Schema:sentrymetaLast_errno:0Killed:0Query_time:0.315758Lock_
Python进阶者 Python进阶者
10个月前
Excel中这日期老是出来00:00:00,怎么用Pandas把这个去除
大家好,我是皮皮。一、前言前几天在Python白银交流群【上海新年人】问了一个Pandas数据筛选的问题。问题如下:这日期老是出来00:00:00,怎么把这个去除。二、实现过程后来【论草莓如何成为冻干莓】给了一个思路和代码如下:pd.toexcel之前把这