diff --git a/Eve-O-Preview/Configuration/ClientLayout.cs b/Eve-O-Preview/Configuration/ClientLayout.cs index b3db46c..02266c4 100644 --- a/Eve-O-Preview/Configuration/ClientLayout.cs +++ b/Eve-O-Preview/Configuration/ClientLayout.cs @@ -2,6 +2,18 @@ namespace EveOPreview.Configuration { public class ClientLayout { + public ClientLayout() + { + } + + public ClientLayout(int x, int y, int width, int height) + { + this.X = x; + this.Y = y; + this.Width = width; + this.Height = height; + } + public int X { get; set; } public int Y { get; set; } diff --git a/Eve-O-Preview/DwmAPI/Implementation/DwmThumbnail.cs b/Eve-O-Preview/DwmAPI/Implementation/DwmThumbnail.cs new file mode 100644 index 0000000..4a52091 --- /dev/null +++ b/Eve-O-Preview/DwmAPI/Implementation/DwmThumbnail.cs @@ -0,0 +1,76 @@ +using System; +using EveOPreview.DwmInterop; + +namespace EveOPreview.DwmAPI +{ + class DwmThumbnail : IDwmThumbnail + { + #region Private fields + private readonly IWindowManager _windowManager; + private IntPtr _handle; + private DWM_THUMBNAIL_PROPERTIES _properties; + #endregion + + public DwmThumbnail(IWindowManager windowManager) + { + this._windowManager = windowManager; + } + + public void Register(IntPtr destination, IntPtr source) + { + this._properties = new DWM_THUMBNAIL_PROPERTIES(); + this._properties.dwFlags = DWM_TNP_CONSTANTS.DWM_TNP_VISIBLE + + DWM_TNP_CONSTANTS.DWM_TNP_OPACITY + + DWM_TNP_CONSTANTS.DWM_TNP_RECTDESTINATION + + DWM_TNP_CONSTANTS.DWM_TNP_SOURCECLIENTAREAONLY; + this._properties.opacity = 255; + this._properties.fVisible = true; + this._properties.fSourceClientAreaOnly = true; + + if (!this._windowManager.IsCompositionEnabled) + { + return; + } + + this._handle = DwmApiNativeMethods.DwmRegisterThumbnail(destination, source); + } + + public void Unregister() + { + if (!this._windowManager.IsCompositionEnabled) + { + return; + } + + try + { + DwmApiNativeMethods.DwmUnregisterThumbnail(this._handle); + } + catch (ArgumentException) + { + } + } + + public void Move(int left, int top, int right, int bottom) + { + this._properties.rcDestination = new RECT(left, top, right, bottom); + } + + public void Update() + { + if (!this._windowManager.IsCompositionEnabled) + { + return; + } + + try + { + DwmApiNativeMethods.DwmUpdateThumbnailProperties(this._handle, this._properties); + } + catch (ArgumentException) + { + //This exception will be thrown if the EVE client disappears while this method is running + } + } + } +} diff --git a/Eve-O-Preview/DwmAPI/Implementation/WindowManager.cs b/Eve-O-Preview/DwmAPI/Implementation/WindowManager.cs new file mode 100644 index 0000000..a257299 --- /dev/null +++ b/Eve-O-Preview/DwmAPI/Implementation/WindowManager.cs @@ -0,0 +1,52 @@ +using System; +using EveOPreview.DwmInterop; + +namespace EveOPreview.DwmAPI +{ + class WindowManager : IWindowManager + { + public WindowManager() + { + this.IsCompositionEnabled = DwmApiNativeMethods.DwmIsCompositionEnabled(); + } + + public bool IsCompositionEnabled { get; } + + public IntPtr GetForegroundWindowHandle() + { + return User32NativeMethods.GetForegroundWindow(); + } + + public void ActivateWindow(IntPtr handle) + { + User32NativeMethods.SetForegroundWindow(handle); + + int style = User32NativeMethods.GetWindowLong(handle, InteropConstants.GWL_STYLE); + + if ((style & InteropConstants.WS_MINIMIZE) == InteropConstants.WS_MINIMIZE) + { + User32NativeMethods.ShowWindowAsync(handle, InteropConstants.SW_SHOWNORMAL); + } + } + + public void DeactivateWindow(IntPtr handle) + { + User32NativeMethods.SendMessage(handle, InteropConstants.WM_SYSCOMMAND, InteropConstants.SC_MINIMIZE, 0); + } + + public void MoveWindow(IntPtr handle, int left, int top, int width, int height) + { + User32NativeMethods.MoveWindow(handle, left, top, width, height, true); + } + + public void GetWindowCoordinates(IntPtr handle, out int left, out int top, out int right, out int bottom) + { + User32NativeMethods.GetWindowRect(handle, out RECT windowRectangle); + + left = windowRectangle.Left; + top = windowRectangle.Top; + right = windowRectangle.Right; + bottom = windowRectangle.Bottom; + } + } +} \ No newline at end of file diff --git a/Eve-O-Preview/DwmAPI/Interface/IDwmThumbnail.cs b/Eve-O-Preview/DwmAPI/Interface/IDwmThumbnail.cs new file mode 100644 index 0000000..395e525 --- /dev/null +++ b/Eve-O-Preview/DwmAPI/Interface/IDwmThumbnail.cs @@ -0,0 +1,13 @@ +using System; + +namespace EveOPreview +{ + public interface IDwmThumbnail + { + void Register(IntPtr destination, IntPtr source); + void Unregister(); + + void Move(int left, int top, int right, int bottom); + void Update(); + } +} diff --git a/Eve-O-Preview/DwmAPI/Interface/IWindowManager.cs b/Eve-O-Preview/DwmAPI/Interface/IWindowManager.cs new file mode 100644 index 0000000..f78f013 --- /dev/null +++ b/Eve-O-Preview/DwmAPI/Interface/IWindowManager.cs @@ -0,0 +1,17 @@ +using System; + +namespace EveOPreview +{ + public interface IWindowManager + { + bool IsCompositionEnabled { get; } + + IntPtr GetForegroundWindowHandle(); + + void ActivateWindow(IntPtr handle); + void DeactivateWindow(IntPtr handle); + + void MoveWindow(IntPtr handle, int left, int top, int width, int height); + void GetWindowCoordinates(IntPtr handle, out int left, out int top, out int right, out int bottom); + } +} \ No newline at end of file diff --git a/Eve-O-Preview/DwmAPI/WindowManagerNativeMethods.cs b/Eve-O-Preview/DwmAPI/Interface/InteropConstants.cs similarity index 58% rename from Eve-O-Preview/DwmAPI/WindowManagerNativeMethods.cs rename to Eve-O-Preview/DwmAPI/Interface/InteropConstants.cs index 6cf3f09..218f8eb 100644 --- a/Eve-O-Preview/DwmAPI/WindowManagerNativeMethods.cs +++ b/Eve-O-Preview/DwmAPI/Interface/InteropConstants.cs @@ -1,66 +1,9 @@ -using System; -using System.Runtime.InteropServices; -using System.Drawing; +using System; namespace EveOPreview { - // Desktop Windows Manager APIs - static class WindowManagerNativeMethods + public static class InteropConstants { - [DllImport("user32.dll")] - public static extern IntPtr GetForegroundWindow(); - - [DllImport("user32.dll")] - public static extern bool SetForegroundWindow(IntPtr window); - - [DllImport("dwmapi.dll", PreserveSig = false)] - public static extern void DwmEnableBlurBehindWindow(IntPtr hWnd, DWM_BLURBEHIND pBlurBehind); - - [DllImport("dwmapi.dll", PreserveSig = false)] - public static extern void DwmExtendFrameIntoClientArea(IntPtr hWnd, MARGINS pMargins); - - [DllImport("dwmapi.dll", PreserveSig = false)] - public static extern bool DwmIsCompositionEnabled(); - - [DllImport("dwmapi.dll", PreserveSig = false)] - public static extern void DwmGetColorizationColor( - out int pcrColorization, - [MarshalAs(UnmanagedType.Bool)]out bool pfOpaqueBlend); - - [DllImport("dwmapi.dll", PreserveSig = false)] - public static extern void DwmEnableComposition(bool bEnable); - - [DllImport("dwmapi.dll", PreserveSig = false)] - public static extern IntPtr DwmRegisterThumbnail(IntPtr dest, IntPtr source); - - [DllImport("dwmapi.dll", PreserveSig = false)] - public static extern void DwmUnregisterThumbnail(IntPtr hThumbnail); - - [DllImport("dwmapi.dll", PreserveSig = false)] - public static extern void DwmUpdateThumbnailProperties(IntPtr hThumbnail, DWM_THUMBNAIL_PROPERTIES props); - - [DllImport("dwmapi.dll", PreserveSig = false)] - public static extern void DwmQueryThumbnailSourceSize(IntPtr hThumbnail, out Size size); - - public const int SW_SHOWNORMAL = 1; - public const int SW_SHOWMINIMIZED = 2; - public const int SW_SHOWMAXIMIZED = 3; - - [DllImport("user32.dll")] - public static extern bool ShowWindowAsync(IntPtr hWnd, int nCmdShow); - - public const int WM_NCLBUTTONDOWN = 0xA1; - public const int HTCAPTION = 0x2; - - [DllImport("User32.dll")] - public static extern bool ReleaseCapture(); - - [DllImport("User32.dll")] - public static extern int SendMessage(IntPtr hWnd, int Msg, int wParam, int lParam); - - [DllImport("user32.dll", SetLastError = true)] - public static extern int GetWindowLong(IntPtr hWnd, int nIndex); - public const int GWL_ID = (-12); public const int GWL_STYLE = (-16); public const int GWL_EXSTYLE = (-20); @@ -129,10 +72,11 @@ namespace EveOPreview public const int SIZE_MAXSHOW = 3; public const int SIZE_MAXHIDE = 4; - [DllImport("user32.dll")] - public static extern int GetWindowRect(IntPtr hwnd, out RECT rect); + public const int WM_NCLBUTTONDOWN = 0xA1; + public const int HTCAPTION = 0x2; - [DllImport("user32.dll")] - public static extern bool MoveWindow(IntPtr hWnd, int X, int Y, int nWidth, int nHeight, bool bRepaint); + public const int SW_SHOWNORMAL = 1; + public const int SW_SHOWMINIMIZED = 2; + public const int SW_SHOWMAXIMIZED = 3; } } \ No newline at end of file diff --git a/Eve-O-Preview/DwmAPI/DWM_BLURBEHIND.cs b/Eve-O-Preview/DwmAPI/Interop/DWM_BLURBEHIND.cs similarity index 90% rename from Eve-O-Preview/DwmAPI/DWM_BLURBEHIND.cs rename to Eve-O-Preview/DwmAPI/Interop/DWM_BLURBEHIND.cs index 14ebd8e..31e2a75 100644 --- a/Eve-O-Preview/DwmAPI/DWM_BLURBEHIND.cs +++ b/Eve-O-Preview/DwmAPI/Interop/DWM_BLURBEHIND.cs @@ -1,7 +1,7 @@ using System; using System.Runtime.InteropServices; -namespace EveOPreview +namespace EveOPreview.DwmInterop { [StructLayout(LayoutKind.Sequential)] class DWM_BLURBEHIND diff --git a/Eve-O-Preview/DwmAPI/DWM_THUMBNAIL_PROPERTIES.cs b/Eve-O-Preview/DwmAPI/Interop/DWM_THUMBNAIL_PROPERTIES.cs similarity index 87% rename from Eve-O-Preview/DwmAPI/DWM_THUMBNAIL_PROPERTIES.cs rename to Eve-O-Preview/DwmAPI/Interop/DWM_THUMBNAIL_PROPERTIES.cs index 5c12e31..cef7946 100644 --- a/Eve-O-Preview/DwmAPI/DWM_THUMBNAIL_PROPERTIES.cs +++ b/Eve-O-Preview/DwmAPI/Interop/DWM_THUMBNAIL_PROPERTIES.cs @@ -1,6 +1,6 @@ using System.Runtime.InteropServices; -namespace EveOPreview +namespace EveOPreview.DwmInterop { [StructLayout(LayoutKind.Sequential)] class DWM_THUMBNAIL_PROPERTIES diff --git a/Eve-O-Preview/DwmAPI/DWM_TNP_CONSTANTS.cs b/Eve-O-Preview/DwmAPI/Interop/DWM_TNP_CONSTANTS.cs similarity index 87% rename from Eve-O-Preview/DwmAPI/DWM_TNP_CONSTANTS.cs rename to Eve-O-Preview/DwmAPI/Interop/DWM_TNP_CONSTANTS.cs index 7042770..da19f2f 100644 --- a/Eve-O-Preview/DwmAPI/DWM_TNP_CONSTANTS.cs +++ b/Eve-O-Preview/DwmAPI/Interop/DWM_TNP_CONSTANTS.cs @@ -1,4 +1,4 @@ -namespace EveOPreview +namespace EveOPreview.DwmInterop { static class DWM_TNP_CONSTANTS { diff --git a/Eve-O-Preview/DwmAPI/Interop/DwmApiNativeMethods.cs b/Eve-O-Preview/DwmAPI/Interop/DwmApiNativeMethods.cs new file mode 100644 index 0000000..639ce2a --- /dev/null +++ b/Eve-O-Preview/DwmAPI/Interop/DwmApiNativeMethods.cs @@ -0,0 +1,38 @@ +using System; +using System.Runtime.InteropServices; +using System.Drawing; + +namespace EveOPreview.DwmInterop +{ + static class DwmApiNativeMethods + { + [DllImport("dwmapi.dll", PreserveSig = false)] + public static extern void DwmEnableBlurBehindWindow(IntPtr hWnd, DWM_BLURBEHIND pBlurBehind); + + [DllImport("dwmapi.dll", PreserveSig = false)] + public static extern void DwmExtendFrameIntoClientArea(IntPtr hWnd, MARGINS pMargins); + + [DllImport("dwmapi.dll", PreserveSig = false)] + public static extern bool DwmIsCompositionEnabled(); + + [DllImport("dwmapi.dll", PreserveSig = false)] + public static extern void DwmGetColorizationColor( + out int pcrColorization, + [MarshalAs(UnmanagedType.Bool)]out bool pfOpaqueBlend); + + [DllImport("dwmapi.dll", PreserveSig = false)] + public static extern void DwmEnableComposition(bool bEnable); + + [DllImport("dwmapi.dll", PreserveSig = false)] + public static extern IntPtr DwmRegisterThumbnail(IntPtr dest, IntPtr source); + + [DllImport("dwmapi.dll", PreserveSig = false)] + public static extern void DwmUnregisterThumbnail(IntPtr hThumbnail); + + [DllImport("dwmapi.dll", PreserveSig = false)] + public static extern void DwmUpdateThumbnailProperties(IntPtr hThumbnail, DWM_THUMBNAIL_PROPERTIES props); + + [DllImport("dwmapi.dll", PreserveSig = false)] + public static extern void DwmQueryThumbnailSourceSize(IntPtr hThumbnail, out Size size); + } +} \ No newline at end of file diff --git a/Eve-O-Preview/DwmAPI/MARGINS.cs b/Eve-O-Preview/DwmAPI/Interop/MARGINS.cs similarity index 87% rename from Eve-O-Preview/DwmAPI/MARGINS.cs rename to Eve-O-Preview/DwmAPI/Interop/MARGINS.cs index 58ad6fc..e9fbb09 100644 --- a/Eve-O-Preview/DwmAPI/MARGINS.cs +++ b/Eve-O-Preview/DwmAPI/Interop/MARGINS.cs @@ -1,6 +1,6 @@ using System.Runtime.InteropServices; -namespace EveOPreview +namespace EveOPreview.DwmInterop { [StructLayout(LayoutKind.Sequential)] class MARGINS diff --git a/Eve-O-Preview/DwmAPI/RECT.cs b/Eve-O-Preview/DwmAPI/Interop/RECT.cs similarity index 86% rename from Eve-O-Preview/DwmAPI/RECT.cs rename to Eve-O-Preview/DwmAPI/Interop/RECT.cs index bc9f5ec..306c40e 100644 --- a/Eve-O-Preview/DwmAPI/RECT.cs +++ b/Eve-O-Preview/DwmAPI/Interop/RECT.cs @@ -1,6 +1,6 @@ using System.Runtime.InteropServices; -namespace EveOPreview +namespace EveOPreview.DwmInterop { [StructLayout(LayoutKind.Sequential)] struct RECT diff --git a/Eve-O-Preview/DwmAPI/Interop/User32NativeMethods.cs b/Eve-O-Preview/DwmAPI/Interop/User32NativeMethods.cs new file mode 100644 index 0000000..8f0fd5a --- /dev/null +++ b/Eve-O-Preview/DwmAPI/Interop/User32NativeMethods.cs @@ -0,0 +1,32 @@ +using System; +using System.Runtime.InteropServices; + +namespace EveOPreview.DwmInterop +{ + static class User32NativeMethods + { + [DllImport("user32.dll")] + public static extern IntPtr GetForegroundWindow(); + + [DllImport("user32.dll")] + public static extern bool SetForegroundWindow(IntPtr window); + + [DllImport("user32.dll")] + public static extern bool ShowWindowAsync(IntPtr hWnd, int nCmdShow); + + [DllImport("User32.dll")] + public static extern bool ReleaseCapture(); + + [DllImport("User32.dll")] + public static extern int SendMessage(IntPtr hWnd, int Msg, int wParam, int lParam); + + [DllImport("user32.dll", SetLastError = true)] + public static extern int GetWindowLong(IntPtr hWnd, int nIndex); + + [DllImport("user32.dll")] + public static extern int GetWindowRect(IntPtr hwnd, out RECT rect); + + [DllImport("user32.dll")] + public static extern bool MoveWindow(IntPtr hWnd, int X, int Y, int nWidth, int nHeight, bool bRepaint); + } +} \ No newline at end of file diff --git a/Eve-O-Preview/Eve-O-Preview.csproj b/Eve-O-Preview/Eve-O-Preview.csproj index e270d00..ffa7348 100644 --- a/Eve-O-Preview/Eve-O-Preview.csproj +++ b/Eve-O-Preview/Eve-O-Preview.csproj @@ -110,13 +110,19 @@ - - - - - + + + + + + + + + + + @@ -177,7 +183,7 @@ ThumbnailView.cs - + diff --git a/Eve-O-Preview/Presentation/ThumbnailManager.cs b/Eve-O-Preview/Presentation/ThumbnailManager.cs index 798ea30..bebbc94 100644 --- a/Eve-O-Preview/Presentation/ThumbnailManager.cs +++ b/Eve-O-Preview/Presentation/ThumbnailManager.cs @@ -18,6 +18,7 @@ namespace EveOPreview.UI #endregion #region Private fields + private readonly IWindowManager _windowManager; private readonly IThumbnailConfig _configuration; private readonly DispatcherTimer _thumbnailUpdateTimer; private readonly IThumbnailViewFactory _thumbnailViewFactory; @@ -30,8 +31,9 @@ namespace EveOPreview.UI private bool _isHoverEffectActive; #endregion - public ThumbnailManager(IThumbnailConfig configuration, IThumbnailViewFactory factory) + public ThumbnailManager(IWindowManager windowManager, IThumbnailConfig configuration, IThumbnailViewFactory factory) { + this._windowManager = windowManager; this._configuration = configuration; this._thumbnailViewFactory = factory; @@ -99,7 +101,7 @@ namespace EveOPreview.UI private void RefreshThumbnails() { - IntPtr foregroundWindowHandle = WindowManagerNativeMethods.GetForegroundWindow(); + IntPtr foregroundWindowHandle = this._windowManager.GetForegroundWindowHandle(); Boolean hideAllThumbnails = this._configuration.HideThumbnailsOnLostFocus && this.IsNonClientWindowActive(foregroundWindowHandle); this.DisableViewEvents(); @@ -196,7 +198,7 @@ namespace EveOPreview.UI Process[] clientProcesses = ThumbnailManager.GetClientProcesses(); List processHandles = new List(clientProcesses.Length); - IntPtr foregroundWindowHandle = WindowManagerNativeMethods.GetForegroundWindow(); + IntPtr foregroundWindowHandle = this._windowManager.GetForegroundWindowHandle(); List viewsAdded = new List(); List viewsUpdated = new List(); @@ -341,14 +343,7 @@ namespace EveOPreview.UI this._activeClientTitle = view.Title; } - WindowManagerNativeMethods.SetForegroundWindow(id); - - int style = WindowManagerNativeMethods.GetWindowLong(id, WindowManagerNativeMethods.GWL_STYLE); - // If the window was minimized then its thumbnail should be reset - if ((style & WindowManagerNativeMethods.WS_MINIMIZE) == WindowManagerNativeMethods.WS_MINIMIZE) - { - WindowManagerNativeMethods.ShowWindowAsync(id, WindowManagerNativeMethods.SW_SHOWNORMAL); - } + this._windowManager.ActivateWindow(id); if (this._configuration.EnableClientLayoutTracking) { @@ -362,13 +357,12 @@ namespace EveOPreview.UI private void ThumbnailDeactivated(IntPtr id) { - IThumbnailView view; - if (!this._thumbnailViews.TryGetValue(id, out view)) + if (!this._thumbnailViews.TryGetValue(id, out IThumbnailView view)) { return; } - WindowManagerNativeMethods.SendMessage(view.Id, WindowManagerNativeMethods.WM_SYSCOMMAND, WindowManagerNativeMethods.SC_MINIMIZE, 0); + this._windowManager.DeactivateWindow(view.Id); this.RefreshThumbnails(); } @@ -453,7 +447,7 @@ namespace EveOPreview.UI return; } - WindowManagerNativeMethods.MoveWindow(clientHandle, clientLayout.X, clientLayout.Y, clientLayout.Width, clientLayout.Height, true); + this._windowManager.MoveWindow(clientHandle, clientLayout.X, clientLayout.Y, clientLayout.Width, clientLayout.Height); } private void UpdateClientLayouts() @@ -462,23 +456,17 @@ namespace EveOPreview.UI foreach (Process process in clientProcesses) { - WindowManagerNativeMethods.GetWindowRect(process.MainWindowHandle, out RECT rect); + this._windowManager.GetWindowCoordinates(process.MainWindowHandle, out int left, out int top, out int right, out int bottom); - int width = Math.Abs(rect.Right - rect.Left); - int height = Math.Abs(rect.Bottom - rect.Top); + int width = Math.Abs(right - left); + int height = Math.Abs(bottom - top); - if (!this.IsValidWindowPosition(rect.Left, rect.Top, width, height)) + if (!this.IsValidWindowPosition(left, top, width, height)) { continue; } - ClientLayout layout = new ClientLayout(); - layout.X = rect.Left; - layout.Y = rect.Top; - layout.Width = width; - layout.Height = height; - - this._configuration.SetClientLayout(process.MainWindowTitle, layout); + this._configuration.SetClientLayout(process.MainWindowTitle, new ClientLayout(left, top, width, height)); } } diff --git a/Eve-O-Preview/Program.cs b/Eve-O-Preview/Program.cs index 494c8de..d3ef4fd 100644 --- a/Eve-O-Preview/Program.cs +++ b/Eve-O-Preview/Program.cs @@ -20,7 +20,7 @@ namespace EveOPreview // during the app lifetime object token = Program.GetInstanceToken(); - // If it was not possible to aquite the app token then another app instance is already running + // If it was not possible to aquire the app token then another app instance is already running // Nothing to do here if (token == null) { @@ -87,8 +87,7 @@ namespace EveOPreview } catch (Exception) { - bool result; - Mutex token = new Mutex(true, Program.MutexName, out result); + Mutex token = new Mutex(true, Program.MutexName, out var result); return result ? token : null; } } @@ -115,6 +114,7 @@ namespace EveOPreview .RegisterService() .RegisterService() .RegisterService() + .RegisterService() .RegisterInstance(new AppConfig()) .RegisterInstance(new ThumbnailConfig()); diff --git a/Eve-O-Preview/UI/Implementation/ThumbnailOverlay.cs b/Eve-O-Preview/UI/Implementation/ThumbnailOverlay.cs index 49a757c..71c0dfe 100644 --- a/Eve-O-Preview/UI/Implementation/ThumbnailOverlay.cs +++ b/Eve-O-Preview/UI/Implementation/ThumbnailOverlay.cs @@ -37,7 +37,7 @@ namespace EveOPreview.UI get { var Params = base.CreateParams; - Params.ExStyle |= (int)WindowManagerNativeMethods.WS_EX_TOOLWINDOW; + Params.ExStyle |= (int)InteropConstants.WS_EX_TOOLWINDOW; return Params; } } diff --git a/Eve-O-Preview/UI/Implementation/ThumbnailView.cs b/Eve-O-Preview/UI/Implementation/ThumbnailView.cs index 5532ba9..33ef18d 100644 --- a/Eve-O-Preview/UI/Implementation/ThumbnailView.cs +++ b/Eve-O-Preview/UI/Implementation/ThumbnailView.cs @@ -2,18 +2,19 @@ using System; using System.ComponentModel; using System.Drawing; using System.Windows.Forms; +using EveOPreview.DwmAPI; namespace EveOPreview.UI { public partial class ThumbnailView : Form, IThumbnailView { #region Private fields - private readonly bool _isDwmCompositionEnabled; + private readonly IWindowManager _windowManager; private readonly ThumbnailOverlay _overlay; + private IDwmThumbnail _thumbnail; // Part of the logic (namely current size / position management) // was moved to the view due to the performance reasons - private bool _isThumbnailSetUp; private bool _isOverlayVisible; private bool _isTopMost; private bool _isPositionChanged; @@ -22,8 +23,6 @@ namespace EveOPreview.UI private bool _isHighlightEnabled; private int _highlightWidth; private DateTime _suppressResizeEventsTimestamp; - private DWM_THUMBNAIL_PROPERTIES _thumbnail; - private IntPtr _thumbnailHandle; private Size _baseZoomSize; private Point _baseZoomLocation; private Point _baseMousePosition; @@ -32,13 +31,14 @@ namespace EveOPreview.UI private HotkeyHandler _hotkeyHandler; #endregion - public ThumbnailView() + public ThumbnailView(IWindowManager windowManager) { + this._windowManager = windowManager; + this.IsEnabled = true; this.IsActive = false; this.IsOverlayEnabled = false; - this._isThumbnailSetUp = false; this._isOverlayVisible = false; this._isTopMost = false; @@ -53,7 +53,6 @@ namespace EveOPreview.UI InitializeComponent(); this._overlay = new ThumbnailOverlay(this, this.MouseDown_Handler); - this._isDwmCompositionEnabled = WindowManagerNativeMethods.DwmIsCompositionEnabled(); } public IntPtr Id { get; set; } @@ -130,9 +129,7 @@ namespace EveOPreview.UI public new void Close() { this.IsActive = false; - - this.UnregisterThumbnail(this._thumbnailHandle); - + this._thumbnail.Unregister(); this._overlay.Close(); base.Close(); } @@ -311,9 +308,9 @@ namespace EveOPreview.UI public void Refresh(bool forceRefresh) { // To prevent flickering the old broken thumbnail is removed AFTER the new shiny one is created - IntPtr obsoleteThumbnailHanlde = forceRefresh ? this._thumbnailHandle : IntPtr.Zero; + IDwmThumbnail obsoleteThumbnail = forceRefresh ? this._thumbnail : null; - if ((this._isThumbnailSetUp == false) || forceRefresh) + if ((this._thumbnail == null) || forceRefresh) { this.RegisterThumbnail(); } @@ -330,10 +327,7 @@ namespace EveOPreview.UI this._isSizeChanged = false; } - if (obsoleteThumbnailHanlde != IntPtr.Zero) - { - this.UnregisterThumbnail(obsoleteThumbnailHanlde); - } + obsoleteThumbnail?.Unregister(); this._overlay.EnableOverlayLabel(this.IsOverlayEnabled); @@ -374,8 +368,8 @@ namespace EveOPreview.UI //this._thumbnail.rcDestination = new RECT(0 + delta, 0 + delta, this.ClientSize.Width - delta, this.ClientSize.Height - delta); if (!this._isHighlightEnabled) { - //No highlighting enables, so no odd math required - this._thumbnail.rcDestination = new RECT(0, 0, this.ClientSize.Width, this.ClientSize.Height); + //No highlighting enabled, so no odd math required + this._thumbnail.Move(0, 0, this.ClientSize.Width, this.ClientSize.Height); return; } @@ -389,7 +383,7 @@ namespace EveOPreview.UI int highlightWidthLeft = (baseWidth - actualWidth) / 2; int highlightWidthRight = baseWidth - actualWidth - highlightWidthLeft; - this._thumbnail.rcDestination = new RECT(0 + highlightWidthLeft, 0 + this._highlightWidth, baseWidth - highlightWidthRight, baseHeight - this._highlightWidth); + this._thumbnail.Move(0 + highlightWidthLeft, 0 + this._highlightWidth, baseWidth - highlightWidthRight, baseHeight - this._highlightWidth); } #region GUI events @@ -398,7 +392,7 @@ namespace EveOPreview.UI get { var Params = base.CreateParams; - Params.ExStyle |= (int)WindowManagerNativeMethods.WS_EX_TOOLWINDOW; + Params.ExStyle |= (int)InteropConstants.WS_EX_TOOLWINDOW; return Params; } } @@ -481,56 +475,13 @@ namespace EveOPreview.UI #region Thumbnail management private void RegisterThumbnail() { - this._isThumbnailSetUp = true; - - this._thumbnail = new DWM_THUMBNAIL_PROPERTIES(); - this._thumbnail.dwFlags = DWM_TNP_CONSTANTS.DWM_TNP_VISIBLE - + DWM_TNP_CONSTANTS.DWM_TNP_OPACITY - + DWM_TNP_CONSTANTS.DWM_TNP_RECTDESTINATION - + DWM_TNP_CONSTANTS.DWM_TNP_SOURCECLIENTAREAONLY; - this._thumbnail.opacity = 255; - this._thumbnail.fVisible = true; - this._thumbnail.fSourceClientAreaOnly = true; - - if (!this._isDwmCompositionEnabled) - { - return; - } - - this._thumbnailHandle = WindowManagerNativeMethods.DwmRegisterThumbnail(this.Handle, this.Id); + this._thumbnail = new DwmThumbnail(this._windowManager); + this._thumbnail.Register(this.Handle, this.Id); } private void UpdateThumbnail() { - if (!this._isDwmCompositionEnabled) - { - return; - } - - try - { - WindowManagerNativeMethods.DwmUpdateThumbnailProperties(this._thumbnailHandle, this._thumbnail); - } - catch (ArgumentException) - { - //This exception will be thrown if the EVE client disappears while this method is running - } - } - - private void UnregisterThumbnail(IntPtr thumbnailHandle) - { - if (!this._isDwmCompositionEnabled) - { - return; - } - - try - { - WindowManagerNativeMethods.DwmUnregisterThumbnail(thumbnailHandle); - } - catch (ArgumentException) - { - } + this._thumbnail.Update(); } #endregion