From fbb6dfbe1a75ac0fb1d74d6744266b4401a76ca9 Mon Sep 17 00:00:00 2001 From: Steven Kirk Date: Thu, 4 Feb 2016 11:56:35 +0100 Subject: [PATCH] Added Window.WindowState. To allow minimize/maximize/restore of Window from code. --- src/Gtk/Perspex.Gtk/WindowImpl.cs | 33 ++++++++++++ src/Perspex.Controls/Perspex.Controls.csproj | 1 + src/Perspex.Controls/Platform/IWindowImpl.cs | 6 +++ .../Platform/PlatformManager.cs | 11 ++-- src/Perspex.Controls/Window.cs | 9 ++++ src/Perspex.Controls/WindowState.cs | 26 +++++++++ .../Perspex.Win32/Interop/UnmanagedMethods.cs | 53 +++++++++++++++++++ src/Windows/Perspex.Win32/WindowImpl.cs | 41 ++++++++++++++ 8 files changed, 175 insertions(+), 5 deletions(-) create mode 100644 src/Perspex.Controls/WindowState.cs diff --git a/src/Gtk/Perspex.Gtk/WindowImpl.cs b/src/Gtk/Perspex.Gtk/WindowImpl.cs index 2c732c84e0..bba8d040cf 100644 --- a/src/Gtk/Perspex.Gtk/WindowImpl.cs +++ b/src/Gtk/Perspex.Gtk/WindowImpl.cs @@ -75,6 +75,39 @@ namespace Perspex.Gtk } } + public Perspex.Controls.WindowState WindowState + { + get + { + switch (GdkWindow.State) + { + case Gdk.WindowState.Iconified: + return Controls.WindowState.Minimized; + case Gdk.WindowState.Maximized: + return Controls.WindowState.Maximized; + default: + return Controls.WindowState.Normal; + } + } + + set + { + switch (value) + { + case Controls.WindowState.Minimized: + GdkWindow.Iconify(); + break; + case Controls.WindowState.Maximized: + GdkWindow.Maximize(); + break; + case Controls.WindowState.Normal: + GdkWindow.Deiconify(); + GdkWindow.Unmaximize(); + break; + } + } + } + IPlatformHandle ITopLevelImpl.Handle => this; [DllImport("libgdk-win32-2.0-0.dll", CallingConvention = CallingConvention.Cdecl)] diff --git a/src/Perspex.Controls/Perspex.Controls.csproj b/src/Perspex.Controls/Perspex.Controls.csproj index 1c2d72190e..33619435d3 100644 --- a/src/Perspex.Controls/Perspex.Controls.csproj +++ b/src/Perspex.Controls/Perspex.Controls.csproj @@ -163,6 +163,7 @@ + diff --git a/src/Perspex.Controls/Platform/IWindowImpl.cs b/src/Perspex.Controls/Platform/IWindowImpl.cs index cb266a9153..5d85fcb707 100644 --- a/src/Perspex.Controls/Platform/IWindowImpl.cs +++ b/src/Perspex.Controls/Platform/IWindowImpl.cs @@ -2,6 +2,7 @@ // Licensed under the MIT license. See licence.md file in the project root for full license information. using System; +using Perspex.Controls; namespace Perspex.Platform { @@ -15,6 +16,11 @@ namespace Perspex.Platform /// Size MaxClientSize { get; } + /// + /// Gets or sets the minimized/maximized state of the window. + /// + WindowState WindowState { get; set; } + /// /// Sets the title of the window. /// diff --git a/src/Perspex.Controls/Platform/PlatformManager.cs b/src/Perspex.Controls/Platform/PlatformManager.cs index 6cec6cfadf..0945e6ff18 100644 --- a/src/Perspex.Controls/Platform/PlatformManager.cs +++ b/src/Perspex.Controls/Platform/PlatformManager.cs @@ -135,8 +135,6 @@ namespace Perspex.Controls.Platform public Action Paint { get; set; } public Action Resized { get; set; } - - public Action Activated { get { return _tl.Activated; } @@ -155,6 +153,12 @@ namespace Perspex.Controls.Platform set { _tl.Deactivated = value; } } + public WindowState WindowState + { + get { return _window.WindowState; } + set { _window.WindowState = value; } + } + public void Dispose() => _tl.Dispose(); public IPlatformHandle Handle => _tl.Handle; @@ -163,9 +167,6 @@ namespace Perspex.Controls.Platform public void SetCursor(IPlatformHandle cursor) => _tl.SetCursor(cursor); - - - public void SetTitle(string title) => _window.SetTitle(title); public void Show() => _tl.Show(); diff --git a/src/Perspex.Controls/Window.cs b/src/Perspex.Controls/Window.cs index 12f646f4cd..22307ab97e 100644 --- a/src/Perspex.Controls/Window.cs +++ b/src/Perspex.Controls/Window.cs @@ -133,6 +133,15 @@ namespace Perspex.Controls set { SetValue(HasSystemDecorationsProperty, value); } } + /// + /// Gets or sets the minimized/maximized state of the window. + /// + public WindowState WindowState + { + get { return this.PlatformImpl.WindowState; } + set { this.PlatformImpl.WindowState = value; } + } + /// Size ILayoutRoot.MaxClientSize => _maxPlatformClientSize; diff --git a/src/Perspex.Controls/WindowState.cs b/src/Perspex.Controls/WindowState.cs new file mode 100644 index 0000000000..f5f671c3d0 --- /dev/null +++ b/src/Perspex.Controls/WindowState.cs @@ -0,0 +1,26 @@ +// Copyright (c) The Perspex Project. All rights reserved. +// Licensed under the MIT license. See licence.md file in the project root for full license information. + +namespace Perspex.Controls +{ + /// + /// Defines the minimized/maximized state of a . + /// + public enum WindowState + { + /// + /// The window is neither minimized or maximized. + /// + Normal, + + /// + /// The window is minimized. + /// + Minimized, + + /// + /// The window is maximized. + /// + Maximized, + } +} diff --git a/src/Windows/Perspex.Win32/Interop/UnmanagedMethods.cs b/src/Windows/Perspex.Win32/Interop/UnmanagedMethods.cs index 02aefb4106..5bb2038813 100644 --- a/src/Windows/Perspex.Win32/Interop/UnmanagedMethods.cs +++ b/src/Windows/Perspex.Win32/Interop/UnmanagedMethods.cs @@ -602,6 +602,9 @@ namespace Perspex.Win32.Interop [DllImport("user32.dll", SetLastError = true)] public static extern uint SetWindowLong(IntPtr hWnd, int nIndex, uint value); + [DllImport("user32.dll", SetLastError = true)] + public static extern bool GetWindowPlacement(IntPtr hWnd, ref WINDOWPLACEMENT lpwndpl); + [DllImport("user32.dll")] public static extern bool GetWindowRect(IntPtr hwnd, out RECT lpRect); @@ -787,6 +790,56 @@ namespace Perspex.Win32.Interop public int dwHoverTime; } + [StructLayout(LayoutKind.Sequential)] + public struct WINDOWPLACEMENT + { + /// + /// The length of the structure, in bytes. Before calling the GetWindowPlacement or SetWindowPlacement functions, set this member to sizeof(WINDOWPLACEMENT). + /// + /// GetWindowPlacement and SetWindowPlacement fail if this member is not set correctly. + /// + /// + public int Length; + + /// + /// Specifies flags that control the position of the minimized window and the method by which the window is restored. + /// + public int Flags; + + /// + /// The current show state of the window. + /// + public ShowWindowCommand ShowCmd; + + /// + /// The coordinates of the window's upper-left corner when the window is minimized. + /// + public POINT MinPosition; + + /// + /// The coordinates of the window's upper-left corner when the window is maximized. + /// + public POINT MaxPosition; + + /// + /// The window's coordinates when the window is in the restored position. + /// + public RECT NormalPosition; + + /// + /// Gets the default (empty) value. + /// + public static WINDOWPLACEMENT Default + { + get + { + WINDOWPLACEMENT result = new WINDOWPLACEMENT(); + result.Length = Marshal.SizeOf(result); + return result; + } + } + } + [StructLayout(LayoutKind.Sequential)] public struct WNDCLASSEX { diff --git a/src/Windows/Perspex.Win32/WindowImpl.cs b/src/Windows/Perspex.Win32/WindowImpl.cs index c749b495ff..c786592a78 100644 --- a/src/Windows/Perspex.Win32/WindowImpl.cs +++ b/src/Windows/Perspex.Win32/WindowImpl.cs @@ -126,6 +126,47 @@ namespace Perspex.Win32 } } + public WindowState WindowState + { + get + { + var placement = default(UnmanagedMethods.WINDOWPLACEMENT); + UnmanagedMethods.GetWindowPlacement(_hwnd, ref placement); + + switch (placement.ShowCmd) + { + case UnmanagedMethods.ShowWindowCommand.Maximize: + return WindowState.Maximized; + case UnmanagedMethods.ShowWindowCommand.Minimize: + return WindowState.Minimized; + default: + return WindowState.Normal; + } + } + + set + { + UnmanagedMethods.ShowWindowCommand command; + + switch (value) + { + case WindowState.Minimized: + command = UnmanagedMethods.ShowWindowCommand.Minimize; + break; + case WindowState.Maximized: + command = UnmanagedMethods.ShowWindowCommand.Maximize; + break; + case WindowState.Normal: + command = UnmanagedMethods.ShowWindowCommand.Restore; + break; + default: + throw new ArgumentException("Invalid WindowState."); + } + + UnmanagedMethods.ShowWindow(_hwnd, command); + } + } + public void Activate() { UnmanagedMethods.SetActiveWindow(_hwnd);