Binary Viewer application for help with explaining file formats and data

This commit is contained in:
Unknown
2017-06-08 15:46:42 +01:00
parent b91d9b4961
commit 05269a8f83
30 changed files with 1438 additions and 0 deletions

View File

@ -0,0 +1,22 @@

Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio 15
VisualStudioVersion = 15.0.26430.12
MinimumVisualStudioVersion = 10.0.40219.1
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "BinaryViewer", "BinaryViewer\BinaryViewer.csproj", "{5CDC1CF1-6873-465D-8098-B08D67CAF7A7}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
Release|Any CPU = Release|Any CPU
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{5CDC1CF1-6873-465D-8098-B08D67CAF7A7}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{5CDC1CF1-6873-465D-8098-B08D67CAF7A7}.Debug|Any CPU.Build.0 = Debug|Any CPU
{5CDC1CF1-6873-465D-8098-B08D67CAF7A7}.Release|Any CPU.ActiveCfg = Release|Any CPU
{5CDC1CF1-6873-465D-8098-B08D67CAF7A7}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
EndGlobalSection
EndGlobal

View File

@ -0,0 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
<configuration>
<startup>
<supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.6.2"/>
</startup>
</configuration>

View File

@ -0,0 +1,15 @@
<Application x:Class="BinaryViewer.App"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:BinaryViewer"
StartupUri="MainWindow.xaml">
<Application.Resources>
<ResourceDictionary>
<ResourceDictionary.MergedDictionaries>
<ResourceDictionary Source="Styles/ComboBox.xaml" />
</ResourceDictionary.MergedDictionaries>
</ResourceDictionary>
</Application.Resources>
</Application>

View File

@ -0,0 +1,17 @@
using System;
using System.Collections.Generic;
using System.Configuration;
using System.Data;
using System.Linq;
using System.Threading.Tasks;
using System.Windows;
namespace BinaryViewer
{
/// <summary>
/// Interaction logic for App.xaml
/// </summary>
public partial class App : Application
{
}
}

View File

@ -0,0 +1,117 @@
using System;
using System.Windows;
namespace BinaryViewer
{
/// <summary>
/// A base attached property to replace the vanilla WPF attached property
/// </summary>
/// <typeparam name="Parent">The parent class to be the attached property</typeparam>
/// <typeparam name="Property">The type of this attached property</typeparam>
public abstract class BaseAttachedProperty<Parent, Property>
where Parent : new()
{
#region Public Events
/// <summary>
/// Fired when the value changes
/// </summary>
public event Action<DependencyObject, DependencyPropertyChangedEventArgs> ValueChanged = (sender, e) => { };
/// <summary>
/// Fired when the value changes, even when the value is the same
/// </summary>
public event Action<DependencyObject, object> ValueUpdated = (sender, value) => { };
#endregion
#region Public Properties
/// <summary>
/// A singleton instance of our parent class
/// </summary>
public static Parent Instance { get; private set; } = new Parent();
#endregion
#region Attached Property Definitions
/// <summary>
/// The attached property for this class
/// </summary>
public static readonly DependencyProperty ValueProperty = DependencyProperty.RegisterAttached(
"Value",
typeof(Property),
typeof(BaseAttachedProperty<Parent, Property>),
new UIPropertyMetadata(
default(Property),
new PropertyChangedCallback(OnValuePropertyChanged),
new CoerceValueCallback(OnValuePropertyUpdated)
));
/// <summary>
/// The callback event when the <see cref="ValueProperty"/> is changed
/// </summary>
/// <param name="d">The UI element that had it's property changed</param>
/// <param name="e">The arguments for the event</param>
private static void OnValuePropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
// Call the parent function
(Instance as BaseAttachedProperty<Parent, Property>)?.OnValueChanged(d, e);
// Call event listeners
(Instance as BaseAttachedProperty<Parent, Property>)?.ValueChanged(d, e);
}
/// <summary>
/// The callback event when the <see cref="ValueProperty"/> is changed, even if it is the same value
/// </summary>
/// <param name="d">The UI element that had it's property changed</param>
/// <param name="e">The arguments for the event</param>
private static object OnValuePropertyUpdated(DependencyObject d, object value)
{
// Call the parent function
(Instance as BaseAttachedProperty<Parent, Property>)?.OnValueUpdated(d, value);
// Call event listeners
(Instance as BaseAttachedProperty<Parent, Property>)?.ValueUpdated(d, value);
// Return the value
return value;
}
/// <summary>
/// Gets the attached property
/// </summary>
/// <param name="d">The element to get the property from</param>
/// <returns></returns>
public static Property GetValue(DependencyObject d) => (Property)d.GetValue(ValueProperty);
/// <summary>
/// Sets the attached property
/// </summary>
/// <param name="d">The element to get the property from</param>
/// <param name="value">The value to set the property to</param>
public static void SetValue(DependencyObject d, Property value) => d.SetValue(ValueProperty, value);
#endregion
#region Event Methods
/// <summary>
/// The method that is called when any attached property of this type is changed
/// </summary>
/// <param name="sender">The UI element that this property was changed for</param>
/// <param name="e">The arguments for this event</param>
public virtual void OnValueChanged(DependencyObject sender, DependencyPropertyChangedEventArgs e) { }
/// <summary>
/// The method that is called when any attached property of this type is changed, even if the value is the same
/// </summary>
/// <param name="sender">The UI element that this property was changed for</param>
/// <param name="e">The arguments for this event</param>
public virtual void OnValueUpdated(DependencyObject sender, object value) { }
#endregion
}
}

View File

@ -0,0 +1,21 @@
using System.Windows;
using System.Windows.Controls;
namespace BinaryViewer
{
/// <summary>
/// Focuses (keyboard focus) this element on load
/// </summary>
public class IsFocusedProperty : BaseAttachedProperty<IsFocusedProperty, bool>
{
public override void OnValueChanged(DependencyObject sender, DependencyPropertyChangedEventArgs e)
{
// If we don't have a control, return
if (!(sender is Control control))
return;
// Focus this control once loaded
control.Loaded += (s, se) => control.Focus();
}
}
}

View File

@ -0,0 +1,139 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
<PropertyGroup>
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
<ProjectGuid>{5CDC1CF1-6873-465D-8098-B08D67CAF7A7}</ProjectGuid>
<OutputType>WinExe</OutputType>
<RootNamespace>BinaryViewer</RootNamespace>
<AssemblyName>BinaryViewer</AssemblyName>
<TargetFrameworkVersion>v4.6.2</TargetFrameworkVersion>
<FileAlignment>512</FileAlignment>
<ProjectTypeGuids>{60dc8134-eba5-43b8-bcc9-bb4bc16c2548};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}</ProjectTypeGuids>
<WarningLevel>4</WarningLevel>
<AutoGenerateBindingRedirects>true</AutoGenerateBindingRedirects>
<TargetFrameworkProfile />
<NuGetPackageImportStamp>
</NuGetPackageImportStamp>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
<PlatformTarget>AnyCPU</PlatformTarget>
<DebugSymbols>true</DebugSymbols>
<DebugType>full</DebugType>
<Optimize>false</Optimize>
<OutputPath>bin\Debug\</OutputPath>
<DefineConstants>DEBUG;TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
<PlatformTarget>AnyCPU</PlatformTarget>
<DebugType>pdbonly</DebugType>
<Optimize>true</Optimize>
<OutputPath>bin\Release\</OutputPath>
<DefineConstants>TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
</PropertyGroup>
<ItemGroup>
<Reference Include="PresentationFramework.Aero2" />
<Reference Include="PropertyChanged, Version=2.1.1.0, Culture=neutral, PublicKeyToken=ee3ee20bcf148ddd, processorArchitecture=MSIL">
<HintPath>..\packages\PropertyChanged.Fody.2.1.1\lib\netstandard1.0\PropertyChanged.dll</HintPath>
<Private>False</Private>
</Reference>
<Reference Include="System" />
<Reference Include="System.Data" />
<Reference Include="System.Xml" />
<Reference Include="Microsoft.CSharp" />
<Reference Include="System.Core" />
<Reference Include="System.Xml.Linq" />
<Reference Include="System.Data.DataSetExtensions" />
<Reference Include="System.Net.Http" />
<Reference Include="System.Xaml">
<RequiredTargetFramework>4.0</RequiredTargetFramework>
</Reference>
<Reference Include="WindowsBase" />
<Reference Include="PresentationCore" />
<Reference Include="PresentationFramework" />
</ItemGroup>
<ItemGroup>
<ApplicationDefinition Include="App.xaml">
<Generator>MSBuild:Compile</Generator>
<SubType>Designer</SubType>
</ApplicationDefinition>
<Compile Include="AttachedProperties\BaseAttachedProperty.cs" />
<Compile Include="AttachedProperties\TextAttachedProperties.cs" />
<Compile Include="DataModels\StringToBinaryFormat.cs" />
<Compile Include="Expressions\ExpressionHelpers.cs" />
<Compile Include="ViewModels\Base\BaseViewModel.cs" />
<Compile Include="ViewModels\Base\RelayCommand.cs" />
<Compile Include="ViewModels\Base\RelayParameterizedCommand.cs" />
<Compile Include="ViewModels\BinaryListDesignModel.cs" />
<Compile Include="ViewModels\BinaryListItemDesignModel.cs" />
<Compile Include="ViewModels\BinaryListViewModel.cs" />
<Compile Include="ViewModels\BinaryListItemViewModel.cs" />
<Page Include="Controls\BinaryListItemControl.xaml">
<SubType>Designer</SubType>
<Generator>MSBuild:Compile</Generator>
</Page>
<Page Include="MainWindow.xaml">
<Generator>MSBuild:Compile</Generator>
<SubType>Designer</SubType>
</Page>
<Compile Include="App.xaml.cs">
<DependentUpon>App.xaml</DependentUpon>
<SubType>Code</SubType>
</Compile>
<Compile Include="Controls\BinaryListItemControl.xaml.cs">
<DependentUpon>BinaryListItemControl.xaml</DependentUpon>
</Compile>
<Compile Include="MainWindow.xaml.cs">
<DependentUpon>MainWindow.xaml</DependentUpon>
<SubType>Code</SubType>
</Compile>
<Page Include="Styles\ComboBox.xaml">
<SubType>Designer</SubType>
<Generator>MSBuild:Compile</Generator>
</Page>
</ItemGroup>
<ItemGroup>
<Compile Include="Properties\AssemblyInfo.cs">
<SubType>Code</SubType>
</Compile>
<Compile Include="Properties\Resources.Designer.cs">
<AutoGen>True</AutoGen>
<DesignTime>True</DesignTime>
<DependentUpon>Resources.resx</DependentUpon>
</Compile>
<Compile Include="Properties\Settings.Designer.cs">
<AutoGen>True</AutoGen>
<DependentUpon>Settings.settings</DependentUpon>
<DesignTimeSharedInput>True</DesignTimeSharedInput>
</Compile>
<EmbeddedResource Include="Properties\Resources.resx">
<Generator>ResXFileCodeGenerator</Generator>
<LastGenOutput>Resources.Designer.cs</LastGenOutput>
</EmbeddedResource>
<None Include="packages.config" />
<None Include="Properties\Settings.settings">
<Generator>SettingsSingleFileGenerator</Generator>
<LastGenOutput>Settings.Designer.cs</LastGenOutput>
</None>
</ItemGroup>
<ItemGroup>
<None Include="App.config" />
</ItemGroup>
<ItemGroup>
<None Include="FodyWeavers.xml" />
</ItemGroup>
<ItemGroup />
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
<Import Project="..\packages\Fody.2.0.0\build\netstandard1.4\Fody.targets" Condition="Exists('..\packages\Fody.2.0.0\build\netstandard1.4\Fody.targets')" />
<Target Name="EnsureNuGetPackageBuildImports" BeforeTargets="PrepareForBuild">
<PropertyGroup>
<ErrorText>This project references NuGet package(s) that are missing on this computer. Use NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}.</ErrorText>
</PropertyGroup>
<Error Condition="!Exists('..\packages\Fody.2.0.0\build\netstandard1.4\Fody.targets')" Text="$([System.String]::Format('$(ErrorText)', '..\packages\Fody.2.0.0\build\netstandard1.4\Fody.targets'))" />
</Target>
</Project>

View File

@ -0,0 +1,21 @@
<UserControl x:Class="BinaryViewer .BinaryListItemControl"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:local="clr-namespace:BinaryViewer"
mc:Ignorable="d"
d:DataContext="{x:Static local:BinaryListItemDesignModel.Instance}"
Background="Black">
<Border Padding="8"
TextBlock.FontFamily="Consolas">
<StackPanel>
<Grid>
<TextBlock Text="{Binding HexString}" Foreground="Gray" />
<TextBlock Text="{Binding DecimalString}" Foreground="Aqua" HorizontalAlignment="Right"/>
</Grid>
<TextBlock Text="{Binding BinaryString}" Foreground="White" />
<TextBlock Text="{Binding UTF8String}" Foreground="Green" />
</StackPanel>
</Border>
</UserControl>

View File

@ -0,0 +1,28 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
namespace BinaryViewer
{
/// <summary>
/// Interaction logic for BinaryListItemControl.xaml
/// </summary>
public partial class BinaryListItemControl : UserControl
{
public BinaryListItemControl()
{
InitializeComponent();
}
}
}

View File

@ -0,0 +1,29 @@
namespace BinaryViewer
{
/// <summary>
/// The format to use when converting strings to binary
/// </summary>
public enum StringToBinaryFormat
{
/// <summary>
/// ASCII format
/// </summary>
ASCII,
/// <summary>
/// UTF7 unicode format
/// </summary>
UTF7,
/// <summary>
/// UTF8 unicode format
/// </summary>
UTF8,
/// <summary>
/// UTF32 unicode format
/// </summary>
UTF32,
/// <summary>
/// Unicode format (USC2)
/// </summary>
Unicode
}
}

View File

@ -0,0 +1,48 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Linq.Expressions;
using System.Reflection;
using System.Text;
using System.Threading.Tasks;
namespace BinaryViewer
{
/// <summary>
/// A helper for expressions
/// </summary>
public static class ExpressionHelpers
{
/// <summary>
/// Compiles an expression and gets the functions return value
/// </summary>
/// <typeparam name="T">The type of return value</typeparam>
/// <param name="lamba">The expression to compile</param>
/// <returns></returns>
public static T GetPropertyValue<T>(this Expression<Func<T>> lamba)
{
return lamba.Compile().Invoke();
}
/// <summary>
/// Sets the underlying properties value to the given value
/// from an expression that contains the property
/// </summary>
/// <typeparam name="T">The type of value to set</typeparam>
/// <param name="lamba">The expression</param>
/// <param name="value">The value to set the property to</param>
public static void SetPropertyValue<T>(this Expression<Func<T>> lamba, T value)
{
// Converts a lamba () => some.Property, to some.Property
var expression = (lamba as LambdaExpression).Body as MemberExpression;
// Get the property information so we can set it
var propertyInfo = (PropertyInfo)expression.Member;
var target = Expression.Lambda(expression.Expression).Compile().DynamicInvoke();
// Set the property value
propertyInfo.SetValue(target, value);
}
}
}

View File

@ -0,0 +1,4 @@
<?xml version="1.0" encoding="utf-8"?>
<Weavers>
<PropertyChanged />
</Weavers>

View File

@ -0,0 +1,69 @@
<Window
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:local="clr-namespace:BinaryViewer"
xmlns:Themes="clr-namespace:Microsoft.Windows.Themes;assembly=PresentationFramework.Aero2" x:Class="BinaryViewer.MainWindow"
mc:Ignorable="d"
DataContext="{x:Static local:BinaryListDesignModel.Instance}"
WindowStartupLocation="CenterScreen"
Title="Binary Viewer" Height="350" Width="525"
>
<Border Padding="5"
Background="Black">
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
<RowDefinition Height="*" />
</Grid.RowDefinitions>
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*" />
<ColumnDefinition Width="Auto" />
</Grid.ColumnDefinitions>
<TextBox Background="Black"
local:IsFocusedProperty.Value="True"
Foreground="White"
Padding="5"
Text="{Binding Text, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"
FontFamily="Consolas"
FontSize="16"
AcceptsReturn="True"
MaxHeight="70"
/>
<ComboBox Grid.Column="1"
ItemsSource="{Binding StringFormats}"
SelectedItem="{Binding StringFormat, Mode=TwoWay}"
/>
</Grid>
<ScrollViewer Grid.Row="1" VerticalScrollBarVisibility="Auto">
<ItemsControl ItemsSource="{Binding Bytes}">
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate>
<WrapPanel IsItemsHost="True" Orientation="Horizontal" />
</ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
<ItemsControl.ItemTemplate>
<DataTemplate>
<local:BinaryListItemControl DataContext="{Binding}" />
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
</ScrollViewer>
</Grid>
</Border>
</Window>

View File

@ -0,0 +1,28 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
namespace BinaryViewer
{
/// <summary>
/// Interaction logic for MainWindow.xaml
/// </summary>
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
}
}
}

View File

@ -0,0 +1,55 @@
using System.Reflection;
using System.Resources;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using System.Windows;
// General Information about an assembly is controlled through the following
// set of attributes. Change these attribute values to modify the information
// associated with an assembly.
[assembly: AssemblyTitle("BinaryViewer")]
[assembly: AssemblyDescription("")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("")]
[assembly: AssemblyProduct("BinaryViewer")]
[assembly: AssemblyCopyright("Copyright © 2017")]
[assembly: AssemblyTrademark("")]
[assembly: AssemblyCulture("")]
// Setting ComVisible to false makes the types in this assembly not visible
// to COM components. If you need to access a type in this assembly from
// COM, set the ComVisible attribute to true on that type.
[assembly: ComVisible(false)]
//In order to begin building localizable applications, set
//<UICulture>CultureYouAreCodingWith</UICulture> in your .csproj file
//inside a <PropertyGroup>. For example, if you are using US english
//in your source files, set the <UICulture> to en-US. Then uncomment
//the NeutralResourceLanguage attribute below. Update the "en-US" in
//the line below to match the UICulture setting in the project file.
//[assembly: NeutralResourcesLanguage("en-US", UltimateResourceFallbackLocation.Satellite)]
[assembly: ThemeInfo(
ResourceDictionaryLocation.None, //where theme specific resource dictionaries are located
//(used if a resource is not found in the page,
// or application resource dictionaries)
ResourceDictionaryLocation.SourceAssembly //where the generic resource dictionary is located
//(used if a resource is not found in the page,
// app, or any theme specific resource dictionaries)
)]
// Version information for an assembly consists of the following four values:
//
// Major Version
// Minor Version
// Build Number
// Revision
//
// You can specify all the values or you can default the Build and Revision Numbers
// by using the '*' as shown below:
// [assembly: AssemblyVersion("1.0.*")]
[assembly: AssemblyVersion("1.0.0.0")]
[assembly: AssemblyFileVersion("1.0.0.0")]

View File

@ -0,0 +1,63 @@
//------------------------------------------------------------------------------
// <auto-generated>
// This code was generated by a tool.
// Runtime Version:4.0.30319.42000
//
// Changes to this file may cause incorrect behavior and will be lost if
// the code is regenerated.
// </auto-generated>
//------------------------------------------------------------------------------
namespace BinaryViewer.Properties {
using System;
/// <summary>
/// A strongly-typed resource class, for looking up localized strings, etc.
/// </summary>
// This class was auto-generated by the StronglyTypedResourceBuilder
// class via a tool like ResGen or Visual Studio.
// To add or remove a member, edit your .ResX file then rerun ResGen
// with the /str option, or rebuild your VS project.
[global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "4.0.0.0")]
[global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
[global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
internal class Resources {
private static global::System.Resources.ResourceManager resourceMan;
private static global::System.Globalization.CultureInfo resourceCulture;
[global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")]
internal Resources() {
}
/// <summary>
/// Returns the cached ResourceManager instance used by this class.
/// </summary>
[global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
internal static global::System.Resources.ResourceManager ResourceManager {
get {
if (object.ReferenceEquals(resourceMan, null)) {
global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("BinaryViewer.Properties.Resources", typeof(Resources).Assembly);
resourceMan = temp;
}
return resourceMan;
}
}
/// <summary>
/// Overrides the current thread's CurrentUICulture property for all
/// resource lookups using this strongly typed resource class.
/// </summary>
[global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
internal static global::System.Globalization.CultureInfo Culture {
get {
return resourceCulture;
}
set {
resourceCulture = value;
}
}
}
}

View File

@ -0,0 +1,117 @@
<?xml version="1.0" encoding="utf-8"?>
<root>
<!--
Microsoft ResX Schema
Version 2.0
The primary goals of this format is to allow a simple XML format
that is mostly human readable. The generation and parsing of the
various data types are done through the TypeConverter classes
associated with the data types.
Example:
... ado.net/XML headers & schema ...
<resheader name="resmimetype">text/microsoft-resx</resheader>
<resheader name="version">2.0</resheader>
<resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
<resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
<data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
<data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
<data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
<value>[base64 mime encoded serialized .NET Framework object]</value>
</data>
<data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
<value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
<comment>This is a comment</comment>
</data>
There are any number of "resheader" rows that contain simple
name/value pairs.
Each data row contains a name, and value. The row also contains a
type or mimetype. Type corresponds to a .NET class that support
text/value conversion through the TypeConverter architecture.
Classes that don't support this are serialized and stored with the
mimetype set.
The mimetype is used for serialized objects, and tells the
ResXResourceReader how to depersist the object. This is currently not
extensible. For a given mimetype the value must be set accordingly:
Note - application/x-microsoft.net.object.binary.base64 is the format
that the ResXResourceWriter will generate, however the reader can
read any of the formats listed below.
mimetype: application/x-microsoft.net.object.binary.base64
value : The object must be serialized with
: System.Serialization.Formatters.Binary.BinaryFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.soap.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Soap.SoapFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.bytearray.base64
value : The object must be serialized into a byte array
: using a System.ComponentModel.TypeConverter
: and then encoded with base64 encoding.
-->
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
<xsd:element name="root" msdata:IsDataSet="true">
<xsd:complexType>
<xsd:choice maxOccurs="unbounded">
<xsd:element name="metadata">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" />
<xsd:attribute name="type" type="xsd:string" />
<xsd:attribute name="mimetype" type="xsd:string" />
</xsd:complexType>
</xsd:element>
<xsd:element name="assembly">
<xsd:complexType>
<xsd:attribute name="alias" type="xsd:string" />
<xsd:attribute name="name" type="xsd:string" />
</xsd:complexType>
</xsd:element>
<xsd:element name="data">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" msdata:Ordinal="1" />
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
</xsd:complexType>
</xsd:element>
<xsd:element name="resheader">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" />
</xsd:complexType>
</xsd:element>
</xsd:choice>
</xsd:complexType>
</xsd:element>
</xsd:schema>
<resheader name="resmimetype">
<value>text/microsoft-resx</value>
</resheader>
<resheader name="version">
<value>2.0</value>
</resheader>
<resheader name="reader">
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<resheader name="writer">
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
</root>

View File

@ -0,0 +1,26 @@
//------------------------------------------------------------------------------
// <auto-generated>
// This code was generated by a tool.
// Runtime Version:4.0.30319.42000
//
// Changes to this file may cause incorrect behavior and will be lost if
// the code is regenerated.
// </auto-generated>
//------------------------------------------------------------------------------
namespace BinaryViewer.Properties {
[global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
[global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator", "15.1.0.0")]
internal sealed partial class Settings : global::System.Configuration.ApplicationSettingsBase {
private static Settings defaultInstance = ((Settings)(global::System.Configuration.ApplicationSettingsBase.Synchronized(new Settings())));
public static Settings Default {
get {
return defaultInstance;
}
}
}
}

View File

@ -0,0 +1,7 @@
<?xml version='1.0' encoding='utf-8'?>
<SettingsFile xmlns="uri:settings" CurrentProfile="(Default)">
<Profiles>
<Profile Name="(Default)" />
</Profiles>
<Settings />
</SettingsFile>

View File

@ -0,0 +1,125 @@
<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:BinaryViewer">
<SolidColorBrush x:Key="ComboBoxNormalBorderBrush" Color="#aaa" />
<SolidColorBrush x:Key="ComboBoxNormalBackgroundBrush" Color="#000" />
<SolidColorBrush x:Key="ComboBoxDisabledForegroundBrush" Color="#fff" />
<SolidColorBrush x:Key="ComboBoxDisabledBackgroundBrush" Color="#222" />
<SolidColorBrush x:Key="ComboBoxDisabledBorderBrush" Color="#444" />
<SolidColorBrush x:Key="ComboBoxHoverArrowBackground" Color="#222" />
<SolidColorBrush x:Key="ComboBoxDroppedDownArrowBackground" Color="#444" />
<SolidColorBrush x:Key="ComboBoxDroppedDownArrow" Color="#888" />
<ControlTemplate TargetType="ToggleButton" x:Key="ComboBoxToggleButtonTemplate">
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition />
<ColumnDefinition Width="20" />
</Grid.ColumnDefinitions>
<Border Grid.ColumnSpan="2" Name="Border"
BorderBrush="{StaticResource ComboBoxNormalBorderBrush}"
CornerRadius="0" BorderThickness="1, 1, 1, 1"
Background="{StaticResource ComboBoxNormalBackgroundBrush}" />
<Border Grid.Column="1" Margin="1, 1, 1, 1" BorderBrush="#444" Name="ButtonBorder"
CornerRadius="0, 0, 0, 0" BorderThickness="0, 0, 0, 0"
Background="{StaticResource ComboBoxNormalBackgroundBrush}" />
<Path Name="Arrow" Grid.Column="1"
Data="M0,0 L0,2 L4,6 L8,2 L8,0 L4,4 z"
HorizontalAlignment="Center" Fill="#444"
VerticalAlignment="Center" />
</Grid>
<ControlTemplate.Triggers>
<Trigger Property="UIElement.IsMouseOver" Value="True">
<!-- Arrow background color when hover -->
<Setter Property="Panel.Background" TargetName="ButtonBorder" Value="{StaticResource ComboBoxHoverArrowBackground}"/>
</Trigger>
<Trigger Property="ToggleButton.IsChecked" Value="True">
<!-- Arrow background color when dropped down -->
<Setter Property="Panel.Background" TargetName="ButtonBorder" Value="{StaticResource ComboBoxDroppedDownArrowBackground}"/>
<!-- Arrow color when dropped down -->
<Setter Property="Shape.Fill" TargetName="Arrow" Value="{StaticResource ComboBoxDroppedDownArrow}"/>
</Trigger>
<Trigger Property="UIElement.IsEnabled" Value="False">
<Setter Property="Panel.Background" TargetName="Border" Value="{StaticResource ComboBoxDisabledBackgroundBrush}"/>
<Setter Property="Panel.Background" TargetName="ButtonBorder" Value="{StaticResource ComboBoxDisabledBackgroundBrush}"/>
<Setter Property="Border.BorderBrush" TargetName="ButtonBorder" Value="{StaticResource ComboBoxDisabledBorderBrush}"/>
<Setter Property="TextElement.Foreground" Value="{StaticResource ComboBoxDisabledForegroundBrush}"/>
<Setter Property="Shape.Fill" TargetName="Arrow" Value="#999"/>
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
<Style TargetType="{x:Type ComboBox}">
<Setter Property="UIElement.SnapsToDevicePixels" Value="True"/>
<Setter Property="FrameworkElement.OverridesDefaultStyle" Value="True"/>
<Setter Property="ScrollViewer.HorizontalScrollBarVisibility" Value="Auto"/>
<Setter Property="ScrollViewer.VerticalScrollBarVisibility" Value="Auto"/>
<Setter Property="ScrollViewer.CanContentScroll" Value="True"/>
<Setter Property="TextElement.Foreground" Value="{StaticResource ComboBoxNormalBorderBrush}"/>
<Setter Property="FrameworkElement.FocusVisualStyle" Value="{x:Null}"/>
<Setter Property="Control.Template">
<Setter.Value>
<ControlTemplate TargetType="ComboBox">
<Grid>
<ToggleButton Name="ToggleButton" Grid.Column="2"
ClickMode="Press" Focusable="False"
IsChecked="{Binding Path=IsDropDownOpen, RelativeSource={RelativeSource TemplatedParent}, Mode=TwoWay}"
Template="{StaticResource ComboBoxToggleButtonTemplate}"/>
<ContentPresenter Name="ContentSite" Margin="5, 3, 23, 3" IsHitTestVisible="False"
HorizontalAlignment="Left" VerticalAlignment="Center"
Content="{TemplateBinding ComboBox.SelectionBoxItem}"
ContentTemplate="{TemplateBinding ComboBox.SelectionBoxItemTemplate}"
ContentTemplateSelector="{TemplateBinding ItemTemplateSelector}"/>
<TextBox Name="PART_EditableTextBox" Margin="3, 3, 23, 3"
IsReadOnly="{TemplateBinding IsReadOnly}"
Visibility="Hidden" Background="Transparent"
HorizontalAlignment="Left" VerticalAlignment="Center"
Focusable="True" >
<TextBox.Template>
<ControlTemplate TargetType="TextBox" >
<Border Name="PART_ContentHost" Focusable="False" />
</ControlTemplate>
</TextBox.Template>
</TextBox>
<!-- Popup showing items -->
<Popup Name="Popup" Placement="Bottom"
Focusable="False" AllowsTransparency="True"
IsOpen="{TemplateBinding ComboBox.IsDropDownOpen}"
PopupAnimation="Slide">
<Grid Name="DropDown" SnapsToDevicePixels="True"
MinWidth="{TemplateBinding FrameworkElement.ActualWidth}"
MaxHeight="{TemplateBinding ComboBox.MaxDropDownHeight}">
<Border Name="DropDownBorder" Background="{StaticResource ComboBoxNormalBackgroundBrush}" Margin="0, 1, 0, 0"
CornerRadius="0" BorderThickness="1,1,1,1"
BorderBrush="{StaticResource ComboBoxNormalBorderBrush}"/>
<ScrollViewer Margin="4" SnapsToDevicePixels="True">
<ItemsPresenter KeyboardNavigation.DirectionalNavigation="Contained" TextBlock.Foreground="{StaticResource ComboBoxNormalBorderBrush}" />
</ScrollViewer>
</Grid>
</Popup>
</Grid>
<ControlTemplate.Triggers>
<Trigger Property="ItemsControl.HasItems" Value="False">
<Setter Property="FrameworkElement.MinHeight" TargetName="DropDownBorder" Value="95"/>
</Trigger>
<Trigger Property="UIElement.IsEnabled" Value="False">
<Setter Property="TextElement.Foreground" Value="{StaticResource ComboBoxDisabledForegroundBrush}"/>
</Trigger>
<Trigger Property="ItemsControl.IsGrouping" Value="True">
<Setter Property="ScrollViewer.CanContentScroll" Value="False"/>
</Trigger>
<Trigger Property="ComboBox.IsEditable" Value="True">
<Setter Property="KeyboardNavigation.IsTabStop" Value="False"/>
<Setter Property="UIElement.Visibility" TargetName="PART_EditableTextBox" Value="Visible"/>
<Setter Property="UIElement.Visibility" TargetName="ContentSite" Value="Hidden"/>
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</ResourceDictionary>

View File

@ -0,0 +1,62 @@
using PropertyChanged;
using System;
using System.ComponentModel;
using System.Linq.Expressions;
using System.Threading.Tasks;
namespace BinaryViewer
{
/// <summary>
/// A base view model that fires Property Changed events as needed
/// </summary>
public class BaseViewModel : INotifyPropertyChanged
{
/// <summary>
/// The event that is fired when any child property changes its value
/// </summary>
public event PropertyChangedEventHandler PropertyChanged = (sender, e) => { };
/// <summary>
/// Call this to fire a <see cref="PropertyChanged"/> event
/// </summary>
/// <param name="name"></param>
public void OnPropertyChanged(string name)
{
PropertyChanged(this, new PropertyChangedEventArgs(name));
}
#region Command Helpers
/// <summary>
/// Runs a command if the updating flag is not set.
/// If the flag is true (indicating the function is already running) then the action is not run.
/// If the flag is false (indicating no running function) then the action is run.
/// Once the action is finished if it was run, then the flag is reset to false
/// </summary>
/// <param name="updatingFlag">The boolean property flag defining if the command is already running</param>
/// <param name="action">The action to run if the command is not already running</param>
/// <returns></returns>
protected async Task RunCommandAsync(Expression<Func<bool>> updatingFlag, Func<Task> action)
{
// Check if the flag property is true (meaning the function is already running)
if (updatingFlag.GetPropertyValue())
return;
// Set the property flag to true to indicate we are running
updatingFlag.SetPropertyValue(true);
try
{
// Run the passed in action
await action();
}
finally
{
// Set the property flag back to false now it's finished
updatingFlag.SetPropertyValue(false);
}
}
#endregion
}
}

View File

@ -0,0 +1,64 @@
using System;
using System.Windows.Input;
namespace BinaryViewer
{
/// <summary>
/// A basic command that runs an Action
/// </summary>
public class RelayCommand : ICommand
{
#region Private Members
/// <summary>
/// The action to run
/// </summary>
private Action mAction;
#endregion
#region Public Events
/// <summary>
/// The event thats fired when the <see cref="CanExecute(object)"/> value has changed
/// </summary>
public event EventHandler CanExecuteChanged = (sender, e) => { };
#endregion
#region Constructor
/// <summary>
/// Default constructor
/// </summary>
public RelayCommand(Action action)
{
mAction = action;
}
#endregion
#region Command Methods
/// <summary>
/// A relay command can always execute
/// </summary>
/// <param name="parameter"></param>
/// <returns></returns>
public bool CanExecute(object parameter)
{
return true;
}
/// <summary>
/// Executes the commands Action
/// </summary>
/// <param name="parameter"></param>
public void Execute(object parameter)
{
mAction();
}
#endregion
}
}

View File

@ -0,0 +1,64 @@
using System;
using System.Windows.Input;
namespace BinaryViewer
{
/// <summary>
/// A basic command that runs an Action
/// </summary>
public class RelayParameterizedCommand : ICommand
{
#region Private Members
/// <summary>
/// The action to run
/// </summary>
private Action<object> mAction;
#endregion
#region Public Events
/// <summary>
/// The event thats fired when the <see cref="CanExecute(object)"/> value has changed
/// </summary>
public event EventHandler CanExecuteChanged = (sender, e) => { };
#endregion
#region Constructor
/// <summary>
/// Default constructor
/// </summary>
public RelayParameterizedCommand(Action<object> action)
{
mAction = action;
}
#endregion
#region Command Methods
/// <summary>
/// A relay command can always execute
/// </summary>
/// <param name="parameter"></param>
/// <returns></returns>
public bool CanExecute(object parameter)
{
return true;
}
/// <summary>
/// Executes the commands Action
/// </summary>
/// <param name="parameter"></param>
public void Execute(object parameter)
{
mAction(parameter);
}
#endregion
}
}

View File

@ -0,0 +1,31 @@
using System;
namespace BinaryViewer
{
/// <summary>
/// The design time view model of <see cref="BinaryListViewModel"/>
/// </summary>
public class BinaryListDesignModel : BinaryListViewModel
{
#region Singleton
/// <summary>
/// A single instance of the design time view model
/// </summary>
public static BinaryListDesignModel Instance => new BinaryListDesignModel();
#endregion
#region Constructor
/// <summary>
/// Default constructor
/// </summary>
public BinaryListDesignModel()
{
Text = "Hello world";
}
#endregion
}
}

View File

@ -0,0 +1,31 @@
using System;
namespace BinaryViewer
{
/// <summary>
/// The design time view model of <see cref="BinaryListItemViewModel"/>
/// </summary>
public class BinaryListItemDesignModel : BinaryListItemViewModel
{
#region Singleton
/// <summary>
/// A single instance of the design time view model
/// </summary>
public static BinaryListItemDesignModel Instance => new BinaryListItemDesignModel();
#endregion
#region Constructor
/// <summary>
/// Default constructor
/// </summary>
public BinaryListItemDesignModel()
{
Byte = 0x41;
}
#endregion
}
}

View File

@ -0,0 +1,36 @@
using System;
using System.Text;
namespace BinaryViewer
{
/// <summary>
/// The view model for a single binary item in the binary list
/// </summary>
public class BinaryListItemViewModel : BaseViewModel
{
/// <summary>
/// The byte to display
/// </summary>
public byte Byte { get; set; }
/// <summary>
/// The hexadecimal display of the byte (e.g. 0x41)
/// </summary>
public string HexString => "0x" + Byte.ToString("X2");
/// <summary>
/// The binary display of the byte (e.g 01000001)
/// </summary>
public string BinaryString => Convert.ToString(Byte, 2).PadLeft(8, '0');
/// <summary>
/// The decimal display of the byte (e.g. 65)
/// </summary>
public string DecimalString => ((int)Byte).ToString();
/// <summary>
/// The UTF8 (Unicode) character representation of the byte
/// </summary>
public string UTF8String => new string((char)Byte, 1);
}
}

View File

@ -0,0 +1,170 @@
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.ComponentModel;
using System.Linq;
using System.Text;
namespace BinaryViewer
{
/// <summary>
/// The view model for a list of bytes in the binary list
/// </summary>
public class BinaryListViewModel : BaseViewModel
{
#region Public Properties
/// <summary>
/// The byte to display
/// </summary>
public ObservableCollection<BinaryListItemViewModel> Bytes { get; set; }
/// <summary>
/// The direct text to bind to that will convert to the Bytes as it changes
/// </summary>
public string Text { get; set; }
/// <summary>
/// The format of the string when converting it to binary
/// </summary>
public StringToBinaryFormat StringFormat { get; set; } = StringToBinaryFormat.UTF8;
/// <summary>
/// A list of all string to binary formats
/// </summary>
public List<StringToBinaryFormat> StringFormats => Enum.GetValues(typeof(StringToBinaryFormat)).Cast<StringToBinaryFormat>().ToList();
#endregion
#region Constructor
/// <summary>
/// Default constructor
/// </summary>
public BinaryListViewModel()
{
PropertyChanged += BinaryListViewModel_PropertyChanged;
}
/// <summary>
/// Construct from a byte array
/// </summary>
/// <param name="bytes">The byte array to use</param>
public BinaryListViewModel(byte[] bytes)
{
FromBytes(bytes);
}
/// <summary>
/// Construct from a string
/// </summary>
/// <param name="string">The string to use</param>
public BinaryListViewModel(string @string)
{
FromString(@string);
}
#endregion
#region Public Methods
/// <summary>
/// Set bytes from byte[]
/// </summary>
public void FromBytes(byte[] bytes)
{
// Create list from bytes
Bytes = new ObservableCollection<BinaryListItemViewModel>(bytes.Select(b => new BinaryListItemViewModel { Byte = b }).ToArray());
}
/// <summary>
/// Set bytes from a string
/// </summary>
public void FromString(string @string)
{
switch (StringFormat)
{
// ASCII string
case StringToBinaryFormat.ASCII:
FromBytes(Encoding.ASCII.GetBytes(@string));
break;
// UTF7 string
case StringToBinaryFormat.UTF7:
FromBytes(Encoding.UTF7.GetBytes(@string));
break;
// UTF8 string
case StringToBinaryFormat.UTF8:
FromBytes(Encoding.UTF8.GetBytes(@string));
break;
// UTF32 string
case StringToBinaryFormat.UTF32:
FromBytes(Encoding.UTF32.GetBytes(@string));
break;
// Unicode string
case StringToBinaryFormat.Unicode:
FromBytes(Encoding.Unicode.GetBytes(@string));
break;
}
}
#endregion
private void BinaryListViewModel_PropertyChanged(object sender, PropertyChangedEventArgs e)
{
// If the text changes, process it
if (string.Equals(e.PropertyName, nameof(Text)))
DetectSpecialText();
// If the format of the string changes, process it
else if (string.Equals(e.PropertyName, nameof(StringFormat)))
DetectSpecialText();
}
private void DetectSpecialText()
{
if (string.IsNullOrEmpty(Text))
return;
// When text changes, update the bytes
// If the bytes are all 0's and 1's and exactly 8 long
// presume the user wants to create a byte from it
if (Text.Length == 8 && !Text.Any(f => f != '0' && f != '1'))
{
// Convert the 8 characters into a single byte
var result = 0;
for (var i = 7; i > 0; i--)
{
if (Text[i] == '1')
result |= (1 << (7 - i));
}
FromBytes(new[] { (byte)result });
}
// Hex value (i.e. 0x45)
else if (Text.Length == 4 && Text.StartsWith("0x") && !Text.Skip(2).Any(f => !IsHex(f)))
{
FromBytes(new[] { Convert.ToByte(Convert.ToInt16(Text, 16)) });
}
// Otherwise, normal string
else
FromString(Text);
}
/// <summary>
/// Checks if this character is a hexadecimal value (between 0-9 or A-F)
/// </summary>
/// <param name="character">The character to check</param>
/// <returns></returns>
private bool IsHex(char character)
{
return (character >= '0' && character <= '9') ||
(character >= 'a' && character <= 'f') ||
(character >= 'A' && character <= 'F');
}
}
}

View File

@ -0,0 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
<packages>
<package id="Fody" version="2.0.0" targetFramework="net462" developmentDependency="true" />
<package id="PropertyChanged.Fody" version="2.1.1" targetFramework="net462" developmentDependency="true" />
</packages>

View File

@ -0,0 +1,12 @@
# Binary Viewer
A simple WPF application that gives easy and quick ways to visualize text and data in all binary formats.
View strings, files and bytes instantly in:
- binary
- hexadecimal
- decimal
- ascii
http://www.angelsix.com/youtube

6
FileFormats/README.md Normal file
View File

@ -0,0 +1,6 @@
# File Formats
Any source code from the File Formats video series on the AngelSix YouTube channel
http://www.angelsix.com/youtube