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>

<CommandBinding Command="u:Commands.NewRecording" CanExecute="Buttons_CanExecute" Executed="Recorder_Executed"/>

<CommandBinding Command="u:Commands.NewWebcamRecording" CanExecute="Buttons_CanExecute" Executed="WebcamRecorder_Executed"/>

<CommandBinding Command="u:Commands.NewBoardRecording" CanExecute="Buttons_CanExecute" Executed="Board_Executed"/>

<CommandBinding Command="u:Commands.Editor" CanExecute="Buttons_CanExecute" Executed="Editor_Executed"/>

<CommandBinding Command="u:Commands.Update" CanExecute="Update_CanExecute" Executed="Update_Executed"/>

<CommandBinding Command="u:Commands.Options" CanExecute="Buttons_CanExecute" Executed="Options_Executed"/>

<!--Command后面是命令的名字,实际执行的函数是executed里写的函数 其他控件必须指明command这个属性

应用场景是菜单栏和工具栏的功能相同,我们要将其映射到同一个command。还有就是一个控件禁用后,相同功能的控件也要一起被禁用,这有CanExecute 来帮助同步,同时可用,或者同时不可用->

</Window.CommandBindings>

<Grid>

<Grid.RowDefinitions>   <!--行定义-->

<RowDefinition Height="45"/>

<RowDefinition />

</Grid.RowDefinitions>

<Grid Grid.Row="0">

<Grid.ColumnDefinitions>   <!--列定义-->

<ColumnDefinition/>

<ColumnDefinition Width="Auto"/>

<ColumnDefinition Width="Auto"/>

<ColumnDefinition Width="Auto"/>

</Grid.ColumnDefinitions>

<Label Grid.Column="0" Content="ScreenToGif" Margin="5" FontSize="18" Foreground="#FF251E46" Effect="{DynamicResource Shadow.Black.Small}"/>

<!--<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"/>-->

<TextBlock Grid.Column="1" Name="UpdateTextBlock" VerticalAlignment="Center" Visibility="Hidden" Effect="{StaticResource Shadow.Black.Small}">

<!--WPF Visibility的用法 Visible 元素在窗体中正常显示 Collaspsed 元素不显示,也不占用空间 Hidden 元素不显示,但是任然为它保留空间 -->

<Hyperlink Command="u:Commands.Update" ToolTip="{DynamicResource NewRelease.Tooltip}" Cursor="Hand">

<Run Name="UpdateRun" Text="{DynamicResource NewRelease}"/>

<!--run指明一连串格式化的或者格式化的内联文本,类似html的<span>-->

</Hyperlink>

</TextBlock>

<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"/>

<!--Effect是简单的像素处理 content属性显示图片  text 显示文本-->

</Grid>

<Grid Grid.Row="1">

<Grid.ColumnDefinitions>

<ColumnDefinition/>

<ColumnDefinition/>

<ColumnDefinition/>

<ColumnDefinition/>

</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>

<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>

<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>

<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><!---这有一个浮动提示->

</n:ImageButton>

</Grid>

</Grid>

</Window>

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

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

资源的四个层级?

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

什么是wpf对象资源?

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

<Window.Resources>

<ResourceDictionary>  <!--这个ResourceDictionary标签可以省略-->

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

我是一个资源

</sys:String>

</ResourceDictionary>

</WIndow.Rescources>

<TextBlock Text=”{StaticResource ResourceKey=str}”  <!--这一行的ResourceKey=可以不写-->

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

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

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

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

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

<window.Resources>

<ResourceDictionary Source=”xxx.xaml”/>

</window.Resources>

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

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

<window.Resources>

<TextBlock x:Key=”res2” text=”我是一只鸡”/>

</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>

<Storyboard x:Key="ShowDiscardStoryboard">

<BooleanAnimationUsingKeyFrames Storyboard.TargetName="DiscardButton" Storyboard.TargetProperty="IsHitTestVisible" Duration="0:0:0" >

<DiscreteBooleanKeyFrame Value="True" KeyTime="0:0:0"/>

</BooleanAnimationUsingKeyFrames>

<ObjectAnimationUsingKeyFrames Storyboard.TargetName="DiscardButton" Storyboard.TargetProperty="Visibility" Duration="0:0:0">

<DiscreteObjectKeyFrame Value="{x:Static Visibility.Visible}" KeyTime="0:0:0"/>

</ObjectAnimationUsingKeyFrames>

<DoubleAnimation Storyboard.TargetName="DiscardButton" Storyboard.TargetProperty="(Button.Opacity)" From="0" To="1" Duration="0:0:1">

<DoubleAnimation.EasingFunction>

<PowerEase Power="8" />

</DoubleAnimation.EasingFunction>

</DoubleAnimation>

</Storyboard>

<Storyboard x:Key="HideDiscardStoryboard">

<BooleanAnimationUsingKeyFrames Storyboard.TargetName="DiscardButton" Storyboard.TargetProperty="IsHitTestVisible" Duration="0:0:0" >

<DiscreteBooleanKeyFrame Value="False" KeyTime="0:0:0"/>

</BooleanAnimationUsingKeyFrames>

<ObjectAnimationUsingKeyFrames Storyboard.TargetName="DiscardButton" Storyboard.TargetProperty="Visibility" Duration="0:0:0">

<DiscreteObjectKeyFrame Value="{x:Static Visibility.Collapsed}" KeyTime="0:0:0"/>

</ObjectAnimationUsingKeyFrames>

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

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

<DoubleAnimation.EasingFunction>

<PowerEase Power="8" />

</DoubleAnimation.EasingFunction>

</DoubleAnimation>

</Storyboard>

<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><!--命令关联,命令前是否可以执行该命令,命令后要做什么-->

<CommandBinding Command="u:Commands.Options" CanExecute="Options_CanExecute" Executed="Options_Executed"/>

<CommandBinding Command="u:Commands.EnableSnapshot" CanExecute="EnableSnapshot_CanExecute" Executed="EnableSnapshot_Executed"/>

<CommandBinding Command="u:Commands.EnableThinMode" CanExecute="EnableThinMode_CanExecute" Executed="EnableThinMode_Executed"/>

<CommandBinding Command="u:Commands.EnableFullScreen" CanExecute="EnableFullScreen_CanExecute" Executed="EnableFullScreen_Executed"/>

<CommandBinding Command="u:Commands.EnableSnapToWindow" CanExecute="SnapToWindow_CanExecute"/>

</Window.CommandBindings>

<Grid x:Name="OutterGrid" UseLayoutRounding="True">

<Grid.RowDefinitions>

<RowDefinition Height="*"/>

<RowDefinition Height="31"/>

</Grid.RowDefinitions>

<!--Hollow part-->

<Border BorderBrush="{Binding ElementName=RecorderLightWindow, Path=BorderBrush}" BorderThickness="{Binding ElementName=RecorderLightWindow, Path=BorderThickness}"/>

<!--Command bar-->

<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>

<ColumnDefinition Width="Auto"/>

<ColumnDefinition/>

</Grid.ColumnDefinitions>

<Grid Grid.Column="0" Visibility="{Binding RecorderThinMode, Source={x:Static u:UserSettings.All}, Converter={StaticResource Bool2Visibility}}">

<Grid.RowDefinitions>

<RowDefinition/>

<RowDefinition/>

</Grid.RowDefinitions>

<Grid.ColumnDefinitions>

<ColumnDefinition Width="Auto"/>

<ColumnDefinition Width="Auto"/>

</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}"/>

</Grid>

<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>

<ToolTip HorizontalOffset="-5" Placement="Bottom" Content="{DynamicResource Recorder.SnapToWindow}"/>

</n:ImageButton.ToolTip>

</n:ImageButton>

<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>

<ToolTip HorizontalOffset="-5" Placement="Bottom" Content="{DynamicResource Options}"/>

</n:ImageButton.ToolTip>

</n:ImageButton>

<Separator Width="1" Margin="5,2"/>

<Viewbox Stretch="UniformToFill" ClipToBounds="True" Focusable="False">

<Viewbox.Visibility>

<MultiBinding Converter="{StaticResource BoolOrToInvertedVisibility}">

<Binding Path="RecorderThinMode" Source="{x:Static u:UserSettings.All}"/>

<Binding Path="SnapshotMode" Source="{x:Static u:UserSettings.All}"/>

</MultiBinding>

</Viewbox.Visibility>

<Grid HorizontalAlignment="Center" VerticalAlignment="Center" FlowDirection="LeftToRight" Margin="-4">

<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"/>

</Grid>

<Viewbox.ToolTip>

<ToolTip HorizontalOffset="-5" Placement="Bottom" Content="{DynamicResource Recorder.FpsRange}"/>

</Viewbox.ToolTip>

</Viewbox>

<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>

<ToolTip HorizontalOffset="-5" Placement="Bottom" Content="{DynamicResource Recorder.Fps}"/>

</n:IntegerUpDown.ToolTip>

</n:IntegerUpDown>

<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}}"/>

<Separator Width="1" Margin="5,2" 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}}"/>

<Separator Width="1" Margin="5,2" 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'}"/>

<!--ToolTip="{Binding Source={x:Static properties:Settings.Default}, Path=StartPauseKey, Converter={StaticResource KeysToStringConverter}}" ToolTipService.Placement="Bottom"-->

<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>

<ContextMenu>

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

<Separator/>

<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"/>

</ContextMenu>

</n:ImageButton.ContextMenu>

</n:ImageButton>

<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'}"/>

</StackPanel>

</Grid>

</Grid>

</n:LightWindow>

问题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<SimpleKeyGesture>(_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;

ScreenToGif 代码分析的更多相关文章

  1. Android代码分析工具lint学习

    1 lint简介 1.1 概述 lint是随Android SDK自带的一个静态代码分析工具.它用来对Android工程的源文件进行检查,找出在正确性.安全.性能.可使用性.可访问性及国际化等方面可能 ...

  2. pmd静态代码分析

    在正式进入测试之前,进行一定的静态代码分析及code review对代码质量及系统提高是有帮助的,以上为数据证明 Pmd 它是一个基于静态规则集的Java源码分析器,它可以识别出潜在的如下问题:– 可 ...

  3. [Asp.net 5] DependencyInjection项目代码分析-目录

    微软DI文章系列如下所示: [Asp.net 5] DependencyInjection项目代码分析 [Asp.net 5] DependencyInjection项目代码分析2-Autofac [ ...

  4. [Asp.net 5] DependencyInjection项目代码分析4-微软的实现(5)(IEnumerable<>补充)

    Asp.net 5的依赖注入注入系列可以参考链接: [Asp.net 5] DependencyInjection项目代码分析-目录 我们在之前讲微软的实现时,对于OpenIEnumerableSer ...

  5. 完整全面的Java资源库(包括构建、操作、代码分析、编译器、数据库、社区等等)

    构建 这里搜集了用来构建应用程序的工具. Apache Maven:Maven使用声明进行构建并进行依赖管理,偏向于使用约定而不是配置进行构建.Maven优于Apache Ant.后者采用了一种过程化 ...

  6. STM32启动代码分析 IAR 比较好

    stm32启动代码分析 (2012-06-12 09:43:31) 转载▼     最近开始使用ST的stm32w108芯片(也是一款zigbee芯片).开始看他的启动代码看的晕晕呼呼呼的. 还好在c ...

  7. 常用 Java 静态代码分析工具的分析与比较

    常用 Java 静态代码分析工具的分析与比较 简介: 本文首先介绍了静态代码分析的基 本概念及主要技术,随后分别介绍了现有 4 种主流 Java 静态代码分析工具 (Checkstyle,FindBu ...

  8. SonarQube-5.6.3 代码分析平台搭建使用

    python代码分析 官网主页: http://docs.sonarqube.org/display/PLUG/Python+Plugin Windows下安装使用: 快速使用: 1.下载jdk ht ...

  9. angular代码分析之异常日志设计

    angular代码分析之异常日志设计 错误异常是面向对象开发中的记录提示程序执行问题的一种重要机制,在程序执行发生问题的条件下,异常会在中断程序执行,同时会沿着代码的执行路径一步一步的向上抛出异常,最 ...

随机推荐

  1. 前端构建工具Gulp使用总结

    1.安装准备 1.1 Node.js安装 在安装Gulp之前首先的安装Node.js, 安装教程详见Node.js 安装配置 1.2 npm安装 在安装node的时候会自动安装npm模块管理器,详见n ...

  2. webstorm使用过程中的一些问题与技巧

    这一篇会随着使用逐渐更新: 1. 问题:string templates are not supported by current javascript version 解决 : setting &g ...

  3. Prometheus Node_exporter 之 Network Netstat UDP

    Network Netstat UDP /proc/net/snmp 1. UDP In / Out type: GraphUnit: shortLabel: Datagrams out (-) / ...

  4. python常用模块之-random模块

    random模块顾名思义就是生成随机数的模块. random模块有以下常见方法: 1,打印0-1之间的任意随机浮点数,不能指定区间. print(random.random()) 2,打印随机符点数, ...

  5. C#中获取数组中相加和最接近或等于(<=)给定值的算法

    , ,,,,,,,,, }; List<List<int>> mylist = new List<List<int>>(); int length = ...

  6. 使用 Azure PowerShell 监视和更新 Windows 虚拟机

    Azure 监视使用代理从 Azure VM 收集启动和性能数据,将此数据存储在 Azure 存储中,并使其可供通过门户.Azure PowerShell 模块和 Azure CLI 进行访问. 使用 ...

  7. ZooKeeper 分布式协调服务介绍

    0. 说明 从自己的独立博客迁移,该部分为 Zookeeper分布式协调服务介绍 原文链接  ZooKeeper 指南 1. ZooKeeper 简介 [官方介绍] ZooKeeper 是一种集中式服 ...

  8. T4学习- 4、Kalman Studio-T4代码生成器

    开源代码生成器-Kalman Studio https://github.com/loamen/Kalman.Studio 软件主要功能如下: 1.基于T4的代码生成工具,根据数据库元数据信息生成代码 ...

  9. Oracle Spatial中SDO_Geometry说明

    Oracle Spatial中SDO_Geometry说明 在ArcGIS中通过SDE存储空间数据到Oracle中有多种存储方式,分别有:二进制Long Raw .ESRI的ST_Geometry以及 ...

  10. BZOJ 1345 序列问题 单调栈

    题目链接: https://www.lydsy.com/JudgeOnline/problem.php?id=1345 题目大意: 对于一个给定的序列a1,…,an,我们对它进行一个操作reduce( ...