mirror of
https://github.com/Artemis-RGB/Artemis
synced 2025-12-13 05:48:35 +00:00
Merge pull request #348 from DarthAffe/development
Added Timer-Based ActiveWindow-detection
This commit is contained in:
commit
954f4864d8
@ -671,7 +671,11 @@
|
||||
<Compile Include="Settings\OffsetSettings.cs" />
|
||||
<Compile Include="Styles\DropTargetAdorners\DropTargetMetroHighlightAdorner.cs" />
|
||||
<Compile Include="Styles\DropTargetAdorners\DropTargetMetroInsertionAdorner.cs" />
|
||||
<Compile Include="Utilities\ActiveWindowHelper.cs" />
|
||||
<Compile Include="Utilities\ActiveWindowDetection\ActiveWindowDetectionType.cs" />
|
||||
<Compile Include="Utilities\ActiveWindowDetection\ActiveWindowHelper.cs" />
|
||||
<Compile Include="Utilities\ActiveWindowDetection\EventActiveWindowDetector.cs" />
|
||||
<Compile Include="Utilities\ActiveWindowDetection\IActiveWindowDetector.cs" />
|
||||
<Compile Include="Utilities\ActiveWindowDetection\TimerActiveWindowDetector.cs" />
|
||||
<Compile Include="Utilities\ColorHelpers.cs" />
|
||||
<Compile Include="Utilities\Converters\JsonConverters.cs" />
|
||||
<Compile Include="Utilities\Converters\NinjectCustomConverter.cs" />
|
||||
|
||||
@ -10,6 +10,7 @@ using Artemis.DAL;
|
||||
using Artemis.InjectionModules;
|
||||
using Artemis.Settings;
|
||||
using Artemis.Utilities;
|
||||
using Artemis.Utilities.ActiveWindowDetection;
|
||||
using Artemis.Utilities.Converters;
|
||||
using Artemis.Utilities.DataReaders;
|
||||
using Artemis.ViewModels;
|
||||
@ -113,7 +114,7 @@ namespace Artemis
|
||||
|
||||
//TODO DarthAffe 17.12.2016: Is this the right location for this?
|
||||
//TODO Move to Mainmanager and make disposable
|
||||
ActiveWindowHelper.Initialize();
|
||||
ActiveWindowHelper.SetActiveWindowDetectionType(SettingsProvider.Load<GeneralSettings>().ActiveWindowDetection);
|
||||
}
|
||||
|
||||
protected override void OnExit(object sender, EventArgs e)
|
||||
|
||||
@ -5,6 +5,7 @@ using Artemis.DAL;
|
||||
using Artemis.Modules.Abstract;
|
||||
using Artemis.Settings;
|
||||
using Artemis.Utilities;
|
||||
using Artemis.Utilities.ActiveWindowDetection;
|
||||
using Ninject.Extensions.Logging;
|
||||
|
||||
namespace Artemis.Managers
|
||||
|
||||
@ -11,6 +11,7 @@ using Artemis.Events;
|
||||
using Artemis.Managers;
|
||||
using Artemis.Modules.Abstract;
|
||||
using Artemis.Utilities;
|
||||
using Artemis.Utilities.ActiveWindowDetection;
|
||||
using CSCore.CoreAudioAPI;
|
||||
using Newtonsoft.Json;
|
||||
using SpotifyAPI.Local;
|
||||
|
||||
@ -5,9 +5,11 @@ using System.Windows;
|
||||
using Artemis.DAL;
|
||||
using Artemis.Profiles.Layers.Types.AmbientLight.ScreenCapturing;
|
||||
using Artemis.Utilities;
|
||||
using Artemis.Utilities.ActiveWindowDetection;
|
||||
using Caliburn.Micro;
|
||||
using MahApps.Metro;
|
||||
using Newtonsoft.Json;
|
||||
using Newtonsoft.Json.Converters;
|
||||
using Squirrel;
|
||||
|
||||
namespace Artemis.Settings
|
||||
@ -68,6 +70,11 @@ namespace Artemis.Settings
|
||||
[JsonProperty(DefaultValueHandling = DefaultValueHandling.Populate)]
|
||||
public string LogLevel { get; set; }
|
||||
|
||||
[DefaultValue(ActiveWindowDetectionType.Events)]
|
||||
[JsonConverter(typeof(StringEnumConverter))]
|
||||
[JsonProperty(DefaultValueHandling = DefaultValueHandling.Populate)]
|
||||
public ActiveWindowDetectionType ActiveWindowDetection { get; set; }
|
||||
|
||||
public Version LastRanVersion { get; set; }
|
||||
|
||||
public void Save()
|
||||
@ -75,6 +82,7 @@ namespace Artemis.Settings
|
||||
SettingsProvider.Save(this);
|
||||
|
||||
Logging.SetupLogging(LogLevel);
|
||||
ActiveWindowHelper.SetActiveWindowDetectionType(ActiveWindowDetection);
|
||||
ApplyAutorun();
|
||||
ApplyTheme();
|
||||
ApplyGamestatePort();
|
||||
|
||||
@ -0,0 +1,9 @@
|
||||
namespace Artemis.Utilities.ActiveWindowDetection
|
||||
{
|
||||
public enum ActiveWindowDetectionType
|
||||
{
|
||||
Disabled = -1,
|
||||
Events = 0,
|
||||
Timer = 1,
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,48 @@
|
||||
namespace Artemis.Utilities.ActiveWindowDetection
|
||||
{
|
||||
public static class ActiveWindowHelper
|
||||
{
|
||||
#region Properties & Fields
|
||||
|
||||
private static ActiveWindowDetectionType _currentDetectionType = ActiveWindowDetectionType.Disabled;
|
||||
private static IActiveWindowDetector _activeWindowDetector;
|
||||
|
||||
public static string ActiveWindowProcessName => _activeWindowDetector?.ActiveWindowProcessName ?? string.Empty;
|
||||
public static string ActiveWindowWindowTitle => _activeWindowDetector?.ActiveWindowWindowTitle ?? string.Empty;
|
||||
public static bool MainWindowActive => ActiveWindowProcessName.Contains("Artemis");
|
||||
|
||||
#endregion
|
||||
|
||||
#region Methods
|
||||
|
||||
public static void Dispose()
|
||||
{
|
||||
_activeWindowDetector?.Dispose();
|
||||
}
|
||||
|
||||
public static void SetActiveWindowDetectionType(ActiveWindowDetectionType detectionType)
|
||||
{
|
||||
if (detectionType == _currentDetectionType) return;
|
||||
|
||||
_activeWindowDetector?.Dispose();
|
||||
|
||||
switch (detectionType)
|
||||
{
|
||||
case ActiveWindowDetectionType.Events:
|
||||
_activeWindowDetector = new EventActiveWindowDetector();
|
||||
break;
|
||||
case ActiveWindowDetectionType.Timer:
|
||||
_activeWindowDetector = new TimerActiveWindowDetector();
|
||||
break;
|
||||
case ActiveWindowDetectionType.Disabled:
|
||||
_activeWindowDetector = null;
|
||||
break;
|
||||
}
|
||||
|
||||
_activeWindowDetector?.Initialize();
|
||||
_currentDetectionType = detectionType;
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
@ -2,9 +2,9 @@
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Text;
|
||||
|
||||
namespace Artemis.Utilities
|
||||
namespace Artemis.Utilities.ActiveWindowDetection
|
||||
{
|
||||
public static class ActiveWindowHelper
|
||||
public class EventActiveWindowDetector : IActiveWindowDetector
|
||||
{
|
||||
#region DLL-Imports
|
||||
|
||||
@ -14,7 +14,7 @@ namespace Artemis.Utilities
|
||||
|
||||
[DllImport("user32.dll")]
|
||||
private static extern IntPtr SetWinEventHook(uint eventMin, uint eventMax, IntPtr hmodWinEventProc,
|
||||
WinEventDelegate lpfnWinEventProc, uint idProcess, uint idThread, uint dwFlags);
|
||||
WinEventDelegate lpfnWinEventProc, uint idProcess, uint idThread, uint dwFlags);
|
||||
|
||||
[DllImport("user32.dll")]
|
||||
private static extern bool UnhookWinEvent(IntPtr hWinEventHook);
|
||||
@ -41,47 +41,46 @@ namespace Artemis.Utilities
|
||||
#region Properties & Fields
|
||||
|
||||
// DarthAffe 17.12.2016: We need to keep a reference to this or it might get collected by the garbage collector and cause some random crashes afterwards.
|
||||
private static WinEventDelegate _activeWindowChangedDelegate;
|
||||
private static IntPtr _activeWindowEventHook;
|
||||
private WinEventDelegate _activeWindowChangedDelegate;
|
||||
private IntPtr _activeWindowEventHook;
|
||||
|
||||
private static WinEventDelegate _windowTitleChangedDelegate;
|
||||
private static IntPtr _windowTitleEventHook;
|
||||
private WinEventDelegate _windowTitleChangedDelegate;
|
||||
private IntPtr _windowTitleEventHook;
|
||||
|
||||
private static WinEventDelegate _windowMinimizedChangedDelegate;
|
||||
private static IntPtr _windowMinimizedEventHook;
|
||||
private WinEventDelegate _windowMinimizedChangedDelegate;
|
||||
private IntPtr _windowMinimizedEventHook;
|
||||
|
||||
private static IntPtr _activeWindow;
|
||||
private IntPtr _activeWindow;
|
||||
|
||||
public static string ActiveWindowProcessName { get; private set; } = string.Empty;
|
||||
public static string ActiveWindowWindowTitle { get; private set; } = string.Empty;
|
||||
public static bool MainWindowActive => ActiveWindowProcessName.Contains("Artemis");
|
||||
public string ActiveWindowProcessName { get; private set; } = string.Empty;
|
||||
public string ActiveWindowWindowTitle { get; private set; } = string.Empty;
|
||||
|
||||
#endregion
|
||||
|
||||
#region Methods
|
||||
|
||||
private static void ActiveWindowChanged(IntPtr hWinEventHook, uint eventType,
|
||||
IntPtr hwnd, int idObject, int idChild, uint dwEventThread, uint dwmsEventTime)
|
||||
private void ActiveWindowChanged(IntPtr hWinEventHook, uint eventType,
|
||||
IntPtr hwnd, int idObject, int idChild, uint dwEventThread, uint dwmsEventTime)
|
||||
{
|
||||
UpdateForWindow(hwnd);
|
||||
}
|
||||
|
||||
private static void WindowTitleChanged(IntPtr hWinEventHook, uint eventType,
|
||||
IntPtr hwnd, int idObject, int idChild, uint dwEventThread, uint dwmsEventTime)
|
||||
private void WindowTitleChanged(IntPtr hWinEventHook, uint eventType,
|
||||
IntPtr hwnd, int idObject, int idChild, uint dwEventThread, uint dwmsEventTime)
|
||||
{
|
||||
if (_activeWindow == hwnd)
|
||||
UpdateForWindow(hwnd);
|
||||
}
|
||||
|
||||
private static void WindowMinimizedChanged(IntPtr hWinEventHook, uint eventType,
|
||||
IntPtr hwnd, int idObject, int idChild, uint dwEventThread, uint dwmsEventTime)
|
||||
private void WindowMinimizedChanged(IntPtr hWinEventHook, uint eventType,
|
||||
IntPtr hwnd, int idObject, int idChild, uint dwEventThread, uint dwmsEventTime)
|
||||
{
|
||||
// DarthAffe 19.12.2016: We expect currently un-minimized windows to be active.
|
||||
// DarthAffe 19.12.2016: The result of the API-function GetActiveWindow at this moment is 'idle' so we can't use this to validate this estimation.
|
||||
UpdateForWindow(hwnd);
|
||||
}
|
||||
|
||||
private static void UpdateForWindow(IntPtr hwnd)
|
||||
private void UpdateForWindow(IntPtr hwnd)
|
||||
{
|
||||
_activeWindow = hwnd;
|
||||
|
||||
@ -89,13 +88,13 @@ namespace Artemis.Utilities
|
||||
ActiveWindowWindowTitle = GetActiveWindowTitle(hwnd) ?? string.Empty;
|
||||
}
|
||||
|
||||
private static string GetActiveWindowProcessName(IntPtr hwnd)
|
||||
private string GetActiveWindowProcessName(IntPtr hwnd)
|
||||
{
|
||||
try
|
||||
{
|
||||
uint pid;
|
||||
GetWindowThreadProcessId(hwnd, out pid);
|
||||
return System.Diagnostics.Process.GetProcessById((int) pid).ProcessName;
|
||||
return System.Diagnostics.Process.GetProcessById((int)pid).ProcessName;
|
||||
}
|
||||
catch
|
||||
{
|
||||
@ -103,7 +102,7 @@ namespace Artemis.Utilities
|
||||
}
|
||||
}
|
||||
|
||||
private static string GetActiveWindowTitle(IntPtr hwnd)
|
||||
private string GetActiveWindowTitle(IntPtr hwnd)
|
||||
{
|
||||
try
|
||||
{
|
||||
@ -116,7 +115,7 @@ namespace Artemis.Utilities
|
||||
}
|
||||
}
|
||||
|
||||
public static void Initialize()
|
||||
public void Initialize()
|
||||
{
|
||||
try
|
||||
{
|
||||
@ -124,21 +123,21 @@ namespace Artemis.Utilities
|
||||
{
|
||||
_activeWindowChangedDelegate = ActiveWindowChanged;
|
||||
_activeWindowEventHook = SetWinEventHook(EVENT_SYSTEM_FOREGROUND, EVENT_SYSTEM_FOREGROUND,
|
||||
IntPtr.Zero, _activeWindowChangedDelegate, 0, 0, WINEVENT_OUTOFCONTEXT);
|
||||
IntPtr.Zero, _activeWindowChangedDelegate, 0, 0, WINEVENT_OUTOFCONTEXT);
|
||||
}
|
||||
|
||||
if (_windowTitleEventHook == IntPtr.Zero)
|
||||
{
|
||||
_windowTitleChangedDelegate = WindowTitleChanged;
|
||||
_windowTitleEventHook = SetWinEventHook(EVENT_OBJECT_NAMECHANGE, EVENT_OBJECT_NAMECHANGE,
|
||||
IntPtr.Zero, _windowTitleChangedDelegate, 0, 0, WINEVENT_OUTOFCONTEXT);
|
||||
IntPtr.Zero, _windowTitleChangedDelegate, 0, 0, WINEVENT_OUTOFCONTEXT);
|
||||
}
|
||||
|
||||
if (_windowMinimizedEventHook == IntPtr.Zero)
|
||||
{
|
||||
_windowMinimizedChangedDelegate = WindowMinimizedChanged;
|
||||
_windowMinimizedEventHook = SetWinEventHook(EVENT_SYSTEM_MINIMIZEEND, EVENT_SYSTEM_MINIMIZEEND,
|
||||
IntPtr.Zero, _windowMinimizedChangedDelegate, 0, 0, WINEVENT_OUTOFCONTEXT);
|
||||
IntPtr.Zero, _windowMinimizedChangedDelegate, 0, 0, WINEVENT_OUTOFCONTEXT);
|
||||
}
|
||||
}
|
||||
catch
|
||||
@ -147,7 +146,7 @@ namespace Artemis.Utilities
|
||||
}
|
||||
}
|
||||
|
||||
public static void Dispose()
|
||||
public void Dispose()
|
||||
{
|
||||
try
|
||||
{
|
||||
@ -180,4 +179,4 @@ namespace Artemis.Utilities
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,12 @@
|
||||
using System;
|
||||
|
||||
namespace Artemis.Utilities.ActiveWindowDetection
|
||||
{
|
||||
public interface IActiveWindowDetector : IDisposable
|
||||
{
|
||||
string ActiveWindowProcessName { get; }
|
||||
string ActiveWindowWindowTitle { get; }
|
||||
|
||||
void Initialize();
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,91 @@
|
||||
using System;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Text;
|
||||
using System.Timers;
|
||||
|
||||
namespace Artemis.Utilities.ActiveWindowDetection
|
||||
{
|
||||
public class TimerActiveWindowDetector : IActiveWindowDetector
|
||||
{
|
||||
#region DLL-Imports
|
||||
|
||||
[DllImport("user32.dll")]
|
||||
static extern IntPtr GetForegroundWindow();
|
||||
|
||||
[DllImport("user32.dll")]
|
||||
private static extern int GetWindowText(IntPtr hWnd, StringBuilder text, int count);
|
||||
|
||||
[DllImport("user32.dll")]
|
||||
private static extern IntPtr GetWindowThreadProcessId(IntPtr hWnd, out uint processId);
|
||||
|
||||
#endregion
|
||||
|
||||
#region Constants
|
||||
|
||||
private const int TIMER_INTERVAL = 1000;
|
||||
private const int MAX_TITLE_LENGTH = 256;
|
||||
|
||||
#endregion
|
||||
|
||||
#region Properties & Fields
|
||||
|
||||
private Timer _timer;
|
||||
|
||||
public string ActiveWindowProcessName { get; private set; }
|
||||
public string ActiveWindowWindowTitle { get; private set; }
|
||||
|
||||
#endregion
|
||||
|
||||
#region Methods
|
||||
|
||||
private void TimerOnElapsed(object sender, ElapsedEventArgs elapsedEventArgs)
|
||||
{
|
||||
IntPtr activeWindow = GetForegroundWindow();
|
||||
ActiveWindowProcessName = GetActiveWindowProcessName(activeWindow);
|
||||
ActiveWindowWindowTitle = GetActiveWindowTitle(activeWindow);
|
||||
}
|
||||
|
||||
private string GetActiveWindowProcessName(IntPtr hwnd)
|
||||
{
|
||||
try
|
||||
{
|
||||
uint pid;
|
||||
GetWindowThreadProcessId(hwnd, out pid);
|
||||
return System.Diagnostics.Process.GetProcessById((int)pid).ProcessName;
|
||||
}
|
||||
catch
|
||||
{
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
private string GetActiveWindowTitle(IntPtr hwnd)
|
||||
{
|
||||
try
|
||||
{
|
||||
StringBuilder buffer = new StringBuilder(MAX_TITLE_LENGTH);
|
||||
return GetWindowText(hwnd, buffer, MAX_TITLE_LENGTH) > 0 ? buffer.ToString() : null;
|
||||
}
|
||||
catch
|
||||
{
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
public void Initialize()
|
||||
{
|
||||
_timer = new Timer(TIMER_INTERVAL) { AutoReset = true };
|
||||
_timer.Elapsed += TimerOnElapsed;
|
||||
_timer.Start();
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
_timer?.Stop();
|
||||
_timer?.Dispose();
|
||||
_timer = null;
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
@ -8,6 +8,7 @@ using Artemis.Events;
|
||||
using Artemis.Managers;
|
||||
using Artemis.Services;
|
||||
using Artemis.Settings;
|
||||
using Artemis.Utilities.ActiveWindowDetection;
|
||||
using Caliburn.Micro;
|
||||
using MahApps.Metro.Controls;
|
||||
using NLog;
|
||||
@ -37,6 +38,8 @@ namespace Artemis.ViewModels.Flyouts
|
||||
LogLevels = new BindableCollection<string>();
|
||||
LogLevels.AddRange(LogLevel.AllLoggingLevels.Select(l => l.Name));
|
||||
|
||||
ActiveWindowDetections = new BindableCollection<ActiveWindowDetectionType>(Enum.GetValues(typeof(ActiveWindowDetectionType)).Cast<ActiveWindowDetectionType>());
|
||||
|
||||
PropertyChanged += KeyboardUpdater;
|
||||
mainManager.EnabledChanged += MainManagerEnabledChanged;
|
||||
mainManager.ModuleManager.EffectChanged += EffectManagerEffectChanged;
|
||||
@ -96,6 +99,7 @@ namespace Artemis.ViewModels.Flyouts
|
||||
public string VersionText => "Artemis " + Assembly.GetExecutingAssembly().GetName().Version;
|
||||
|
||||
public BindableCollection<string> LogLevels { get; set; }
|
||||
public BindableCollection<ActiveWindowDetectionType> ActiveWindowDetections { get; set; }
|
||||
|
||||
public string SelectedTheme
|
||||
{
|
||||
@ -130,6 +134,17 @@ namespace Artemis.ViewModels.Flyouts
|
||||
}
|
||||
}
|
||||
|
||||
public ActiveWindowDetectionType SelectedActiveWindowDetection
|
||||
{
|
||||
get { return GeneralSettings.ActiveWindowDetection; }
|
||||
set
|
||||
{
|
||||
if (value == GeneralSettings.ActiveWindowDetection) return;
|
||||
GeneralSettings.ActiveWindowDetection = value;
|
||||
NotifyOfPropertyChange(() => SelectedActiveWindowDetection);
|
||||
}
|
||||
}
|
||||
|
||||
public string SelectedKeyboardProvider
|
||||
{
|
||||
get { return _selectedKeyboardProvider; }
|
||||
|
||||
@ -23,6 +23,7 @@ using Artemis.Properties;
|
||||
using Artemis.Services;
|
||||
using Artemis.Styles.DropTargetAdorners;
|
||||
using Artemis.Utilities;
|
||||
using Artemis.Utilities.ActiveWindowDetection;
|
||||
using Caliburn.Micro;
|
||||
using Castle.Components.DictionaryAdapter;
|
||||
using GongSolutions.Wpf.DragDrop;
|
||||
|
||||
@ -6,7 +6,7 @@
|
||||
xmlns:controls="http://metro.mahapps.com/winfx/xaml/controls"
|
||||
xmlns:cal="http://www.caliburnproject.org"
|
||||
mc:Ignorable="d"
|
||||
d:DesignHeight="600" d:DesignWidth="300">
|
||||
d:DesignHeight="600" d:DesignWidth="310">
|
||||
<Grid>
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition Width="Auto" />
|
||||
@ -25,6 +25,7 @@
|
||||
<RowDefinition Height="Auto" />
|
||||
<RowDefinition Height="Auto" />
|
||||
<RowDefinition Height="Auto" />
|
||||
<RowDefinition Height="Auto" />
|
||||
<RowDefinition Height="*" />
|
||||
</Grid.RowDefinitions>
|
||||
|
||||
@ -94,30 +95,36 @@
|
||||
<controls:NumericUpDown Grid.Row="8" Grid.Column="1" Margin="10" VerticalAlignment="Center"
|
||||
HorizontalAlignment="Right" Width="140" Minimum="1" Maximum="60"
|
||||
Value="{Binding Path=GeneralSettings.ScreenCaptureFPS, Mode=TwoWay}" />
|
||||
|
||||
<!-- Logging -->
|
||||
|
||||
<Label Grid.Row="9" Grid.Column="0" Margin="5" VerticalAlignment="Center" HorizontalAlignment="Left"
|
||||
Content="Log level:" />
|
||||
<ComboBox Grid.Row="9" Grid.Column="1" x:Name="LogLevels" Margin="10" VerticalAlignment="Center"
|
||||
Content="Active window detection" />
|
||||
<ComboBox Grid.Row="9" Grid.Column="1" x:Name="ActiveWindowDetections" Margin="10" VerticalAlignment="Center"
|
||||
HorizontalAlignment="Right"
|
||||
Width="140" />
|
||||
<Button Grid.Row="10" Grid.Column="0" Margin="10" x:Name="ShowLogs" Content="Show logs"
|
||||
|
||||
<!-- Logging -->
|
||||
<Label Grid.Row="10" Grid.Column="0" Margin="5" VerticalAlignment="Center" HorizontalAlignment="Left"
|
||||
Content="Log level:" />
|
||||
<ComboBox Grid.Row="10" Grid.Column="1" x:Name="LogLevels" Margin="10" VerticalAlignment="Center"
|
||||
HorizontalAlignment="Right"
|
||||
Width="140" />
|
||||
<Button Grid.Row="11" Grid.Column="0" Margin="10" x:Name="ShowLogs" Content="Show logs"
|
||||
VerticalAlignment="Center" Width="100" HorizontalAlignment="Left"
|
||||
Style="{DynamicResource SquareButtonStyle}" />
|
||||
<Button Grid.Row="10" Grid.Column="1" Margin="10" x:Name="ShowDebug" Content="Show debugger"
|
||||
<Button Grid.Row="11" Grid.Column="1" Margin="10" x:Name="ShowDebug" Content="Show debugger"
|
||||
VerticalAlignment="Center" Width="100" HorizontalAlignment="Right"
|
||||
Style="{DynamicResource SquareButtonStyle}" />
|
||||
|
||||
<!-- Buttons -->
|
||||
<Button Grid.Row="11" Grid.Column="0" Margin="10" x:Name="ResetSettings" Content="Reset settings"
|
||||
<Button Grid.Row="12" Grid.Column="0" Margin="10" x:Name="ResetSettings" Content="Reset settings"
|
||||
VerticalAlignment="Center" HorizontalAlignment="Left" Width="100"
|
||||
Style="{DynamicResource SquareButtonStyle}" />
|
||||
<Button Grid.Row="11" Grid.Column="1" Margin="11" x:Name="SaveSettings" Content="Save changes"
|
||||
<Button Grid.Row="12" Grid.Column="1" Margin="11" x:Name="SaveSettings" Content="Save changes"
|
||||
VerticalAlignment="Center" HorizontalAlignment="Right" Width="100"
|
||||
Style="{DynamicResource SquareButtonStyle}" />
|
||||
|
||||
<!-- Version -->
|
||||
<Grid Grid.Row="12" Grid.Column="0" Grid.ColumnSpan="2" Margin="10" VerticalAlignment="Bottom">
|
||||
<Grid Grid.Row="13" Grid.Column="0" Grid.ColumnSpan="2" Margin="10" VerticalAlignment="Bottom">
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition Width="*" />
|
||||
<ColumnDefinition Width="*" />
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user