mirror of
https://github.com/Stone-Red-Code/DesktopMagic.git
synced 2026-09-05 15:56:15 +02:00
- Rename src to _src
This commit is contained in:
@@ -0,0 +1,35 @@
|
||||
using DesktopMagicPluginAPI;
|
||||
|
||||
using System.Drawing;
|
||||
|
||||
namespace DesktopMagic.Plugins
|
||||
{
|
||||
internal class PluginData : IPluginData
|
||||
{
|
||||
private readonly PluginWindow window;
|
||||
|
||||
public PluginData(PluginWindow window)
|
||||
{
|
||||
this.window = window;
|
||||
}
|
||||
|
||||
public string Font => Theme.Font;
|
||||
|
||||
public Color Color => Theme.PrimaryColor;
|
||||
|
||||
public ITheme Theme { get; } = MainWindow.Theme;
|
||||
|
||||
public Size WindowSize => new Size((int)window.ActualWidth, (int)window.ActualHeight);
|
||||
|
||||
public Point WindowPosition => new Point((int)window.Left, (int)window.Top);
|
||||
|
||||
public string PluginName => window.PluginName;
|
||||
|
||||
public string PluginPath => window.PluginFolderPath;
|
||||
|
||||
public void UpdateWindow()
|
||||
{
|
||||
window.UpdatePluginWindow();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,31 @@
|
||||
<Window x:Class="DesktopMagic.PluginWindow"
|
||||
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:DesktopMagic"
|
||||
mc:Ignorable="d"
|
||||
Title="PluginWindow" Height="450" Width="800"
|
||||
Background="Transparent"
|
||||
WindowStyle="None"
|
||||
AllowsTransparency="True"
|
||||
LocationChanged="Window_LocationChanged"
|
||||
SizeChanged="Window_SizeChanged"
|
||||
Closing="Window_Closing"
|
||||
ContentRendered="Window_ContentRendered"
|
||||
x:Name="window">
|
||||
<Grid>
|
||||
<Rectangle x:Name="panel" Fill="#4CBAFFEF" Stroke="White" Margin="0,0,0,0" Visibility="Collapsed" />
|
||||
|
||||
<Border x:Name="border"/>
|
||||
<Viewbox x:Name="viewBox" StretchDirection="Both" Stretch="Uniform">
|
||||
<Viewbox.Clip>
|
||||
<RectangleGeometry x:Name="rectangleGeometry" RadiusX="{Binding ElementName=border, Path=CornerRadius.TopLeft}" RadiusY="{Binding ElementName=border, Path=CornerRadius.TopLeft}"/>
|
||||
</Viewbox.Clip>
|
||||
<Image x:Name="image" HorizontalAlignment="Left" RenderOptions.EdgeMode="Aliased" Margin="0,0,0,0" VerticalAlignment="Top" RenderTransformOrigin="0.5,0.5" Stretch="Uniform" MouseDown="Window_MouseDown" MouseMove="Window_MouseMove" MouseWheel="Window_MouseWheel"/>
|
||||
</Viewbox>
|
||||
</Grid>
|
||||
<WindowChrome.WindowChrome>
|
||||
<WindowChrome x:Name="tileBar" CaptionHeight="30" ResizeBorderThickness="{x:Static SystemParameters.WindowResizeBorderThickness}" />
|
||||
</WindowChrome.WindowChrome>
|
||||
</Window>
|
||||
@@ -0,0 +1,407 @@
|
||||
using DesktopMagic.Plugins;
|
||||
|
||||
using DesktopMagicPluginAPI;
|
||||
using DesktopMagicPluginAPI.Drawing;
|
||||
using DesktopMagicPluginAPI.Inputs;
|
||||
|
||||
using Microsoft.Win32;
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Drawing;
|
||||
using System.Drawing.Imaging;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Reflection;
|
||||
using System.Threading;
|
||||
using System.Timers;
|
||||
using System.Windows;
|
||||
using System.Windows.Interop;
|
||||
using System.Windows.Media;
|
||||
using System.Windows.Media.Imaging;
|
||||
|
||||
namespace DesktopMagic
|
||||
{
|
||||
public partial class PluginWindow : Window
|
||||
{
|
||||
private readonly RegistryKey key;
|
||||
private Thread pluginThread;
|
||||
private System.Timers.Timer valueTimer;
|
||||
|
||||
private Plugin pluginClassInstance;
|
||||
|
||||
public bool IsRunning { get; private set; } = true;
|
||||
public string PluginName { get; private set; }
|
||||
public string PluginFolderPath { get; private set; }
|
||||
|
||||
public event Action PluginLoaded;
|
||||
|
||||
public event Action OnExit;
|
||||
|
||||
public PluginWindow(string pluginName)
|
||||
{
|
||||
InitializeComponent();
|
||||
|
||||
Window w = new()
|
||||
{
|
||||
Top = -100,
|
||||
Left = -100,
|
||||
Width = 0,
|
||||
Height = 0,
|
||||
|
||||
WindowStyle = WindowStyle.ToolWindow,
|
||||
ShowInTaskbar = false
|
||||
};
|
||||
w.Show();
|
||||
Owner = w;
|
||||
w.Hide();
|
||||
|
||||
System.Timers.Timer t = new System.Timers.Timer();
|
||||
t.Interval = 100;
|
||||
t.Elapsed += UpdateTimer_Elapsed;
|
||||
t.Start();
|
||||
|
||||
PluginName = pluginName;
|
||||
|
||||
key = Registry.CurrentUser.CreateSubKey(@"Software\" + App.AppName);
|
||||
Top = double.Parse(key.GetValue(pluginName + "WindowTop", 100).ToString());
|
||||
Left = double.Parse(key.GetValue(pluginName + "WindowLeft", 100).ToString());
|
||||
Height = double.Parse(key.GetValue(pluginName + "WindowHeight", 200).ToString());
|
||||
Width = double.Parse(key.GetValue(pluginName + "WindowWidth", 500).ToString());
|
||||
}
|
||||
|
||||
public PluginWindow(Plugin pluginClassInstance, string pluginName) : this(pluginName)
|
||||
{
|
||||
this.pluginClassInstance = pluginClassInstance;
|
||||
}
|
||||
|
||||
protected override void OnSourceInitialized(EventArgs e)
|
||||
{
|
||||
base.OnSourceInitialized(e);
|
||||
|
||||
//Set the window style to noactivate.
|
||||
WindowInteropHelper helper = new(this);
|
||||
_ = WindowPos.SetWindowLong(helper.Handle, WindowPos.GWL_EXSTYLE,
|
||||
WindowPos.GetWindowLong(helper.Handle, WindowPos.GWL_EXSTYLE) | WindowPos.WS_EX_NOACTIVATE);
|
||||
}
|
||||
|
||||
private void Window_ContentRendered(object sender, EventArgs e)
|
||||
{
|
||||
pluginThread = new Thread(() =>
|
||||
{
|
||||
LoadPlugin();
|
||||
});
|
||||
pluginThread.Start();
|
||||
}
|
||||
|
||||
public void UpdatePluginWindow()
|
||||
{
|
||||
ValueTimer_Elapsed(valueTimer, null);
|
||||
}
|
||||
|
||||
private void UpdateTimer_Elapsed(object sender, ElapsedEventArgs e)
|
||||
{
|
||||
Dispatcher.Invoke(() =>
|
||||
{
|
||||
if (MainWindow.EditMode)
|
||||
{
|
||||
panel.Visibility = Visibility.Visible;
|
||||
WindowPos.SetIsLocked(this, false);
|
||||
tileBar.CaptionHeight = tileBar.CaptionHeight = ActualHeight - 10 < 0 ? 0 : ActualHeight - 10;
|
||||
ResizeMode = ResizeMode.CanResize;
|
||||
}
|
||||
else
|
||||
{
|
||||
panel.Visibility = Visibility.Collapsed;
|
||||
WindowPos.SetIsLocked(this, true);
|
||||
tileBar.CaptionHeight = 0;
|
||||
ResizeMode = ResizeMode.NoResize;
|
||||
}
|
||||
|
||||
if (!IsRunning)
|
||||
{
|
||||
((System.Timers.Timer)sender).Stop();
|
||||
}
|
||||
else
|
||||
{
|
||||
viewBox.Margin = new Thickness(MainWindow.Theme.Margin);
|
||||
border.Width = viewBox.ActualWidth + (MainWindow.Theme.Margin * 2);
|
||||
border.Height = viewBox.ActualHeight + (MainWindow.Theme.Margin * 2);
|
||||
rectangleGeometry.Rect = new Rect(-MainWindow.Theme.Margin, -MainWindow.Theme.Margin, border.ActualWidth, border.ActualHeight);
|
||||
border.Background = MainWindow.Theme.BackgroundBrush;
|
||||
border.CornerRadius = new CornerRadius(MainWindow.Theme.CornerRadius);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private void LoadPlugin()
|
||||
{
|
||||
if (pluginClassInstance is null)
|
||||
{
|
||||
PluginFolderPath = $"{Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData)}\\{App.AppName}\\Plugins\\{PluginName}";
|
||||
|
||||
if (!File.Exists($"{PluginFolderPath}\\{PluginName}.dll"))
|
||||
{
|
||||
_ = MessageBox.Show("File does not exist!", "Error", MessageBoxButton.OK, MessageBoxImage.Error);
|
||||
Exit();
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
ExecuteSource();
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
App.Logger.Log(ex.ToString(), "Plugin");
|
||||
_ = MessageBox.Show("File execution error:\n" + ex, "Error", MessageBoxButton.OK, MessageBoxImage.Error);
|
||||
Exit();
|
||||
return;
|
||||
}
|
||||
PluginLoaded?.Invoke();
|
||||
}
|
||||
|
||||
private void ExecuteSource()
|
||||
{
|
||||
object instance = pluginClassInstance;
|
||||
if (instance is null)
|
||||
{
|
||||
byte[] assemblyBytes = File.ReadAllBytes($"{PluginFolderPath}\\{PluginName}.dll");
|
||||
Assembly dll = Assembly.Load(assemblyBytes);
|
||||
Type instanceType = dll.GetTypes().FirstOrDefault(type => type.GetTypeInfo().BaseType == typeof(Plugin));
|
||||
|
||||
if (instanceType is null)
|
||||
{
|
||||
_ = MessageBox.Show($"The \"Plugin\" class could not be found! It has to inherit from \"{typeof(Plugin).FullName}\"", "Error", MessageBoxButton.OK, MessageBoxImage.Error);
|
||||
Exit();
|
||||
return;
|
||||
}
|
||||
|
||||
instance = Activator.CreateInstance(instanceType);
|
||||
}
|
||||
if (instance is Plugin)
|
||||
{
|
||||
pluginClassInstance = instance as Plugin;
|
||||
pluginClassInstance.Application = new PluginData(this);
|
||||
}
|
||||
else
|
||||
{
|
||||
_ = MessageBox.Show($"The \"Plugin\" class has to inherit from \"{typeof(Plugin).FullName}\"", "Error", MessageBoxButton.OK, MessageBoxImage.Error);
|
||||
Exit();
|
||||
return;
|
||||
}
|
||||
|
||||
LoadOptions(instance);
|
||||
|
||||
valueTimer = new System.Timers.Timer();
|
||||
valueTimer.Interval = 1000;
|
||||
valueTimer.Elapsed += ValueTimer_Elapsed;
|
||||
|
||||
pluginClassInstance.Start();
|
||||
UpdatePluginWindow();
|
||||
|
||||
if (pluginClassInstance.UpdateInterval > 0)
|
||||
{
|
||||
valueTimer.Interval = pluginClassInstance.UpdateInterval;
|
||||
valueTimer.Start();
|
||||
}
|
||||
}
|
||||
|
||||
private void LoadOptions(object instance)
|
||||
{
|
||||
try
|
||||
{
|
||||
FieldInfo[] props = instance.GetType().GetFields(BindingFlags.Instance | BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.GetField);
|
||||
|
||||
List<SettingElement> settingElements = new List<SettingElement>();
|
||||
foreach (FieldInfo prop in props)
|
||||
{
|
||||
if (prop.GetValue(instance) is Element element)
|
||||
{
|
||||
object[] attributes = prop.GetCustomAttributes(true);
|
||||
foreach (object attribute in attributes)
|
||||
{
|
||||
if (attribute is ElementAttribute elementAttribute)
|
||||
{
|
||||
settingElements.Add(new SettingElement(element, elementAttribute.Name, elementAttribute.OrderIndex));
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
settingElements = settingElements.OrderBy(x => x.OrderIndex).ToList();
|
||||
if (MainWindow.PluginsSettings.ContainsKey(PluginName))
|
||||
{
|
||||
MainWindow.PluginsSettings[PluginName] = settingElements;
|
||||
}
|
||||
else
|
||||
{
|
||||
MainWindow.PluginsSettings.Add(PluginName, settingElements);
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
IsRunning = false;
|
||||
App.Logger.Log(ex.ToString(), "Plugin");
|
||||
_ = MessageBox.Show("File execution error:\n" + ex, "Error", MessageBoxButton.OK, MessageBoxImage.Error);
|
||||
Exit();
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
private void ValueTimer_Elapsed(object sender, ElapsedEventArgs e)
|
||||
{
|
||||
try
|
||||
{
|
||||
if (IsRunning)
|
||||
{
|
||||
Bitmap result = pluginClassInstance.Main();
|
||||
|
||||
if (pluginClassInstance.UpdateInterval > 0)
|
||||
{
|
||||
valueTimer.Interval = pluginClassInstance.UpdateInterval;
|
||||
}
|
||||
else
|
||||
{
|
||||
valueTimer.Stop();
|
||||
}
|
||||
|
||||
if (result is not null)
|
||||
{
|
||||
BitmapScalingMode renderOptions = pluginClassInstance.RenderQuality switch
|
||||
{
|
||||
RenderQuality.High => BitmapScalingMode.HighQuality,
|
||||
RenderQuality.Low => BitmapScalingMode.LowQuality,
|
||||
RenderQuality.Performance => BitmapScalingMode.NearestNeighbor,
|
||||
_ => BitmapScalingMode.Unspecified
|
||||
};
|
||||
|
||||
//Update Image
|
||||
Dispatcher.Invoke(() =>
|
||||
{
|
||||
RenderOptions.SetBitmapScalingMode(image, renderOptions);
|
||||
image.Source = BitmapToImageSource(result);
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
IsRunning = false;
|
||||
App.Logger.Log(ex.ToString(), "Plugin");
|
||||
_ = MessageBox.Show("File execution error:\n" + ex, "Error", MessageBoxButton.OK, MessageBoxImage.Error);
|
||||
Exit();
|
||||
return;
|
||||
}
|
||||
|
||||
if (!IsRunning)
|
||||
{
|
||||
valueTimer.Stop();
|
||||
}
|
||||
}
|
||||
|
||||
private static BitmapSource BitmapToImageSource(Bitmap bitmap)
|
||||
{
|
||||
BitmapData bitmapData = bitmap.LockBits(
|
||||
new Rectangle(0, 0, bitmap.Width, bitmap.Height),
|
||||
ImageLockMode.ReadOnly, bitmap.PixelFormat);
|
||||
|
||||
BitmapSource bitmapSource = BitmapSource.Create(
|
||||
bitmapData.Width, bitmapData.Height,
|
||||
bitmap.HorizontalResolution, bitmap.VerticalResolution,
|
||||
PixelFormats.Bgra32, null,
|
||||
bitmapData.Scan0, bitmapData.Stride * bitmapData.Height, bitmapData.Stride);
|
||||
|
||||
bitmap.UnlockBits(bitmapData);
|
||||
return bitmapSource;
|
||||
}
|
||||
|
||||
public void Exit()
|
||||
{
|
||||
IsRunning = false;
|
||||
|
||||
Dispatcher.Invoke(() =>
|
||||
{
|
||||
OnExit?.Invoke();
|
||||
});
|
||||
}
|
||||
|
||||
private void Window_Closing(object sender, System.ComponentModel.CancelEventArgs e)
|
||||
{
|
||||
pluginClassInstance?.Stop();
|
||||
IsRunning = false;
|
||||
}
|
||||
|
||||
#region Window Events
|
||||
|
||||
private void Window_LocationChanged(object sender, EventArgs e)
|
||||
{
|
||||
key.SetValue(PluginName + "WindowTop", Top);
|
||||
key.SetValue(PluginName + "WindowLeft", Left);
|
||||
}
|
||||
|
||||
private void Window_SizeChanged(object sender, SizeChangedEventArgs e)
|
||||
{
|
||||
key.SetValue(PluginName + "WindowHeight", Height);
|
||||
key.SetValue(PluginName + "WindowWidth", Width);
|
||||
tileBar.CaptionHeight = ActualHeight - 10;
|
||||
}
|
||||
|
||||
private void Window_MouseDown(object sender, System.Windows.Input.MouseButtonEventArgs e)
|
||||
{
|
||||
ImageSource imageSource = image.Source;
|
||||
BitmapSource bitmapImage = (BitmapSource)imageSource;
|
||||
double pixelMousePositionX = e.GetPosition(image).X * bitmapImage.PixelWidth / image.ActualHeight;
|
||||
double pixelMousePositionY = e.GetPosition(image).Y * bitmapImage.PixelHeight / image.ActualHeight;
|
||||
|
||||
MouseButton mouseButton;
|
||||
|
||||
switch (e.ChangedButton)
|
||||
{
|
||||
case System.Windows.Input.MouseButton.Left:
|
||||
mouseButton = MouseButton.Left;
|
||||
break;
|
||||
|
||||
case System.Windows.Input.MouseButton.Middle:
|
||||
mouseButton = MouseButton.Middle;
|
||||
break;
|
||||
|
||||
case System.Windows.Input.MouseButton.Right:
|
||||
mouseButton = MouseButton.Right;
|
||||
break;
|
||||
|
||||
default:
|
||||
return;
|
||||
};
|
||||
|
||||
System.Drawing.Point point = new System.Drawing.Point((int)pixelMousePositionX, (int)pixelMousePositionY);
|
||||
pluginClassInstance.OnMouseClick(point, mouseButton);
|
||||
}
|
||||
|
||||
private void Window_MouseMove(object sender, System.Windows.Input.MouseEventArgs e)
|
||||
{
|
||||
ImageSource imageSource = image.Source;
|
||||
BitmapSource bitmapImage = (BitmapSource)imageSource;
|
||||
double pixelMousePositionX = e.GetPosition(image).X * bitmapImage.PixelWidth / image.ActualHeight;
|
||||
double pixelMousePositionY = e.GetPosition(image).Y * bitmapImage.PixelHeight / image.ActualHeight;
|
||||
|
||||
System.Drawing.Point point = new System.Drawing.Point((int)pixelMousePositionX, (int)pixelMousePositionY);
|
||||
pluginClassInstance.OnMouseMove(point);
|
||||
}
|
||||
|
||||
private void Window_MouseWheel(object sender, System.Windows.Input.MouseWheelEventArgs e)
|
||||
{
|
||||
ImageSource imageSource = image.Source;
|
||||
BitmapSource bitmapImage = (BitmapSource)imageSource;
|
||||
double pixelMousePositionX = e.GetPosition(image).X * bitmapImage.PixelWidth / image.ActualHeight;
|
||||
double pixelMousePositionY = e.GetPosition(image).Y * bitmapImage.PixelHeight / image.ActualHeight;
|
||||
|
||||
System.Drawing.Point point = new System.Drawing.Point((int)pixelMousePositionX, (int)pixelMousePositionY);
|
||||
pluginClassInstance.OnMouseWheel(point, e.Delta);
|
||||
}
|
||||
|
||||
#endregion Window Events
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
using DesktopMagicPluginAPI.Inputs;
|
||||
|
||||
namespace DesktopMagic.Plugins
|
||||
{
|
||||
internal class SettingElement
|
||||
{
|
||||
public Element Element { get; }
|
||||
public string Name { get; }
|
||||
public int OrderIndex { get; }
|
||||
|
||||
public SettingElement(Element element, string name, int orderIndex)
|
||||
{
|
||||
Element = element;
|
||||
Name = name;
|
||||
OrderIndex = orderIndex;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,21 @@
|
||||
using DesktopMagicPluginAPI;
|
||||
|
||||
using System.Drawing;
|
||||
|
||||
namespace DesktopMagic.Plugins
|
||||
{
|
||||
internal class Theme : ITheme
|
||||
{
|
||||
public Color PrimaryColor { get; set; } = Color.White;
|
||||
public Color SecondaryColor { get; set; } = Color.White;
|
||||
public Color BackgroundColor { get; set; } = Color.Transparent;
|
||||
|
||||
public string Font { get; set; } = "Segoe UI";
|
||||
public int CornerRadius { get; set; }
|
||||
public int Margin { get; set; }
|
||||
|
||||
public System.Windows.Media.Brush PrimaryBrush { get; set; } = System.Windows.Media.Brushes.White;
|
||||
public System.Windows.Media.Brush SecondaryBrush { get; set; } = System.Windows.Media.Brushes.White;
|
||||
public System.Windows.Media.Brush BackgroundBrush { get; set; } = System.Windows.Media.Brushes.Transparent;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user