diff --git a/Artemis/Artemis/Artemis.csproj b/Artemis/Artemis/Artemis.csproj index ac305a684..b56f3704b 100644 --- a/Artemis/Artemis/Artemis.csproj +++ b/Artemis/Artemis/Artemis.csproj @@ -610,6 +610,7 @@ + diff --git a/Artemis/Artemis/ArtemisBootstrapper.cs b/Artemis/Artemis/ArtemisBootstrapper.cs index 30f3b2d3c..754eed3cc 100644 --- a/Artemis/Artemis/ArtemisBootstrapper.cs +++ b/Artemis/Artemis/ArtemisBootstrapper.cs @@ -90,11 +90,15 @@ namespace Artemis ContractResolver = _kernel.Get() }; JsonConvert.DefaultSettings = () => settings; + + //TODO DarthAffe 17.12.2016: Is this the right location for this? + ActiveWindowHelper.Initialize(); } protected override void OnExit(object sender, EventArgs e) { _kernel.Dispose(); + ActiveWindowHelper.Dispose(); base.OnExit(sender, e); } diff --git a/Artemis/Artemis/Modules/Effects/WindowsProfile/WindowsProfileDataModel.cs b/Artemis/Artemis/Modules/Effects/WindowsProfile/WindowsProfileDataModel.cs index 400bfa441..7efdf765f 100644 --- a/Artemis/Artemis/Modules/Effects/WindowsProfile/WindowsProfileDataModel.cs +++ b/Artemis/Artemis/Modules/Effects/WindowsProfile/WindowsProfileDataModel.cs @@ -14,6 +14,7 @@ namespace Artemis.Modules.Effects.WindowsProfile Performance = new PerformanceDataModel(); CurrentTime = new CurrentTime(); Keyboard = new KbDataModel(); + ActiveWindow = new ActiveWindow(); } public CpuDataModel Cpu { get; set; } @@ -22,6 +23,7 @@ namespace Artemis.Modules.Effects.WindowsProfile public GooglePlayMusic GooglePlayMusic { get; set; } public CurrentTime CurrentTime { get; set; } public KbDataModel Keyboard { get; set; } + public ActiveWindow ActiveWindow { get; set; } } [MoonSharpUserData] @@ -110,4 +112,11 @@ namespace Artemis.Modules.Effects.WindowsProfile public bool CapsLock { get; set; } public bool ScrollLock { get; set; } } + + [MoonSharpUserData] + public class ActiveWindow + { + public string ProcessName { get; set; } + public string WindowTitle { get; set; } + } } \ No newline at end of file diff --git a/Artemis/Artemis/Modules/Effects/WindowsProfile/WindowsProfileModel.cs b/Artemis/Artemis/Modules/Effects/WindowsProfile/WindowsProfileModel.cs index 724535874..7a5607c43 100644 --- a/Artemis/Artemis/Modules/Effects/WindowsProfile/WindowsProfileModel.cs +++ b/Artemis/Artemis/Modules/Effects/WindowsProfile/WindowsProfileModel.cs @@ -9,6 +9,7 @@ using Artemis.DAL; using Artemis.Managers; using Artemis.Models; using Artemis.Profiles.Layers.Models; +using Artemis.Utilities; using Newtonsoft.Json; using SpotifyAPI.Local; @@ -52,6 +53,7 @@ namespace Artemis.Modules.Effects.WindowsProfile UpdateMusicPlayers(dataModel); UpdateDay(dataModel); UpdateKeyStates(dataModel); + UpdateActiveWindow(dataModel); } #region Current Time @@ -66,7 +68,7 @@ namespace Artemis.Modules.Effects.WindowsProfile } #endregion - + #region CPU private void SetupCpu() @@ -249,6 +251,12 @@ namespace Artemis.Modules.Effects.WindowsProfile dataModel.Keyboard.ScrollLock = ((ushort)GetKeyState(0x91) & 0xffff) != 0; } + private void UpdateActiveWindow(WindowsProfileDataModel dataModel) + { + dataModel.ActiveWindow.ProcessName = ActiveWindowHelper.ActiveWindowProcessName; + dataModel.ActiveWindow.WindowTitle = ActiveWindowHelper.ActiveWindowWindowTitle; + } + #endregion } } \ No newline at end of file diff --git a/Artemis/Artemis/Profiles/Layers/Types/AmbientLight/AmbientLightType.cs b/Artemis/Artemis/Profiles/Layers/Types/AmbientLight/AmbientLightType.cs index c176040f9..5795bdbb0 100644 --- a/Artemis/Artemis/Profiles/Layers/Types/AmbientLight/AmbientLightType.cs +++ b/Artemis/Artemis/Profiles/Layers/Types/AmbientLight/AmbientLightType.cs @@ -70,6 +70,8 @@ namespace Artemis.Profiles.Layers.Types.AmbientLight properties.AmbientLightBrush = new DrawingBrush(new ImageDrawing (BitmapSource.Create(width, height, 96, 96, ScreenCaptureManager.LastCapturePixelFormat, null, _lastData, stride), new Rect(0, 0, width, height))); + + layerModel.ApplyProperties(true); } public void Draw(LayerModel layerModel, DrawingContext c) diff --git a/Artemis/Artemis/Utilities/ActiveWindowHelper.cs b/Artemis/Artemis/Utilities/ActiveWindowHelper.cs new file mode 100644 index 000000000..2b4e712f7 --- /dev/null +++ b/Artemis/Artemis/Utilities/ActiveWindowHelper.cs @@ -0,0 +1,110 @@ +using System; +using System.Runtime.InteropServices; +using System.Text; + +namespace Artemis.Utilities +{ + public static class ActiveWindowHelper + { + #region DLL-Imports + + private delegate void WinEventDelegate(IntPtr hWinEventHook, uint eventType, IntPtr hwnd, int idObject, int idChild, uint dwEventThread, uint dwmsEventTime); + + [DllImport("user32.dll")] + private static extern IntPtr SetWinEventHook(uint eventMin, uint eventMax, IntPtr hmodWinEventProc, WinEventDelegate lpfnWinEventProc, uint idProcess, uint idThread, uint dwFlags); + + [DllImport("user32.dll")] + private static extern bool UnhookWinEvent(IntPtr hWinEventHook); + + [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 uint WINEVENT_OUTOFCONTEXT = 0; + private const uint EVENT_SYSTEM_FOREGROUND = 3; + + private const int MAX_TITLE_LENGTH = 256; + + #endregion + + #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 _winEventHook; + + public static string ActiveWindowProcessName { get; private set; } + public static string ActiveWindowWindowTitle { get; private set; } + + #endregion + + #region Methods + + private static void ActiveWindowChanged(IntPtr hWinEventHook, uint eventType, + IntPtr hwnd, int idObject, int idChild, uint dwEventThread, uint dwmsEventTime) + { + ActiveWindowProcessName = GetActiveWindowProcessName(hwnd) ?? string.Empty; + ActiveWindowWindowTitle = GetActiveWindowTitle(hwnd) ?? string.Empty; + } + + private static string GetActiveWindowProcessName(IntPtr hwnd) + { + try + { + uint pid; + GetWindowThreadProcessId(hwnd, out pid); + return System.Diagnostics.Process.GetProcessById((int)pid).ProcessName; + } + catch + { + return null; + } + } + + private static 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 static void Initialize() + { + try + { + if (_winEventHook != IntPtr.Zero) return; + + _activeWindowChangedDelegate = ActiveWindowChanged; + _winEventHook = SetWinEventHook(EVENT_SYSTEM_FOREGROUND, EVENT_SYSTEM_FOREGROUND, IntPtr.Zero, _activeWindowChangedDelegate, 0, 0, WINEVENT_OUTOFCONTEXT); + } + catch { /* catch'em all - I don't want it to crash here */ } + } + + public static void Dispose() + { + try + { + if (_winEventHook == IntPtr.Zero) return; + + UnhookWinEvent(_winEventHook); + _activeWindowChangedDelegate = null; + _winEventHook = IntPtr.Zero; + } + catch { /* catch'em all - I don't want it to crash here */ } + } + + #endregion + } +}