diff --git a/SuperSize/DisplayUtils.cs b/SuperSize/DisplayUtils.cs deleted file mode 100644 index 7138e17..0000000 --- a/SuperSize/DisplayUtils.cs +++ /dev/null @@ -1,28 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Drawing; -using System.Text; -using System.Windows.Forms; - -namespace SuperSize -{ - public class DisplayUtils - { - public static Rectangle GetAllScreenBounds() - { - var top = 0; - var right = 0; - var bottom = 0; - var left = 0; - foreach (var screen in Screen.AllScreens) { - var (x, y, width, height) = screen.Bounds; - if (x < left) left = x; - if (y < top) top = y; - if (x + width > right) right = x + width; - if (y + height > bottom) bottom = y + height; - } - - return new(left, top, right - left, bottom - top); - } - } -} diff --git a/SuperSize/Forms/ConfigForm.cs b/SuperSize/Forms/ConfigForm.cs index e671373..95dea64 100644 --- a/SuperSize/Forms/ConfigForm.cs +++ b/SuperSize/Forms/ConfigForm.cs @@ -36,7 +36,7 @@ private void RenderDisplayConfiguration(Bitmap bmp) // get displays var screens = Screen.GetAllScreens(); - var screenBounds = DisplayUtils.GetAllScreenBounds(); + var screenBounds = Utilities.GetAllScreenBounds(); // calculate scaling factors var scale = Math.Min( diff --git a/SuperSize/Forms/NotifyIconForm.Designer.cs b/SuperSize/Forms/NotifyIconForm.Designer.cs index 8907463..c99f47a 100644 --- a/SuperSize/Forms/NotifyIconForm.Designer.cs +++ b/SuperSize/Forms/NotifyIconForm.Designer.cs @@ -36,16 +36,19 @@ private void InitializeComponent() this.contextMenuStrip = new System.Windows.Forms.ContextMenuStrip(this.components); this.maxActiveWindow = new System.Windows.Forms.ToolStripMenuItem(); this.maxWindowMenu = new System.Windows.Forms.ToolStripMenuItem(); + this.windowMenu = new System.Windows.Forms.ContextMenuStrip(this.components); + this.toolStripMenuItem1 = new System.Windows.Forms.ToolStripMenuItem(); this.openConfigForm = new System.Windows.Forms.ToolStripMenuItem(); this.quit = new System.Windows.Forms.ToolStripMenuItem(); s1 = new System.Windows.Forms.ToolStripSeparator(); this.contextMenuStrip.SuspendLayout(); + this.windowMenu.SuspendLayout(); this.SuspendLayout(); // // s1 // s1.Name = "s1"; - s1.Size = new System.Drawing.Size(356, 6); + s1.Size = new System.Drawing.Size(204, 6); // // notifyIcon // @@ -53,6 +56,7 @@ private void InitializeComponent() this.notifyIcon.Icon = ((System.Drawing.Icon)(resources.GetObject("notifyIcon.Icon"))); this.notifyIcon.Text = "SuperSize"; this.notifyIcon.Visible = true; + this.notifyIcon.MouseClick += new System.Windows.Forms.MouseEventHandler(this.notifyIcon_MouseClick); this.notifyIcon.MouseDoubleClick += new System.Windows.Forms.MouseEventHandler(this.notifyIcon1_MouseDoubleClick); // // contextMenuStrip @@ -65,41 +69,57 @@ private void InitializeComponent() this.openConfigForm, this.quit}); this.contextMenuStrip.Name = "contextMenuStrip"; - this.contextMenuStrip.Size = new System.Drawing.Size(360, 162); + this.contextMenuStrip.Size = new System.Drawing.Size(208, 98); this.contextMenuStrip.Opening += new System.ComponentModel.CancelEventHandler(this.contextMenuStrip_Opening); // // maxActiveWindow // this.maxActiveWindow.Name = "maxActiveWindow"; - this.maxActiveWindow.Size = new System.Drawing.Size(359, 38); + this.maxActiveWindow.Size = new System.Drawing.Size(207, 22); this.maxActiveWindow.Text = "SuperSize &Active Window"; // // maxWindowMenu // + this.maxWindowMenu.DropDown = this.windowMenu; this.maxWindowMenu.Name = "maxWindowMenu"; - this.maxWindowMenu.Size = new System.Drawing.Size(359, 38); + this.maxWindowMenu.Size = new System.Drawing.Size(207, 22); this.maxWindowMenu.Text = "SuperSize &Window"; // + // windowMenu + // + this.windowMenu.Items.AddRange(new System.Windows.Forms.ToolStripItem[] { + this.toolStripMenuItem1}); + this.windowMenu.Name = "windowMenu"; + this.windowMenu.Size = new System.Drawing.Size(427, 26); + // + // toolStripMenuItem1 + // + this.toolStripMenuItem1.Name = "toolStripMenuItem1"; + this.toolStripMenuItem1.Size = new System.Drawing.Size(426, 22); + this.toolStripMenuItem1.Text = "Hello World - This is an example item. It\'s here only to size the box."; + // // openConfigForm // this.openConfigForm.Name = "openConfigForm"; - this.openConfigForm.Size = new System.Drawing.Size(359, 38); + this.openConfigForm.Size = new System.Drawing.Size(207, 22); this.openConfigForm.Text = "&Settings..."; // // quit // this.quit.Name = "quit"; - this.quit.Size = new System.Drawing.Size(359, 38); + this.quit.Size = new System.Drawing.Size(207, 22); this.quit.Text = "&Quit"; // // NotifyIconForm // - this.AutoScaleDimensions = new System.Drawing.SizeF(13F, 32F); + this.AutoScaleDimensions = new System.Drawing.SizeF(7F, 15F); this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; - this.ClientSize = new System.Drawing.Size(800, 450); + this.ClientSize = new System.Drawing.Size(431, 211); + this.Margin = new System.Windows.Forms.Padding(2, 1, 2, 1); this.Name = "NotifyIconForm"; this.Text = "NotifyIconForm"; this.contextMenuStrip.ResumeLayout(false); + this.windowMenu.ResumeLayout(false); this.ResumeLayout(false); } @@ -112,5 +132,7 @@ private void InitializeComponent() private System.Windows.Forms.ToolStripMenuItem maxWindowMenu; private System.Windows.Forms.ToolStripMenuItem openConfigForm; private System.Windows.Forms.ToolStripMenuItem quit; + private System.Windows.Forms.ContextMenuStrip windowMenu; + private System.Windows.Forms.ToolStripMenuItem toolStripMenuItem1; } } \ No newline at end of file diff --git a/SuperSize/Forms/NotifyIconForm.cs b/SuperSize/Forms/NotifyIconForm.cs index 846bbe7..6bbca30 100644 --- a/SuperSize/Forms/NotifyIconForm.cs +++ b/SuperSize/Forms/NotifyIconForm.cs @@ -1,4 +1,5 @@ -using System; +using SuperSize.Service; +using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; @@ -15,6 +16,26 @@ public partial class NotifyIconForm : Form public NotifyIconForm() { InitializeComponent(); + PopulateWindowList(); + } + + private void PopulateWindowList() + { + // generate a window list + windowMenu.Items.Clear(); + windowMenu.Items.AddRange( + OS.Utilities.GetOpenWindows() + .Select((window) => + { + var item = new ToolStripMenuItem + { + Text = window.Title + }; + item.Click += (_, _) => Sizer.SizeWindow(window.Handle); + + return item; + }) + .ToArray()); } private void notifyIcon1_MouseDoubleClick(object sender, MouseEventArgs e) @@ -24,12 +45,28 @@ private void notifyIcon1_MouseDoubleClick(object sender, MouseEventArgs e) private void contextMenuStrip_Opening(object sender, CancelEventArgs e) { - // generate a window list - maxWindowMenu.DropDownItems.Clear(); - maxWindowMenu.DropDownItems.AddRange( - OS.Utilities.GetOpenWindows() - .Select((window) => new ToolStripDropDownButton { Text = window.Title }) - .ToArray()); + } + + private void notifyIcon_MouseClick(object sender, MouseEventArgs e) + { + switch (e.Button) + { + case MouseButtons.Left: + break; + case MouseButtons.None: + break; + case MouseButtons.Right: + //PopulateWindowList(); + break; + case MouseButtons.Middle: + break; + case MouseButtons.XButton1: + break; + case MouseButtons.XButton2: + break; + default: + break; + } } } } diff --git a/SuperSize/Forms/NotifyIconForm.resx b/SuperSize/Forms/NotifyIconForm.resx index 3575e18..7bb9b0b 100644 --- a/SuperSize/Forms/NotifyIconForm.resx +++ b/SuperSize/Forms/NotifyIconForm.resx @@ -60,7 +60,7 @@ False - + AAABAAkAAAAAAAEAIADpHQAAlgAAAICAAAABACAAKAgBAH8eAABgYAAAAQAgAKiUAACnJgEASEgAAAEA diff --git a/SuperSize/Model/KeyboardShortcut.cs b/SuperSize/Model/KeyboardShortcut.cs index c0b0331..20a168f 100644 --- a/SuperSize/Model/KeyboardShortcut.cs +++ b/SuperSize/Model/KeyboardShortcut.cs @@ -51,5 +51,15 @@ public enum ModifierKeys : uint Alt = 1, Shift = 4 } + + public static bool operator ==(KeyboardShortcut left, KeyboardShortcut right) + { + return left.Equals(right); + } + + public static bool operator !=(KeyboardShortcut left, KeyboardShortcut right) + { + return !(left == right); + } } } diff --git a/SuperSize/Model/SizingLogic.cs b/SuperSize/Model/SizingLogic.cs index 7118729..f5a40b1 100644 --- a/SuperSize/Model/SizingLogic.cs +++ b/SuperSize/Model/SizingLogic.cs @@ -9,6 +9,9 @@ namespace SuperSize.Model { public abstract class SizingLogic { + + public Rectangle Calculate() => Calculate(Screen.GetAllScreens()); + public abstract Rectangle Calculate(Screen[] screens); } } diff --git a/SuperSize/OS/NativeImports.cs b/SuperSize/OS/NativeImports.cs index 6ef39af..e48877e 100644 --- a/SuperSize/OS/NativeImports.cs +++ b/SuperSize/OS/NativeImports.cs @@ -7,7 +7,10 @@ namespace SuperSize.OS { - internal class NativeImports + /// + /// Definitions for Win32 API calls. + /// + internal static class NativeImports { [DllImport("user32.dll")] public static extern bool RegisterHotKey(IntPtr hWnd, int id, uint fsModifiers, uint vk); @@ -31,5 +34,37 @@ internal class NativeImports [DllImport("USER32.DLL")] public static extern IntPtr GetShellWindow(); + + [DllImport("user32.dll", SetLastError = true)] + public static extern bool BringWindowToTop(IntPtr hWnd); + + [DllImport("user32.dll")] + public static extern bool ShowWindowAsync(IntPtr hWnd, int nCmdShow); + + [DllImport("user32.dll")] + public static extern bool SetForegroundWindow(IntPtr hWnd); + + /// + /// Changes the size, position, and Z order of a child, pop-up, or top-level window. These windows are ordered according to their appearance on the screen. The topmost window receives the highest rank and is the first window in the Z order. + /// + /// A handle to the window. + /// A handle to the window to precede the positioned window in the Z order. This parameter must be a window handle or one of . + /// The new position of the left side of the window, in client coordinates. + /// The new position of the top of the window, in client coordinates. + /// The new width of the window, in pixels. + /// The new height of the window, in pixels. + /// The window sizing and positioning flags. This parameter can be a combination of the following values. + /// If the function succeeds, the return value is nonzero. If the function fails, the return value is zero. To get extended error information, call GetLastError. + /// + [DllImport("user32.dll")] + public static extern bool SetWindowPos(IntPtr hWnd, IntPtr hWndInsertAfter, int x, int y, int cx, int cy, uint uFlags); + + public static class HWnd + { + public static IntPtr Bottom { get; } = new IntPtr(1); + public static IntPtr NoTopMost { get; } = new IntPtr(-2); + public static IntPtr Top { get; } = new IntPtr(0); + public static IntPtr TopMost { get; } = new IntPtr(-1); + } } } diff --git a/SuperSize/OS/Utilities.cs b/SuperSize/OS/Utilities.cs index 696199c..b05471f 100644 --- a/SuperSize/OS/Utilities.cs +++ b/SuperSize/OS/Utilities.cs @@ -5,6 +5,7 @@ using System.Threading.Tasks; using System.Diagnostics; using System.Windows.Forms; +using System.Drawing; namespace SuperSize.OS { @@ -25,6 +26,9 @@ public static class Utilities var strBuilder = new StringBuilder(strLength); NativeImports.GetWindowText(hWnd, strBuilder, strLength + 1); + // ignore it if the title is empty + if (strBuilder.ToString() == string.Empty) return true; + // add to dict list.Add((hWnd, strBuilder.ToString())); return true; @@ -32,5 +36,22 @@ public static class Utilities return list; } + public static Rectangle GetAllScreenBounds() + { + var top = 0; + var right = 0; + var bottom = 0; + var left = 0; + foreach (var screen in Screen.AllScreens) + { + var (x, y, width, height) = screen.Bounds; + if (x < left) left = x; + if (y < top) top = y; + if (x + width > right) right = x + width; + if (y + height > bottom) bottom = y + height; + } + + return new(left, top, right - left, bottom - top); + } } } diff --git a/SuperSize/Properties/Settings.Designer.cs b/SuperSize/Properties/Settings.Designer.cs index 0fd1a9b..a642737 100644 --- a/SuperSize/Properties/Settings.Designer.cs +++ b/SuperSize/Properties/Settings.Designer.cs @@ -73,7 +73,7 @@ public uint ShortcutModifier { [global::System.Configuration.UserScopedSettingAttribute()] [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] - [global::System.Configuration.DefaultSettingValueAttribute("")] + [global::System.Configuration.DefaultSettingValueAttribute("Fill out completely")] public string BuiltinScript { get { return ((string)(this["BuiltinScript"])); diff --git a/SuperSize/Properties/Settings.settings b/SuperSize/Properties/Settings.settings index 8c95b26..38b4b9f 100644 --- a/SuperSize/Properties/Settings.settings +++ b/SuperSize/Properties/Settings.settings @@ -15,7 +15,7 @@ 0 - + Fill out completely 45, 125, 154 diff --git a/SuperSize/Scripts/FillOutCompletely.cs b/SuperSize/Scripts/FillOutCompletely.cs new file mode 100644 index 0000000..2dbd52e --- /dev/null +++ b/SuperSize/Scripts/FillOutCompletely.cs @@ -0,0 +1,19 @@ +using SuperSize.Model; +using SuperSize.OS; +using System; +using System.Collections.Generic; +using System.Drawing; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace SuperSize.Scripts +{ + public class FillOutCompletely : SizingLogic + { + public override Rectangle Calculate(Screen[] screens) + { + return Utilities.GetAllScreenBounds(); + } + } +} diff --git a/SuperSize/Service/PythonSizingLogic.cs b/SuperSize/Service/PythonSizingLogic.cs index d187208..07825bd 100644 --- a/SuperSize/Service/PythonSizingLogic.cs +++ b/SuperSize/Service/PythonSizingLogic.cs @@ -1,6 +1,7 @@ using IronPython.Hosting; using Microsoft.Scripting.Hosting; using SuperSize.Model; +using SuperSize.OS; using System; using System.Collections.Generic; using System.Drawing; @@ -76,7 +77,7 @@ private void PythonSetup() // screen detail { "get_screens", new Func(() => Screen.GetAllScreens()) }, - { "get_all_screen_bounds", new Func(() => DisplayUtils.GetAllScreenBounds()) }, + { "get_all_screen_bounds", new Func(() => Utilities.GetAllScreenBounds()) }, // .NET object constructors { "rectange", new Func((x, y, w, h) => new Rectangle(x, y, w, h)) }, diff --git a/SuperSize/Service/Sizer.cs b/SuperSize/Service/Sizer.cs new file mode 100644 index 0000000..5ef6a32 --- /dev/null +++ b/SuperSize/Service/Sizer.cs @@ -0,0 +1,44 @@ +using SuperSize.Model; +using SuperSize.OS; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace SuperSize.Service +{ + public static class Sizer + { + + private static Dictionary> _builtInScripts = new() + { + { "Fill out completely", () => new Scripts.FillOutCompletely() } + }; + + public static SizingLogic SelectedLogic() + { + var settings = Properties.Settings.Default; + return settings.UseCustomScript + ? PythonSizingLogic.FromSource(settings.Script) + : _builtInScripts[settings.BuiltinScript](); + } + + public static void SizeWindow(IntPtr window) => SizeWindow(window, SelectedLogic()); + + public static void SizeWindow(IntPtr window, SizingLogic logic) + { + NativeImports.SetForegroundWindow(window); + + var calculateSize = logic.Calculate(); + NativeImports.SetWindowPos( + window, + NativeImports.HWnd.Top, + calculateSize.X, + calculateSize.Y, + calculateSize.Width, + calculateSize.Height, + uFlags: 0); + } + } +} diff --git a/SuperSize/Service/Window.cs b/SuperSize/Service/Window.cs deleted file mode 100644 index e410ded..0000000 --- a/SuperSize/Service/Window.cs +++ /dev/null @@ -1,13 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; - -namespace SuperSize.Service -{ - public class Window - { - - } -}