From 687520d2eb84a74476b8c33301d15eb4c0438cab Mon Sep 17 00:00:00 2001 From: Anton Kasyanov Date: Mon, 29 Apr 2019 19:51:47 +0300 Subject: [PATCH] Display thumbnails even when Aero is disabled --- .../Implementation/ThumbnailConfiguration.cs | 5 + .../Interface/IThumbnailConfiguration.cs | 2 + Eve-O-Preview/Eve-O-Preview.csproj | 12 +- Eve-O-Preview/Program.cs | 10 +- .../Services/Implementation/DwmThumbnail.cs | 6 +- .../Implementation/ThumbnailManager.cs | 2 +- .../Services/Implementation/WindowManager.cs | 41 +++- .../Services/Interface/IWindowManager.cs | 4 +- ...piNativeMethods.cs => DwmNativeMethods.cs} | 2 +- .../Services/Interop/Gdi32NativeMethods.cs | 28 +++ .../Services/Interop/User32NativeMethods.cs | 14 +- .../View/Implementation/LiveThumbnailView.cs | 48 ++++ .../View/Implementation/MainForm.resx | 213 ++++++++++++++++++ .../Implementation/StaticThumbnailImage.cs | 23 ++ .../Implementation/StaticThumbnailView.cs | 49 ++++ .../Implementation/ThumbnailView.Designer.cs | 3 +- .../View/Implementation/ThumbnailView.cs | 153 ++++++------- .../Implementation/ThumbnailViewFactory.cs | 9 +- 18 files changed, 519 insertions(+), 105 deletions(-) rename Eve-O-Preview/Services/Interop/{DwmApiNativeMethods.cs => DwmNativeMethods.cs} (95%) create mode 100644 Eve-O-Preview/Services/Interop/Gdi32NativeMethods.cs create mode 100644 Eve-O-Preview/View/Implementation/LiveThumbnailView.cs create mode 100644 Eve-O-Preview/View/Implementation/StaticThumbnailImage.cs create mode 100644 Eve-O-Preview/View/Implementation/StaticThumbnailView.cs diff --git a/Eve-O-Preview/Configuration/Implementation/ThumbnailConfiguration.cs b/Eve-O-Preview/Configuration/Implementation/ThumbnailConfiguration.cs index eac17e9..79fd030 100644 --- a/Eve-O-Preview/Configuration/Implementation/ThumbnailConfiguration.cs +++ b/Eve-O-Preview/Configuration/Implementation/ThumbnailConfiguration.cs @@ -24,6 +24,8 @@ namespace EveOPreview.Configuration.Implementation this.MinimizeToTray = false; this.ThumbnailRefreshPeriod = 500; + this.EnableCompatibilityMode = false; + this.ThumbnailOpacity = 0.5; this.EnableClientLayoutTracking = false; @@ -54,6 +56,9 @@ namespace EveOPreview.Configuration.Implementation public bool MinimizeToTray { get; set; } public int ThumbnailRefreshPeriod { get; set; } + [JsonProperty("PotatoMode")] + public bool EnableCompatibilityMode { get; set; } + [JsonProperty("ThumbnailsOpacity")] public double ThumbnailOpacity { get; set; } diff --git a/Eve-O-Preview/Configuration/Interface/IThumbnailConfiguration.cs b/Eve-O-Preview/Configuration/Interface/IThumbnailConfiguration.cs index 565e395..3cb1158 100644 --- a/Eve-O-Preview/Configuration/Interface/IThumbnailConfiguration.cs +++ b/Eve-O-Preview/Configuration/Interface/IThumbnailConfiguration.cs @@ -8,6 +8,8 @@ namespace EveOPreview.Configuration bool MinimizeToTray { get; set; } int ThumbnailRefreshPeriod { get; set; } + bool EnableCompatibilityMode { get; set; } + double ThumbnailOpacity { get; set; } bool EnableClientLayoutTracking { get; set; } diff --git a/Eve-O-Preview/Eve-O-Preview.csproj b/Eve-O-Preview/Eve-O-Preview.csproj index c469a1f..5e9d4aa 100644 --- a/Eve-O-Preview/Eve-O-Preview.csproj +++ b/Eve-O-Preview/Eve-O-Preview.csproj @@ -147,6 +147,7 @@ + @@ -157,6 +158,15 @@ + + Form + + + Component + + + Form + @@ -212,7 +222,7 @@ ThumbnailView.cs - + diff --git a/Eve-O-Preview/Program.cs b/Eve-O-Preview/Program.cs index 430e490..16fc709 100644 --- a/Eve-O-Preview/Program.cs +++ b/Eve-O-Preview/Program.cs @@ -18,7 +18,7 @@ namespace EveOPreview static void Main() { #if DEBUG - var expirationDate = new DateTime(2019, 5, 1); + var expirationDate = new DateTime(2019, 5, 15); if (DateTime.Today >= expirationDate) { MessageBox.Show(@"This Beta version is expired. Please download a new build at https://github.com/Phrynohyas/eve-o-preview/releases", @"EVE-O Preview", MessageBoxButtons.OK, MessageBoxIcon.Exclamation); @@ -105,9 +105,11 @@ namespace EveOPreview IApplicationController controller = new ApplicationController(container); // UI classes - controller.RegisterView() - .RegisterView() - .RegisterInstance(new ApplicationContext()); + controller.RegisterView(); + controller.RegisterView(); + + controller.RegisterView(); + controller.RegisterInstance(new ApplicationContext()); return controller; } diff --git a/Eve-O-Preview/Services/Implementation/DwmThumbnail.cs b/Eve-O-Preview/Services/Implementation/DwmThumbnail.cs index 76b9388..873ded8 100644 --- a/Eve-O-Preview/Services/Implementation/DwmThumbnail.cs +++ b/Eve-O-Preview/Services/Implementation/DwmThumbnail.cs @@ -36,7 +36,7 @@ namespace EveOPreview.Services.Implementation try { - this._handle = DwmApiNativeMethods.DwmRegisterThumbnail(destination, source); + this._handle = DwmNativeMethods.DwmRegisterThumbnail(destination, source); } catch (ArgumentException) { @@ -63,7 +63,7 @@ namespace EveOPreview.Services.Implementation try { - DwmApiNativeMethods.DwmUnregisterThumbnail(this._handle); + DwmNativeMethods.DwmUnregisterThumbnail(this._handle); } catch (ArgumentException) { @@ -88,7 +88,7 @@ namespace EveOPreview.Services.Implementation try { - DwmApiNativeMethods.DwmUpdateThumbnailProperties(this._handle, this._properties); + DwmNativeMethods.DwmUpdateThumbnailProperties(this._handle, this._properties); } catch (ArgumentException) { diff --git a/Eve-O-Preview/Services/Implementation/ThumbnailManager.cs b/Eve-O-Preview/Services/Implementation/ThumbnailManager.cs index 005927c..9f55ac2 100644 --- a/Eve-O-Preview/Services/Implementation/ThumbnailManager.cs +++ b/Eve-O-Preview/Services/Implementation/ThumbnailManager.cs @@ -10,7 +10,7 @@ using MediatR; namespace EveOPreview.Services { - class ThumbnailManager : IThumbnailManager + sealed class ThumbnailManager : IThumbnailManager { #region Private constants private const int WINDOW_POSITION_THRESHOLD_LOW = -10_000; diff --git a/Eve-O-Preview/Services/Implementation/WindowManager.cs b/Eve-O-Preview/Services/Implementation/WindowManager.cs index a2096f1..b7e7135 100644 --- a/Eve-O-Preview/Services/Implementation/WindowManager.cs +++ b/Eve-O-Preview/Services/Implementation/WindowManager.cs @@ -1,14 +1,19 @@ using System; +using System.Drawing; using System.Runtime.InteropServices; using EveOPreview.Services.Interop; namespace EveOPreview.Services.Implementation { - class WindowManager : IWindowManager + sealed class WindowManager : IWindowManager { + #region Private constants + private const int WINDOW_SIZE_THRESHOLD = 300; + #endregion + public WindowManager() { - this.IsCompositionEnabled = DwmApiNativeMethods.DwmIsCompositionEnabled(); + this.IsCompositionEnabled = DwmNativeMethods.DwmIsCompositionEnabled(); } public bool IsCompositionEnabled { get; } @@ -63,12 +68,42 @@ namespace EveOPreview.Services.Implementation return User32NativeMethods.IsIconic(handle); } - public IDwmThumbnail RegisterThumbnail(IntPtr destination, IntPtr source) + public IDwmThumbnail GetLiveThumbnail(IntPtr destination, IntPtr source) { IDwmThumbnail thumbnail = new DwmThumbnail(this); thumbnail.Register(destination, source); return thumbnail; } + + public Image GetStaticThumbnail(IntPtr source) + { + var sourceContext = User32NativeMethods.GetDC(source); + + User32NativeMethods.GetClientRect(source, out RECT windowRect); + + var width = windowRect.Right - windowRect.Left; + var height = windowRect.Bottom - windowRect.Top; + + // Check if there is anything to make thumbnail of + if ((width < WINDOW_SIZE_THRESHOLD) || (height < WINDOW_SIZE_THRESHOLD)) + { + return null; + } + + var destContext = Gdi32NativeMethods.CreateCompatibleDC(sourceContext); + var bitmap = Gdi32NativeMethods.CreateCompatibleBitmap(sourceContext, width, height); + + var oldBitmap = Gdi32NativeMethods.SelectObject(destContext, bitmap); + Gdi32NativeMethods.BitBlt(destContext, 0, 0, width, height, sourceContext, 0, 0, Gdi32NativeMethods.SRCCOPY); + Gdi32NativeMethods.SelectObject(destContext, oldBitmap); + Gdi32NativeMethods.DeleteDC(destContext); + User32NativeMethods.ReleaseDC(source, sourceContext); + + Image image = Image.FromHbitmap(bitmap); + Gdi32NativeMethods.DeleteObject(bitmap); + + return image; + } } } \ No newline at end of file diff --git a/Eve-O-Preview/Services/Interface/IWindowManager.cs b/Eve-O-Preview/Services/Interface/IWindowManager.cs index e482a16..50a01b6 100644 --- a/Eve-O-Preview/Services/Interface/IWindowManager.cs +++ b/Eve-O-Preview/Services/Interface/IWindowManager.cs @@ -1,4 +1,5 @@ using System; +using System.Drawing; namespace EveOPreview.Services { @@ -15,6 +16,7 @@ namespace EveOPreview.Services (int Left, int Top, int Right, int Bottom) GetWindowPosition(IntPtr handle); bool IsWindowMinimized(IntPtr handle); - IDwmThumbnail RegisterThumbnail(IntPtr destination, IntPtr source); + IDwmThumbnail GetLiveThumbnail(IntPtr destination, IntPtr source); + Image GetStaticThumbnail(IntPtr source); } } \ No newline at end of file diff --git a/Eve-O-Preview/Services/Interop/DwmApiNativeMethods.cs b/Eve-O-Preview/Services/Interop/DwmNativeMethods.cs similarity index 95% rename from Eve-O-Preview/Services/Interop/DwmApiNativeMethods.cs rename to Eve-O-Preview/Services/Interop/DwmNativeMethods.cs index 90794e0..5cb7325 100644 --- a/Eve-O-Preview/Services/Interop/DwmApiNativeMethods.cs +++ b/Eve-O-Preview/Services/Interop/DwmNativeMethods.cs @@ -4,7 +4,7 @@ using System.Drawing; namespace EveOPreview.Services.Interop { - static class DwmApiNativeMethods + static class DwmNativeMethods { [DllImport("dwmapi.dll", PreserveSig = false)] public static extern void DwmEnableBlurBehindWindow(IntPtr hWnd, DWM_BLURBEHIND pBlurBehind); diff --git a/Eve-O-Preview/Services/Interop/Gdi32NativeMethods.cs b/Eve-O-Preview/Services/Interop/Gdi32NativeMethods.cs new file mode 100644 index 0000000..f966511 --- /dev/null +++ b/Eve-O-Preview/Services/Interop/Gdi32NativeMethods.cs @@ -0,0 +1,28 @@ +using System; +using System.Runtime.InteropServices; + +namespace EveOPreview.Services.Interop +{ + static class Gdi32NativeMethods + { + public const int SRCCOPY = 13369376; + + [DllImport("gdi32.dll")] + public static extern IntPtr CreateCompatibleDC(IntPtr hdc); + + [DllImport("gdi32.dll")] + public static extern bool DeleteDC(IntPtr hdc); + + [DllImport("gdi32.dll")] + public static extern IntPtr CreateCompatibleBitmap(IntPtr hdc, int width, int height); + + [DllImport("gdi32.dll")] + public static extern IntPtr SelectObject(IntPtr hdc, IntPtr hObject); + + [DllImport("gdi32.dll")] + public static extern bool DeleteObject(IntPtr hObject); + + [DllImport("gdi32.dll")] + public static extern bool BitBlt(IntPtr hObject, int nXDest, int nYDest, int nWidth, int nHeight, IntPtr hObjectSource, int nXSrc, int nYSrc, int dwRop); + } +} diff --git a/Eve-O-Preview/Services/Interop/User32NativeMethods.cs b/Eve-O-Preview/Services/Interop/User32NativeMethods.cs index fbde187..6adc97a 100644 --- a/Eve-O-Preview/Services/Interop/User32NativeMethods.cs +++ b/Eve-O-Preview/Services/Interop/User32NativeMethods.cs @@ -24,7 +24,10 @@ namespace EveOPreview.Services.Interop public static extern int GetWindowLong(IntPtr hWnd, int nIndex); [DllImport("user32.dll")] - public static extern int GetWindowRect(IntPtr hwnd, out RECT rect); + public static extern int GetWindowRect(IntPtr hWnd, out RECT rect); + + [DllImport("user32.dll")] + public static extern bool GetClientRect(IntPtr hWnd, out RECT rect); [DllImport("user32.dll", SetLastError = true)] [return: MarshalAs(UnmanagedType.Bool)] @@ -42,5 +45,14 @@ namespace EveOPreview.Services.Interop [DllImport("user32.dll")] public static extern bool IsZoomed(IntPtr hWnd); + + [DllImport("user32.dll")] + public static extern IntPtr GetWindowDC(IntPtr hWnd); + + [DllImport("user32.dll")] + public static extern IntPtr GetDC(IntPtr hWnd); + + [DllImport("user32.dll")] + public static extern IntPtr ReleaseDC(IntPtr hWnd, IntPtr hdc); } } \ No newline at end of file diff --git a/Eve-O-Preview/View/Implementation/LiveThumbnailView.cs b/Eve-O-Preview/View/Implementation/LiveThumbnailView.cs new file mode 100644 index 0000000..543c94d --- /dev/null +++ b/Eve-O-Preview/View/Implementation/LiveThumbnailView.cs @@ -0,0 +1,48 @@ +using System; +using EveOPreview.Services; + +namespace EveOPreview.View +{ + sealed class LiveThumbnailView : ThumbnailView + { + #region Private fields + private IDwmThumbnail _thumbnail; + #endregion + + public LiveThumbnailView(IWindowManager windowManager) + : base(windowManager) + { + } + + public override void Close() + { + this._thumbnail?.Unregister(); + base.Close(); + } + + protected override void RefreshThumbnail(bool forceRefresh) + { + // To prevent flickering the old broken thumbnail is removed AFTER the new shiny one is created + IDwmThumbnail obsoleteThumbnail = forceRefresh ? this._thumbnail : null; + + if ((this._thumbnail == null) || forceRefresh) + { + this.RegisterThumbnail(); + } + + obsoleteThumbnail?.Unregister(); + } + + protected override void ResizeThumbnail(int baseWidth, int baseHeight, int highlightWidthTop, int highlightWidthRight, int highlightWidthBottom, int highlightWidthLeft) + { + this._thumbnail.Move(0 + highlightWidthLeft, 0 + highlightWidthTop, baseWidth - highlightWidthRight, baseHeight - highlightWidthBottom); + this._thumbnail.Update(); + } + + private void RegisterThumbnail() + { + this._thumbnail = this.WindowManager.GetLiveThumbnail(this.Handle, this.Id); + this._thumbnail.Update(); + } + } +} diff --git a/Eve-O-Preview/View/Implementation/MainForm.resx b/Eve-O-Preview/View/Implementation/MainForm.resx index 426d527..0537524 100644 --- a/Eve-O-Preview/View/Implementation/MainForm.resx +++ b/Eve-O-Preview/View/Implementation/MainForm.resx @@ -141,12 +141,72 @@ True + + False + + + True + + + True + + + False + + + True + + + False + + + True + + + False + + + True + + + False + + + True + False True + + False + + + True + + + True + + + True + + + True + + + True + + + True + + + True + + + True + True @@ -180,6 +240,39 @@ True + + False + + + True + + + False + + + True + + + False + + + True + + + True + + + True + + + True + + + False + + + True + False @@ -216,6 +309,12 @@ True + + False + + + True + False @@ -225,6 +324,54 @@ True + + False + + + True + + + True + + + True + + + False + + + True + + + True + + + True + + + True + + + True + + + True + + + True + + + True + + + True + + + True + + + True + True @@ -276,6 +423,27 @@ True + + False + + + True + + + True + + + True + + + True + + + True + + + True + True @@ -303,6 +471,21 @@ True + + False + + + True + + + True + + + False + + + True + True @@ -324,6 +507,36 @@ True + + False + + + True + + + False + + + True + + + False + + + True + + + True + + + False + + + True + + + True + False diff --git a/Eve-O-Preview/View/Implementation/StaticThumbnailImage.cs b/Eve-O-Preview/View/Implementation/StaticThumbnailImage.cs new file mode 100644 index 0000000..f5ec500 --- /dev/null +++ b/Eve-O-Preview/View/Implementation/StaticThumbnailImage.cs @@ -0,0 +1,23 @@ +using System; +using System.Windows.Forms; + +namespace EveOPreview.View +{ + sealed class StaticThumbnailImage : PictureBox + { + protected override void WndProc(ref Message m) + { + const int WM_NCHITTEST = 0x0084; + const int HTTRANSPARENT = (-1); + + if (m.Msg == WM_NCHITTEST) + { + m.Result = (IntPtr)HTTRANSPARENT; + } + else + { + base.WndProc(ref m); + } + } + } +} diff --git a/Eve-O-Preview/View/Implementation/StaticThumbnailView.cs b/Eve-O-Preview/View/Implementation/StaticThumbnailView.cs new file mode 100644 index 0000000..cabe743 --- /dev/null +++ b/Eve-O-Preview/View/Implementation/StaticThumbnailView.cs @@ -0,0 +1,49 @@ +using System; +using System.Drawing; +using System.Windows.Forms; +using EveOPreview.Services; + +namespace EveOPreview.View +{ + sealed class StaticThumbnailView : ThumbnailView + { + #region Private fields + private readonly PictureBox _thumbnail; + #endregion + + public StaticThumbnailView(IWindowManager windowManager) + : base(windowManager) + { + this._thumbnail = new StaticThumbnailImage + { + TabStop = false, + SizeMode = PictureBoxSizeMode.StretchImage, + Location = new Point(0, 0), + Size = new Size(this.ClientSize.Width, this.ClientSize.Height) + }; + this.Controls.Add(this._thumbnail); + } + + protected override void RefreshThumbnail(bool forceRefresh) + { + if (!forceRefresh) + { + return; + } + + var thumbnail = this.WindowManager.GetStaticThumbnail(this.Id); + if (thumbnail != null) + { + var oldImage = this._thumbnail.Image; + this._thumbnail.Image = thumbnail; + oldImage?.Dispose(); + } + } + + protected override void ResizeThumbnail(int baseWidth, int baseHeight, int highlightWidthTop, int highlightWidthRight, int highlightWidthBottom, int highlightWidthLeft) + { + this._thumbnail.Location = new Point(0 + highlightWidthLeft, 0 + highlightWidthTop); + this._thumbnail.Size = new Size(baseWidth - highlightWidthLeft - highlightWidthRight, baseHeight - highlightWidthTop - highlightWidthBottom); + } + } +} \ No newline at end of file diff --git a/Eve-O-Preview/View/Implementation/ThumbnailView.Designer.cs b/Eve-O-Preview/View/Implementation/ThumbnailView.Designer.cs index c0540fd..697d424 100644 --- a/Eve-O-Preview/View/Implementation/ThumbnailView.Designer.cs +++ b/Eve-O-Preview/View/Implementation/ThumbnailView.Designer.cs @@ -19,11 +19,12 @@ namespace EveOPreview.View // ThumbnailView // this.AccessibleRole = System.Windows.Forms.AccessibleRole.None; - this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F); this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.None; this.BackColor = System.Drawing.Color.Black; + this.BackgroundImageLayout = System.Windows.Forms.ImageLayout.Stretch; this.ClientSize = new System.Drawing.Size(153, 89); this.ControlBox = false; + this.DoubleBuffered = true; this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.SizableToolWindow; this.MaximizeBox = false; this.MinimizeBox = false; diff --git a/Eve-O-Preview/View/Implementation/ThumbnailView.cs b/Eve-O-Preview/View/Implementation/ThumbnailView.cs index bc5cf0f..7755687 100644 --- a/Eve-O-Preview/View/Implementation/ThumbnailView.cs +++ b/Eve-O-Preview/View/Implementation/ThumbnailView.cs @@ -7,26 +7,25 @@ using EveOPreview.UI.Hotkeys; namespace EveOPreview.View { - public partial class ThumbnailView : Form, IThumbnailView + public abstract partial class ThumbnailView : Form, IThumbnailView { #region Private constants private const int RESIZE_EVENT_TIMEOUT = 500; #endregion #region Private fields - 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 _isOverlayVisible; private bool _isTopMost; + private bool _isHighlightEnabled; + private bool _isHighlightRequested; + private int _highlightWidth; private bool _isLocationChanged; private bool _isSizeChanged; private bool _isCustomMouseModeActive; - private bool _isHighlightEnabled; - private int _highlightWidth; private DateTime _suppressResizeEventsTimestamp; private Size _baseZoomSize; private Point _baseZoomLocation; @@ -36,29 +35,32 @@ namespace EveOPreview.View private HotkeyHandler _hotkeyHandler; #endregion - public ThumbnailView(IWindowManager windowManager) + protected ThumbnailView(IWindowManager windowManager) { this.SuppressResizeEvent(); - this._windowManager = windowManager; + this.WindowManager = windowManager; this.IsActive = false; this.IsOverlayEnabled = false; this._isOverlayVisible = false; this._isTopMost = false; + this._isHighlightEnabled = false; this._isLocationChanged = true; this._isSizeChanged = true; this._isCustomMouseModeActive = false; - this._isHighlightEnabled = false; + this._isHighlightRequested = false; InitializeComponent(); this._overlay = new ThumbnailOverlay(this, this.MouseDown_Handler); } + protected IWindowManager WindowManager { get; } + public IntPtr Id { get; set; } public string Title @@ -131,12 +133,11 @@ namespace EveOPreview.View base.Hide(); } - public new void Close() + public new virtual void Close() { this.SuppressResizeEvent(); this.IsActive = false; - this._thumbnail?.Unregister(); this._overlay.Close(); base.Close(); } @@ -177,9 +178,6 @@ namespace EveOPreview.View this.SuppressResizeEvent(); this.FormBorderStyle = style; - - // Notify about possible contents position change - this._isSizeChanged = true; } public void SetTopMost(bool enableTopmost) @@ -198,20 +196,20 @@ namespace EveOPreview.View public void SetHighlight(bool enabled, Color color, int width) { - if (this._isHighlightEnabled == enabled) + if (this._isHighlightRequested == enabled) { return; } if (enabled) { - this._isHighlightEnabled = true; + this._isHighlightRequested = true; this._highlightWidth = width; this.BackColor = color; } else { - this._isHighlightEnabled = false; + this._isHighlightRequested = false; this.BackColor = SystemColors.Control; } @@ -305,69 +303,31 @@ namespace EveOPreview.View public void Refresh(bool forceRefresh) { - // To prevent flickering the old broken thumbnail is removed AFTER the new shiny one is created - IDwmThumbnail obsoleteThumbnail = forceRefresh ? this._thumbnail : null; + this.RefreshThumbnail(forceRefresh); + this.HighlightThumbnail(forceRefresh || this._isSizeChanged); + this.RefreshOverlay(forceRefresh || this._isSizeChanged || this._isLocationChanged); - if ((this._thumbnail == null) || forceRefresh) - { - this.RegisterThumbnail(); - } - - bool sizeChanged = this._isSizeChanged || forceRefresh; - bool locationChanged = this._isLocationChanged || forceRefresh; - - if (sizeChanged) - { - this.RecalculateThumbnailSize(); - - this.UpdateThumbnail(); - - this._isSizeChanged = false; - } - - obsoleteThumbnail?.Unregister(); - - this._overlay.EnableOverlayLabel(this.IsOverlayEnabled); - - if (!this._isOverlayVisible) - { - // One-time action to show the Overlay before it is set up - // Otherwise its position won't be set - this._overlay.Show(); - this._isOverlayVisible = true; - } - else - { - if (!(sizeChanged || locationChanged)) - { - // No need to adjust in the overlay location if it is already visible and properly set - return; - } - } - - Size overlaySize = this.ClientSize; - Point overlayLocation = this.Location; - - int borderWidth = (this.Size.Width - this.ClientSize.Width) / 2; - overlayLocation.X += borderWidth; - overlayLocation.Y += (this.Size.Height - this.ClientSize.Height) - borderWidth; - - this._isLocationChanged = false; - this._overlay.Size = overlaySize; - this._overlay.Location = overlayLocation; - this._overlay.Refresh(); + this._isSizeChanged = false; } - private void RecalculateThumbnailSize() + protected abstract void RefreshThumbnail(bool forceRefresh); + + protected abstract void ResizeThumbnail(int baseWidth, int baseHeight, int highlightWidthTop, int highlightWidthRight, int highlightWidthBottom, int highlightWidthLeft); + + private void HighlightThumbnail(bool forceRefresh) { - // This approach would work only for square-shaped thumbnail window - // To get PROPER results we have to do some crazy math - //int delta = this._isHighlightEnabled ? this._highlightWidth : 0; - //this._thumbnail.rcDestination = new RECT(0 + delta, 0 + delta, this.ClientSize.Width - delta, this.ClientSize.Height - delta); - if (!this._isHighlightEnabled) + if (!forceRefresh && (this._isHighlightRequested == this._isHighlightEnabled)) { - //No highlighting enabled, so no odd math required - this._thumbnail.Move(0, 0, this.ClientSize.Width, this.ClientSize.Height); + // Nothing to do here + return; + } + + this._isHighlightEnabled = this._isHighlightRequested; + + if (!this._isHighlightRequested) + { + //No highlighting enabled, so no math required + this.ResizeThumbnail(this.ClientSize.Width, this.ClientSize.Height, 0, 0, 0, 0); return; } @@ -381,7 +341,38 @@ namespace EveOPreview.View int highlightWidthLeft = (baseWidth - actualWidth) / 2; int highlightWidthRight = baseWidth - actualWidth - highlightWidthLeft; - this._thumbnail.Move(0 + highlightWidthLeft, 0 + this._highlightWidth, baseWidth - highlightWidthRight, baseHeight - this._highlightWidth); + this.ResizeThumbnail(this.ClientSize.Width, this.ClientSize.Height, this._highlightWidth, highlightWidthRight, this._highlightWidth, highlightWidthLeft); + } + + private void RefreshOverlay(bool forceRefresh) + { + if (this._isOverlayVisible && !forceRefresh) + { + // No need to update anything. Everything is already set up + return; + } + + this._overlay.EnableOverlayLabel(this.IsOverlayEnabled); + + if (!this._isOverlayVisible) + { + // One-time action to show the Overlay before it is set up + // Otherwise its position won't be set + this._overlay.Show(); + this._isOverlayVisible = true; + } + + Size overlaySize = this.ClientSize; + Point overlayLocation = this.Location; + + int borderWidth = (this.Size.Width - this.ClientSize.Width) / 2; + overlayLocation.X += borderWidth; + overlayLocation.Y += (this.Size.Height - this.ClientSize.Height) - borderWidth; + + this._isLocationChanged = false; + this._overlay.Size = overlaySize; + this._overlay.Location = overlayLocation; + this._overlay.Refresh(); } private void SuppressResizeEvent() @@ -482,18 +473,6 @@ namespace EveOPreview.View } #endregion - #region Thumbnail management - private void RegisterThumbnail() - { - this._thumbnail = this._windowManager.RegisterThumbnail(this.Handle, this.Id); - } - - private void UpdateThumbnail() - { - this._thumbnail.Update(); - } - #endregion - #region Custom Mouse mode // This pair of methods saves/restores certain window properties // Methods are used to remove the 'Zoom' effect (if any) when the diff --git a/Eve-O-Preview/View/Implementation/ThumbnailViewFactory.cs b/Eve-O-Preview/View/Implementation/ThumbnailViewFactory.cs index 22c8715..83d271e 100644 --- a/Eve-O-Preview/View/Implementation/ThumbnailViewFactory.cs +++ b/Eve-O-Preview/View/Implementation/ThumbnailViewFactory.cs @@ -1,20 +1,25 @@ using System; using System.Drawing; +using EveOPreview.Configuration; namespace EveOPreview.View { sealed class ThumbnailViewFactory : IThumbnailViewFactory { private readonly IApplicationController _controller; + private readonly bool _isCompatibilityModeEnabled; - public ThumbnailViewFactory(IApplicationController controller) + public ThumbnailViewFactory(IApplicationController controller, IThumbnailConfiguration configuration) { this._controller = controller; + this._isCompatibilityModeEnabled = configuration.EnableCompatibilityMode; } public IThumbnailView Create(IntPtr id, string title, Size size) { - IThumbnailView view = this._controller.Create(); + IThumbnailView view = this._isCompatibilityModeEnabled + ? (IThumbnailView)this._controller.Create() + : (IThumbnailView)this._controller.Create(); view.Id = id; view.Title = title;