From 5277a52bae83b9ad5c407ed1e38447a5fb78545a Mon Sep 17 00:00:00 2001 From: Anton Kasyanov Date: Sat, 17 Jun 2017 18:45:15 +0300 Subject: [PATCH] Allow to minimize the client by Crtl+Click on its thumbnail --- .../DwmAPI/WindowManagerNativeMethods.cs | 192 +++++++++--------- .../Presentation/ThumbnailManager.cs | 24 +++ .../UI/Implementation/ThumbnailView.cs | 11 +- Eve-O-Preview/UI/Interface/IThumbnailView.cs | 2 + 4 files changed, 134 insertions(+), 95 deletions(-) diff --git a/Eve-O-Preview/DwmAPI/WindowManagerNativeMethods.cs b/Eve-O-Preview/DwmAPI/WindowManagerNativeMethods.cs index 66899eb..6cf3f09 100644 --- a/Eve-O-Preview/DwmAPI/WindowManagerNativeMethods.cs +++ b/Eve-O-Preview/DwmAPI/WindowManagerNativeMethods.cs @@ -4,121 +4,125 @@ using System.Drawing; namespace EveOPreview { - // Desktop Windows Manager APIs - static class WindowManagerNativeMethods - { - [DllImport("user32.dll")] - public static extern IntPtr GetForegroundWindow(); + // Desktop Windows Manager APIs + static class WindowManagerNativeMethods + { + [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 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 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 void DwmExtendFrameIntoClientArea(IntPtr hWnd, MARGINS pMargins); - [DllImport("dwmapi.dll", PreserveSig = false)] - public static extern bool DwmIsCompositionEnabled(); + [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 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 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 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 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 DwmUpdateThumbnailProperties(IntPtr hThumbnail, DWM_THUMBNAIL_PROPERTIES props); - [DllImport("dwmapi.dll", PreserveSig = false)] - public static extern void DwmQueryThumbnailSourceSize(IntPtr hThumbnail, out Size size); + [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; + 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); + [DllImport("user32.dll")] + public static extern bool ShowWindowAsync(IntPtr hWnd, int nCmdShow); - public const int WM_NCLBUTTONDOWN = 0xA1; - public const int HTCAPTION = 0x2; + 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 bool ReleaseCapture(); - [DllImport("User32.dll")] - public static extern int SendMessage(IntPtr hWnd, int Msg, int wParam, int lParam); + [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", 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); + public const int GWL_ID = (-12); + public const int GWL_STYLE = (-16); + public const int GWL_EXSTYLE = (-20); - // Window Styles - public const UInt32 WS_OVERLAPPED = 0; - public const UInt32 WS_POPUP = 0x80000000; - public const UInt32 WS_CHILD = 0x40000000; - public const UInt32 WS_MINIMIZE = 0x20000000; - public const UInt32 WS_VISIBLE = 0x10000000; - public const UInt32 WS_DISABLED = 0x8000000; - public const UInt32 WS_CLIPSIBLINGS = 0x4000000; - public const UInt32 WS_CLIPCHILDREN = 0x2000000; - public const UInt32 WS_MAXIMIZE = 0x1000000; - public const UInt32 WS_CAPTION = 0xC00000; // WS_BORDER or WS_DLGFRAME - public const UInt32 WS_BORDER = 0x800000; - public const UInt32 WS_DLGFRAME = 0x400000; - public const UInt32 WS_VSCROLL = 0x200000; - public const UInt32 WS_HSCROLL = 0x100000; - public const UInt32 WS_SYSMENU = 0x80000; - public const UInt32 WS_THICKFRAME = 0x40000; - public const UInt32 WS_GROUP = 0x20000; - public const UInt32 WS_TABSTOP = 0x10000; - public const UInt32 WS_MINIMIZEBOX = 0x20000; - public const UInt32 WS_MAXIMIZEBOX = 0x10000; - public const UInt32 WS_TILED = WS_OVERLAPPED; - public const UInt32 WS_ICONIC = WS_MINIMIZE; - public const UInt32 WS_SIZEBOX = WS_THICKFRAME; + // Window Styles + public const UInt32 WS_OVERLAPPED = 0; + public const UInt32 WS_POPUP = 0x80000000; + public const UInt32 WS_CHILD = 0x40000000; + public const UInt32 WS_MINIMIZE = 0x20000000; + public const UInt32 WS_VISIBLE = 0x10000000; + public const UInt32 WS_DISABLED = 0x8000000; + public const UInt32 WS_CLIPSIBLINGS = 0x4000000; + public const UInt32 WS_CLIPCHILDREN = 0x2000000; + public const UInt32 WS_MAXIMIZE = 0x1000000; + public const UInt32 WS_CAPTION = 0xC00000; // WS_BORDER or WS_DLGFRAME + public const UInt32 WS_BORDER = 0x800000; + public const UInt32 WS_DLGFRAME = 0x400000; + public const UInt32 WS_VSCROLL = 0x200000; + public const UInt32 WS_HSCROLL = 0x100000; + public const UInt32 WS_SYSMENU = 0x80000; + public const UInt32 WS_THICKFRAME = 0x40000; + public const UInt32 WS_GROUP = 0x20000; + public const UInt32 WS_TABSTOP = 0x10000; + public const UInt32 WS_MINIMIZEBOX = 0x20000; + public const UInt32 WS_MAXIMIZEBOX = 0x10000; + public const UInt32 WS_TILED = WS_OVERLAPPED; + public const UInt32 WS_ICONIC = WS_MINIMIZE; + public const UInt32 WS_SIZEBOX = WS_THICKFRAME; - // Extended Window Styles - public const UInt32 WS_EX_DLGMODALFRAME = 0x0001; - public const UInt32 WS_EX_NOPARENTNOTIFY = 0x0004; - public const UInt32 WS_EX_TOPMOST = 0x0008; - public const UInt32 WS_EX_ACCEPTFILES = 0x0010; - public const UInt32 WS_EX_TRANSPARENT = 0x0020; - public const UInt32 WS_EX_MDICHILD = 0x0040; - public const UInt32 WS_EX_TOOLWINDOW = 0x0080; - public const UInt32 WS_EX_WINDOWEDGE = 0x0100; - public const UInt32 WS_EX_CLIENTEDGE = 0x0200; - public const UInt32 WS_EX_CONTEXTHELP = 0x0400; - public const UInt32 WS_EX_RIGHT = 0x1000; - public const UInt32 WS_EX_LEFT = 0x0000; - public const UInt32 WS_EX_RTLREADING = 0x2000; - public const UInt32 WS_EX_LTRREADING = 0x0000; - public const UInt32 WS_EX_LEFTSCROLLBAR = 0x4000; - public const UInt32 WS_EX_RIGHTSCROLLBAR = 0x0000; - public const UInt32 WS_EX_CONTROLPARENT = 0x10000; - public const UInt32 WS_EX_STATICEDGE = 0x20000; - public const UInt32 WS_EX_APPWINDOW = 0x40000; - public const UInt32 WS_EX_OVERLAPPEDWINDOW = (WS_EX_WINDOWEDGE | WS_EX_CLIENTEDGE); - public const UInt32 WS_EX_PALETTEWINDOW = (WS_EX_WINDOWEDGE | WS_EX_TOOLWINDOW | WS_EX_TOPMOST); - public const UInt32 WS_EX_LAYERED = 0x00080000; - public const UInt32 WS_EX_NOINHERITLAYOUT = 0x00100000; // Disable inheritence of mirroring by children - public const UInt32 WS_EX_LAYOUTRTL = 0x00400000; // Right to left mirroring - public const UInt32 WS_EX_COMPOSITED = 0x02000000; - public const UInt32 WS_EX_NOACTIVATE = 0x08000000; + // Extended Window Styles + public const UInt32 WS_EX_DLGMODALFRAME = 0x0001; + public const UInt32 WS_EX_NOPARENTNOTIFY = 0x0004; + public const UInt32 WS_EX_TOPMOST = 0x0008; + public const UInt32 WS_EX_ACCEPTFILES = 0x0010; + public const UInt32 WS_EX_TRANSPARENT = 0x0020; + public const UInt32 WS_EX_MDICHILD = 0x0040; + public const UInt32 WS_EX_TOOLWINDOW = 0x0080; + public const UInt32 WS_EX_WINDOWEDGE = 0x0100; + public const UInt32 WS_EX_CLIENTEDGE = 0x0200; + public const UInt32 WS_EX_CONTEXTHELP = 0x0400; + public const UInt32 WS_EX_RIGHT = 0x1000; + public const UInt32 WS_EX_LEFT = 0x0000; + public const UInt32 WS_EX_RTLREADING = 0x2000; + public const UInt32 WS_EX_LTRREADING = 0x0000; + public const UInt32 WS_EX_LEFTSCROLLBAR = 0x4000; + public const UInt32 WS_EX_RIGHTSCROLLBAR = 0x0000; + public const UInt32 WS_EX_CONTROLPARENT = 0x10000; + public const UInt32 WS_EX_STATICEDGE = 0x20000; + public const UInt32 WS_EX_APPWINDOW = 0x40000; + public const UInt32 WS_EX_OVERLAPPEDWINDOW = (WS_EX_WINDOWEDGE | WS_EX_CLIENTEDGE); + public const UInt32 WS_EX_PALETTEWINDOW = (WS_EX_WINDOWEDGE | WS_EX_TOOLWINDOW | WS_EX_TOPMOST); + public const UInt32 WS_EX_LAYERED = 0x00080000; + public const UInt32 WS_EX_NOINHERITLAYOUT = 0x00100000; // Disable inheritence of mirroring by children + public const UInt32 WS_EX_LAYOUTRTL = 0x00400000; // Right to left mirroring + public const UInt32 WS_EX_COMPOSITED = 0x02000000; + public const UInt32 WS_EX_NOACTIVATE = 0x08000000; public const int WM_SIZE = 5; + public const int WM_SYSCOMMAND = 0x0112; + + public const int SC_MINIMIZE = 0xf020; + public const int SIZE_RESTORED = 0; public const int SIZE_MINIMIZED = 1; public const int SIZE_MAXIMIZED = 2; diff --git a/Eve-O-Preview/Presentation/ThumbnailManager.cs b/Eve-O-Preview/Presentation/ThumbnailManager.cs index b175765..b308c41 100644 --- a/Eve-O-Preview/Presentation/ThumbnailManager.cs +++ b/Eve-O-Preview/Presentation/ThumbnailManager.cs @@ -227,6 +227,7 @@ namespace EveOPreview.UI view.ThumbnailFocused = this.ThumbnailViewFocused; view.ThumbnailLostFocus = this.ThumbnailViewLostFocus; view.ThumbnailActivated = this.ThumbnailActivated; + view.ThumbnailDeactivated = this.ThumbnailDeactivated; view.RegisterHotkey(this._configuration.GetClientHotkey(processTitle)); @@ -353,6 +354,29 @@ namespace EveOPreview.UI view?.Refresh(true); } + private void ThumbnailDeactivated(IntPtr id) + { + IThumbnailView view; + this._thumbnailViews.TryGetValue(id, out view); + + + if (view?.Id == this._activeClientHandle) + { + WindowManagerNativeMethods.SendMessage(view.Id, WindowManagerNativeMethods.WM_SYSCOMMAND, WindowManagerNativeMethods.SC_MINIMIZE, 0); + } + else + { + int style = WindowManagerNativeMethods.GetWindowLong(id, WindowManagerNativeMethods.GWL_STYLE); + // If the window is not already minimized then minimize it + if ((style & WindowManagerNativeMethods.WS_MINIMIZE) != WindowManagerNativeMethods.WS_MINIMIZE) + { + WindowManagerNativeMethods.ShowWindowAsync(id, WindowManagerNativeMethods.SW_SHOWMINIMIZED); + } + } + + this.RefreshThumbnails(); + } + private void ThumbnailViewResized(IntPtr id) { if (this._ignoreViewEvents) diff --git a/Eve-O-Preview/UI/Implementation/ThumbnailView.cs b/Eve-O-Preview/UI/Implementation/ThumbnailView.cs index d8627f7..ba7d11a 100644 --- a/Eve-O-Preview/UI/Implementation/ThumbnailView.cs +++ b/Eve-O-Preview/UI/Implementation/ThumbnailView.cs @@ -101,6 +101,8 @@ namespace EveOPreview.UI public Action ThumbnailActivated { get; set; } + public Action ThumbnailDeactivated { get; set; } + public new void Show() { base.Show(); @@ -435,7 +437,14 @@ namespace EveOPreview.UI { if (e.Button == MouseButtons.Left) { - this.ThumbnailActivated?.Invoke(this.Id); + if (Control.ModifierKeys == Keys.Control) + { + this.ThumbnailDeactivated?.Invoke(this.Id); + } + else + { + this.ThumbnailActivated?.Invoke(this.Id); + } } if ((e.Button == MouseButtons.Right) || (e.Button == (MouseButtons.Left | MouseButtons.Right))) diff --git a/Eve-O-Preview/UI/Interface/IThumbnailView.cs b/Eve-O-Preview/UI/Interface/IThumbnailView.cs index 20f5b41..4dc9127 100644 --- a/Eve-O-Preview/UI/Interface/IThumbnailView.cs +++ b/Eve-O-Preview/UI/Interface/IThumbnailView.cs @@ -35,6 +35,8 @@ namespace EveOPreview.UI Action ThumbnailMoved { get; set; } Action ThumbnailFocused { get; set; } Action ThumbnailLostFocus { get; set; } + Action ThumbnailActivated { get; set; } + Action ThumbnailDeactivated { get; set; } } } \ No newline at end of file