first commit

This commit is contained in:
Luis Reich
2026-09-22 22:41:43 +02:00
parent e513c7aacc
commit 9d0e837622
55 changed files with 5109 additions and 0 deletions

View File

@@ -0,0 +1,9 @@
<Application x:Class="OnscreenTranslator.App"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:OnscreenTranslator"
StartupUri="MainWindow.xaml">
<Application.Resources>
</Application.Resources>
</Application>

View File

@@ -0,0 +1,14 @@
using System.Configuration;
using System.Data;
using System.Windows;
using System.Windows.Input;
using Process.NET.Windows;
namespace OnscreenTranslator;
/// <summary>
/// Interaction logic for App.xaml
/// </summary>
public partial class App : Application
{
}

View File

@@ -0,0 +1,10 @@
using System.Windows;
[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)
)]

View File

@@ -0,0 +1,282 @@
using System.Diagnostics;
using System.Drawing;
using System.IO;
using LibreTranslate.Net.Enhanced.Constants;
using LibreTranslate.Net.Enhanced.Models;
using Overlay.NET.Common;
using Overlay.NET.Directx;
using Process.NET.Windows;
using TesseractOCR;
using TesseractOCR.Enums;
using Image = TesseractOCR.Pix.Image;
using ImageFormat = System.Drawing.Imaging.ImageFormat;
using Point = System.Drawing.Point;
using Rectangle = System.Drawing.Rectangle;
namespace OnscreenTranslator;
public class DirectXOverlay : DirectXOverlayPlugin
{
private readonly TickEngine _tickEngine = new();
public readonly ISettings<OverlaySettings> Settings = new SerializableSettings<OverlaySettings>();
private int _displayFps;
private int _font;
private int _hugeFont;
private int _i;
private int _interiorBrush;
private int _redBrush;
private int _redOpacityBrush;
private float _rotation;
private Stopwatch _watch;
private readonly List<Element> TranslatedElements = new();
private List<Element> UntranslatedElements = new();
public override void Initialize(IWindow targetWindow)
{
// Set target window by calling the base method
base.Initialize(targetWindow);
// For demo, show how to use settings
var current = Settings.Current;
var type = GetType();
if (current.UpdateRate == 0)
current.UpdateRate = 1000 / 60;
current.Author = GetAuthor(type);
current.Description = GetDescription(type);
current.Identifier = GetIdentifier(type);
current.Name = GetName(type);
current.Version = GetVersion(type);
// File is made from above info
Settings.Save();
Settings.Load();
//Console.Title = @"OverlayExample";
OverlayWindow = new DirectXOverlayWindow(targetWindow.Handle, false);
_watch = Stopwatch.StartNew();
_redBrush = OverlayWindow.Graphics.CreateBrush(0x7FFF0000);
_redOpacityBrush = OverlayWindow.Graphics.CreateBrush(Color.FromArgb(80, 255, 0, 0));
_interiorBrush = OverlayWindow.Graphics.CreateBrush(0x7FFFFF00);
_font = OverlayWindow.Graphics.CreateFont("Arial", 20);
_hugeFont = OverlayWindow.Graphics.CreateFont("Arial", 50, true);
_rotation = 0.0f;
_displayFps = 0;
_i = 0;
// Set up update interval and register events for the tick engine.
_tickEngine.PreTick += OnPreTick;
_tickEngine.Tick += OnTick;
}
private void OnPreTick(object sender, EventArgs e)
{
var targetWindowIsActivated = TargetWindow.IsActivated;
if (!targetWindowIsActivated && OverlayWindow.IsVisible)
{
_watch.Stop();
ClearScreen();
OverlayWindow.Hide();
}
else if (targetWindowIsActivated && !OverlayWindow.IsVisible)
{
OverlayWindow.Show();
}
}
private void OnTick(object sender, EventArgs e)
{
if (!OverlayWindow.IsVisible) return;
OverlayWindow.Update();
InternalRender();
}
public override void Enable()
{
_tickEngine.Interval = Settings.Current.UpdateRate.Milliseconds();
_tickEngine.IsTicking = true;
base.Enable();
}
public override void Disable()
{
_tickEngine.IsTicking = false;
base.Disable();
}
public override void Update()
{
_tickEngine.Pulse();
}
protected void InternalRender()
{
if (!_watch.IsRunning) _watch.Start();
OverlayWindow.Graphics.BeginScene();
OverlayWindow.Graphics.ClearScene();
RenderElements(TranslatedElements);
if (_watch.ElapsedMilliseconds > 1000)
{
_i = _displayFps;
_displayFps = 0;
_watch.Restart();
}
else
{
_displayFps++;
}
OverlayWindow.Graphics.EndScene();
}
public void TriggerTranslation()
{
var HTML = GetScreenHTML();
UntranslatedElements = GetScreenElements(HTML);
TranslateElements();
}
private string GetScreenHTML()
{
var mem = GetScreenDataFromTargetWindow();
var languages = new List<Language>();
languages.Add(Language.Japanese);
languages.Add(Language.JapaneseVertical);
languages.Add(Language.English);
var engine = new Engine("F:/Downloads/tessdata-4.1.0/tessdata-4.1.0", languages);
var img = Image.LoadFromMemory(mem);
var page = engine.Process(img);
return page.HOcrText();
}
private List<Element> GetScreenElements(string HTML)
{
var elements = new List<Element>();
var Index = 0;
while (Index != -1)
{
Index = HTML.IndexOf("class='ocrx_word'", Index);
if (Index == -1) break;
var BbboxIndex = HTML.IndexOf("bbox", Index);
if (BbboxIndex == -1) break;
var XIndex = BbboxIndex + 4;
var YIndex = HTML.IndexOf(" ", XIndex + 1);
if (YIndex == -1) break;
++YIndex;
var YEnd = HTML.IndexOf(" ", YIndex + 1);
if (YEnd == -1) break;
var WordStart = HTML.IndexOf(">", YIndex);
if (WordStart == -1) break;
++WordStart;
var WordEnd = HTML.IndexOf("<", WordStart);
if (WordEnd == -1) break;
var NewElement = new Element();
var XString = HTML.Substring(XIndex, YIndex - XIndex);
var YString = HTML.Substring(YIndex, YEnd - YIndex);
NewElement.X = int.Parse(XString);
NewElement.Y = int.Parse(YString);
NewElement.Input = HTML.Substring(WordStart, WordEnd - WordStart);
elements.Add(NewElement);
Index = WordEnd;
}
return elements;
}
private async void TranslateElements()
{
var libreTranslate = new LibreTranslate.Net.Enhanced.LibreTranslate("http://127.0.0.1:5000", "");
TranslatedElements.Clear();
foreach (var element in UntranslatedElements)
{
if (element.Input == "")
continue;
var Detection = await libreTranslate.DetectAsync(new Detect
{
Text = element.Input
});
if (Detection != null)
{
var First = Detection.FirstOrDefault();
if (First != null)
if (First.Confidence == 0)
continue;
}
var TargetText = await libreTranslate.TranslateAsync(new Translate
{
Source = LanguageCode.English,
Target = LanguageCode.German,
Text = element.Input
});
var New = element;
New.Output = TargetText;
TranslatedElements.Add(New);
}
}
private void RenderElements(List<Element> elements)
{
foreach (var element in elements)
OverlayWindow.Graphics.DrawText(element.Input, _font, _redBrush, element.X, element.Y);
}
public override void Dispose()
{
if (OverlayWindow != null) OverlayWindow.Dispose();
base.Dispose();
}
public void ClearScreen()
{
OverlayWindow.Graphics.BeginScene();
OverlayWindow.Graphics.ClearScene();
OverlayWindow.Graphics.EndScene();
}
private MemoryStream GetScreenDataFromTargetWindow()
{
var bounds = new Rectangle(TargetWindow.X,
TargetWindow.Y,
TargetWindow.Width,
TargetWindow.Height);
using var bitmap = new Bitmap(bounds.Width, bounds.Height);
using (var g = Graphics.FromImage(bitmap))
{
g.CopyFromScreen(new Point(bounds.Left, bounds.Top), Point.Empty, bounds.Size);
}
// bitmap.Save("C://test.jpg", ImageFormat.Jpeg);
System.Drawing.Image im = System.Drawing.Image.FromHbitmap(bitmap.GetHbitmap());
var mem = new MemoryStream();
im.Save(mem, ImageFormat.Bmp);
return mem;
}
private struct Element
{
public int X;
public int Y;
public string Input;
public string Output;
}
}

View File

@@ -0,0 +1,15 @@
<Window x:Class="OnscreenTranslator.MainWindow"
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:OnscreenTranslator"
mc:Ignorable="d"
Title="OnscreenTranslator" Height="450" Width="800" >
<Grid>
<ComboBox x:Name="ComboBox" HorizontalAlignment="Left" Margin="319,208,0,0" VerticalAlignment="Top" Width="120" Loaded="ComboBox_Loaded" SelectionChanged="ComboBox_SelectionChanged"/>
<Button x:Name="Translate" Content="Button" HorizontalAlignment="Left" Margin="444,209,0,0" VerticalAlignment="Top" Click="Translate_Click"/>
<TextBlock x:Name="TextBlock" HorizontalAlignment="Center" Margin="0,297,0,0" TextWrapping="Wrap" Text="TextBlock" VerticalAlignment="Top"/>
</Grid>
</Window>

View File

@@ -0,0 +1,223 @@
using System.Runtime.InteropServices;
using System.Text;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Input;
using System.Windows.Interop;
using Process.NET;
using Process.NET.Memory;
using Process.NET.Windows;
namespace OnscreenTranslator;
/// <summary>
/// Interaction logic for MainWindow.xaml
/// </summary>
public partial class MainWindow : Window
{
private bool IsRendering;
private DirectXOverlay Overlay = new();
private IWindow? TargetWindow;
private System.Diagnostics.Process? TrackedProcess;
[DllImport("user32.dll")]
private static extern bool RegisterHotKey(IntPtr hWnd, int id, uint fsModifiers, uint vk);
[DllImport("user32.dll")]
private static extern bool UnregisterHotKey(IntPtr hWnd, int id);
private const int HOTKEY_ID = 9000;
//Modifiers:
private const uint MOD_NONE = 0x0000; //[NONE]
private const uint MOD_ALT = 0x0001; //ALT
private const uint MOD_CONTROL = 0x0002; //CTRL
private const uint MOD_SHIFT = 0x0004; //SHIFT
private const uint MOD_WIN = 0x0008; //WINDOWS
//CAPS LOCK:
private const uint VK_CAPITAL = 0x14;
private const uint VK_F9 = 0x78;
private HwndSource source;
public MainWindow()
{
InitializeComponent();
}
[DllImport("user32.dll", SetLastError = true)]
[return: MarshalAs(UnmanagedType.Bool)]
internal static extern bool IsWindowVisible(IntPtr hWnd);
[DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)]
internal static extern int GetWindowText(IntPtr hWnd, StringBuilder lpString, int nMaxCount);
[DllImport("user32.dll", SetLastError = true, CharSet = CharSet.Auto)]
internal static extern int GetWindowTextLength(IntPtr hWnd);
[DllImport("user32.dll")]
[return: MarshalAs(UnmanagedType.Bool)]
internal static extern bool EnumWindows(EnumWindowsProc lpEnumFunc, IntPtr lParam);
internal delegate bool EnumWindowsProc(IntPtr hWnd, IntPtr lParam);
[DllImport("user32.dll", SetLastError = true, CharSet = CharSet.Auto)]
internal static extern int GetClassName(IntPtr hWnd, StringBuilder lpClassName, int nMaxCount);
private IntPtr HwndHook(IntPtr hwnd, int msg, IntPtr wParam, IntPtr lParam, ref bool handled)
{
const int WM_HOTKEY = 0x0312;
switch (msg)
{
case WM_HOTKEY:
switch (wParam.ToInt32())
{
case HOTKEY_ID:
int vkey = (((int)lParam >> 16) & 0xFFFF);
if (vkey == VK_F9)
{
GetWindow();
}
handled = true;
break;
}
break;
}
return IntPtr.Zero;
}
public void GetWindow()
{
// Get own hWnd
WindowInteropHelper windowHwnd = new(this);
IntPtr ownHwnd = windowHwnd.Handle;
// Find target hWnd
IntPtr targetHWnd = IntPtr.Zero;
EnumWindows((hWnd, lParam) =>
{
if (hWnd == ownHwnd) { return true; } // Ignore own window
if (!IsWindowVisible(hWnd)) { return true; } // Ignore hidden windows
if (GetClassName(hWnd).Equals("Shell_TrayWnd", StringComparison.OrdinalIgnoreCase)) { return true; } // Ignore taskbar window
if (string.IsNullOrEmpty(GetWindowTitle(hWnd))) { return true; } // Ignore windows without a title
targetHWnd = hWnd; // Found target hWnd
return false; // Stop iterating
}, IntPtr.Zero);
if (targetHWnd == IntPtr.Zero)
{
return;
}
System.Diagnostics.Process? p = null;
var processes = System.Diagnostics.Process.GetProcesses();
foreach (var process in processes)
if (process.MainWindowTitle == GetWindowTitle(targetHWnd))
{
var processSharp = new ProcessSharp(process, MemoryType.Remote);
TargetWindow = processSharp.WindowFactory.MainWindow;
Overlay.Dispose();
var fps = 60;
Overlay.Settings.Current.UpdateRate = 1000 / fps;
Overlay.Initialize(TargetWindow);
Overlay.ClearScreen();
Overlay.TriggerTranslation();
Overlay.Update();
return;
}
}
private string GetWindowTitle(IntPtr hWnd)
{
int textLength = GetWindowTextLength(hWnd);
StringBuilder sb = new(textLength + 1);
GetWindowText(hWnd, sb, sb.Capacity);
return sb.ToString();
}
private string GetClassName(IntPtr hWnd)
{
StringBuilder sb = new(256);
GetClassName(hWnd, sb, sb.Capacity);
return sb.ToString().Trim();
}
private void ComboBox_Loaded(object sender, RoutedEventArgs e)
{
ComboBox.Items.Clear();
var Processes = new List<System.Diagnostics.Process>();
var processes = System.Diagnostics.Process.GetProcesses();
foreach (var process in processes)
if (process.MainWindowTitle != "")
Processes.Add(process);
ComboBox.ItemsSource = Processes;
ComboBox.DisplayMemberPath = "MainWindowTitle";
IntPtr handle = new WindowInteropHelper(this).Handle;
source = HwndSource.FromHwnd(handle);
source.AddHook(HwndHook);
RegisterHotKey(handle, HOTKEY_ID, MOD_CONTROL, VK_F9); //CTRL + CAPS_LOCK
}
private void Translate_Click(object sender, RoutedEventArgs e)
{
if (Overlay != null) Overlay.TriggerTranslation();
}
private void ComboBox_SelectionChanged(object sender, SelectionChangedEventArgs e)
{
TrackedProcess = ComboBox.SelectedValue as System.Diagnostics.Process;
if (TrackedProcess != null)
{
TextBlock.Text = "FOund something";
var processSharp = new ProcessSharp(TrackedProcess, MemoryType.Remote);
TargetWindow = processSharp.WindowFactory.MainWindow;
Overlay.Dispose();
var fps = 60;
Overlay.Settings.Current.UpdateRate = 1000 / fps;
Overlay.Initialize(TargetWindow);
Overlay.ClearScreen();
}
else
{
TextBlock.Text = "FOund NOTHING";
}
}
private void StartRendering()
{
if (IsRendering)
return;
IsRendering = true;
if (TargetWindow == null) return;
Overlay = new DirectXOverlay();
var fps = 60;
Overlay.Settings.Current.UpdateRate = 1000 / fps;
Overlay.Initialize(TargetWindow);
Overlay.Enable();
var info = Overlay.Settings.Current;
while (true) Overlay.Update();
// Overlay.Update();
}
}

View File

@@ -0,0 +1,22 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<OutputType>WinExe</OutputType>
<TargetFramework>net9.0-windows</TargetFramework>
<Nullable>enable</Nullable>
<ImplicitUsings>enable</ImplicitUsings>
<UseWPF>true</UseWPF>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="LibreTranslate.Net.Enhanced" Version="1.9.5.1" />
<PackageReference Include="Process.NET" Version="1.0.8" />
<PackageReference Include="System.Drawing.Common" Version="10.0.8" />
<PackageReference Include="TesseractOCR" Version="5.5.2" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\Overlay.NET\Overlay.NET.csproj" />
</ItemGroup>
</Project>

View File

@@ -0,0 +1,259 @@
<Project>
<PropertyGroup>
<AssemblyName>OnscreenTranslator</AssemblyName>
<IntermediateOutputPath>obj\Debug\</IntermediateOutputPath>
<BaseIntermediateOutputPath>obj\</BaseIntermediateOutputPath>
<MSBuildProjectExtensionsPath>F:\Downloads\Overlay.NET-master\Overlay.NET-master\src\OnscreenTranslator\obj\</MSBuildProjectExtensionsPath>
<_TargetAssemblyProjectName>OnscreenTranslator</_TargetAssemblyProjectName>
<RootNamespace>OnscreenTranslator</RootNamespace>
</PropertyGroup>
<Import Project="Sdk.props" Sdk="Microsoft.NET.Sdk" />
<PropertyGroup>
<OutputType>WinExe</OutputType>
<TargetFramework>net9.0-windows</TargetFramework>
<Nullable>enable</Nullable>
<ImplicitUsings>enable</ImplicitUsings>
<UseWPF>true</UseWPF>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="LibreTranslate.Net.Enhanced" Version="1.9.5.1" />
<PackageReference Include="Process.NET" Version="1.0.8" />
<PackageReference Include="TesseractOCR" Version="5.5.2" />
</ItemGroup>
<ItemGroup>
<ReferencePath Include="C:\Program Files\dotnet\packs\Microsoft.WindowsDesktop.App.Ref\9.0.15\ref\net9.0\Accessibility.dll" />
<ReferencePath Include="C:\Users\luis-\.nuget\packages\libretranslate.net.enhanced\1.9.5.1\lib\net8.0\LibreTranslate.Net.Enhanced.dll" />
<ReferencePath Include="C:\Program Files\dotnet\packs\Microsoft.NETCore.App.Ref\9.0.15\ref\net9.0\Microsoft.CSharp.dll" />
<ReferencePath Include="C:\Users\luis-\.nuget\packages\microsoft.extensions.configuration.abstractions\10.0.7\lib\net9.0\Microsoft.Extensions.Configuration.Abstractions.dll" />
<ReferencePath Include="C:\Users\luis-\.nuget\packages\microsoft.extensions.configuration.binder\10.0.7\lib\net9.0\Microsoft.Extensions.Configuration.Binder.dll" />
<ReferencePath Include="C:\Users\luis-\.nuget\packages\microsoft.extensions.configuration\10.0.7\lib\net9.0\Microsoft.Extensions.Configuration.dll" />
<ReferencePath Include="C:\Users\luis-\.nuget\packages\microsoft.extensions.dependencyinjection.abstractions\10.0.7\lib\net9.0\Microsoft.Extensions.DependencyInjection.Abstractions.dll" />
<ReferencePath Include="C:\Users\luis-\.nuget\packages\microsoft.extensions.dependencyinjection\10.0.7\lib\net9.0\Microsoft.Extensions.DependencyInjection.dll" />
<ReferencePath Include="C:\Users\luis-\.nuget\packages\microsoft.extensions.diagnostics.abstractions\10.0.7\lib\net9.0\Microsoft.Extensions.Diagnostics.Abstractions.dll" />
<ReferencePath Include="C:\Users\luis-\.nuget\packages\microsoft.extensions.diagnostics\10.0.7\lib\net9.0\Microsoft.Extensions.Diagnostics.dll" />
<ReferencePath Include="C:\Users\luis-\.nuget\packages\microsoft.extensions.http\10.0.7\lib\net9.0\Microsoft.Extensions.Http.dll" />
<ReferencePath Include="C:\Users\luis-\.nuget\packages\microsoft.extensions.logging.abstractions\10.0.7\lib\net9.0\Microsoft.Extensions.Logging.Abstractions.dll" />
<ReferencePath Include="C:\Users\luis-\.nuget\packages\microsoft.extensions.logging\10.0.7\lib\net9.0\Microsoft.Extensions.Logging.dll" />
<ReferencePath Include="C:\Users\luis-\.nuget\packages\microsoft.extensions.options.configurationextensions\10.0.7\lib\net9.0\Microsoft.Extensions.Options.ConfigurationExtensions.dll" />
<ReferencePath Include="C:\Users\luis-\.nuget\packages\microsoft.extensions.options\10.0.7\lib\net9.0\Microsoft.Extensions.Options.dll" />
<ReferencePath Include="C:\Users\luis-\.nuget\packages\microsoft.extensions.primitives\10.0.7\lib\net9.0\Microsoft.Extensions.Primitives.dll" />
<ReferencePath Include="C:\Program Files\dotnet\packs\Microsoft.NETCore.App.Ref\9.0.15\ref\net9.0\Microsoft.VisualBasic.Core.dll" />
<ReferencePath Include="C:\Program Files\dotnet\packs\Microsoft.NETCore.App.Ref\9.0.15\ref\net9.0\Microsoft.VisualBasic.dll" />
<ReferencePath Include="C:\Program Files\dotnet\packs\Microsoft.NETCore.App.Ref\9.0.15\ref\net9.0\Microsoft.Win32.Primitives.dll" />
<ReferencePath Include="C:\Program Files\dotnet\packs\Microsoft.WindowsDesktop.App.Ref\9.0.15\ref\net9.0\Microsoft.Win32.Registry.AccessControl.dll" />
<ReferencePath Include="C:\Program Files\dotnet\packs\Microsoft.NETCore.App.Ref\9.0.15\ref\net9.0\Microsoft.Win32.Registry.dll" />
<ReferencePath Include="C:\Program Files\dotnet\packs\Microsoft.WindowsDesktop.App.Ref\9.0.15\ref\net9.0\Microsoft.Win32.SystemEvents.dll" />
<ReferencePath Include="C:\Program Files\dotnet\packs\Microsoft.NETCore.App.Ref\9.0.15\ref\net9.0\mscorlib.dll" />
<ReferencePath Include="C:\Program Files\dotnet\packs\Microsoft.NETCore.App.Ref\9.0.15\ref\net9.0\netstandard.dll" />
<ReferencePath Include="C:\Users\luis-\.nuget\packages\newtonsoft.json\13.0.1\lib\netstandard2.0\Newtonsoft.Json.dll" />
<ReferencePath Include="C:\Program Files\dotnet\packs\Microsoft.WindowsDesktop.App.Ref\9.0.15\ref\net9.0\PresentationCore.dll" />
<ReferencePath Include="C:\Program Files\dotnet\packs\Microsoft.WindowsDesktop.App.Ref\9.0.15\ref\net9.0\PresentationFramework.Aero.dll" />
<ReferencePath Include="C:\Program Files\dotnet\packs\Microsoft.WindowsDesktop.App.Ref\9.0.15\ref\net9.0\PresentationFramework.Aero2.dll" />
<ReferencePath Include="C:\Program Files\dotnet\packs\Microsoft.WindowsDesktop.App.Ref\9.0.15\ref\net9.0\PresentationFramework.AeroLite.dll" />
<ReferencePath Include="C:\Program Files\dotnet\packs\Microsoft.WindowsDesktop.App.Ref\9.0.15\ref\net9.0\PresentationFramework.Classic.dll" />
<ReferencePath Include="C:\Program Files\dotnet\packs\Microsoft.WindowsDesktop.App.Ref\9.0.15\ref\net9.0\PresentationFramework.dll" />
<ReferencePath Include="C:\Program Files\dotnet\packs\Microsoft.WindowsDesktop.App.Ref\9.0.15\ref\net9.0\PresentationFramework.Luna.dll" />
<ReferencePath Include="C:\Program Files\dotnet\packs\Microsoft.WindowsDesktop.App.Ref\9.0.15\ref\net9.0\PresentationFramework.Royale.dll" />
<ReferencePath Include="C:\Program Files\dotnet\packs\Microsoft.WindowsDesktop.App.Ref\9.0.15\ref\net9.0\PresentationUI.dll" />
<ReferencePath Include="C:\Users\luis-\.nuget\packages\process.net\1.0.8\lib\Process.NET.dll" />
<ReferencePath Include="C:\Program Files\dotnet\packs\Microsoft.WindowsDesktop.App.Ref\9.0.15\ref\net9.0\ReachFramework.dll" />
<ReferencePath Include="C:\Program Files\dotnet\packs\Microsoft.NETCore.App.Ref\9.0.15\ref\net9.0\System.AppContext.dll" />
<ReferencePath Include="C:\Program Files\dotnet\packs\Microsoft.NETCore.App.Ref\9.0.15\ref\net9.0\System.Buffers.dll" />
<ReferencePath Include="C:\Program Files\dotnet\packs\Microsoft.WindowsDesktop.App.Ref\9.0.15\ref\net9.0\System.CodeDom.dll" />
<ReferencePath Include="C:\Program Files\dotnet\packs\Microsoft.NETCore.App.Ref\9.0.15\ref\net9.0\System.Collections.Concurrent.dll" />
<ReferencePath Include="C:\Program Files\dotnet\packs\Microsoft.NETCore.App.Ref\9.0.15\ref\net9.0\System.Collections.dll" />
<ReferencePath Include="C:\Program Files\dotnet\packs\Microsoft.NETCore.App.Ref\9.0.15\ref\net9.0\System.Collections.Immutable.dll" />
<ReferencePath Include="C:\Program Files\dotnet\packs\Microsoft.NETCore.App.Ref\9.0.15\ref\net9.0\System.Collections.NonGeneric.dll" />
<ReferencePath Include="C:\Program Files\dotnet\packs\Microsoft.NETCore.App.Ref\9.0.15\ref\net9.0\System.Collections.Specialized.dll" />
<ReferencePath Include="C:\Program Files\dotnet\packs\Microsoft.NETCore.App.Ref\9.0.15\ref\net9.0\System.ComponentModel.Annotations.dll" />
<ReferencePath Include="C:\Program Files\dotnet\packs\Microsoft.NETCore.App.Ref\9.0.15\ref\net9.0\System.ComponentModel.DataAnnotations.dll" />
<ReferencePath Include="C:\Program Files\dotnet\packs\Microsoft.NETCore.App.Ref\9.0.15\ref\net9.0\System.ComponentModel.dll" />
<ReferencePath Include="C:\Program Files\dotnet\packs\Microsoft.NETCore.App.Ref\9.0.15\ref\net9.0\System.ComponentModel.EventBasedAsync.dll" />
<ReferencePath Include="C:\Program Files\dotnet\packs\Microsoft.NETCore.App.Ref\9.0.15\ref\net9.0\System.ComponentModel.Primitives.dll" />
<ReferencePath Include="C:\Program Files\dotnet\packs\Microsoft.NETCore.App.Ref\9.0.15\ref\net9.0\System.ComponentModel.TypeConverter.dll" />
<ReferencePath Include="C:\Program Files\dotnet\packs\Microsoft.WindowsDesktop.App.Ref\9.0.15\ref\net9.0\System.Configuration.ConfigurationManager.dll" />
<ReferencePath Include="C:\Program Files\dotnet\packs\Microsoft.NETCore.App.Ref\9.0.15\ref\net9.0\System.Configuration.dll" />
<ReferencePath Include="C:\Program Files\dotnet\packs\Microsoft.NETCore.App.Ref\9.0.15\ref\net9.0\System.Console.dll" />
<ReferencePath Include="C:\Program Files\dotnet\packs\Microsoft.NETCore.App.Ref\9.0.15\ref\net9.0\System.Core.dll" />
<ReferencePath Include="C:\Program Files\dotnet\packs\Microsoft.NETCore.App.Ref\9.0.15\ref\net9.0\System.Data.Common.dll" />
<ReferencePath Include="C:\Program Files\dotnet\packs\Microsoft.NETCore.App.Ref\9.0.15\ref\net9.0\System.Data.DataSetExtensions.dll" />
<ReferencePath Include="C:\Program Files\dotnet\packs\Microsoft.NETCore.App.Ref\9.0.15\ref\net9.0\System.Data.dll" />
<ReferencePath Include="C:\Program Files\dotnet\packs\Microsoft.NETCore.App.Ref\9.0.15\ref\net9.0\System.Diagnostics.Contracts.dll" />
<ReferencePath Include="C:\Program Files\dotnet\packs\Microsoft.NETCore.App.Ref\9.0.15\ref\net9.0\System.Diagnostics.Debug.dll" />
<ReferencePath Include="C:\Users\luis-\.nuget\packages\system.diagnostics.diagnosticsource\10.0.7\lib\net9.0\System.Diagnostics.DiagnosticSource.dll" />
<ReferencePath Include="C:\Program Files\dotnet\packs\Microsoft.WindowsDesktop.App.Ref\9.0.15\ref\net9.0\System.Diagnostics.EventLog.dll" />
<ReferencePath Include="C:\Program Files\dotnet\packs\Microsoft.NETCore.App.Ref\9.0.15\ref\net9.0\System.Diagnostics.FileVersionInfo.dll" />
<ReferencePath Include="C:\Program Files\dotnet\packs\Microsoft.WindowsDesktop.App.Ref\9.0.15\ref\net9.0\System.Diagnostics.PerformanceCounter.dll" />
<ReferencePath Include="C:\Program Files\dotnet\packs\Microsoft.NETCore.App.Ref\9.0.15\ref\net9.0\System.Diagnostics.Process.dll" />
<ReferencePath Include="C:\Program Files\dotnet\packs\Microsoft.NETCore.App.Ref\9.0.15\ref\net9.0\System.Diagnostics.StackTrace.dll" />
<ReferencePath Include="C:\Program Files\dotnet\packs\Microsoft.NETCore.App.Ref\9.0.15\ref\net9.0\System.Diagnostics.TextWriterTraceListener.dll" />
<ReferencePath Include="C:\Program Files\dotnet\packs\Microsoft.NETCore.App.Ref\9.0.15\ref\net9.0\System.Diagnostics.Tools.dll" />
<ReferencePath Include="C:\Program Files\dotnet\packs\Microsoft.NETCore.App.Ref\9.0.15\ref\net9.0\System.Diagnostics.TraceSource.dll" />
<ReferencePath Include="C:\Program Files\dotnet\packs\Microsoft.NETCore.App.Ref\9.0.15\ref\net9.0\System.Diagnostics.Tracing.dll" />
<ReferencePath Include="C:\Program Files\dotnet\packs\Microsoft.WindowsDesktop.App.Ref\9.0.15\ref\net9.0\System.DirectoryServices.dll" />
<ReferencePath Include="C:\Program Files\dotnet\packs\Microsoft.NETCore.App.Ref\9.0.15\ref\net9.0\System.dll" />
<ReferencePath Include="C:\Program Files\dotnet\packs\Microsoft.NETCore.App.Ref\9.0.15\ref\net9.0\System.Drawing.dll" />
<ReferencePath Include="C:\Program Files\dotnet\packs\Microsoft.NETCore.App.Ref\9.0.15\ref\net9.0\System.Drawing.Primitives.dll" />
<ReferencePath Include="C:\Program Files\dotnet\packs\Microsoft.NETCore.App.Ref\9.0.15\ref\net9.0\System.Dynamic.Runtime.dll" />
<ReferencePath Include="C:\Program Files\dotnet\packs\Microsoft.NETCore.App.Ref\9.0.15\ref\net9.0\System.Formats.Asn1.dll" />
<ReferencePath Include="C:\Program Files\dotnet\packs\Microsoft.WindowsDesktop.App.Ref\9.0.15\ref\net9.0\System.Formats.Nrbf.dll" />
<ReferencePath Include="C:\Program Files\dotnet\packs\Microsoft.NETCore.App.Ref\9.0.15\ref\net9.0\System.Formats.Tar.dll" />
<ReferencePath Include="C:\Program Files\dotnet\packs\Microsoft.NETCore.App.Ref\9.0.15\ref\net9.0\System.Globalization.Calendars.dll" />
<ReferencePath Include="C:\Program Files\dotnet\packs\Microsoft.NETCore.App.Ref\9.0.15\ref\net9.0\System.Globalization.dll" />
<ReferencePath Include="C:\Program Files\dotnet\packs\Microsoft.NETCore.App.Ref\9.0.15\ref\net9.0\System.Globalization.Extensions.dll" />
<ReferencePath Include="C:\Program Files\dotnet\packs\Microsoft.NETCore.App.Ref\9.0.15\ref\net9.0\System.IO.Compression.Brotli.dll" />
<ReferencePath Include="C:\Program Files\dotnet\packs\Microsoft.NETCore.App.Ref\9.0.15\ref\net9.0\System.IO.Compression.dll" />
<ReferencePath Include="C:\Program Files\dotnet\packs\Microsoft.NETCore.App.Ref\9.0.15\ref\net9.0\System.IO.Compression.FileSystem.dll" />
<ReferencePath Include="C:\Program Files\dotnet\packs\Microsoft.NETCore.App.Ref\9.0.15\ref\net9.0\System.IO.Compression.ZipFile.dll" />
<ReferencePath Include="C:\Program Files\dotnet\packs\Microsoft.NETCore.App.Ref\9.0.15\ref\net9.0\System.IO.dll" />
<ReferencePath Include="C:\Program Files\dotnet\packs\Microsoft.NETCore.App.Ref\9.0.15\ref\net9.0\System.IO.FileSystem.AccessControl.dll" />
<ReferencePath Include="C:\Program Files\dotnet\packs\Microsoft.NETCore.App.Ref\9.0.15\ref\net9.0\System.IO.FileSystem.dll" />
<ReferencePath Include="C:\Program Files\dotnet\packs\Microsoft.NETCore.App.Ref\9.0.15\ref\net9.0\System.IO.FileSystem.DriveInfo.dll" />
<ReferencePath Include="C:\Program Files\dotnet\packs\Microsoft.NETCore.App.Ref\9.0.15\ref\net9.0\System.IO.FileSystem.Primitives.dll" />
<ReferencePath Include="C:\Program Files\dotnet\packs\Microsoft.NETCore.App.Ref\9.0.15\ref\net9.0\System.IO.FileSystem.Watcher.dll" />
<ReferencePath Include="C:\Program Files\dotnet\packs\Microsoft.NETCore.App.Ref\9.0.15\ref\net9.0\System.IO.IsolatedStorage.dll" />
<ReferencePath Include="C:\Program Files\dotnet\packs\Microsoft.NETCore.App.Ref\9.0.15\ref\net9.0\System.IO.MemoryMappedFiles.dll" />
<ReferencePath Include="C:\Program Files\dotnet\packs\Microsoft.WindowsDesktop.App.Ref\9.0.15\ref\net9.0\System.IO.Packaging.dll" />
<ReferencePath Include="C:\Program Files\dotnet\packs\Microsoft.NETCore.App.Ref\9.0.15\ref\net9.0\System.IO.Pipelines.dll" />
<ReferencePath Include="C:\Program Files\dotnet\packs\Microsoft.NETCore.App.Ref\9.0.15\ref\net9.0\System.IO.Pipes.AccessControl.dll" />
<ReferencePath Include="C:\Program Files\dotnet\packs\Microsoft.NETCore.App.Ref\9.0.15\ref\net9.0\System.IO.Pipes.dll" />
<ReferencePath Include="C:\Program Files\dotnet\packs\Microsoft.NETCore.App.Ref\9.0.15\ref\net9.0\System.IO.UnmanagedMemoryStream.dll" />
<ReferencePath Include="C:\Program Files\dotnet\packs\Microsoft.NETCore.App.Ref\9.0.15\ref\net9.0\System.Linq.dll" />
<ReferencePath Include="C:\Program Files\dotnet\packs\Microsoft.NETCore.App.Ref\9.0.15\ref\net9.0\System.Linq.Expressions.dll" />
<ReferencePath Include="C:\Program Files\dotnet\packs\Microsoft.NETCore.App.Ref\9.0.15\ref\net9.0\System.Linq.Parallel.dll" />
<ReferencePath Include="C:\Program Files\dotnet\packs\Microsoft.NETCore.App.Ref\9.0.15\ref\net9.0\System.Linq.Queryable.dll" />
<ReferencePath Include="C:\Program Files\dotnet\packs\Microsoft.NETCore.App.Ref\9.0.15\ref\net9.0\System.Memory.dll" />
<ReferencePath Include="C:\Program Files\dotnet\packs\Microsoft.NETCore.App.Ref\9.0.15\ref\net9.0\System.Net.dll" />
<ReferencePath Include="C:\Program Files\dotnet\packs\Microsoft.NETCore.App.Ref\9.0.15\ref\net9.0\System.Net.Http.dll" />
<ReferencePath Include="C:\Program Files\dotnet\packs\Microsoft.NETCore.App.Ref\9.0.15\ref\net9.0\System.Net.Http.Json.dll" />
<ReferencePath Include="C:\Program Files\dotnet\packs\Microsoft.NETCore.App.Ref\9.0.15\ref\net9.0\System.Net.HttpListener.dll" />
<ReferencePath Include="C:\Program Files\dotnet\packs\Microsoft.NETCore.App.Ref\9.0.15\ref\net9.0\System.Net.Mail.dll" />
<ReferencePath Include="C:\Program Files\dotnet\packs\Microsoft.NETCore.App.Ref\9.0.15\ref\net9.0\System.Net.NameResolution.dll" />
<ReferencePath Include="C:\Program Files\dotnet\packs\Microsoft.NETCore.App.Ref\9.0.15\ref\net9.0\System.Net.NetworkInformation.dll" />
<ReferencePath Include="C:\Program Files\dotnet\packs\Microsoft.NETCore.App.Ref\9.0.15\ref\net9.0\System.Net.Ping.dll" />
<ReferencePath Include="C:\Program Files\dotnet\packs\Microsoft.NETCore.App.Ref\9.0.15\ref\net9.0\System.Net.Primitives.dll" />
<ReferencePath Include="C:\Program Files\dotnet\packs\Microsoft.NETCore.App.Ref\9.0.15\ref\net9.0\System.Net.Quic.dll" />
<ReferencePath Include="C:\Program Files\dotnet\packs\Microsoft.NETCore.App.Ref\9.0.15\ref\net9.0\System.Net.Requests.dll" />
<ReferencePath Include="C:\Program Files\dotnet\packs\Microsoft.NETCore.App.Ref\9.0.15\ref\net9.0\System.Net.Security.dll" />
<ReferencePath Include="C:\Program Files\dotnet\packs\Microsoft.NETCore.App.Ref\9.0.15\ref\net9.0\System.Net.ServicePoint.dll" />
<ReferencePath Include="C:\Program Files\dotnet\packs\Microsoft.NETCore.App.Ref\9.0.15\ref\net9.0\System.Net.Sockets.dll" />
<ReferencePath Include="C:\Program Files\dotnet\packs\Microsoft.NETCore.App.Ref\9.0.15\ref\net9.0\System.Net.WebClient.dll" />
<ReferencePath Include="C:\Program Files\dotnet\packs\Microsoft.NETCore.App.Ref\9.0.15\ref\net9.0\System.Net.WebHeaderCollection.dll" />
<ReferencePath Include="C:\Program Files\dotnet\packs\Microsoft.NETCore.App.Ref\9.0.15\ref\net9.0\System.Net.WebProxy.dll" />
<ReferencePath Include="C:\Program Files\dotnet\packs\Microsoft.NETCore.App.Ref\9.0.15\ref\net9.0\System.Net.WebSockets.Client.dll" />
<ReferencePath Include="C:\Program Files\dotnet\packs\Microsoft.NETCore.App.Ref\9.0.15\ref\net9.0\System.Net.WebSockets.dll" />
<ReferencePath Include="C:\Program Files\dotnet\packs\Microsoft.NETCore.App.Ref\9.0.15\ref\net9.0\System.Numerics.dll" />
<ReferencePath Include="C:\Program Files\dotnet\packs\Microsoft.NETCore.App.Ref\9.0.15\ref\net9.0\System.Numerics.Vectors.dll" />
<ReferencePath Include="C:\Program Files\dotnet\packs\Microsoft.NETCore.App.Ref\9.0.15\ref\net9.0\System.ObjectModel.dll" />
<ReferencePath Include="C:\Program Files\dotnet\packs\Microsoft.WindowsDesktop.App.Ref\9.0.15\ref\net9.0\System.Printing.dll" />
<ReferencePath Include="C:\Program Files\dotnet\packs\Microsoft.NETCore.App.Ref\9.0.15\ref\net9.0\System.Reflection.DispatchProxy.dll" />
<ReferencePath Include="C:\Program Files\dotnet\packs\Microsoft.NETCore.App.Ref\9.0.15\ref\net9.0\System.Reflection.dll" />
<ReferencePath Include="C:\Program Files\dotnet\packs\Microsoft.NETCore.App.Ref\9.0.15\ref\net9.0\System.Reflection.Emit.dll" />
<ReferencePath Include="C:\Program Files\dotnet\packs\Microsoft.NETCore.App.Ref\9.0.15\ref\net9.0\System.Reflection.Emit.ILGeneration.dll" />
<ReferencePath Include="C:\Program Files\dotnet\packs\Microsoft.NETCore.App.Ref\9.0.15\ref\net9.0\System.Reflection.Emit.Lightweight.dll" />
<ReferencePath Include="C:\Program Files\dotnet\packs\Microsoft.NETCore.App.Ref\9.0.15\ref\net9.0\System.Reflection.Extensions.dll" />
<ReferencePath Include="C:\Program Files\dotnet\packs\Microsoft.NETCore.App.Ref\9.0.15\ref\net9.0\System.Reflection.Metadata.dll" />
<ReferencePath Include="C:\Program Files\dotnet\packs\Microsoft.NETCore.App.Ref\9.0.15\ref\net9.0\System.Reflection.Primitives.dll" />
<ReferencePath Include="C:\Program Files\dotnet\packs\Microsoft.NETCore.App.Ref\9.0.15\ref\net9.0\System.Reflection.TypeExtensions.dll" />
<ReferencePath Include="C:\Program Files\dotnet\packs\Microsoft.WindowsDesktop.App.Ref\9.0.15\ref\net9.0\System.Resources.Extensions.dll" />
<ReferencePath Include="C:\Program Files\dotnet\packs\Microsoft.NETCore.App.Ref\9.0.15\ref\net9.0\System.Resources.Reader.dll" />
<ReferencePath Include="C:\Program Files\dotnet\packs\Microsoft.NETCore.App.Ref\9.0.15\ref\net9.0\System.Resources.ResourceManager.dll" />
<ReferencePath Include="C:\Program Files\dotnet\packs\Microsoft.NETCore.App.Ref\9.0.15\ref\net9.0\System.Resources.Writer.dll" />
<ReferencePath Include="C:\Program Files\dotnet\packs\Microsoft.NETCore.App.Ref\9.0.15\ref\net9.0\System.Runtime.CompilerServices.Unsafe.dll" />
<ReferencePath Include="C:\Program Files\dotnet\packs\Microsoft.NETCore.App.Ref\9.0.15\ref\net9.0\System.Runtime.CompilerServices.VisualC.dll" />
<ReferencePath Include="C:\Program Files\dotnet\packs\Microsoft.NETCore.App.Ref\9.0.15\ref\net9.0\System.Runtime.dll" />
<ReferencePath Include="C:\Program Files\dotnet\packs\Microsoft.NETCore.App.Ref\9.0.15\ref\net9.0\System.Runtime.Extensions.dll" />
<ReferencePath Include="C:\Program Files\dotnet\packs\Microsoft.NETCore.App.Ref\9.0.15\ref\net9.0\System.Runtime.Handles.dll" />
<ReferencePath Include="C:\Program Files\dotnet\packs\Microsoft.NETCore.App.Ref\9.0.15\ref\net9.0\System.Runtime.InteropServices.dll" />
<ReferencePath Include="C:\Program Files\dotnet\packs\Microsoft.NETCore.App.Ref\9.0.15\ref\net9.0\System.Runtime.InteropServices.JavaScript.dll" />
<ReferencePath Include="C:\Program Files\dotnet\packs\Microsoft.NETCore.App.Ref\9.0.15\ref\net9.0\System.Runtime.InteropServices.RuntimeInformation.dll" />
<ReferencePath Include="C:\Program Files\dotnet\packs\Microsoft.NETCore.App.Ref\9.0.15\ref\net9.0\System.Runtime.Intrinsics.dll" />
<ReferencePath Include="C:\Program Files\dotnet\packs\Microsoft.NETCore.App.Ref\9.0.15\ref\net9.0\System.Runtime.Loader.dll" />
<ReferencePath Include="C:\Program Files\dotnet\packs\Microsoft.NETCore.App.Ref\9.0.15\ref\net9.0\System.Runtime.Numerics.dll" />
<ReferencePath Include="C:\Program Files\dotnet\packs\Microsoft.NETCore.App.Ref\9.0.15\ref\net9.0\System.Runtime.Serialization.dll" />
<ReferencePath Include="C:\Program Files\dotnet\packs\Microsoft.NETCore.App.Ref\9.0.15\ref\net9.0\System.Runtime.Serialization.Formatters.dll" />
<ReferencePath Include="C:\Program Files\dotnet\packs\Microsoft.NETCore.App.Ref\9.0.15\ref\net9.0\System.Runtime.Serialization.Json.dll" />
<ReferencePath Include="C:\Program Files\dotnet\packs\Microsoft.NETCore.App.Ref\9.0.15\ref\net9.0\System.Runtime.Serialization.Primitives.dll" />
<ReferencePath Include="C:\Program Files\dotnet\packs\Microsoft.NETCore.App.Ref\9.0.15\ref\net9.0\System.Runtime.Serialization.Xml.dll" />
<ReferencePath Include="C:\Program Files\dotnet\packs\Microsoft.NETCore.App.Ref\9.0.15\ref\net9.0\System.Security.AccessControl.dll" />
<ReferencePath Include="C:\Program Files\dotnet\packs\Microsoft.NETCore.App.Ref\9.0.15\ref\net9.0\System.Security.Claims.dll" />
<ReferencePath Include="C:\Program Files\dotnet\packs\Microsoft.NETCore.App.Ref\9.0.15\ref\net9.0\System.Security.Cryptography.Algorithms.dll" />
<ReferencePath Include="C:\Program Files\dotnet\packs\Microsoft.NETCore.App.Ref\9.0.15\ref\net9.0\System.Security.Cryptography.Cng.dll" />
<ReferencePath Include="C:\Program Files\dotnet\packs\Microsoft.NETCore.App.Ref\9.0.15\ref\net9.0\System.Security.Cryptography.Csp.dll" />
<ReferencePath Include="C:\Program Files\dotnet\packs\Microsoft.NETCore.App.Ref\9.0.15\ref\net9.0\System.Security.Cryptography.dll" />
<ReferencePath Include="C:\Program Files\dotnet\packs\Microsoft.NETCore.App.Ref\9.0.15\ref\net9.0\System.Security.Cryptography.Encoding.dll" />
<ReferencePath Include="C:\Program Files\dotnet\packs\Microsoft.NETCore.App.Ref\9.0.15\ref\net9.0\System.Security.Cryptography.OpenSsl.dll" />
<ReferencePath Include="C:\Program Files\dotnet\packs\Microsoft.WindowsDesktop.App.Ref\9.0.15\ref\net9.0\System.Security.Cryptography.Pkcs.dll" />
<ReferencePath Include="C:\Program Files\dotnet\packs\Microsoft.NETCore.App.Ref\9.0.15\ref\net9.0\System.Security.Cryptography.Primitives.dll" />
<ReferencePath Include="C:\Program Files\dotnet\packs\Microsoft.WindowsDesktop.App.Ref\9.0.15\ref\net9.0\System.Security.Cryptography.ProtectedData.dll" />
<ReferencePath Include="C:\Program Files\dotnet\packs\Microsoft.NETCore.App.Ref\9.0.15\ref\net9.0\System.Security.Cryptography.X509Certificates.dll" />
<ReferencePath Include="C:\Program Files\dotnet\packs\Microsoft.WindowsDesktop.App.Ref\9.0.15\ref\net9.0\System.Security.Cryptography.Xml.dll" />
<ReferencePath Include="C:\Program Files\dotnet\packs\Microsoft.NETCore.App.Ref\9.0.15\ref\net9.0\System.Security.dll" />
<ReferencePath Include="C:\Program Files\dotnet\packs\Microsoft.WindowsDesktop.App.Ref\9.0.15\ref\net9.0\System.Security.Permissions.dll" />
<ReferencePath Include="C:\Program Files\dotnet\packs\Microsoft.NETCore.App.Ref\9.0.15\ref\net9.0\System.Security.Principal.dll" />
<ReferencePath Include="C:\Program Files\dotnet\packs\Microsoft.NETCore.App.Ref\9.0.15\ref\net9.0\System.Security.Principal.Windows.dll" />
<ReferencePath Include="C:\Program Files\dotnet\packs\Microsoft.NETCore.App.Ref\9.0.15\ref\net9.0\System.Security.SecureString.dll" />
<ReferencePath Include="C:\Program Files\dotnet\packs\Microsoft.NETCore.App.Ref\9.0.15\ref\net9.0\System.ServiceModel.Web.dll" />
<ReferencePath Include="C:\Program Files\dotnet\packs\Microsoft.NETCore.App.Ref\9.0.15\ref\net9.0\System.ServiceProcess.dll" />
<ReferencePath Include="C:\Program Files\dotnet\packs\Microsoft.NETCore.App.Ref\9.0.15\ref\net9.0\System.Text.Encoding.CodePages.dll" />
<ReferencePath Include="C:\Program Files\dotnet\packs\Microsoft.NETCore.App.Ref\9.0.15\ref\net9.0\System.Text.Encoding.dll" />
<ReferencePath Include="C:\Program Files\dotnet\packs\Microsoft.NETCore.App.Ref\9.0.15\ref\net9.0\System.Text.Encoding.Extensions.dll" />
<ReferencePath Include="C:\Program Files\dotnet\packs\Microsoft.NETCore.App.Ref\9.0.15\ref\net9.0\System.Text.Encodings.Web.dll" />
<ReferencePath Include="C:\Program Files\dotnet\packs\Microsoft.NETCore.App.Ref\9.0.15\ref\net9.0\System.Text.Json.dll" />
<ReferencePath Include="C:\Program Files\dotnet\packs\Microsoft.NETCore.App.Ref\9.0.15\ref\net9.0\System.Text.RegularExpressions.dll" />
<ReferencePath Include="C:\Program Files\dotnet\packs\Microsoft.WindowsDesktop.App.Ref\9.0.15\ref\net9.0\System.Threading.AccessControl.dll" />
<ReferencePath Include="C:\Program Files\dotnet\packs\Microsoft.NETCore.App.Ref\9.0.15\ref\net9.0\System.Threading.Channels.dll" />
<ReferencePath Include="C:\Program Files\dotnet\packs\Microsoft.NETCore.App.Ref\9.0.15\ref\net9.0\System.Threading.dll" />
<ReferencePath Include="C:\Program Files\dotnet\packs\Microsoft.NETCore.App.Ref\9.0.15\ref\net9.0\System.Threading.Overlapped.dll" />
<ReferencePath Include="C:\Program Files\dotnet\packs\Microsoft.NETCore.App.Ref\9.0.15\ref\net9.0\System.Threading.Tasks.Dataflow.dll" />
<ReferencePath Include="C:\Program Files\dotnet\packs\Microsoft.NETCore.App.Ref\9.0.15\ref\net9.0\System.Threading.Tasks.dll" />
<ReferencePath Include="C:\Program Files\dotnet\packs\Microsoft.NETCore.App.Ref\9.0.15\ref\net9.0\System.Threading.Tasks.Extensions.dll" />
<ReferencePath Include="C:\Program Files\dotnet\packs\Microsoft.NETCore.App.Ref\9.0.15\ref\net9.0\System.Threading.Tasks.Parallel.dll" />
<ReferencePath Include="C:\Program Files\dotnet\packs\Microsoft.NETCore.App.Ref\9.0.15\ref\net9.0\System.Threading.Thread.dll" />
<ReferencePath Include="C:\Program Files\dotnet\packs\Microsoft.NETCore.App.Ref\9.0.15\ref\net9.0\System.Threading.ThreadPool.dll" />
<ReferencePath Include="C:\Program Files\dotnet\packs\Microsoft.NETCore.App.Ref\9.0.15\ref\net9.0\System.Threading.Timer.dll" />
<ReferencePath Include="C:\Program Files\dotnet\packs\Microsoft.NETCore.App.Ref\9.0.15\ref\net9.0\System.Transactions.dll" />
<ReferencePath Include="C:\Program Files\dotnet\packs\Microsoft.NETCore.App.Ref\9.0.15\ref\net9.0\System.Transactions.Local.dll" />
<ReferencePath Include="C:\Program Files\dotnet\packs\Microsoft.NETCore.App.Ref\9.0.15\ref\net9.0\System.ValueTuple.dll" />
<ReferencePath Include="C:\Program Files\dotnet\packs\Microsoft.NETCore.App.Ref\9.0.15\ref\net9.0\System.Web.dll" />
<ReferencePath Include="C:\Program Files\dotnet\packs\Microsoft.NETCore.App.Ref\9.0.15\ref\net9.0\System.Web.HttpUtility.dll" />
<ReferencePath Include="C:\Program Files\dotnet\packs\Microsoft.WindowsDesktop.App.Ref\9.0.15\ref\net9.0\System.Windows.Controls.Ribbon.dll" />
<ReferencePath Include="C:\Program Files\dotnet\packs\Microsoft.NETCore.App.Ref\9.0.15\ref\net9.0\System.Windows.dll" />
<ReferencePath Include="C:\Program Files\dotnet\packs\Microsoft.WindowsDesktop.App.Ref\9.0.15\ref\net9.0\System.Windows.Extensions.dll" />
<ReferencePath Include="C:\Program Files\dotnet\packs\Microsoft.WindowsDesktop.App.Ref\9.0.15\ref\net9.0\System.Windows.Input.Manipulations.dll" />
<ReferencePath Include="C:\Program Files\dotnet\packs\Microsoft.WindowsDesktop.App.Ref\9.0.15\ref\net9.0\System.Windows.Presentation.dll" />
<ReferencePath Include="C:\Program Files\dotnet\packs\Microsoft.WindowsDesktop.App.Ref\9.0.15\ref\net9.0\System.Xaml.dll" />
<ReferencePath Include="C:\Program Files\dotnet\packs\Microsoft.NETCore.App.Ref\9.0.15\ref\net9.0\System.Xml.dll" />
<ReferencePath Include="C:\Program Files\dotnet\packs\Microsoft.NETCore.App.Ref\9.0.15\ref\net9.0\System.Xml.Linq.dll" />
<ReferencePath Include="C:\Program Files\dotnet\packs\Microsoft.NETCore.App.Ref\9.0.15\ref\net9.0\System.Xml.ReaderWriter.dll" />
<ReferencePath Include="C:\Program Files\dotnet\packs\Microsoft.NETCore.App.Ref\9.0.15\ref\net9.0\System.Xml.Serialization.dll" />
<ReferencePath Include="C:\Program Files\dotnet\packs\Microsoft.NETCore.App.Ref\9.0.15\ref\net9.0\System.Xml.XDocument.dll" />
<ReferencePath Include="C:\Program Files\dotnet\packs\Microsoft.NETCore.App.Ref\9.0.15\ref\net9.0\System.Xml.XmlDocument.dll" />
<ReferencePath Include="C:\Program Files\dotnet\packs\Microsoft.NETCore.App.Ref\9.0.15\ref\net9.0\System.Xml.XmlSerializer.dll" />
<ReferencePath Include="C:\Program Files\dotnet\packs\Microsoft.NETCore.App.Ref\9.0.15\ref\net9.0\System.Xml.XPath.dll" />
<ReferencePath Include="C:\Program Files\dotnet\packs\Microsoft.NETCore.App.Ref\9.0.15\ref\net9.0\System.Xml.XPath.XDocument.dll" />
<ReferencePath Include="C:\Users\luis-\.nuget\packages\tesseractocr\5.5.2\lib\netstandard2.1\TesseractOCR.dll" />
<ReferencePath Include="C:\Program Files\dotnet\packs\Microsoft.WindowsDesktop.App.Ref\9.0.15\ref\net9.0\UIAutomationClient.dll" />
<ReferencePath Include="C:\Program Files\dotnet\packs\Microsoft.WindowsDesktop.App.Ref\9.0.15\ref\net9.0\UIAutomationClientSideProviders.dll" />
<ReferencePath Include="C:\Program Files\dotnet\packs\Microsoft.WindowsDesktop.App.Ref\9.0.15\ref\net9.0\UIAutomationProvider.dll" />
<ReferencePath Include="C:\Program Files\dotnet\packs\Microsoft.WindowsDesktop.App.Ref\9.0.15\ref\net9.0\UIAutomationTypes.dll" />
<ReferencePath Include="C:\Program Files\dotnet\packs\Microsoft.WindowsDesktop.App.Ref\9.0.15\ref\net9.0\WindowsBase.dll" />
</ItemGroup>
<ItemGroup>
<Compile Include="F:\Downloads\Overlay.NET-master\Overlay.NET-master\src\OnscreenTranslator\obj\Debug\net9.0-windows\MainWindow.g.cs" />
<Compile Include="F:\Downloads\Overlay.NET-master\Overlay.NET-master\src\OnscreenTranslator\obj\Debug\net9.0-windows\App.g.cs" />
</ItemGroup>
<ItemGroup>
<Analyzer Include="C:\Program Files\dotnet\sdk\9.0.313\Sdks\Microsoft.NET.Sdk\targets\..\analyzers\Microsoft.CodeAnalysis.CSharp.NetAnalyzers.dll" />
<Analyzer Include="C:\Program Files\dotnet\sdk\9.0.313\Sdks\Microsoft.NET.Sdk\targets\..\analyzers\Microsoft.CodeAnalysis.NetAnalyzers.dll" />
<Analyzer Include="C:\Users\luis-\.nuget\packages\microsoft.extensions.logging.abstractions\10.0.7\analyzers\dotnet\roslyn4.4\cs\Microsoft.Extensions.Logging.Generators.dll" />
<Analyzer Include="C:\Users\luis-\.nuget\packages\microsoft.extensions.options\10.0.7\analyzers\dotnet\roslyn4.4\cs\Microsoft.Extensions.Options.SourceGeneration.dll" />
<Analyzer Include="C:\Program Files\dotnet\packs\Microsoft.NETCore.App.Ref\9.0.15\analyzers/dotnet/cs/Microsoft.Interop.ComInterfaceGenerator.dll" />
<Analyzer Include="C:\Program Files\dotnet\packs\Microsoft.NETCore.App.Ref\9.0.15\analyzers/dotnet/cs/Microsoft.Interop.JavaScript.JSImportGenerator.dll" />
<Analyzer Include="C:\Program Files\dotnet\packs\Microsoft.NETCore.App.Ref\9.0.15\analyzers/dotnet/cs/Microsoft.Interop.LibraryImportGenerator.dll" />
<Analyzer Include="C:\Program Files\dotnet\packs\Microsoft.NETCore.App.Ref\9.0.15\analyzers/dotnet/cs/Microsoft.Interop.SourceGeneration.dll" />
<Analyzer Include="C:\Program Files\dotnet\packs\Microsoft.NETCore.App.Ref\9.0.15\analyzers/dotnet/cs/System.Text.Json.SourceGeneration.dll" />
<Analyzer Include="C:\Program Files\dotnet\packs\Microsoft.NETCore.App.Ref\9.0.15\analyzers/dotnet/cs/System.Text.RegularExpressions.Generator.dll" />
</ItemGroup>
<Import Project="Sdk.targets" Sdk="Microsoft.NET.Sdk" />
</Project>

View File

@@ -0,0 +1,13 @@
namespace OnscreenTranslator;
public class OverlaySettings
{
// 60 frames/sec roughly
public int UpdateRate { get; set; }
public string Author { get; set; }
public string Description { get; set; }
public string Identifier { get; set; }
public string Name { get; set; }
public string Version { get; set; }
}

View File

@@ -0,0 +1,24 @@
<?xml version="1.0" encoding="utf-8"?>
<configuration>
<startup>
<supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.6.2" />
</startup>
<runtime>
<assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
<dependentAssembly>
<assemblyIdentity name="Microsoft.Extensions.DependencyInjection.Abstractions" publicKeyToken="adb9793829ddae60" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-10.0.0.7" newVersion="10.0.0.7" />
</dependentAssembly>
<dependentAssembly>
<assemblyIdentity name="Microsoft.Extensions.Http" publicKeyToken="adb9793829ddae60" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-10.0.0.7" newVersion="10.0.0.7" />
</dependentAssembly>
<dependentAssembly>
<assemblyIdentity name="Microsoft.Extensions.Logging.Abstractions" publicKeyToken="adb9793829ddae60" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-10.0.0.7" newVersion="10.0.0.7" />
</dependentAssembly>
</assemblyBinding>
</runtime>
</configuration>

View File

@@ -0,0 +1,69 @@
using System;
using System.Globalization;
using System.Linq;
using Overlay.NET.Common;
using Process.NET;
using Process.NET.Memory;
namespace Overlay.NET.Demo.Directx {
public class DirectXOverlayDemo {
private OverlayPlugin _directXoverlayPluginExample;
private ProcessSharp _processSharp;
public void StartDemo() {
Log.Debug(@"Please type the process name of the window you want to attach to, e.g 'notepad.");
Log.Debug("Note: If there is more than one process found, the first will be used.");
var processName = Console.ReadLine();
var process = System.Diagnostics.Process.GetProcessesByName(processName).FirstOrDefault();
if (process == null) {
Log.Warn($"No process by the name of {processName} was found.");
Log.Warn("Please open one or use a different name and restart the demo.");
Console.ReadLine();
return;
}
_directXoverlayPluginExample = new DirectxOverlayPluginExample();
_processSharp = new ProcessSharp(process, MemoryType.Remote);
Log.Debug("Enter the frame rate the overlay should render at. e.g '60'");
var result = Console.ReadLine();
var fpsValid = int.TryParse(Convert.ToString(result, CultureInfo.InvariantCulture), NumberStyles.Any,
NumberFormatInfo.InvariantInfo, out int fps);
if (!fpsValid) {
Log.Debug($"{result} is not valid. Please reload and try again by entering an integer such as '30' or '60' ");
return;
}
var d3DOverlay = (DirectxOverlayPluginExample) _directXoverlayPluginExample;
d3DOverlay.Settings.Current.UpdateRate = 1000 / fps;
_directXoverlayPluginExample.Initialize(_processSharp.WindowFactory.MainWindow);
_directXoverlayPluginExample.Enable();
// Log some info about the overlay.
Log.Debug("Starting update loop (open the process you specified and drag around)");
Log.Debug("Update rate: " + d3DOverlay.Settings.Current.UpdateRate.Milliseconds());
var info = d3DOverlay.Settings.Current;
Log.Debug($"Author: {info.Author}");
Log.Debug($"Description: {info.Description}");
Log.Debug($"Name: {info.Name}");
Log.Debug($"Identifier: {info.Identifier}");
Log.Debug($"Version: {info.Version}");
Log.Info("Note: Settings are saved to a settings folder in your main app folder.");
Log.Info("Give your window focus to enable the overlay (and unfocus to disable..)");
Log.Info("Close the console to end the demo.");
while (true) {
_directXoverlayPluginExample.Update();
}
}
}
}

View File

@@ -0,0 +1,296 @@
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Drawing;
using Overlay.NET.Common;
using Overlay.NET.Demo.Internals;
using Overlay.NET.Directx;
using Process.NET.Windows;
using System.Runtime.InteropServices;
using System.Drawing;
using System.Drawing.Imaging;
using System.IO;
using LibreTranslate.Net.Enhanced.Constants;
using LibreTranslate.Net.Enhanced.Models;
using Process.NET.Native.Types;
using TesseractOCR;
using TesseractOCR.Enums;
using Point = System.Drawing.Point;
using Rectangle = System.Drawing.Rectangle;
namespace Overlay.NET.Demo.Directx {
[RegisterPlugin("DirectXverlayDemo-1", "Jacob Kemple", "DirectXOverlayDemo", "0.0",
"A basic demo of the DirectXoverlay.")]
public class DirectxOverlayPluginExample : DirectXOverlayPlugin {
private readonly TickEngine _tickEngine = new TickEngine();
public readonly ISettings<DemoOverlaySettings> Settings = new SerializableSettings<DemoOverlaySettings>();
private int _displayFps;
private int _font;
private int _hugeFont;
private int _i;
private int _interiorBrush;
private int _redBrush;
private int _redOpacityBrush;
private float _rotation;
private Stopwatch _watch;
private struct Element
{
public int X;
public int Y;
public String Input;
public String Output;
}
public override void Initialize(IWindow targetWindow) {
// Set target window by calling the base method
base.Initialize(targetWindow);
// For demo, show how to use settings
var current = Settings.Current;
var type = GetType();
if (current.UpdateRate == 0)
current.UpdateRate = 1000 / 60;
current.Author = GetAuthor(type);
current.Description = GetDescription(type);
current.Identifier = GetIdentifier(type);
current.Name = GetName(type);
current.Version = GetVersion(type);
// File is made from above info
Settings.Save();
Settings.Load();
Console.Title = @"OverlayExample";
OverlayWindow = new DirectXOverlayWindow(targetWindow.Handle, false);
_watch = Stopwatch.StartNew();
_redBrush = OverlayWindow.Graphics.CreateBrush(0x7FFF0000);
_redOpacityBrush = OverlayWindow.Graphics.CreateBrush(Color.FromArgb(80, 255, 0, 0));
_interiorBrush = OverlayWindow.Graphics.CreateBrush(0x7FFFFF00);
_font = OverlayWindow.Graphics.CreateFont("Arial", 20);
_hugeFont = OverlayWindow.Graphics.CreateFont("Arial", 50, true);
_rotation = 0.0f;
_displayFps = 0;
_i = 0;
// Set up update interval and register events for the tick engine.
_tickEngine.PreTick += OnPreTick;
_tickEngine.Tick += OnTick;
}
private void OnTick(object sender, EventArgs e) {
if (!OverlayWindow.IsVisible) {
return;
}
OverlayWindow.Update();
InternalRender();
}
private void OnPreTick(object sender, EventArgs e) {
var targetWindowIsActivated = TargetWindow.IsActivated;
if (!targetWindowIsActivated && OverlayWindow.IsVisible) {
_watch.Stop();
ClearScreen();
OverlayWindow.Hide();
}
else if (targetWindowIsActivated && !OverlayWindow.IsVisible) {
OverlayWindow.Show();
}
}
// ReSharper disable once RedundantOverriddenMember
public override void Enable() {
_tickEngine.Interval = Settings.Current.UpdateRate.Milliseconds();
_tickEngine.IsTicking = true;
base.Enable();
}
// ReSharper disable once RedundantOverriddenMember
public override void Disable() {
_tickEngine.IsTicking = false;
base.Disable();
}
public override void Update() => _tickEngine.Pulse();
protected void InternalRender() {
if (!_watch.IsRunning) {
_watch.Start();
}
OverlayWindow.Graphics.BeginScene();
OverlayWindow.Graphics.ClearScene();
Rectangle bounds = new Rectangle(TargetWindow.X,
TargetWindow.Y,
TargetWindow.Width,
TargetWindow.Height);
using (Bitmap bitmap = new Bitmap(bounds.Width, bounds.Height))
{
using (Graphics g = Graphics.FromImage(bitmap))
{
g.CopyFromScreen(new Point(bounds.Left,bounds.Top), Point.Empty, bounds.Size);
}
// bitmap.Save("C://test.jpg", ImageFormat.Jpeg);
Image im = Image.FromHbitmap(bitmap.GetHbitmap());
MemoryStream mem = new MemoryStream();
im.Save(mem, System.Drawing.Imaging.ImageFormat.Bmp);
List<Language> languages = new List<Language>();
languages.Add(Language.Japanese);
languages.Add(Language.JapaneseVertical);
languages.Add(Language.English);
var engine = new Engine("F:/Downloads/tessdata-4.1.0/tessdata-4.1.0", languages, EngineMode.Default);
var img = TesseractOCR.Pix.Image.LoadFromMemory(mem);
var page = engine.Process(img);
var HTML = page.HOcrText(false);
List<Element> elements = new List<Element>();
var Index = 0;
while (Index != -1)
{
Index = HTML.IndexOf("class='ocrx_word'", Index);
if (Index == -1)
{
break;
}
var BbboxIndex = HTML.IndexOf("bbox", Index);
if (BbboxIndex == -1)
{
break;
}
var XIndex = BbboxIndex + 4;
var YIndex = HTML.IndexOf(" ", XIndex + 1);
if (YIndex == -1)
{
break;
}
++YIndex;
var YEnd = HTML.IndexOf(" ", YIndex + 1);
if (YEnd == -1)
{
break;
}
var WordStart = HTML.IndexOf(">", YIndex);
if (WordStart == -1)
{
break;
}
++WordStart;
var WordEnd = HTML.IndexOf("<", WordStart);
if (WordEnd == -1)
{
break;
}
var NewElement = new Element();
var XString = HTML.Substring(XIndex, YIndex - XIndex);
var YString = HTML.Substring(YIndex, YEnd - YIndex);
NewElement.X = int.Parse(XString);
NewElement.Y = int.Parse(YString);
NewElement.Input = HTML.Substring(WordStart, WordEnd - WordStart);
elements.Add(NewElement);
Index = WordEnd;
}
Console.WriteLine("Mean confidence: {0}", page.MeanConfidence);
Console.WriteLine("Text: \r\n{0}", page.Text);
// foreach (var element in elements)
// {
// var libreTranslate = new LibreTranslate.Net.Enhanced.LibreTranslate("http://127.0.0.1:5000", "");
//
// string TargetText = await TranslateAsync(new LibreTranslate.Net.Enhanced.Models.Translate
// {
// Source = LanguageCode.English,
// Target = LanguageCode.German,
// Text = Input
// });
//
// Console.WriteLine(TargetText);
// OverlayWindow.Graphics.DrawText(element.Input, _font, _redBrush, element.X, element.Y);
// }
}
// //first row
// OverlayWindow.Graphics.DrawText("DrawBarH", _font, _redBrush, 50, 40);
// OverlayWindow.Graphics.DrawBarH(50, 70, 20, 100, 80, 2, _redBrush, _interiorBrush);
//
// OverlayWindow.Graphics.DrawText("DrawBarV", _font, _redBrush, 200, 40);
// OverlayWindow.Graphics.DrawBarV(200, 120, 100, 20, 80, 2, _redBrush, _interiorBrush);
//
// OverlayWindow.Graphics.DrawText("DrawBox2D", _font, _redBrush, 350, 40);
// OverlayWindow.Graphics.DrawBox2D(350, 70, 50, 100, 2, _redBrush, _redOpacityBrush);
//
// OverlayWindow.Graphics.DrawText("DrawBox3D", _font, _redBrush, 500, 40);
// OverlayWindow.Graphics.DrawBox3D(500, 80, 50, 100, 10, 2, _redBrush, _redOpacityBrush);
//
// OverlayWindow.Graphics.DrawText("DrawCircle3D", _font, _redBrush, 650, 40);
// OverlayWindow.Graphics.DrawCircle(700, 120, 35, 2, _redBrush);
//
// OverlayWindow.Graphics.DrawText("DrawEdge", _font, _redBrush, 800, 40);
// OverlayWindow.Graphics.DrawEdge(800, 70, 50, 100, 10, 2, _redBrush);
//
// OverlayWindow.Graphics.DrawText("DrawLine", _font, _redBrush, 950, 40);
// OverlayWindow.Graphics.DrawLine(950, 70, 1000, 200, 2, _redBrush);
//
// //second row
// OverlayWindow.Graphics.DrawText("DrawPlus", _font, _redBrush, 50, 250);
// OverlayWindow.Graphics.DrawPlus(70, 300, 15, 2, _redBrush);
//
// OverlayWindow.Graphics.DrawText("DrawRectangle", _font, _redBrush, 200, 250);
// OverlayWindow.Graphics.DrawRectangle(200, 300, 50, 100, 2, _redBrush);
//
// OverlayWindow.Graphics.DrawText("DrawRectangle3D", _font, _redBrush, 350, 250);
// OverlayWindow.Graphics.DrawRectangle3D(350, 320, 50, 100, 10, 2, _redBrush);
//
// OverlayWindow.Graphics.DrawText("FillCircle", _font, _redBrush, 800, 250);
// OverlayWindow.Graphics.FillCircle(850, 350, 50, _redBrush);
//
// OverlayWindow.Graphics.DrawText("FillRectangle", _font, _redBrush, 950, 250);
// OverlayWindow.Graphics.FillRectangle(950, 300, 50, 100, _redBrush);
_rotation += 0.03f; //related to speed
if (_rotation > 50.0f) //size of the swastika
{
_rotation = -50.0f;
}
if (_watch.ElapsedMilliseconds > 1000) {
_i = _displayFps;
_displayFps = 0;
_watch.Restart();
}
else {
_displayFps++;
}
// OverlayWindow.Graphics.DrawText("FPS: " + _i, _hugeFont, _redBrush, 400, 600, false);
OverlayWindow.Graphics.EndScene();
}
public override void Dispose() {
OverlayWindow.Dispose();
base.Dispose();
}
private void ClearScreen() {
OverlayWindow.Graphics.BeginScene();
OverlayWindow.Graphics.ClearScene();
OverlayWindow.Graphics.EndScene();
}
}
}

View File

@@ -0,0 +1,8 @@
using System;
using Overlay.NET.Common;
namespace Overlay.NET.Demo.Internals {
public class ConsoleLog : ILogger {
public void WriteLine(string line) => Console.WriteLine(line);
}
}

View File

@@ -0,0 +1,13 @@
namespace Overlay.NET.Demo.Internals {
// Example settings
public class DemoOverlaySettings {
// 60 frames/sec roughly
public int UpdateRate { get; set; }
public string Author { get; set; }
public string Description { get; set; }
public string Identifier { get; set; }
public string Name { get; set; }
public string Version { get; set; }
}
}

View File

@@ -0,0 +1,146 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="14.0" DefaultTargets="Build" 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>{DBC09A34-CD3F-4D2A-8DD4-C768D36284FE}</ProjectGuid>
<OutputType>Exe</OutputType>
<AppDesignerFolder>Properties</AppDesignerFolder>
<RootNamespace>Overlay.NET.Demo</RootNamespace>
<AssemblyName>Overlay.NET.Demo</AssemblyName>
<TargetFrameworkVersion>v4.6.2</TargetFrameworkVersion>
<FileAlignment>512</FileAlignment>
<AutoGenerateBindingRedirects>true</AutoGenerateBindingRedirects>
<TargetFrameworkProfile />
</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>
<Prefer32Bit>false</Prefer32Bit>
</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>
<Prefer32Bit>false</Prefer32Bit>
</PropertyGroup>
<ItemGroup>
<Reference Include="LibreTranslate.Net.Enhanced, Version=1.9.5.1, Culture=neutral, processorArchitecture=MSIL">
<HintPath>..\packages\LibreTranslate.Net.Enhanced.1.9.5.1\lib\netstandard2.0\LibreTranslate.Net.Enhanced.dll</HintPath>
</Reference>
<Reference Include="Microsoft.Bcl.AsyncInterfaces, Version=10.0.0.7, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51, processorArchitecture=MSIL">
<HintPath>..\packages\Microsoft.Bcl.AsyncInterfaces.10.0.7\lib\net462\Microsoft.Bcl.AsyncInterfaces.dll</HintPath>
</Reference>
<Reference Include="Microsoft.Extensions.Configuration.Abstractions, Version=10.0.0.7, Culture=neutral, PublicKeyToken=adb9793829ddae60, processorArchitecture=MSIL">
<HintPath>..\packages\Microsoft.Extensions.Configuration.Abstractions.10.0.7\lib\net462\Microsoft.Extensions.Configuration.Abstractions.dll</HintPath>
</Reference>
<Reference Include="Microsoft.Extensions.DependencyInjection, Version=10.0.0.7, Culture=neutral, PublicKeyToken=adb9793829ddae60, processorArchitecture=MSIL">
<HintPath>..\packages\Microsoft.Extensions.DependencyInjection.10.0.7\lib\net462\Microsoft.Extensions.DependencyInjection.dll</HintPath>
</Reference>
<Reference Include="Microsoft.Extensions.DependencyInjection.Abstractions, Version=10.0.0.7, Culture=neutral, PublicKeyToken=adb9793829ddae60, processorArchitecture=MSIL">
<HintPath>..\packages\Microsoft.Extensions.DependencyInjection.Abstractions.10.0.7\lib\net462\Microsoft.Extensions.DependencyInjection.Abstractions.dll</HintPath>
</Reference>
<Reference Include="Microsoft.Extensions.Http, Version=10.0.0.7, Culture=neutral, PublicKeyToken=adb9793829ddae60, processorArchitecture=MSIL">
<HintPath>..\packages\Microsoft.Extensions.Http.10.0.7\lib\net462\Microsoft.Extensions.Http.dll</HintPath>
</Reference>
<Reference Include="Microsoft.Extensions.Logging, Version=10.0.0.7, Culture=neutral, PublicKeyToken=adb9793829ddae60, processorArchitecture=MSIL">
<HintPath>..\packages\Microsoft.Extensions.Logging.10.0.7\lib\net462\Microsoft.Extensions.Logging.dll</HintPath>
</Reference>
<Reference Include="Microsoft.Extensions.Logging.Abstractions, Version=10.0.0.7, Culture=neutral, PublicKeyToken=adb9793829ddae60, processorArchitecture=MSIL">
<HintPath>..\packages\Microsoft.Extensions.Logging.Abstractions.10.0.7\lib\net462\Microsoft.Extensions.Logging.Abstractions.dll</HintPath>
</Reference>
<Reference Include="Microsoft.Extensions.Options, Version=10.0.0.7, Culture=neutral, PublicKeyToken=adb9793829ddae60, processorArchitecture=MSIL">
<HintPath>..\packages\Microsoft.Extensions.Options.10.0.7\lib\net462\Microsoft.Extensions.Options.dll</HintPath>
</Reference>
<Reference Include="Microsoft.Extensions.Primitives, Version=10.0.0.7, Culture=neutral, PublicKeyToken=adb9793829ddae60, processorArchitecture=MSIL">
<HintPath>..\packages\Microsoft.Extensions.Primitives.10.0.7\lib\net462\Microsoft.Extensions.Primitives.dll</HintPath>
</Reference>
<Reference Include="mscorlib" />
<Reference Include="Newtonsoft.Json, Version=13.0.0.0, Culture=neutral, PublicKeyToken=30ad4fe6b2a6aeed, processorArchitecture=MSIL">
<HintPath>..\packages\Newtonsoft.Json.13.0.1\lib\net45\Newtonsoft.Json.dll</HintPath>
</Reference>
<Reference Include="PresentationCore" />
<Reference Include="PresentationFramework" />
<Reference Include="Process.NET, Version=1.0.0.0, Culture=neutral, processorArchitecture=MSIL">
<HintPath>..\packages\Process.NET.1.0.8\lib\Process.NET.dll</HintPath>
</Reference>
<Reference Include="System" />
<Reference Include="System.Buffers, Version=4.0.5.0, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51, processorArchitecture=MSIL">
<HintPath>..\packages\System.Buffers.4.6.1\lib\net462\System.Buffers.dll</HintPath>
</Reference>
<Reference Include="System.ComponentModel.DataAnnotations" />
<Reference Include="System.Core" />
<Reference Include="System.Diagnostics.DiagnosticSource, Version=10.0.0.7, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51, processorArchitecture=MSIL">
<HintPath>..\packages\System.Diagnostics.DiagnosticSource.10.0.7\lib\net462\System.Diagnostics.DiagnosticSource.dll</HintPath>
</Reference>
<Reference Include="System.Drawing" />
<Reference Include="System.Memory, Version=4.0.5.0, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51, processorArchitecture=MSIL">
<HintPath>..\packages\System.Memory.4.6.3\lib\net462\System.Memory.dll</HintPath>
</Reference>
<Reference Include="System.Net.Http" />
<Reference Include="System.Numerics" />
<Reference Include="System.Numerics.Vectors, Version=4.1.6.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL">
<HintPath>..\packages\System.Numerics.Vectors.4.6.1\lib\net462\System.Numerics.Vectors.dll</HintPath>
</Reference>
<Reference Include="System.Runtime.CompilerServices.Unsafe, Version=6.0.3.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL">
<HintPath>..\packages\System.Runtime.CompilerServices.Unsafe.6.1.2\lib\net462\System.Runtime.CompilerServices.Unsafe.dll</HintPath>
</Reference>
<Reference Include="System.Threading.Tasks.Extensions, Version=4.2.4.0, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51, processorArchitecture=MSIL">
<HintPath>..\packages\System.Threading.Tasks.Extensions.4.6.3\lib\net462\System.Threading.Tasks.Extensions.dll</HintPath>
</Reference>
<Reference Include="System.ValueTuple, Version=4.0.5.0, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51, processorArchitecture=MSIL">
<HintPath>..\packages\System.ValueTuple.4.6.2\lib\net462\System.ValueTuple.dll</HintPath>
</Reference>
<Reference Include="System.Xaml" />
<Reference Include="TesseractOCR, Version=5.5.2.0, Culture=neutral, processorArchitecture=MSIL">
<HintPath>..\packages\TesseractOCR.5.5.2\lib\netstandard2.0\TesseractOCR.dll</HintPath>
</Reference>
<Reference Include="WindowsBase" />
</ItemGroup>
<ItemGroup>
<Compile Include="Directx\DirectXOverlayDemo.cs" />
<Compile Include="Internals\ConsoleLog.cs" />
<Compile Include="Directx\DirectxOverlayPluginExample.cs" />
<Compile Include="Program.cs" />
<Compile Include="Properties\AssemblyInfo.cs" />
<Compile Include="Internals\DemoOverlaySettings.cs" />
<Compile Include="Wpf\WpfOverlayDemoExample.cs" />
<Compile Include="Wpf\WpfOverlayExampleDemo.cs" />
</ItemGroup>
<ItemGroup>
<None Include="App.config" />
<None Include="packages.config" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\Overlay.NET\Overlay.NET.csproj">
<Project>{2d411ea5-bc00-4630-b25e-43c554323e72}</Project>
<Name>Overlay.NET</Name>
</ProjectReference>
</ItemGroup>
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
<Import Project="..\packages\TesseractOCR.5.5.2\build\TesseractOCR.targets" Condition="Exists('..\packages\TesseractOCR.5.5.2\build\TesseractOCR.targets')" />
<Target Name="EnsureNuGetPackageBuildImports" BeforeTargets="PrepareForBuild">
<PropertyGroup>
<ErrorText>This project references NuGet package(s) that are missing on this computer. Enable 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\TesseractOCR.5.5.2\build\TesseractOCR.targets')" Text="$([System.String]::Format('$(ErrorText)', '..\packages\TesseractOCR.5.5.2\build\TesseractOCR.targets'))" />
</Target>
<!-- To modify your build process, add your task inside one of the targets below and uncomment it.
Other similar extension points exist, see Microsoft.Common.targets.
<Target Name="BeforeBuild">
</Target>
<Target Name="AfterBuild">
</Target>
-->
</Project>

View File

@@ -0,0 +1,114 @@
using System;
using System.Net.Http;
using System.Threading.Tasks;
using Overlay.NET.Common;
using Overlay.NET.Demo.Directx;
using Overlay.NET.Demo.Internals;
using Overlay.NET.Demo.Wpf;
using LibreTranslate.Net.Enhanced;
using LibreTranslate.Net.Enhanced.Constants;
using LibreTranslate.Net.Enhanced.Models;
using TesseractOCR;
using TesseractOCR.Enums;
// using System.Diagnostics;
// using Process.NET;
namespace Overlay.NET.Demo {
/// <summary>
/// </summary>
public static class Program {
/// <summary>
/// Defines the entry point of the application.
/// </summary>
[STAThread]
public static void Main()
{
Log.Register("Console", new ConsoleLog());
// Log.Debug("Enter text to translate:");
// while (true)
// {
// String Text = Console.ReadLine();
//
// Translate(Text);
// }
// var engine = new Engine("F:/Downloads/tessdata-4.1.0/tessdata-4.1.0", Language.English, EngineMode.Default);
// var img = TesseractOCR.Pix.Image.LoadFromFile("C:/Users/luis-/Desktop/HIAXnBzWcAAKyGQ.png");
// var page = engine.Process(img);
// Console.WriteLine("Mean confidence: {0}", page.MeanConfidence);
// Console.WriteLine("Text: \r\n{0}", page.Text);
//
// Console.ReadLine();
// ProcessStartInfo start = new ProcessStartInfo();
// // Enter in the command line arguments, everything you would enter after the executable name itself
// start.Arguments = arguments;
// // Enter the executable to run, including the complete path
// start.FileName = "C:/Program Files/Tesseract-OCR/tesseract.exe";
// start.FileName = "C:/Program Files/Tesseract-OCR/tesseract.exe";
// // Do you want to show a console window?
// start.WindowStyle = ProcessWindowStyle.Hidden;
// start.CreateNoWindow = true;
// int exitCode;
//
//
// // Run the external process & wait for it to finish
// using (Process proc = Process.Start(start))
// {
// proc.WaitForExit();
//
// // Retrieve the app's exit code
// exitCode = proc.ExitCode;
// }
Log.Debug("Enter 1 to run WPF overlay demo");
Log.Debug("Enter 2 to run DirectX overlay demo");
var result = Console.ReadLine();
int oneOrTwo;
var parsed = int.TryParse(result, out oneOrTwo);
if (!parsed) {
Log.Debug("Unable to read your input, make sure it consist of '1' or '2' only and try again");
return;
}
// ReSharper disable once SwitchStatementMissingSomeCases
switch (oneOrTwo) {
case 1:
var wpfDemo = new WpfOverlayExampleDemo();
wpfDemo.StartDemo();
Log.WriteLine("Demo running..");
break;
case 2:
var directXDemo = new DirectXOverlayDemo();
directXDemo.StartDemo();
Log.WriteLine("Demo running..");
break;
}
Console.ReadLine();
}
static async Task Translate(String Input)
{
var libreTranslate = new LibreTranslate.Net.Enhanced.LibreTranslate("http://127.0.0.1:5000", "");
string TargetText = await libreTranslate.TranslateAsync(new Translate
{
Source = LanguageCode.English,
Target = LanguageCode.German,
Text = Input
});
Console.WriteLine(TargetText);
}
}
}

View File

@@ -0,0 +1,39 @@
using System.Reflection;
using System.Runtime.InteropServices;
// 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("Overlay.NET.Demo")]
[assembly: AssemblyDescription("")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("")]
[assembly: AssemblyProduct("Overlay.NET.Demo")]
[assembly: AssemblyCopyright("Copyright © 2016")]
[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)]
// The following GUID is for the ID of the typelib if this project is exposed to COM
[assembly: Guid("dbc09a34-cd3f-4d2a-8dd4-c768d36284fe")]
// 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,178 @@
using System;
using System.Windows;
using System.Windows.Media;
using System.Windows.Shapes;
using Overlay.NET.Common;
using Overlay.NET.Demo.Internals;
using Overlay.NET.Wpf;
using Process.NET.Windows;
using OverlayWindow = Overlay.NET.Wpf.OverlayWindow;
namespace Overlay.NET.Demo.Wpf {
[RegisterPlugin("WpfOverlayDemo-1", "Jacob Kemple", "WpfOverlayDemo", "0.0", "A basic demo of the WPF overlay.")]
public class WpfOverlayDemoExample : WpfOverlayPlugin {
public ISettings<DemoOverlaySettings> Settings { get; } = new SerializableSettings<DemoOverlaySettings>();
// Used to limit update rates via timestamps
// This way we can avoid thread issues with wanting to delay updates
private readonly TickEngine _tickEngine = new TickEngine();
private Ellipse _ellipse;
private bool _isDisposed;
private bool _isSetup;
// Shapes used in the demo
private Line _line;
private Polygon _polygon;
private Rectangle _rectangle;
public override void Enable() {
_tickEngine.IsTicking = true;
base.Enable();
}
public override void Disable() {
_tickEngine.IsTicking = false;
base.Disable();
}
public override void Initialize(IWindow targetWindow) {
// Set target window by calling the base method
base.Initialize(targetWindow);
OverlayWindow = new OverlayWindow(targetWindow);
// For demo, show how to use settings
var current = Settings.Current;
var type = GetType();
current.UpdateRate = 1000 / 60;
current.Author = GetAuthor(type);
current.Description = GetDescription(type);
current.Identifier = GetIdentifier(type);
current.Name = GetName(type);
current.Version = GetVersion(type);
// File is made from above info
Settings.Save();
Settings.Load();
// Set up update interval and register events for the tick engine.
_tickEngine.Interval = Settings.Current.UpdateRate.Milliseconds();
_tickEngine.PreTick += OnPreTick;
_tickEngine.Tick += OnTick;
}
private void OnTick(object sender, EventArgs eventArgs) {
// This will only be true if the target window is active
// (or very recently has been, depends on your update rate)
if (OverlayWindow.IsVisible) {
OverlayWindow.Update();
}
}
private void OnPreTick(object sender, EventArgs eventArgs) {
// Only want to set them up once.
if (!_isSetup) {
SetUp();
_isSetup = true;
}
var activated = TargetWindow.IsActivated;
var visible = OverlayWindow.IsVisible;
// Ensure window is shown or hidden correctly prior to updating
if (!activated && visible) {
OverlayWindow.Hide();
}
else if (activated && !visible) {
OverlayWindow.Show();
}
}
public override void Update() => _tickEngine.Pulse();
// Clear objects
public override void Dispose() {
if (_isDisposed) {
return;
}
if (IsEnabled) {
Disable();
}
OverlayWindow?.Hide();
OverlayWindow?.Close();
OverlayWindow = null;
_tickEngine.Stop();
Settings.Save();
base.Dispose();
_isDisposed = true;
}
~WpfOverlayDemoExample() {
Dispose();
}
// Random shapes.. thanks Julian ^_^
private void SetUp() {
_polygon = new Polygon {
Points = new PointCollection(5) {
new Point(100, 150),
new Point(120, 130),
new Point(140, 150),
new Point(140, 200),
new Point(100, 200)
},
Stroke = new SolidColorBrush(Color.FromRgb(0, 0, 255)),
Fill =
new RadialGradientBrush(
Color.FromRgb(255, 255, 0),
Color.FromRgb(255, 0, 255))
};
OverlayWindow.Add(_polygon);
// Create a line
_line = new Line {
X1 = 100,
X2 = 300,
Y1 = 200,
Y2 = 200,
Stroke = new SolidColorBrush(Color.FromRgb(0, 255, 0)),
StrokeThickness = 2
};
OverlayWindow.Add(_line);
// Create an ellipse (circle)
_ellipse = new Ellipse {
Width = 15,
Height = 15,
Margin = new Thickness(300, 300, 0, 0),
Stroke =
new SolidColorBrush(Color.FromRgb(0, 255, 255))
};
OverlayWindow.Add(_ellipse);
// Create a rectangle
_rectangle = new Rectangle {
RadiusX = 2,
RadiusY = 2,
Width = 50,
Height = 100,
Margin = new Thickness(400, 400, 0, 0),
Stroke = new SolidColorBrush(Color.FromRgb(255, 0, 0)),
Fill =
new SolidColorBrush(Color.FromArgb(100, 255, 255,
255))
};
OverlayWindow.Add(_rectangle);
}
}
}

View File

@@ -0,0 +1,98 @@
using System;
using System.Globalization;
using System.Linq;
using System.Windows;
using System.Windows.Documents;
using System.Windows.Media;
using System.Windows.Media.Media3D;
using Overlay.NET.Common;
using Process.NET;
using Process.NET.Memory;
namespace Overlay.NET.Demo.Wpf {
/// <summary>
/// </summary>
public class WpfOverlayExampleDemo {
/// <summary>
/// The overlay
/// </summary>
private static OverlayPlugin _overlay;
/// <summary>
/// The process sharp
/// </summary>
private static ProcessSharp _processSharp;
/// <summary>
/// The work
/// </summary>
private static bool _work;
/// <summary>
/// Starts the demo.
/// </summary>
public void StartDemo() {
Log.Debug(@"Please type the process name of the window you want to attach to, e.g 'notepad.");
Log.Debug("Note: If there is more than one process found, the first will be used.");
// Set up objects/overlay
var processName = Console.ReadLine();
var process = System.Diagnostics.Process.GetProcessesByName(processName).FirstOrDefault();
if (process == null) {
Log.Warn($"No process by the name of {processName} was found.");
Log.Warn("Please open one or use a different name and restart the demo.");
Console.ReadLine();
return;
}
_processSharp = new ProcessSharp(process, MemoryType.Remote);
_overlay = new WpfOverlayDemoExample();
var wpfOverlay = (WpfOverlayDemoExample) _overlay;
// This is done to focus on the fact the Init method
// is overriden in the wpf overlay demo in order to set the
// wpf overlay window instance
wpfOverlay.Initialize(_processSharp.WindowFactory.MainWindow);
wpfOverlay.Enable();
_work = true;
// Log some info about the overlay.
Log.Debug("Starting update loop (open the process you specified and drag around)");
Log.Debug("Update rate: " + wpfOverlay.Settings.Current.UpdateRate.Milliseconds());
var info = wpfOverlay.Settings.Current;
Log.Debug($"Author: {info.Author}");
Log.Debug($"Description: {info.Description}");
Log.Debug($"Name: {info.Name}");
Log.Debug($"Identifier: {info.Identifier}");
Log.Debug($"Version: {info.Version}");
Log.Info("Note: Settings are saved to a settings folder in your main app folder.");
Log.Info("Give your window focus to enable the overlay (and unfocus to disable..)");
Log.Info("Close the console to end the demo.");
wpfOverlay.OverlayWindow.Draw += OnDraw;
// Do work
while (_work) {
_overlay.Update();
}
Log.Debug("Demo complete.");
}
private static void OnDraw(object sender, DrawingContext context) {
// Draw a formatted text string into the DrawingContext.
context.DrawText(
new FormattedText("Click Me!", CultureInfo.GetCultureInfo("en-us"), FlowDirection.LeftToRight,
new Typeface("Verdana"), 36, Brushes.BlueViolet), new Point(200, 116));
context.DrawLine(new Pen(Brushes.Blue, 10), new Point(100, 100), new Point(10, 10));
}
}
}

View File

@@ -0,0 +1,24 @@
<?xml version="1.0" encoding="utf-8"?>
<packages>
<package id="LibreTranslate.Net.Enhanced" version="1.9.5.1" targetFramework="net462" />
<package id="Microsoft.Bcl.AsyncInterfaces" version="10.0.7" targetFramework="net462" />
<package id="Microsoft.Extensions.Configuration.Abstractions" version="10.0.7" targetFramework="net462" />
<package id="Microsoft.Extensions.DependencyInjection" version="10.0.7" targetFramework="net462" />
<package id="Microsoft.Extensions.DependencyInjection.Abstractions" version="10.0.7" targetFramework="net462" />
<package id="Microsoft.Extensions.Http" version="10.0.7" targetFramework="net462" />
<package id="Microsoft.Extensions.Logging" version="10.0.7" targetFramework="net462" />
<package id="Microsoft.Extensions.Logging.Abstractions" version="10.0.7" targetFramework="net462" />
<package id="Microsoft.Extensions.Options" version="10.0.7" targetFramework="net462" />
<package id="Microsoft.Extensions.Primitives" version="10.0.7" targetFramework="net462" />
<package id="Newtonsoft.Json" version="13.0.1" targetFramework="net462" />
<package id="Process.NET" version="1.0.8" targetFramework="net462" />
<package id="System.Buffers" version="4.6.1" targetFramework="net462" />
<package id="System.Diagnostics.DiagnosticSource" version="10.0.7" targetFramework="net462" />
<package id="System.Memory" version="4.6.3" targetFramework="net462" />
<package id="System.Numerics.Vectors" version="4.6.1" targetFramework="net462" />
<package id="System.Reflection.Emit" version="4.7.0" targetFramework="net462" />
<package id="System.Runtime.CompilerServices.Unsafe" version="6.1.2" targetFramework="net462" />
<package id="System.Threading.Tasks.Extensions" version="4.6.3" targetFramework="net462" />
<package id="System.ValueTuple" version="4.6.2" targetFramework="net462" />
<package id="TesseractOCR" version="5.5.2" targetFramework="net462" />
</packages>

34
src/Overlay.NET.sln Normal file
View File

@@ -0,0 +1,34 @@
Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio 14
VisualStudioVersion = 14.0.25420.1
MinimumVisualStudioVersion = 10.0.40219.1
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Overlay.NET", "Overlay.NET\Overlay.NET.csproj", "{2D411EA5-BC00-4630-B25E-43C554323E72}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Overlay.NET.Demo", "Overlay.NET.Demo\Overlay.NET.Demo.csproj", "{DBC09A34-CD3F-4D2A-8DD4-C768D36284FE}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "OnscreenTranslator", "OnscreenTranslator\OnscreenTranslator.csproj", "{ED544BF9-B8F3-4A7B-AD26-173DEE5C000F}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
Release|Any CPU = Release|Any CPU
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{2D411EA5-BC00-4630-B25E-43C554323E72}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{2D411EA5-BC00-4630-B25E-43C554323E72}.Debug|Any CPU.Build.0 = Debug|Any CPU
{2D411EA5-BC00-4630-B25E-43C554323E72}.Release|Any CPU.ActiveCfg = Release|Any CPU
{2D411EA5-BC00-4630-B25E-43C554323E72}.Release|Any CPU.Build.0 = Release|Any CPU
{DBC09A34-CD3F-4D2A-8DD4-C768D36284FE}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{DBC09A34-CD3F-4D2A-8DD4-C768D36284FE}.Debug|Any CPU.Build.0 = Debug|Any CPU
{DBC09A34-CD3F-4D2A-8DD4-C768D36284FE}.Release|Any CPU.ActiveCfg = Release|Any CPU
{DBC09A34-CD3F-4D2A-8DD4-C768D36284FE}.Release|Any CPU.Build.0 = Release|Any CPU
{ED544BF9-B8F3-4A7B-AD26-173DEE5C000F}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{ED544BF9-B8F3-4A7B-AD26-173DEE5C000F}.Debug|Any CPU.Build.0 = Debug|Any CPU
{ED544BF9-B8F3-4A7B-AD26-173DEE5C000F}.Release|Any CPU.ActiveCfg = Release|Any CPU
{ED544BF9-B8F3-4A7B-AD26-173DEE5C000F}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
EndGlobalSection
EndGlobal

View File

@@ -0,0 +1,16 @@
<?xml version="1.0" encoding="utf-8"?>
<configuration>
<startup>
<supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.6.2" />
</startup>
<runtime>
<assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
<dependentAssembly>
<assemblyIdentity name="SharpDX" publicKeyToken="b4dcf0f35e5521f1" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-4.2.0.0" newVersion="4.2.0.0" />
</dependentAssembly>
</assemblyBinding>
</runtime>
</configuration>

View File

@@ -0,0 +1,58 @@
using System;
using System.Diagnostics;
using System.IO;
namespace Overlay.NET.Common {
public sealed class FileLogger : ILogger {
public string Path { get; set; }
public bool IsDisposed { get; set; }
public bool MustBeDisposed { get; set; } = true;
public void WriteLine(string entry) {
try {
_stream.WriteLine(entry);
}
catch (Exception e) {
Trace.WriteLine(e.Message);
}
}
public static readonly FileLogger Instance = new FileLogger();
private readonly StreamWriter _stream;
public FileLogger(RelativeFile file) {
Path = file.GetFullPath();
_stream = new StreamWriter(Path, true) {AutoFlush = true};
}
public FileLogger(string file) {
Path = file;
_stream = new StreamWriter(Path, true) {AutoFlush = true};
}
private FileLogger() {
var file = new RelativeFile {
Name = "AppLog",
Extension = ".txt",
SubDirectory = "Logs",
TimeStampFile = true,
UseDetailedTimeStamp = false
};
Path = file.GetFullPath();
_stream = new StreamWriter(Path, true) {AutoFlush = true};
}
public void Dispose() {
if (IsDisposed) {
return;
}
IsDisposed = true;
_stream.Flush();
_stream.Close();
}
}
}

View File

@@ -0,0 +1,42 @@
using System.Text;
namespace Overlay.NET.Common {
/// <summary>
/// Interface that defines common ways to serialize/deserialize objects to and from strings.
/// </summary>
public interface ISerializer {
/// <summary>
/// Serializes the specified object and returns the document.
/// </summary>
/// <typeparam name="T">The type of the object to serialize.</typeparam>
/// <param name="obj">The object to serialize.</param>
/// <returns>XML document of the serialized object.</returns>
string ExportToString<T>(T obj);
/// <summary>
/// Deserializes the document to the specified object.
/// </summary>
/// <typeparam name="T">The type of the object to deserialize.</typeparam>
/// <param name="serializedObj">The string representing the serialized object.</param>
/// <returns>The deserialized object.</returns>
T ImportFromString<T>(string serializedObj);
/// <summary>
/// Serializes the specified object and writes the document to the specified path.
/// </summary>
/// <typeparam name="T">The type of the object to serialize.</typeparam>
/// <param name="obj">The object to serialize.</param>
/// <param name="file">The path where the file is saved.</param>
/// <param name="encoding">The encoding to generate.</param>
void ExportToFile<T>(T obj, string file, Encoding encoding);
/// <summary>
/// Deserializes the specified file into an object.
/// </summary>
/// <typeparam name="T">The type of the object to deserialize.</typeparam>
/// <param name="path">The path where the object is read.</param>
/// <param name="encoding">The character encoding to use. </param>
/// <returns>The deserialized object.</returns>
T ImportFromFile<T>(string path, Encoding encoding);
}
}

View File

@@ -0,0 +1,27 @@
namespace Overlay.NET.Common {
/// <summary>
/// Interface that defines a way to load and save settings.
/// </summary>
/// <typeparam name="T"></typeparam>
public interface ISettings<out T> {
/// <summary>
/// Gets the current settings instance
/// </summary>
/// <value>
/// The current settings.
/// </value>
T Current { get; }
/// <summary>
/// Saves the settings to the specified target.
/// </summary>
/// <param name="target">The target.</param>
void Save(string target = "");
/// <summary>
/// Loads the settings from the specified location.
/// </summary>
/// <param name="location">The location.</param>
void Load(string location = "");
}
}

View File

@@ -0,0 +1,67 @@
using System;
using System.Collections.Generic;
using System.Linq;
namespace Overlay.NET.Common {
public enum LogLevel {
Normal,
Debug,
Information,
Warning,
Error,
Fatal
}
public interface ILogger {
void WriteLine(string line);
}
public static class Log {
public static Func<LogLevel, string, object[], string> LogFormatterFunc { get; set; }
private static Dictionary<string, ILogger> Loggers { get; }
static Log() {
Loggers = new Dictionary<string, ILogger>();
LogFormatterFunc = DefaultFormatter;
Loggers.Add("File", FileLogger.Instance);
}
public static void Register(string publicKey, ILogger logger) => Loggers.Add(publicKey, logger);
public static bool Unregister(string publicKey) => Loggers.Remove(publicKey);
public static ILogger Get(string key) => !Loggers.ContainsKey(key) ? Loggers["File"] : Loggers[key];
public static void WriteLine(string format, params object[] args) => WriteLogEntry(LogLevel.Normal, format, args);
public static void Debug(string format, params object[] args) => WriteLogEntry(LogLevel.Debug, format, args);
public static void Info(string format, params object[] args) => WriteLogEntry(LogLevel.Information, format, args);
public static void Warn(string format, params object[] args) => WriteLogEntry(LogLevel.Warning, format, args);
public static void Error(string format, params object[] args) => WriteLogEntry(LogLevel.Error, format, args);
public static void Fatal(string format, params object[] args) => WriteLogEntry(LogLevel.Fatal, format, args);
private static void WriteLogEntry(LogLevel logLevel, string format, params object[] args) {
var formatted = LogFormatterFunc(logLevel, format, args);
foreach (var logger in Loggers.ToArray()) {
logger.Value.WriteLine(formatted);
}
}
private static string DefaultFormatter(LogLevel type, string format, params object[] args) {
if (args != null && args.Any()) {
format = string.Format(format, args);
}
var time = DateTime.Now;
var logType = type == LogLevel.Normal ? "" : $"[{type}]";
return $"{logType}[{time}] {format}";
}
}
}

View File

@@ -0,0 +1,91 @@
using System;
using System.Runtime.InteropServices;
namespace Overlay.NET.Common {
internal class Native {
[DllImport("user32.dll")]
public static extern IntPtr CreateWindowEx(
uint dwExStyle,
string lpClassName,
string lpWindowName,
uint dwStyle,
int x,
int y,
int nWidth,
int nHeight,
IntPtr hWndParent,
IntPtr hMenu,
IntPtr hInstance,
IntPtr lpParam);
[DllImport("user32.dll")]
public static extern int DestroyWindow(IntPtr hwnd);
[DllImport("user32.dll")]
public static extern int SetWindowPos(IntPtr hWnd, int hWndInsertAfter, int x, int y, int cx, int cy,
uint uFlags);
[DllImport("user32.dll")]
public static extern IntPtr GetDesktopWindow();
[DllImport("user32.dll")]
public static extern int GetSystemMetrics(int index);
[DllImport("user32.dll")]
public static extern int ShowWindow(IntPtr hWnd, uint nCmdShow);
[DllImport("user32.dll")]
public static extern int GetWindowRect(IntPtr hwnd, out Rect lpRect);
[DllImport("user32.dll")]
public static extern bool SetLayeredWindowAttributes(IntPtr hwnd, uint crKey, byte bAlpha, uint dwFlags);
[DllImport("user32.dll")]
public static extern bool UpdateLayeredWindow(IntPtr hwnd, IntPtr hdc, ref Point point, ref Point size,
IntPtr hdcSrc, IntPtr pptSrc, int crKey, IntPtr blend, uint flags);
[DllImport("dwmapi.dll")]
public static extern void DwmExtendFrameIntoClientArea(IntPtr hWnd, ref RawMargin pMargins);
public static IntPtr SetWindowLongPtr(IntPtr hWnd, int nIndex, IntPtr dwNewLong)
=> IntPtr.Size == 8 ? SetWindowLongPtr64(hWnd, nIndex, dwNewLong) : new IntPtr(SetWindowLong32(hWnd, nIndex, dwNewLong.ToInt32()));
[DllImport("user32.dll", EntryPoint = "SetWindowLong")]
private static extern int SetWindowLong32(IntPtr hWnd, int nIndex, int dwNewLong);
[DllImport("user32.dll", EntryPoint = "SetWindowLongPtr")]
private static extern IntPtr SetWindowLongPtr64(IntPtr hWnd, int nIndex, IntPtr dwNewLong);
[DllImport("user32.dll", EntryPoint = "GetWindowLong")]
private static extern IntPtr GetWindowLongPtr32(IntPtr hWnd, int nIndex);
[DllImport("user32.dll", EntryPoint = "GetWindowLongPtr")]
private static extern IntPtr GetWindowLongPtr64(IntPtr hWnd, int nIndex);
// This static method is required because Win32 does not support
// GetWindowLongPtr directly
public static IntPtr GetWindowLongPtr(IntPtr hWnd, int nIndex) => IntPtr.Size == 8 ? GetWindowLongPtr64(hWnd, nIndex) : GetWindowLongPtr32(hWnd, nIndex);
[StructLayout(LayoutKind.Sequential)]
public struct Rect {
public int Left;
public int Top;
public int Right;
public int Bottom;
}
[StructLayout(LayoutKind.Sequential)]
public struct Point {
public int X;
public int Y;
}
[StructLayout(LayoutKind.Sequential)]
public struct RawMargin {
public int cxLeftWidth;
public int cxRightWidth;
public int cyTopHeight;
public int cyBottomHeight;
}
}
}

View File

@@ -0,0 +1,123 @@
using System;
using System.Linq;
namespace Overlay.NET.Common {
/// <summary>
/// The abstract base class for plugins.
/// </summary>
public abstract class PluginBase {
/// <summary>
/// Gets the plugin's Author, or empty string if it fails.
/// </summary>
/// <param name="type">The plugin's Type.</param>
/// <returns>The plugin's Author, or empty string if it fails.</returns>
public static string GetAuthor(Type type) {
var attribute = GetAttribute(type);
return attribute == null ? string.Empty : attribute.Author ?? string.Empty;
}
/// <summary>
/// Gets the plugin's Description, or empty string if it fails.
/// </summary>
/// <param name="type">The plugin's Type.</param>
/// <returns>The plugin's Description, or empty string if it fails.</returns>
public static string GetDescription(Type type) {
var attribute = GetAttribute(type);
return attribute == null ? string.Empty : attribute.Description ?? string.Empty;
}
/// <summary>
/// Gets the identifier for the plugin, or empty string if it fails.
/// </summary>
/// <param name="type">The plugin's Type.</param>
/// <returns>The identifier for the plugin, or empty string if it fails.</returns>
public static string GetIdentifier(Type type) {
var attribute = GetAttribute(type);
return attribute == null ? string.Empty : attribute.Identifier ?? string.Empty;
}
/// <summary>
/// Gets the plugin's Name, or empty string if it fails.
/// </summary>
/// <param name="type">The plugin's Type.</param>
/// <returns>The plugin's Name, or empty string if it fails.</returns>
public static string GetName(Type type) {
var attribute = GetAttribute(type);
return attribute == null ? string.Empty : attribute.Name ?? string.Empty;
}
/// <summary>
/// Gets the plugin's Version, or empty string if it fails.
/// </summary>
/// <param name="type">The plugin's Type.</param>
/// <returns>The plugin's Version, or empty string if it fails.</returns>
public static string GetVersion(Type type) {
var attribute = GetAttribute(type);
return attribute == null ? string.Empty : attribute.Version ?? string.Empty;
}
/// <summary>
/// Gets whether the Type is a registered plugin or not.
/// </summary>
/// <param name="type">The plugin's Type.</param>
/// <returns>Whether the Type is a registered plugin or not.</returns>
public static bool IsRegisteredPlugin(Type type) => GetAttribute(type) != null;
/// <summary>
/// Gets the plugin's RegisteredPluginAttribute, or null if it fails.
/// </summary>
/// <param name="type">The plugin's Type.</param>
/// <returns>The plugin's RegisteredPluginAttribute, or null if it fails.</returns>
private static RegisterPluginAttribute GetAttribute(Type type) => (RegisterPluginAttribute)
type.GetCustomAttributes(typeof(RegisterPluginAttribute), false).FirstOrDefault();
/// <summary>
/// Marks a PluginBase derived class as to be loaded and contains some optional information about the plugin.
/// </summary>
[AttributeUsage(AttributeTargets.Class, Inherited = false)]
protected sealed class RegisterPluginAttribute : Attribute {
/// <summary>
/// Gets the plugin's Author.
/// </summary>
public string Author { get; }
/// <summary>
/// Gets the plugin's Description.
/// </summary>
public string Description { get; }
/// <summary>
/// Gets an identifier for the plugin.
/// </summary>
public string Identifier { get; }
/// <summary>
/// Gets the plugin's Name.
/// </summary>
public string Name { get; }
/// <summary>
/// Gets the plugin's Version.
/// </summary>
public string Version { get; }
/// <summary>
/// Creates a new instance of the <see cref="SharpPlugins.PluginBase.RegisterPluginAttribute" /> class
/// with the identifier, given optional information about the plugin to mark it as to be loaded.
/// </summary>
/// <param name="identifier">The identifier for the plugin.</param>
/// <param name="author">The plugin's Author.</param>
/// <param name="name">The plugin's Name.</param>
/// <param name="version">The plugin's Version.</param>
/// <param name="description">The plugin's Description.</param>
public RegisterPluginAttribute(string identifier, string author = "", string name = "", string version = "",
string description = "") {
Identifier = identifier;
Author = author;
Name = name;
Version = version;
Description = description;
}
}
}
}

View File

@@ -0,0 +1,74 @@
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Reflection;
namespace Overlay.NET.Common {
/// <summary>
/// Contains static methods for loading plugin types from .dll files.
/// </summary>
public static class PluginLoader {
/// <summary>
/// Creates instances of all the given types that are instanciable plugins.
/// </summary>
/// <typeparam name="TPlugin">The PluginBase derived plugin type.</typeparam>
/// <param name="types">The types to create instances from.</param>
/// <returns>Instances of all the types that are instanciable plugins.</returns>
public static IEnumerable<TPlugin> InstanciatePlugins<TPlugin>(IEnumerable<Type> types)
where TPlugin : PluginBase => InstanciatePlugins<TPlugin>(types, new object[0]);
/// <summary>
/// Creates instances of all the given Types that are instanciable plugins using the given arguments for the
/// constructor.
/// </summary>
/// <typeparam name="TPlugin">The PluginBase derived plugin type.</typeparam>
/// <param name="types">The Types to create instances from.</param>
/// <param name="args">The arguments for the constructor.</param>
/// <returns>Instances of all the types that are instanciable plugins.</returns>
public static IEnumerable<TPlugin> InstanciatePlugins<TPlugin>(IEnumerable<Type> types, params object[] args)
where TPlugin : PluginBase => from type in types
where IsInstanciablePlugin(type)
select (TPlugin) Activator.CreateInstance(type, args);
/// <summary>
/// Determines whether the given Type is an instanciable plugin or not.
/// </summary>
/// <param name="type">The Type to check.</param>
/// <returns>Whether the given Type is an instanciable plugin or not.</returns>
public static bool IsInstanciablePlugin(Type type) => PluginBase.IsRegisteredPlugin(type) && !type.IsAbstract;
/// <summary>
/// Takes file paths and checks if each exists, and loads .dll files to find the instanciable plugin types deriving
/// from TPlugin.
/// </summary>
/// <typeparam name="TPlugin">The Type that the plugins have to be derived from.</typeparam>
/// <param name="pluginFiles">The paths to the .dll files to check.</param>
/// <returns>The Types of the found instanciable plugins.</returns>
public static IEnumerable<Type> LoadPluginsFromFiles<TPlugin>(IEnumerable<string> pluginFiles)
where TPlugin : PluginBase => from pluginFile in pluginFiles
let extension = Path.GetExtension(pluginFile)
where
extension != null && File.Exists(pluginFile) &&
extension.Equals(".dll", StringComparison.InvariantCultureIgnoreCase)
let assembly = Assembly.LoadFrom(pluginFile)
from type in assembly.GetExportedTypes()
where typeof(TPlugin).IsAssignableFrom(type) && IsInstanciablePlugin(type)
select type;
/// <summary>
/// Takes directory paths and checks if each exists, and loads .dll files, including from subfolders,
/// to find the instanciable plugin types deriving from TPlugin.
/// </summary>
/// <typeparam name="TPlugin">The Type that the plugins have to be derived from.</typeparam>
/// <param name="pluginFolders">The paths to the folders to check.</param>
/// <returns>The Types of the found instanciable plugins.</returns>
public static IEnumerable<Type> LoadPluginsFromFolders<TPlugin>(IEnumerable<string> pluginFolders)
where TPlugin : PluginBase => from pluginFolder in pluginFolders
where Directory.Exists(pluginFolder)
let files = Directory.EnumerateFiles(pluginFolder, "*.dll", SearchOption.AllDirectories)
let types = LoadPluginsFromFiles<TPlugin>(files)
from type in types
select type;
}
}

View File

@@ -0,0 +1,163 @@
using System;
using System.IO;
using System.Linq;
namespace Overlay.NET.Common {
/// <summary>
/// Class representing a relative file on the device's storage.
/// </summary>
public class RelativeFile {
/// <summary>
/// Gets the base directory.
/// </summary>
/// <value>
/// The base directory.
/// </value>
public string Directory {
get {
if (string.IsNullOrEmpty(_directory)) {
_directory = AppDomain.CurrentDomain.BaseDirectory;
}
return _directory;
}
set { _directory = value; }
}
/// <summary>
/// Gets or sets the folder.
/// </summary>
/// <value>
/// The folder.
/// </value>
public string SubDirectory { get; set; }
/// <summary>
/// Gets or sets the name.
/// </summary>
/// <value>
/// The name.
/// </value>
public string Name { get; set; }
/// <summary>
/// Gets or sets the extension.
/// </summary>
/// <value>
/// The extension.
/// </value>
public string Extension { get; set; }
/// <summary>
/// Gets or sets a value indicating whether [use detailed time stamp].
/// </summary>
/// <value>
/// <c>true</c> if [use detailed time stamp]; otherwise, <c>false</c>.
/// </value>
public bool UseDetailedTimeStamp { get; set; }
/// <summary>
/// Gets or sets a value indicating whether [time stamp file].
/// </summary>
/// <value>
/// <c>true</c> if [time stamp file]; otherwise, <c>false</c>.
/// </value>
public bool TimeStampFile { get; set; }
private string _directory;
/// <summary>
/// Initializes a new instance of the <see cref="RelativeFile" /> class.
/// </summary>
/// <param name="directory">The base directory.</param>
public RelativeFile(string directory) {
_directory = directory;
}
/// <summary>
/// Initializes a new instance of the <see cref="RelativeFile" /> class.
/// </summary>
public RelativeFile() : this(AppDomain.CurrentDomain.BaseDirectory) {}
/// <summary>
/// Creates the a text file in a your app domains base directory, or if a subdirectory is set, in a sub directory
/// relative to your app folder.
/// </summary>
/// <param name="fileName">Name of the file.</param>
/// <param name="relativeSubDirectoryName">The name of the relative sub directory, if any.</param>
/// <param name="timeStampFile">if set to <c>true</c> [the file will be time stamped]</param>
/// <param name="useDetailedTimeStamp">if set to <c>true</c> [the time stamp will be more detailed, if one is used].</param>
/// <returns>
/// <see cref="RelativeFile" />
/// </returns>
public static RelativeFile JsonFile(string fileName, string relativeSubDirectoryName = "",
bool timeStampFile = false, bool useDetailedTimeStamp = true) => new RelativeFile {
Name = fileName,
Extension = ".json",
SubDirectory = relativeSubDirectoryName,
TimeStampFile = timeStampFile,
UseDetailedTimeStamp = useDetailedTimeStamp
};
/// <summary>
/// Creates the a text file in a your app domains base directory, or if a subdirectory is set, in a sub directory
/// relative to your app folder.
/// </summary>
/// <param name="fileName">Name of the file.</param>
/// <param name="relativeSubDirectoryName">The name of the relative sub directory, if any.</param>
/// <param name="timeStampFile">if set to <c>true</c> [the file will be time stamped]</param>
/// <param name="useDetailedTimeStamp">if set to <c>true</c> [the time stamp will be more detailed, if one is used].</param>
/// <returns>
/// <see cref="RelativeFile" />
/// </returns>
public static RelativeFile XmlFile(string fileName, string relativeSubDirectoryName = "",
bool timeStampFile = false, bool useDetailedTimeStamp = true) => new RelativeFile {
Name = fileName,
Extension = ".xml",
SubDirectory = relativeSubDirectoryName,
TimeStampFile = timeStampFile,
UseDetailedTimeStamp = useDetailedTimeStamp
};
/// <summary>
/// Gets the full path.
/// </summary>
/// <returns></returns>
/// <exception cref="System.ArgumentException">@The file detail can not be blank or null</exception>
public string GetFullPath() {
var checks = new[] {
Directory, Name, Extension
};
foreach (var fileDetail in checks.Where(string.IsNullOrEmpty)) {
throw new ArgumentException($@"The file detail can not be blank or null {fileDetail}", fileDetail);
}
if (!Extension.StartsWith(".")) {
Extension = "." + Extension;
}
if (TimeStampFile) {
Name = UseDetailedTimeStamp
? $"{Name}-{DateTime.Now:yyyy-MM-dd_hh-mm-ss}"
: $"{Name}-{DateTime.Now:yyyy-MM-dd}";
}
var path = Directory;
var combineDirectory = !string.IsNullOrEmpty(SubDirectory);
if (combineDirectory) {
path = Path.Combine(Directory, SubDirectory);
}
if (!System.IO.Directory.Exists(path)) {
System.IO.Directory.CreateDirectory(path);
}
return combineDirectory
? Path.Combine(Directory, SubDirectory, Name + Extension)
: Path.Combine(Directory, Name + Extension);
}
}
}

View File

@@ -0,0 +1,201 @@
using System;
using System.Globalization;
using System.IO;
using System.Text;
namespace Overlay.NET.Common {
public class SerializableSettings<T> : ISettings<T> where T : new() {
/// <summary>
/// Gets or sets the file.
/// </summary>
/// <value>
/// The file.
/// </value>
public RelativeFile SettingsFile {
get { return _file ?? (_file = RelativeFile.XmlFile(typeof(T).Name, "Settings")); }
set { _file = value; }
}
/// <summary>
/// Gets or sets a value indicating whether [backup on save].
/// </summary>
/// <value>
/// <c>true</c> if [backup on save]; otherwise, <c>false</c>.
/// </value>
public bool BackupOnSave { get; set; } = true;
/// <summary>
/// Gets or sets the path.
/// </summary>
/// <value>
/// The path.
/// </value>
public string Path {
get {
if (string.IsNullOrEmpty(_path)) {
_path = SettingsFile.GetFullPath();
}
return _path;
}
protected set { _path = value; }
}
/// <summary>
/// Gets or sets the name of the settings.
/// </summary>
/// <value>
/// The name.
/// </value>
public string Name {
get {
if (string.IsNullOrEmpty(_name)) {
_name = typeof(T).Name;
}
return _name;
}
set { _name = value; }
}
/// <summary>
/// Gets or sets the encoding.
/// </summary>
/// <value>
/// The encoding.
/// </value>
public Encoding Encoding {
get { return _encoding ?? (_encoding = Encoding.UTF8); }
set { _encoding = value; }
}
/// <summary>
/// Gets or sets the current settings instance.
/// </summary>
/// <value>
/// The current.
/// </value>
public T Current {
get {
if (_currentExist) {
return _current;
}
_current = new T();
_currentExist = true;
return _current;
}
set {
_current = value;
_currentExist = true;
}
}
/// <summary>
/// Gets or sets the serializer.
/// </summary>
/// <value>
/// The serializer.
/// </value>
protected ISerializer Serializer {
get {
if (_serializer != null) {
return _serializer;
}
_serializer = new XmlSerializerEx();
SettingsFile.Extension = ".xml";
SettingsFile.SubDirectory = "XmlSettings";
return _serializer;
}
set { _serializer = value; }
}
/// <summary>
/// Saves the settings to the specified file.
/// </summary>
/// <param name="file">The file.</param>
public void Save(string file = "") {
if (string.IsNullOrEmpty(file)) {
file = Path;
}
if (File.Exists(file) && BackupOnSave) {
BackupSettings(file);
}
Serializer.ExportToFile(Current, file, Encoding.UTF8);
}
/// <summary>
/// Loads the settings from the specified location.
/// </summary>
/// <param name="location">
/// The location of the file./param>
/// <exception cref="System.ArgumentNullException"></exception>
/// </param>
public void Load(string location = "") {
if (string.IsNullOrEmpty(location)) {
location = Path;
}
if (!File.Exists(location)) {
Save(location);
}
var settings = Serializer.ImportFromFile<T>(location, Encoding);
if (settings == null) {
throw new ArgumentNullException(nameof(settings));
}
Current = settings;
RaiseOnSettingsChanged(location);
}
private T _current;
private bool _currentExist;
private Encoding _encoding;
private RelativeFile _file;
private string _name;
private string _path;
private ISerializer _serializer;
/// <summary>
/// Backups the settings if one already exist.
/// </summary>
/// <param name="target">The target to back up settings to.</param>
/// <exception cref="System.ArgumentNullException"></exception>
protected void BackupSettings(string target = "") {
if (string.IsNullOrEmpty(target)) {
target = Path;
}
var extension = System.IO.Path.GetExtension(target);
if (extension == null) {
throw new ArgumentNullException(Path + " does not contain an extension.");
}
var time = DateTime.Now;
var backup = target.Replace(extension,
$"-{time.ToString("yyyy-MM-dd-HH-mm-ss", CultureInfo.InvariantCulture)}{extension}");
Serializer.ExportToFile(Current, backup, Encoding);
}
/// <summary>
/// Occurs when [on settings changed].
/// </summary>
public event EventHandler<string> OnSettingsChanged;
/// <summary>
/// Raises the on settings changed.
/// </summary>
/// <param name="e">The e.</param>
protected virtual void RaiseOnSettingsChanged(string e) => OnSettingsChanged?.Invoke(this, e);
}
}

View File

@@ -0,0 +1,87 @@
using System;
namespace Overlay.NET.Common {
/// <summary>
/// </summary>
public class TickEngine {
/// <summary>
/// Gets or sets the interval.
/// </summary>
/// <value>
/// The interval.
/// </value>
public TimeSpan Interval {
get { return _waitTimer.WaitTime; }
set { _waitTimer.WaitTime = value; }
}
/// <summary>
/// Gets or sets a value indicating whether this instance is ticking.
/// </summary>
/// <value>
/// <c>true</c> if this instance is ticking; otherwise, <c>false</c>.
/// </value>
public bool IsTicking { get; set; }
/// <summary>
/// The wait timer
/// </summary>
private readonly WaitTimer _waitTimer = new WaitTimer();
/// <summary>
/// Occurs when [pre tick].
/// </summary>
public event EventHandler PreTick;
/// <summary>
/// Occurs when [tick].
/// </summary>
public event EventHandler Tick;
/// <summary>
/// Occurs when [post tick].
/// </summary>
public event EventHandler PostTick;
/// <summary>
/// Stops this instance.
/// </summary>
public void Stop() => _waitTimer.Stop();
/// <summary>
/// Pulses this instance.
/// </summary>
public void Pulse() {
if (!IsTicking) {
return;
}
if (!_waitTimer.Update()) {
return;
}
OnPreTick();
OnTick();
OnPostTick();
_waitTimer.Reset();
}
/// <summary>
/// Called when [tick].
/// </summary>
protected virtual void OnTick() => Tick?.Invoke(this, EventArgs.Empty);
/// <summary>
/// Called when [pre tick].
/// </summary>
protected virtual void OnPreTick() => PreTick?.Invoke(this, EventArgs.Empty);
/// <summary>
/// Called when [post tick].
/// </summary>
protected virtual void OnPostTick() => PostTick?.Invoke(this, EventArgs.Empty);
}
}

View File

@@ -0,0 +1,15 @@
using System;
namespace Overlay.NET.Common {
public static class TimeSpanExtensions {
public static TimeSpan Days(this int days) => new TimeSpan(days, 0, 0, 0);
public static TimeSpan Hours(this int hours) => new TimeSpan(0, hours, 0, 0);
public static TimeSpan Minutes(this int minutes) => new TimeSpan(0, 0, minutes, 0);
public static TimeSpan Seconds(this int seconds) => new TimeSpan(0, 0, 0, seconds);
public static TimeSpan Milliseconds(this int milliseconds) => new TimeSpan(0, 0, 0, 0, milliseconds);
}
}

View File

@@ -0,0 +1,132 @@
using System;
namespace Overlay.NET.Common {
/// <summary>
/// </summary>
/// <seealso cref="System.EventArgs" />
public sealed class WaitTimerEventArgs : EventArgs {
/// <summary>
/// Gets or sets the time finished.
/// </summary>
/// <value>
/// The time finished.
/// </value>
public DateTime TimeFinished { get; set; }
/// <summary>
/// Gets or sets the wait time.
/// </summary>
/// <value>
/// The wait time.
/// </value>
public TimeSpan WaitTime { get; set; }
/// <summary>
/// Gets or sets the time started.
/// </summary>
/// <value>
/// The time started.
/// </value>
public DateTime TimeStarted { get; set; }
}
/// <summary>
/// </summary>
public class WaitTimer {
/// <summary>
/// Gets or sets the wait time.
/// </summary>
/// <value>
/// The wait time.
/// </value>
public TimeSpan WaitTime { get; set; }
/// <summary>
/// Gets the end time.
/// </summary>
/// <value>
/// The end time.
/// </value>
public DateTime EndTime => StartTime + WaitTime;
/// <summary>
/// Gets the start time.
/// </summary>
/// <value>
/// The start time.
/// </value>
public DateTime StartTime { get; private set; }
/// <summary>
/// Gets a value indicating whether this instance is finished.
/// </summary>
/// <value>
/// <c>true</c> if this instance is finished; otherwise, <c>false</c>.
/// </value>
public bool IsFinished => EndTime <= DateTime.Now;
/// <summary>
/// Gets the time left.
/// </summary>
/// <value>
/// The time left.
/// </value>
public TimeSpan TimeLeft => EndTime - DateTime.Now;
/// <summary>
/// Initializes a new instance of the <see cref="WaitTimer" /> class.
/// </summary>
/// <param name="waitTime">The wait time.</param>
public WaitTimer(TimeSpan waitTime) {
WaitTime = waitTime;
Stop();
}
/// <summary>
/// Initializes a new instance of the <see cref="WaitTimer" /> class.
/// </summary>
public WaitTimer() {
WaitTime = TimeSpan.Zero;
Stop();
}
/// <summary>
/// Occurs when [finished].
/// </summary>
public event EventHandler<WaitTimerEventArgs> Finished;
/// <summary>
/// Resets this instance.
/// </summary>
public void Reset() => StartTime = DateTime.Now;
/// <summary>
/// Stops this instance.
/// </summary>
public void Stop() => StartTime = DateTime.Now.AddDays(-5.0);
/// <summary>
/// Updates this instance.
/// </summary>
/// <returns></returns>
public bool Update() {
if (!IsFinished) {
return false;
}
OnFinished(new WaitTimerEventArgs {
TimeFinished = DateTime.Now,
TimeStarted = StartTime,
WaitTime = WaitTime
});
return true;
}
/// <summary>
/// Raises the <see cref="E:Finished" /> event.
/// </summary>
/// <param name="e">The <see cref="WaitTimerEventArgs" /> instance containing the event data.</param>
protected virtual void OnFinished(WaitTimerEventArgs e) => Finished?.Invoke(this, e);
}
}

View File

@@ -0,0 +1,81 @@
namespace Overlay.NET.Common {
/// <summary>
/// </summary>
internal class WindowConstants {
/// <summary>
/// The sm cx screen
/// </summary>
public const int SmCxScreen = 0;
/// <summary>
/// The sm cy screen
/// </summary>
public const int SmCyScreen = 1;
/// <summary>
/// The desktop class
/// </summary>
public const string DesktopClass = "Static"; // System Class for a static control
/// <summary>
/// The window style dx
/// </summary>
public const uint WindowStyleDx = 0x8000000 //WS_DISABLED
| 0x10000000 //WS_VISIBLE
| 0x80000000; //WS_POPUP
/// <summary>
/// The window ex style dx
/// </summary>
public const uint WindowExStyleDx = 0x8000000 //WS_EX_NOACTIVATE
| 0x80000 //WS_EX_LAYERED
| 0x80 //WS_EX_TOOLWINDOW -> Not in taskbar
| 0x8 //WS_EX_TOPMOST
| 0x20; //WS_EX_TRANSPARENT
/// <summary>
/// The layered window attribute alpha (LWA_ALPHA)
/// </summary>
public const int LwaAlpha = 0x00000002;
/// <summary>
/// The HWND notopmost
/// </summary>
public const int HwndNotopmost = -2;
/// <summary>
/// The HWND topmost
/// </summary>
public const int HwndTopmost = -1;
/// <summary>
/// The HWND top
/// </summary>
public const int HwndTop = 0;
/// <summary>
/// The HWND bottom
/// </summary>
public const int HwndBottom = 1;
/// <summary>
/// The SWP flags show
/// </summary>
public const uint SwpFlagsShow = 0x40;
/// <summary>
/// The SWP flags hide
/// </summary>
public const uint SwpFlagsHide = 0x80;
/// <summary>
/// The sw show
/// </summary>
public const uint SwShow = 5;
/// <summary>
/// The sw hide
/// </summary>
public const uint SwHide = 0;
}
}

View File

@@ -0,0 +1,19 @@
using System;
using System.Runtime.InteropServices;
using System.Windows;
using System.Windows.Interop;
namespace Overlay.NET.Common {
public static class WindowExtensions {
private const int GwlExstyle = -20;
private const int WsExTransparent = 0x00000020;
public static void MakeWindowTransparent(this Window wnd) {
if (!wnd.IsInitialized)
throw new Exception("The extension method MakeWindowTransparent can not be called prior to the window being initialized.");
var hwnd = new WindowInteropHelper(wnd).Handle;
var extendedStyle = Native.GetWindowLongPtr(hwnd, GwlExstyle);
Native.SetWindowLongPtr(hwnd, GwlExstyle, new IntPtr(extendedStyle.ToInt32() | WsExTransparent));
}
}
}

View File

@@ -0,0 +1,68 @@
using System.IO;
using System.Text;
using System.Xml.Serialization;
namespace Overlay.NET.Common {
/// <summary>
/// Class to serialize/deserialize XML objects to and from strings, and to and from files.
/// </summary>
/// <seealso cref="ISerializer" />
public class XmlSerializerEx : ISerializer {
/// <summary>
/// Serializes the specified object and returns the document.
/// </summary>
/// <typeparam name="T">The type of the object to serialize.</typeparam>
/// <param name="obj">The object to serialize.</param>
/// <returns>
/// XML document of the serialized object.
/// </returns>
public string ExportToString<T>(T obj) {
var serializer = new XmlSerializer(typeof(T));
using (var stringWriter = new StringWriter()) {
serializer.Serialize(stringWriter, obj);
return stringWriter.ToString();
}
}
/// <summary>
/// Deserializes the document to the specified object.
/// </summary>
/// <typeparam name="T">The type of the object to deserialize.</typeparam>
/// <param name="serializedObj">The string representing the serialized object.</param>
/// <returns>
/// The deserialized object.
/// </returns>
public T ImportFromString<T>(string serializedObj) {
var serializer = new XmlSerializer(typeof(T));
using (var stringWriter = new StringReader(serializedObj)) {
return (T) serializer.Deserialize(stringWriter);
}
}
/// <summary>
/// Serializes the specified object and writes the document to the specified path.
/// </summary>
/// <typeparam name="T">The type of the object to serialize.</typeparam>
/// <param name="obj">The object to serialize.</param>
/// <param name="file">The path where the file is saved.</param>
/// <param name="encoding">The encoding to generate.</param>
public void ExportToFile<T>(T obj, string file, Encoding encoding) {
using (var fileWriter = new StreamWriter(file, false, encoding)) {
fileWriter.Write(ExportToString(obj));
}
}
/// <summary>
/// Deserializes the specified file into an object.
/// </summary>
/// <typeparam name="T">The type of the object to deserialize.</typeparam>
/// <param name="path">The path where the object is read.</param>
/// <param name="encoding">The character encoding to use. </param>
/// <returns>The deserialized object.</returns>
public T ImportFromFile<T>(string path, Encoding encoding) {
using (var fileReader = new StreamReader(path, encoding)) {
return ImportFromString<T>(fileReader.ReadToEnd());
}
}
}
}

View File

@@ -0,0 +1,644 @@
using System;
using System.Collections.Generic;
using System.Runtime.CompilerServices;
using Overlay.NET.Common;
using SharpDX;
using SharpDX.Direct2D1;
using SharpDX.DirectWrite;
using SharpDX.DXGI;
using SharpDX.Mathematics.Interop;
using AlphaMode = SharpDX.Direct2D1.AlphaMode;
using Color = System.Drawing.Color;
using Factory = SharpDX.DirectWrite.Factory;
using TextAntialiasMode = SharpDX.Direct2D1.TextAntialiasMode;
namespace Overlay.NET.Directx {
/// <summary>
/// </summary>
public class Direct2DRenderer {
/// <summary>
/// Gets the size of the buffer brush.
/// </summary>
/// <value>
/// The size of the buffer brush.
/// </value>
public int BufferBrushSize { get; private set; }
/// <summary>
/// Gets the size of the buffer font.
/// </summary>
/// <value>
/// The size of the buffer font.
/// </value>
public int BufferFontSize { get; private set; }
/// <summary>
/// Gets the size of the buffer layout.
/// </summary>
/// <value>
/// The size of the buffer layout.
/// </value>
public int BufferLayoutSize { get; private set; }
//transparent background color
/// <summary>
/// The GDI transparent
/// </summary>
private static Color _gdiTransparent = Color.Transparent;
/// <summary>
/// The transparent
/// </summary>
private static readonly RawColor4 Transparent = new RawColor4(_gdiTransparent.R, _gdiTransparent.G, _gdiTransparent.B,
_gdiTransparent.A);
//direct x vars
/// <summary>
/// The device
/// </summary>
private readonly WindowRenderTarget _device;
/// <summary>
/// The factory
/// </summary>
private readonly SharpDX.Direct2D1.Factory _factory;
/// <summary>
/// The font factory
/// </summary>
private readonly Factory _fontFactory;
/// <summary>
/// The brush container
/// </summary>
private List<SolidColorBrush> _brushContainer = new List<SolidColorBrush>(32);
//thread safe resizing
/// <summary>
/// The do resize
/// </summary>
private bool _doResize;
/// <summary>
/// The font container
/// </summary>
private List<TextFormat> _fontContainer = new List<TextFormat>(32);
/// <summary>
/// The layout container
/// </summary>
private List<TextLayoutBuffer> _layoutContainer = new List<TextLayoutBuffer>(32);
/// <summary>
/// The resize x
/// </summary>
private int _resizeX;
/// <summary>
/// The resize y
/// </summary>
private int _resizeY;
/// <summary>
/// Initializes a new instance of the <see cref="Direct2DRenderer" /> class.
/// </summary>
/// <param name="hwnd">The HWND.</param>
/// <param name="limitFps">if set to <c>true</c> [limit FPS].</param>
public Direct2DRenderer(IntPtr hwnd, bool limitFps) {
_factory = new SharpDX.Direct2D1.Factory();
_fontFactory = new Factory();
Native.Rect bounds;
Native.GetWindowRect(hwnd, out bounds);
var targetProperties = new HwndRenderTargetProperties {
Hwnd = hwnd,
PixelSize = new Size2(bounds.Right - bounds.Left, bounds.Bottom - bounds.Top),
PresentOptions = limitFps ? PresentOptions.None : PresentOptions.Immediately
};
var prop = new RenderTargetProperties(RenderTargetType.Hardware,
new PixelFormat(Format.B8G8R8A8_UNorm, AlphaMode.Premultiplied), 0, 0, RenderTargetUsage.None,
FeatureLevel.Level_DEFAULT);
_device = new WindowRenderTarget(_factory, prop, targetProperties) {
TextAntialiasMode = TextAntialiasMode.Aliased,
AntialiasMode = AntialiasMode.Aliased
};
}
/// <summary>
/// Do not call if you use OverlayWindow class
/// </summary>
public void Dispose() {
DeleteBrushContainer();
DeleteFontContainer();
DeleteLayoutContainer();
_brushContainer = null;
_fontContainer = null;
_layoutContainer = null;
_fontFactory.Dispose();
_factory.Dispose();
_device.Dispose();
}
/// <summary>
/// tells renderer to resize when possible
/// </summary>
/// <param name="x">Width</param>
/// <param name="y">Height</param>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public void AutoResize(int x, int y) {
_doResize = true;
_resizeX = x;
_resizeY = y;
}
/// <summary>
/// Call this after EndScene if you created brushes within a loop
/// </summary>
public void DeleteBrushContainer() {
BufferBrushSize = _brushContainer.Count;
foreach (var solidColorBrush in _brushContainer) {
solidColorBrush.Dispose();
}
_brushContainer = new List<SolidColorBrush>(BufferBrushSize);
}
/// <summary>
/// Call this after EndScene if you created fonts within a loop
/// </summary>
public void DeleteFontContainer() {
BufferFontSize = _fontContainer.Count;
foreach (var textFormat in _fontContainer) {
textFormat.Dispose();
}
_fontContainer = new List<TextFormat>(BufferFontSize);
}
/// <summary>
/// Call this after EndScene if you changed your text's font or have problems with huge memory usage
/// </summary>
public void DeleteLayoutContainer() {
BufferLayoutSize = _layoutContainer.Count;
foreach (var layoutBuffer in _layoutContainer) {
layoutBuffer.Dispose();
}
_layoutContainer = new List<TextLayoutBuffer>(BufferLayoutSize);
}
/// <summary>
/// Creates a new SolidColorBrush
/// </summary>
/// <param name="color">0x7FFFFFF Premultiplied alpha color</param>
/// <returns>
/// int Brush identifier
/// </returns>
public int CreateBrush(int color) {
_brushContainer.Add(new SolidColorBrush(_device,
new RawColor4((color >> 16) & 255L, (color >> 8) & 255L, (byte) color & 255L, (color >> 24) & 255L)));
return _brushContainer.Count - 1;
}
/// <summary>
/// Creates a new SolidColorBrush. Make sure you applied an alpha value
/// </summary>
/// <param name="color">System.Drawing.Color struct</param>
/// <returns>
/// int Brush identifier
/// </returns>
public int CreateBrush(Color color) {
if (color.A == 0) {
color = Color.FromArgb(255, color);
}
_brushContainer.Add(new SolidColorBrush(_device, new RawColor4(color.R, color.G, color.B, color.A / 255.0f)));
return _brushContainer.Count - 1;
}
/// <summary>
/// Creates a new Font
/// </summary>
/// <param name="fontFamilyName">i.e. Arial</param>
/// <param name="size">size in units</param>
/// <param name="bold">print bold text</param>
/// <param name="italic">print italic text</param>
/// <returns></returns>
public int CreateFont(string fontFamilyName, float size, bool bold = false, bool italic = false) {
_fontContainer.Add(new TextFormat(_fontFactory, fontFamilyName, bold ? FontWeight.Bold : FontWeight.Normal,
italic ? FontStyle.Italic : FontStyle.Normal, size));
return _fontContainer.Count - 1;
}
/// <summary>
/// Do your drawing after this
/// </summary>
public void BeginScene() {
if (_doResize) {
_device.Resize(new Size2(_resizeX, _resizeY));
_doResize = false;
}
_device.BeginDraw();
}
/// <summary>
/// Present frame. Do not draw after this.
/// </summary>
public void EndScene() {
_device.EndDraw();
if (!_doResize) {
return;
}
_device.Resize(new Size2(_resizeX, _resizeY));
_doResize = false;
}
/// <summary>
/// Clears the frame
/// </summary>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public void ClearScene() => _device.Clear(Transparent);
/// <summary>
/// Draws the line.
/// </summary>
/// <param name="startX">The start x.</param>
/// <param name="startY">The start y.</param>
/// <param name="endX">The end x.</param>
/// <param name="endY">The end y.</param>
/// <param name="stroke">The stroke.</param>
/// <param name="brush">The brush.</param>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public void DrawLine(int startX, int startY, int endX, int endY, float stroke, int brush) => _device.DrawLine(new RawVector2(startX, startY), new RawVector2(endX, endY), _brushContainer[brush], stroke);
/// <summary>
/// Draws the rectangle.
/// </summary>
/// <param name="x">The x.</param>
/// <param name="y">The y.</param>
/// <param name="width">The width.</param>
/// <param name="height">The height.</param>
/// <param name="stroke">The stroke.</param>
/// <param name="brush">The brush.</param>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public void DrawRectangle(int x, int y, int width, int height, float stroke, int brush) => _device.DrawRectangle(new RawRectangleF(x, y, x + width, y + height), _brushContainer[brush], stroke);
/// <summary>
/// Draws the circle.
/// </summary>
/// <param name="x">The x.</param>
/// <param name="y">The y.</param>
/// <param name="radius">The radius.</param>
/// <param name="stroke">The stroke.</param>
/// <param name="brush">The brush.</param>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public void DrawCircle(int x, int y, int radius, float stroke, int brush) => _device.DrawEllipse(new Ellipse(new RawVector2(x, y), radius, radius), _brushContainer[brush], stroke);
/// <summary>
/// Draws the box2 d.
/// </summary>
/// <param name="x">The x.</param>
/// <param name="y">The y.</param>
/// <param name="width">The width.</param>
/// <param name="height">The height.</param>
/// <param name="stroke">The stroke.</param>
/// <param name="brush">The brush.</param>
/// <param name="interiorBrush">The interior brush.</param>
public void DrawBox2D(int x, int y, int width, int height, float stroke, int brush, int interiorBrush) {
_device.DrawRectangle(new RawRectangleF(x, y, x + width, y + height), _brushContainer[brush], stroke);
_device.FillRectangle(new RawRectangleF(x + stroke, y + stroke, x + width - stroke, y + height - stroke),
_brushContainer[interiorBrush]);
}
/// <summary>
/// Draws the box3 d.
/// </summary>
/// <param name="x">The x.</param>
/// <param name="y">The y.</param>
/// <param name="width">The width.</param>
/// <param name="height">The height.</param>
/// <param name="length">The length.</param>
/// <param name="stroke">The stroke.</param>
/// <param name="brush">The brush.</param>
/// <param name="interiorBrush">The interior brush.</param>
public void DrawBox3D(int x, int y, int width, int height, int length, float stroke, int brush,
int interiorBrush) {
var first = new RawRectangleF(x, y, x + width, y + height);
var second = new RawRectangleF(x + length, y - length, first.Right + length, first.Bottom - length);
var lineStart = new RawVector2(x, y);
var lineEnd = new RawVector2(second.Left, second.Top);
_device.DrawRectangle(first, _brushContainer[brush], stroke);
_device.DrawRectangle(second, _brushContainer[brush], stroke);
_device.FillRectangle(first, _brushContainer[interiorBrush]);
_device.FillRectangle(second, _brushContainer[interiorBrush]);
_device.DrawLine(lineStart, lineEnd, _brushContainer[brush], stroke);
lineStart.X += width;
lineEnd.X = lineStart.X + length;
_device.DrawLine(lineStart, lineEnd, _brushContainer[brush], stroke);
lineStart.Y += height;
lineEnd.Y += height;
_device.DrawLine(lineStart, lineEnd, _brushContainer[brush], stroke);
lineStart.X -= width;
lineEnd.X -= width;
_device.DrawLine(lineStart, lineEnd, _brushContainer[brush], stroke);
}
/// <summary>
/// Draws the rectangle3 d.
/// </summary>
/// <param name="x">The x.</param>
/// <param name="y">The y.</param>
/// <param name="width">The width.</param>
/// <param name="height">The height.</param>
/// <param name="length">The length.</param>
/// <param name="stroke">The stroke.</param>
/// <param name="brush">The brush.</param>
public void DrawRectangle3D(int x, int y, int width, int height, int length, float stroke, int brush) {
var first = new RawRectangleF(x, y, x + width, y + height);
var second = new RawRectangleF(x + length, y - length, first.Right + length, first.Bottom - length);
var lineStart = new RawVector2(x, y);
var lineEnd = new RawVector2(second.Left, second.Top);
_device.DrawRectangle(first, _brushContainer[brush], stroke);
_device.DrawRectangle(second, _brushContainer[brush], stroke);
_device.DrawLine(lineStart, lineEnd, _brushContainer[brush], stroke);
lineStart.X += width;
lineEnd.X = lineStart.X + length;
_device.DrawLine(lineStart, lineEnd, _brushContainer[brush], stroke);
lineStart.Y += height;
lineEnd.Y += height;
_device.DrawLine(lineStart, lineEnd, _brushContainer[brush], stroke);
lineStart.X -= width;
lineEnd.X -= width;
_device.DrawLine(lineStart, lineEnd, _brushContainer[brush], stroke);
}
/// <summary>
/// Draws the plus.
/// </summary>
/// <param name="x">The x.</param>
/// <param name="y">The y.</param>
/// <param name="length">The length.</param>
/// <param name="stroke">The stroke.</param>
/// <param name="brush">The brush.</param>
public void DrawPlus(int x, int y, int length, float stroke, int brush) {
var first = new RawVector2(x - length, y);
var second = new RawVector2(x + length, y);
var third = new RawVector2(x, y - length);
var fourth = new RawVector2(x, y + length);
_device.DrawLine(first, second, _brushContainer[brush], stroke);
_device.DrawLine(third, fourth, _brushContainer[brush], stroke);
}
/// <summary>
/// Draws the edge.
/// </summary>
/// <param name="x">The x.</param>
/// <param name="y">The y.</param>
/// <param name="width">The width.</param>
/// <param name="height">The height.</param>
/// <param name="length">The length.</param>
/// <param name="stroke">The stroke.</param>
/// <param name="brush">The brush.</param>
public void DrawEdge(int x, int y, int width, int height, int length, float stroke, int brush) //geht
{
var first = new RawVector2(x, y);
var second = new RawVector2(x, y + length);
var third = new RawVector2(x + length, y);
_device.DrawLine(first, second, _brushContainer[brush], stroke);
_device.DrawLine(first, third, _brushContainer[brush], stroke);
first.Y += height;
second.Y = first.Y - length;
third.Y = first.Y;
third.X = first.X + length;
_device.DrawLine(first, second, _brushContainer[brush], stroke);
_device.DrawLine(first, third, _brushContainer[brush], stroke);
first.X = x + width;
first.Y = y;
second.X = first.X - length;
second.Y = first.Y;
third.X = first.X;
third.Y = first.Y + length;
_device.DrawLine(first, second, _brushContainer[brush], stroke);
_device.DrawLine(first, third, _brushContainer[brush], stroke);
first.Y += height;
second.X += length;
second.Y = first.Y - length;
third.Y = first.Y;
third.X = first.X - length;
_device.DrawLine(first, second, _brushContainer[brush], stroke);
_device.DrawLine(first, third, _brushContainer[brush], stroke);
}
/// <summary>
/// Draws the bar h.
/// </summary>
/// <param name="x">The x.</param>
/// <param name="y">The y.</param>
/// <param name="width">The width.</param>
/// <param name="height">The height.</param>
/// <param name="value">The value.</param>
/// <param name="stroke">The stroke.</param>
/// <param name="brush">The brush.</param>
/// <param name="interiorBrush">The interior brush.</param>
public void DrawBarH(int x, int y, int width, int height, float value, float stroke, int brush,
int interiorBrush) {
var first = new RawRectangleF(x, y, x + width, y + height);
_device.DrawRectangle(first, _brushContainer[brush], stroke);
if (Math.Abs(value) < 0) {
return;
}
first.Top += height - height / 100.0f * value;
_device.FillRectangle(first, _brushContainer[interiorBrush]);
}
/// <summary>
/// Draws the bar v.
/// </summary>
/// <param name="x">The x.</param>
/// <param name="y">The y.</param>
/// <param name="width">The width.</param>
/// <param name="height">The height.</param>
/// <param name="value">The value.</param>
/// <param name="stroke">The stroke.</param>
/// <param name="brush">The brush.</param>
/// <param name="interiorBrush">The interior brush.</param>
public void DrawBarV(int x, int y, int width, int height, float value, float stroke, int brush,
int interiorBrush) {
var first = new RawRectangleF(x, y, x + width, y + height);
_device.DrawRectangle(first, _brushContainer[brush], stroke);
if (Math.Abs(value) < 0) {
return;
}
first.Right -= width - width / 100.0f * value;
_device.FillRectangle(first, _brushContainer[interiorBrush]);
}
/// <summary>
/// Fills the rectangle.
/// </summary>
/// <param name="x">The x.</param>
/// <param name="y">The y.</param>
/// <param name="width">The width.</param>
/// <param name="height">The height.</param>
/// <param name="brush">The brush.</param>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public void FillRectangle(int x, int y, int width, int height, int brush) => _device.FillRectangle(new RawRectangleF(x, y, x + width, y + height), _brushContainer[brush]);
/// <summary>
/// Fills the circle.
/// </summary>
/// <param name="x">The x.</param>
/// <param name="y">The y.</param>
/// <param name="radius">The radius.</param>
/// <param name="brush">The brush.</param>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public void FillCircle(int x, int y, int radius, int brush) => _device.FillEllipse(new Ellipse(new RawVector2(x, y), radius, radius), _brushContainer[brush]);
/// <summary>
/// Bordereds the line.
/// </summary>
/// <param name="startX">The start x.</param>
/// <param name="startY">The start y.</param>
/// <param name="endX">The end x.</param>
/// <param name="endY">The end y.</param>
/// <param name="stroke">The stroke.</param>
/// <param name="brush">The brush.</param>
/// <param name="borderBrush">The border brush.</param>
public void BorderedLine(int startX, int startY, int endX, int endY, float stroke, int brush, int borderBrush) {
_device.DrawLine(new RawVector2(startX, startY), new RawVector2(endX, endY), _brushContainer[brush], stroke);
_device.DrawLine(new RawVector2(startX, startY - stroke), new RawVector2(endX, endY - stroke),
_brushContainer[borderBrush], stroke);
_device.DrawLine(new RawVector2(startX, startY + stroke), new RawVector2(endX, endY + stroke),
_brushContainer[borderBrush], stroke);
_device.DrawLine(new RawVector2(startX - stroke / 2, startY - stroke * 1.5f),
new RawVector2(startX - stroke / 2, startY + stroke * 1.5f), _brushContainer[borderBrush], stroke);
_device.DrawLine(new RawVector2(endX - stroke / 2, endY - stroke * 1.5f),
new RawVector2(endX - stroke / 2, endY + stroke * 1.5f), _brushContainer[borderBrush], stroke);
}
/// <summary>
/// Bordereds the rectangle.
/// </summary>
/// <param name="x">The x.</param>
/// <param name="y">The y.</param>
/// <param name="width">The width.</param>
/// <param name="height">The height.</param>
/// <param name="stroke">The stroke.</param>
/// <param name="borderStroke">The border stroke.</param>
/// <param name="brush">The brush.</param>
/// <param name="borderBrush">The border brush.</param>
public void BorderedRectangle(int x, int y, int width, int height, float stroke, float borderStroke, int brush,
int borderBrush) {
_device.DrawRectangle(
new RawRectangleF(x - (stroke - borderStroke), y - (stroke - borderStroke),
x + width + stroke - borderStroke, y + height + stroke - borderStroke), _brushContainer[borderBrush],
borderStroke);
_device.DrawRectangle(new RawRectangleF(x, y, x + width, y + height), _brushContainer[brush], stroke);
_device.DrawRectangle(
new RawRectangleF(x + (stroke - borderStroke), y + (stroke - borderStroke),
x + width - stroke + borderStroke, y + height - stroke + borderStroke), _brushContainer[borderBrush],
borderStroke);
}
/// <summary>
/// Bordereds the circle.
/// </summary>
/// <param name="x">The x.</param>
/// <param name="y">The y.</param>
/// <param name="radius">The radius.</param>
/// <param name="stroke">The stroke.</param>
/// <param name="brush">The brush.</param>
/// <param name="borderBrush">The border brush.</param>
public void BorderedCircle(int x, int y, int radius, float stroke, int brush, int borderBrush) {
_device.DrawEllipse(new Ellipse(new RawVector2(x, y), radius + stroke, radius + stroke),
_brushContainer[borderBrush], stroke);
_device.DrawEllipse(new Ellipse(new RawVector2(x, y), radius, radius), _brushContainer[brush], stroke);
_device.DrawEllipse(new Ellipse(new RawVector2(x, y), radius - stroke, radius - stroke),
_brushContainer[borderBrush], stroke);
}
/// <summary>
/// Do not buffer text if you draw i.e. FPS. Use buffer for player names, rank....
/// </summary>
/// <param name="text">The text.</param>
/// <param name="font">The font.</param>
/// <param name="brush">The brush.</param>
/// <param name="x">The x.</param>
/// <param name="y">The y.</param>
/// <param name="bufferText">if set to <c>true</c> [buffer text].</param>
public void DrawText(string text, int font, int brush, int x, int y, bool bufferText = true) {
if (bufferText) {
var bufferPos = -1;
for (var i = 0; i < _layoutContainer.Count; i++) {
if (_layoutContainer[i].Text.Length != text.Length || _layoutContainer[i].Text != text) {
continue;
}
bufferPos = i;
break;
}
if (bufferPos == -1) {
_layoutContainer.Add(new TextLayoutBuffer(text,
new TextLayout(_fontFactory, text, _fontContainer[font], float.MaxValue, float.MaxValue)));
bufferPos = _layoutContainer.Count - 1;
}
_device.DrawTextLayout(new RawVector2(x, y), _layoutContainer[bufferPos].TextLayout,
_brushContainer[brush], DrawTextOptions.NoSnap);
}
else {
var layout = new TextLayout(_fontFactory, text, _fontContainer[font], float.MaxValue, float.MaxValue);
_device.DrawTextLayout(new RawVector2(x, y), layout, _brushContainer[brush]);
layout.Dispose();
}
}
}
}

View File

@@ -0,0 +1,14 @@
namespace Overlay.NET.Directx {
/// <summary>
/// </summary>
/// <seealso cref="Overlay.NET.OverlayPlugin" />
public abstract class DirectXOverlayPlugin : OverlayPlugin {
/// <summary>
/// Gets or sets the overlay window.
/// </summary>
/// <value>
/// The overlay window.
/// </value>
public DirectXOverlayWindow OverlayWindow { get; protected set; }
}
}

View File

@@ -0,0 +1,318 @@
using System;
using System.Threading;
using System.Threading.Tasks;
using Overlay.NET.Common;
namespace Overlay.NET.Directx {
public class DirectXOverlayWindow {
/// <summary>
/// Gets a value indicating whether this instance is disposing.
/// </summary>
/// <value>
/// <c>true</c> if this instance is disposing; otherwise, <c>false</c>.
/// </value>
public bool IsDisposing { get; private set; }
/// <summary>
/// Gets a value indicating whether [parent window exists].
/// </summary>
/// <value>
/// <c>true</c> if [parent window exists]; otherwise, <c>false</c>.
/// </value>
public bool ParentWindowExists { get; private set; }
/// <summary>
/// Gets a value indicating whether this instance is top most.
/// </summary>
/// <value>
/// <c>true</c> if this instance is top most; otherwise, <c>false</c>.
/// </value>
public bool IsTopMost { get; private set; }
/// <summary>
/// Gets a value indicating whether this instance is visible.
/// </summary>
/// <value>
/// <c>true</c> if this instance is visible; otherwise, <c>false</c>.
/// </value>
public bool IsVisible { get; private set; }
/// <summary>
/// Gets the x.
/// </summary>
/// <value>
/// The x.
/// </value>
public int X { get; private set; }
/// <summary>
/// Gets the y.
/// </summary>
/// <value>
/// The y.
/// </value>
public int Y { get; private set; }
/// <summary>
/// Gets the width.
/// </summary>
/// <value>
/// The width.
/// </value>
public int Width { get; private set; }
/// <summary>
/// Gets the height.
/// </summary>
/// <value>
/// The height.
/// </value>
public int Height { get; private set; }
/// <summary>
/// Gets the handle.
/// </summary>
/// <value>
/// The handle.
/// </value>
public IntPtr Handle { get; private set; }
/// <summary>
/// Gets the parent window.
/// </summary>
/// <value>
/// The parent window.
/// </value>
public IntPtr ParentWindow { get; }
/// <summary>
/// The margin
/// </summary>
private Native.RawMargin _margin;
/// <summary>
/// The graphics
/// </summary>
public Direct2DRenderer Graphics;
/// <summary>
/// Makes a transparent Fullscreen window
/// </summary>
/// <param name="limitFps">VSync</param>
/// <exception cref="Exception">Could not create OverlayWindow</exception>
public DirectXOverlayWindow(bool limitFps = true) {
IsDisposing = false;
IsVisible = true;
IsTopMost = true;
ParentWindowExists = false;
X = 0;
Y = 0;
Width = Native.GetSystemMetrics(WindowConstants.SmCxScreen);
Height = Native.GetSystemMetrics(WindowConstants.SmCyScreen);
ParentWindow = IntPtr.Zero;
if (!CreateWindow()) {
throw new Exception("Could not create OverlayWindow");
}
Graphics = new Direct2DRenderer(Handle, limitFps);
SetBounds(X, Y, Width, Height);
}
/// <summary>
/// Makes a transparent window which adjust it's size and position to fit the parent window
/// </summary>
/// <param name="parent">HWND/Handle of a window</param>
/// <param name="limitFps">VSync</param>
/// <exception cref="Exception">
/// The handle of the parent window isn't valid
/// or
/// Could not create OverlayWindow
/// </exception>
public DirectXOverlayWindow(IntPtr parent, bool limitFps = true) {
if (parent == IntPtr.Zero) {
throw new Exception("The handle of the parent window isn't valid");
}
Native.Rect bounds;
Native.GetWindowRect(parent, out bounds);
IsDisposing = false;
IsVisible = true;
IsTopMost = true;
ParentWindowExists = true;
X = bounds.Left;
Y = bounds.Top;
Width = bounds.Right - bounds.Left;
Height = bounds.Bottom - bounds.Top;
ParentWindow = parent;
if (!CreateWindow()) {
throw new Exception("Could not create OverlayWindow");
}
Graphics = new Direct2DRenderer(Handle, limitFps);
SetBounds(X, Y, Width, Height);
}
/// <summary>
/// Finalizes an instance of the <see cref="DirectXOverlayWindow" /> class.
/// </summary>
~DirectXOverlayWindow() {
Dispose();
}
/// <summary>
/// Clean up used ressources and destroy window
/// </summary>
public void Dispose() {
IsDisposing = true;
Graphics.Dispose();
Native.DestroyWindow(Handle);
}
/// <summary>
/// Creates a window with the information's stored in this class
/// </summary>
/// <returns>
/// true on success
/// </returns>
private bool CreateWindow() {
Handle = Native.CreateWindowEx(
WindowConstants.WindowExStyleDx,
WindowConstants.DesktopClass,
"",
WindowConstants.WindowStyleDx,
X,
Y,
Width,
Height,
IntPtr.Zero,
IntPtr.Zero,
IntPtr.Zero,
IntPtr.Zero);
if (Handle == IntPtr.Zero) {
return false;
}
Native.SetLayeredWindowAttributes(Handle, 0, 255, WindowConstants.LwaAlpha);
ExtendFrameIntoClient();
return true;
}
/// <summary>
/// Resize and set new position if the parent window's bounds change
/// </summary>
public void Update() {
if (!ParentWindowExists)
return;
Native.Rect bounds;
Native.GetWindowRect(ParentWindow, out bounds);
if (X != bounds.Left || Y != bounds.Top || Width != bounds.Right - bounds.Left ||
Height != bounds.Bottom - bounds.Top) {
SetBounds(bounds.Left, bounds.Top, bounds.Right - bounds.Left, bounds.Bottom - bounds.Top);
}
}
/// <summary>
/// Extends the frame into client.
/// </summary>
private void ExtendFrameIntoClient() {
_margin.cxLeftWidth = X;
_margin.cxRightWidth = Width;
_margin.cyBottomHeight = Height;
_margin.cyTopHeight = Y;
Native.DwmExtendFrameIntoClientArea(Handle, ref _margin);
}
/// <summary>
/// Sets the position.
/// </summary>
/// <param name="x">The x.</param>
/// <param name="y">The y.</param>
public void SetPos(int x, int y) {
X = x;
Y = y;
Native.SetWindowPos(Handle, WindowConstants.HwndTopmost, X, Y, Width, Height, 0);
ExtendFrameIntoClient();
}
/// <summary>
/// Sets the size.
/// </summary>
/// <param name="width">The width.</param>
/// <param name="height">The height.</param>
public void SetSize(int width, int height) {
Width = width;
Height = height;
Native.SetWindowPos(Handle, WindowConstants.HwndTopmost, X, Y, Width, Height, 0);
Graphics.AutoResize(Width, Height);
ExtendFrameIntoClient();
}
/// <summary>
/// Sets the bounds.
/// </summary>
/// <param name="x">The x.</param>
/// <param name="y">The y.</param>
/// <param name="width">The width.</param>
/// <param name="height">The height.</param>
public void SetBounds(int x, int y, int width, int height) {
X = x;
Y = y;
Width = width;
Height = height;
Native.SetWindowPos(Handle, WindowConstants.HwndTopmost, X, Y, Width, Height, 0);
Graphics?.AutoResize(Width, Height);
ExtendFrameIntoClient();
}
/// <summary>
/// Shows this instance.
/// </summary>
public void Show() {
if (IsVisible) {
return;
}
Native.ShowWindow(Handle, WindowConstants.SwShow);
IsVisible = true;
ExtendFrameIntoClient();
}
/// <summary>
/// Hides this instance.
/// </summary>
public void Hide() {
if (!IsVisible) {
return;
}
Native.ShowWindow(Handle, WindowConstants.SwHide);
IsVisible = false;
}
}
}

View File

@@ -0,0 +1,37 @@
using SharpDX.DirectWrite;
namespace Overlay.NET.Directx {
/// <summary>
/// </summary>
internal class TextLayoutBuffer {
/// <summary>
/// The text
/// </summary>
public string Text { get; set; }
/// <summary>
/// The text layout
/// </summary>
public TextLayout TextLayout { get; set; }
/// <summary>
/// Initializes a new instance of the <see cref="TextLayoutBuffer" /> class.
/// </summary>
/// <param name="text">The text.</param>
/// <param name="layout">The layout.</param>
public TextLayoutBuffer(string text, TextLayout layout) {
Text = text;
TextLayout = layout;
TextLayout.TextAlignment = TextAlignment.Leading;
TextLayout.WordWrapping = WordWrapping.NoWrap;
}
/// <summary>
/// Releases unmanaged and - optionally - managed resources.
/// </summary>
public void Dispose() {
TextLayout.Dispose();
Text = null;
}
}
}

View File

@@ -0,0 +1,135 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="14.0" DefaultTargets="Build" 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>{2D411EA5-BC00-4630-B25E-43C554323E72}</ProjectGuid>
<OutputType>Library</OutputType>
<AppDesignerFolder>Properties</AppDesignerFolder>
<RootNamespace>Overlay.NET</RootNamespace>
<AssemblyName>Overlay.NET</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 />
</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>
<PropertyGroup>
<StartupObject />
</PropertyGroup>
<ItemGroup>
<Reference Include="Process.NET, Version=1.0.0.0, Culture=neutral, processorArchitecture=MSIL">
<HintPath>..\packages\Process.NET.1.0.8\lib\Process.NET.dll</HintPath>
</Reference>
<Reference Include="SharpDX, Version=4.2.0.0, Culture=neutral, PublicKeyToken=b4dcf0f35e5521f1, processorArchitecture=MSIL">
<HintPath>..\packages\SharpDX.4.2.0\lib\net45\SharpDX.dll</HintPath>
</Reference>
<Reference Include="SharpDX.Direct2D1, Version=4.2.0.0, Culture=neutral, PublicKeyToken=b4dcf0f35e5521f1, processorArchitecture=MSIL">
<HintPath>..\packages\SharpDX.Direct2D1.4.2.0\lib\net45\SharpDX.Direct2D1.dll</HintPath>
</Reference>
<Reference Include="SharpDX.DXGI, Version=4.2.0.0, Culture=neutral, PublicKeyToken=b4dcf0f35e5521f1, processorArchitecture=MSIL">
<HintPath>..\packages\SharpDX.DXGI.4.2.0\lib\net45\SharpDX.DXGI.dll</HintPath>
</Reference>
<Reference Include="SharpDX.Mathematics, Version=4.2.0.0, Culture=neutral, PublicKeyToken=b4dcf0f35e5521f1, processorArchitecture=MSIL">
<HintPath>..\packages\SharpDX.Mathematics.4.2.0\lib\net45\SharpDX.Mathematics.dll</HintPath>
</Reference>
<Reference Include="System" />
<Reference Include="System.Drawing" />
<Reference Include="System.Xml" />
<Reference Include="System.Core" />
<Reference Include="System.Xaml">
<RequiredTargetFramework>4.0</RequiredTargetFramework>
</Reference>
<Reference Include="WindowsBase" />
<Reference Include="PresentationCore" />
<Reference Include="PresentationFramework" />
</ItemGroup>
<ItemGroup>
<Page Include="Wpf\OverlayWindow.xaml">
<Generator>MSBuild:Compile</Generator>
<SubType>Designer</SubType>
</Page>
</ItemGroup>
<ItemGroup>
<Compile Include="Common\FileLogger.cs" />
<Compile Include="Common\ISerializer.cs" />
<Compile Include="Common\ISettings.cs" />
<Compile Include="Common\Log.cs" />
<Compile Include="Common\Native.cs" />
<Compile Include="Common\PluginBase.cs" />
<Compile Include="Common\PluginLoader.cs" />
<Compile Include="Common\RelativeFile.cs" />
<Compile Include="Common\SerializableSettings.cs" />
<Compile Include="Common\TickEngine.cs" />
<Compile Include="Common\TimeSpanExtensions.cs" />
<Compile Include="Common\WaitTimer.cs" />
<Compile Include="Common\XmlSerializerEx.cs" />
<Compile Include="Directx\Direct2DRenderer.cs" />
<Compile Include="Directx\DirectExternalXOverlayPlugin.cs" />
<Compile Include="Directx\DirectXOverlayWindow.cs" />
<Compile Include="Directx\TextLayoutBuffer.cs" />
<Compile Include="Common\WindowConstants.cs" />
<Compile Include="OverlayPlugin.cs" />
<Compile Include="Wpf\OverlayWindow.xaml.cs">
<DependentUpon>OverlayWindow.xaml</DependentUpon>
</Compile>
<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>
<Compile Include="Common\WindowExtensions.cs" />
<Compile Include="Wpf\WpfOverlayPlugin.cs" />
<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>
<AppDesigner Include="Properties\" />
</ItemGroup>
<ItemGroup>
<None Include="App.config" />
</ItemGroup>
<ItemGroup />
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
<!-- To modify your build process, add your task inside one of the targets below and uncomment it.
Other similar extension points exist, see Microsoft.Common.targets.
<Target Name="BeforeBuild">
</Target>
<Target Name="AfterBuild">
</Target>
-->
</Project>

View File

@@ -0,0 +1,54 @@
using System;
using Overlay.NET.Common;
using Process.NET.Windows;
namespace Overlay.NET {
/// <summary>
/// Abstract class that defines basic overlay operations and values.
/// </summary>
/// <seealso cref="Overlay.NET.Common.PluginBase" />
/// <seealso cref="System.IDisposable" />
public abstract class OverlayPlugin : PluginBase, IDisposable {
/// <summary>
/// Gets or sets the target window that the overlay is to 'attach' to.
/// </summary>
/// <value>
/// The target window.
/// </value>
public IWindow TargetWindow { get; protected set; }
/// <summary>
/// Gets or sets a value indicating whether this instance is enabled.
/// </summary>
/// <value>
/// <c>true</c> if this instance is enabled; otherwise, <c>false</c>.
/// </value>
public bool IsEnabled { get; protected set; }
/// <summary>
/// Performs application-defined tasks associated with freeing, releasing, or resetting unmanaged resources.
/// </summary>
public virtual void Dispose() {}
/// <summary>
/// Enables this instance.
/// </summary>
public virtual void Enable() => IsEnabled = true;
/// <summary>
/// Disables this instance.
/// </summary>
public virtual void Disable() => IsEnabled = false;
/// <summary>
/// Initializes the specified target window.
/// </summary>
/// <param name="targetWindow">The target window.</param>
public virtual void Initialize(IWindow targetWindow) => TargetWindow = targetWindow;
/// <summary>
/// Updates this instance.
/// </summary>
public virtual void Update() {}
}
}

View File

@@ -0,0 +1,54 @@
using System.Reflection;
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("Overlay.NET")]
[assembly: AssemblyDescription("")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("")]
[assembly: AssemblyProduct("Overlay.NET")]
[assembly: AssemblyCopyright("Copyright © 2016")]
[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 Overlay.NET.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("Overlay.NET.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 Overlay.NET.Properties {
[global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
[global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator", "15.0.1.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,8 @@
<?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,15 @@
<Window x:Class="Overlay.NET.Wpf.OverlayWindow"
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"
mc:Ignorable="d"
Title="WowSharp Overlay OverlayWindow" Height="300" Width="300"
WindowStyle="None"
Topmost="True"
AllowsTransparency="True">
<Window.Background>
<SolidColorBrush Opacity="0.0" Color="Black" />
</Window.Background>
<Canvas x:Name="OverlayGrid" HorizontalAlignment="Left" Height="300" VerticalAlignment="Top" Width="300" />
</Window>

View File

@@ -0,0 +1,93 @@
using System;
using System.Windows;
using System.Windows.Media;
using Overlay.NET.Common;
using Process.NET.Windows;
namespace Overlay.NET.Wpf {
/// <summary>
/// Interaction logic for OverlayWindow.xaml
/// </summary>
public partial class OverlayWindow : Window {
private readonly IWindow _targetWindow;
/// <summary>
/// Initializes a new instance of the <see cref="OverlayWindow" /> class.
/// </summary>
/// <param name="targetWindow">The window.</param>
public OverlayWindow(IWindow targetWindow) {
_targetWindow = targetWindow;
InitializeComponent();
}
public event EventHandler<DrawingContext> Draw;
/// <summary>
/// Updates this instance.
/// </summary>
public void Update() {
Width = _targetWindow.Width;
Height = _targetWindow.Height;
Left = _targetWindow.X;
Top = _targetWindow.Y;
}
/// <summary>
/// Raises the <see cref="E:System.Windows.Window.SourceInitialized" /> event.
/// </summary>
/// <param name="e">An <see cref="T:System.EventArgs" /> that contains the event data.</param>
protected override void OnSourceInitialized(EventArgs e) {
base.OnSourceInitialized(e);
// We need to do this in order to allow shapes
// drawn on the canvas to be click-through.
// There is no other way to do this.
// Source: https://social.msdn.microsoft.com/Forums/en-US/c32889d3-effa-4b82-b179-76489ffa9f7d/how-to-clicking-throughpassing-shapesellipserectangle?forum=wpf
this.MakeWindowTransparent();
}
/// <summary>
/// When overridden in a derived class, participates in rendering operations that are directed by the layout system.
/// The rendering instructions for this element are not used directly when this method is invoked, and are instead
/// preserved for later asynchronous use by layout and drawing.
/// </summary>
/// <param name="drawingContext">
/// The drawing instructions for a specific element. This context is provided to the layout
/// system.
/// </param>
protected override void OnRender(DrawingContext drawingContext) {
OnDraw(drawingContext);
base.OnRender(drawingContext);
}
/// <summary>
/// Adds the specified element.
/// </summary>
/// <param name="element">The element.</param>
public void Add(UIElement element) => OverlayGrid.Children.Add(element);
/// <summary>
/// Removes the specified element.
/// </summary>
/// <param name="element">The element.</param>
public void Remove(UIElement element) => OverlayGrid.Children.Remove(element);
/// <summary>
/// Adds the specified element.
/// </summary>
/// <param name="element">The element.</param>
/// <param name="index">The index.</param>
public void Add(UIElement element, int index) => OverlayGrid.Children[index] = element;
/// <summary>
/// Removes the specified index.
/// </summary>
/// <param name="index">The index.</param>
public void Remove(int index) => OverlayGrid.Children.RemoveAt(index);
/// <summary>
/// Called when [draw].
/// </summary>
/// <param name="e">The e.</param>
protected virtual void OnDraw(DrawingContext e) => Draw?.Invoke(this, e);
}
}

View File

@@ -0,0 +1,15 @@
namespace Overlay.NET.Wpf {
/// <summary>
/// Abstract overlay that uses a transparent WPF window to do its rendering.
/// </summary>
/// <seealso cref="Overlay.NET.OverlayPlugin" />
public abstract class WpfOverlayPlugin : OverlayPlugin {
/// <summary>
/// Gets or sets the overlay window.
/// </summary>
/// <value>
/// The overlay window.
/// </value>
public OverlayWindow OverlayWindow { get; protected set; }
}
}

View File

@@ -0,0 +1,8 @@
<?xml version="1.0" encoding="utf-8"?>
<packages>
<package id="Process.NET" version="1.0.8" targetFramework="net461" />
<package id="SharpDX" version="4.2.0" targetFramework="net462" />
<package id="SharpDX.Direct2D1" version="4.2.0" targetFramework="net462" />
<package id="SharpDX.DXGI" version="4.2.0" targetFramework="net462" />
<package id="SharpDX.Mathematics" version="4.2.0" targetFramework="net462" />
</packages>