diff --git a/README.md b/README.md index c486d6e..ca510a0 100644 --- a/README.md +++ b/README.md @@ -9,5 +9,9 @@ 1. 手动修复 2. 定时修复 3. 通过快捷键修复 -4. 设置游戏无边框全屏 -5. 设置游戏有边框最大化 + +## 窗口模式 +1. 无边框全屏 +2. 有边框最大化 +3. 无边框4:3窗口 +4. 自定义窗口 \ No newline at end of file diff --git a/War3FixFont.sln b/War3FixFont.sln index bf06075..73fed9f 100644 --- a/War3FixFont.sln +++ b/War3FixFont.sln @@ -1,5 +1,8 @@  Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio Version 17 +VisualStudioVersion = 17.6.33829.357 +MinimumVisualStudioVersion = 10.0.40219.1 Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "War3FixFont", "src\War3FixFont\War3FixFont.csproj", "{8C88E5B7-BFCA-4A69-AAC4-F73983255481}" EndProject Global @@ -13,4 +16,10 @@ Global {8C88E5B7-BFCA-4A69-AAC4-F73983255481}.Release|Any CPU.ActiveCfg = Release|Any CPU {8C88E5B7-BFCA-4A69-AAC4-F73983255481}.Release|Any CPU.Build.0 = Release|Any CPU EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection + GlobalSection(ExtensibilityGlobals) = postSolution + SolutionGuid = {13072089-63E4-4979-9B2B-63ABD0E4D5C4} + EndGlobalSection EndGlobal diff --git a/src/War3FixFont/FixHelper.cs b/src/War3FixFont/FixHelper.cs deleted file mode 100644 index f41ea2c..0000000 --- a/src/War3FixFont/FixHelper.cs +++ /dev/null @@ -1,200 +0,0 @@ -using System; -using System.Threading.Tasks; -using System.Windows.Forms; -using War3FixFont.WinAPI; - -namespace War3FixFont; - -public static class FixHelper -{ - /// - /// 获取魔兽3窗口句柄 - /// - /// - public static IntPtr GetWar3Window() - { - var window = API.FindWindowA("Warcraft III", "Warcraft III"); - if (window != IntPtr.Zero) - { - return window; - } - - window = API.FindWindowA("Black Warcraft III", "Warcraft III"); - if (window == IntPtr.Zero) - { - return IntPtr.Zero; - } - - var child = API.GetWindow(window, API.GW_CHILD); - return child; - } - - public static IntPtr Get5211War3Window() - { - return API.FindWindowA("Black Warcraft III", "Warcraft III"); - } - - /// - /// 设置窗口无边框 - /// - public static void Borderless() - { - var window = GetWar3Window(); - if (window == IntPtr.Zero) - { - return; - } - - var wndStyle = API.GetWindowLong(window, API.GWL_STYLE); - wndStyle &= ~(API.WS_BORDER | API.WS_THICKFRAME | API.WS_CAPTION); - API.SetWindowLong(window, API.GWL_STYLE, wndStyle); - - var exStyle = API.GetWindowLong(window, API.GWL_EXSTYLE); - exStyle &= ~(API.WS_EX_WINDOWEDGE | API.WS_EX_DLGMODALFRAME); - API.SetWindowLong(window, API.GWL_EXSTYLE, exStyle); - } - - /// - /// 设置窗口边框 - /// - public static void Border() - { - var window = GetWar3Window(); - if (window == IntPtr.Zero) - { - return; - } - - var wndStyle = API.GetWindowLong(window, API.GWL_STYLE); - wndStyle |= API.WS_BORDER | API.WS_THICKFRAME | API.WS_CAPTION; - API.SetWindowLong(window, API.GWL_STYLE, wndStyle); - - var exStyle = API.GetWindowLong(window, API.GWL_EXSTYLE); - exStyle |= API.WS_EX_WINDOWEDGE | API.WS_EX_DLGMODALFRAME; - API.SetWindowLong(window, API.GWL_EXSTYLE, exStyle); - } - - /// - /// 全屏化 - /// - public static void FullScreen() - { - var window = GetWar3Window(); - if (window == IntPtr.Zero) - { - return; - } - - var width = Screen.PrimaryScreen.Bounds.Width; - var height = Screen.PrimaryScreen.Bounds.Height; - - API.SetWindowPos(window, IntPtr.Zero, 0, 0, width, height, 0); - } - - public static void NormalWindow() - { - var window = GetWar3Window(); - if (window == IntPtr.Zero) - { - return; - } - - API.ShowWindow(window, API.SW_SHOWNORMAL); - } - - public static void MaxWindow() - { - var window = GetWar3Window(); - if (window == IntPtr.Zero) - { - return; - } - - API.ShowWindow(window, API.SW_MAXIMIZE); - } - - public static void FixCurrentWindow() - { - Task.Run( - async () => - { - var window = GetWar3Window(); - if (window == IntPtr.Zero) - { - return; - } - - if (!API.GetWindowRect(window, out var rect)) - { - return; - } - - var x = rect.Left; - var y = rect.Top; - var width = rect.Right - rect.Left; - var height = rect.Bottom - rect.Top; - - API.SetWindowPos(window, IntPtr.Zero, x, y, width + 1, height, 0); - if (!API.GetWindowRect(window, out var rect2)) - { - return; - } - - var width2 = rect2.Right - rect2.Left; - if (width != width2) - { - await Task.Delay(1000); - API.SetWindowPos(window, IntPtr.Zero, x, y, width, height, 0); - } - else - { - API.ShowWindow(window, API.SW_SHOWNORMAL); - await Task.Delay(100); - API.ShowWindow(window, API.SW_MAXIMIZE); - } - }); - } - - /// - /// 修复普通窗口 - /// - public static void FixFullScreenWindow() - { - Task.Run( - async () => - { - var window = GetWar3Window(); - if (window == IntPtr.Zero) - { - return; - } - - var width = Screen.PrimaryScreen.Bounds.Width; - var height = Screen.PrimaryScreen.Bounds.Height; - - API.SetWindowPos(window, IntPtr.Zero, 0, 0, width + 1, height, 0); - await Task.Delay(1000); - API.SetWindowPos(window, IntPtr.Zero, 0, 0, width, height, 0); - }); - } - - /// - /// 修复最大化窗口 - /// - public static void FixMaxWindow() - { - var window = GetWar3Window(); - if (window == IntPtr.Zero) - { - return; - } - - Task.Run( - async () => - { - API.ShowWindow(window, API.SW_SHOWNORMAL); - await Task.Delay(100); - API.ShowWindow(window, API.SW_MAXIMIZE); - }); - } -} \ No newline at end of file diff --git a/src/War3FixFont/Fixer.cs b/src/War3FixFont/Fixer.cs new file mode 100644 index 0000000..145a829 --- /dev/null +++ b/src/War3FixFont/Fixer.cs @@ -0,0 +1,357 @@ +using System; +using System.Collections.Generic; +using System.Threading.Tasks; +using System.Windows.Forms; +using Newtonsoft.Json; +using War3FixFont.WinAPI; + +namespace War3FixFont; + +/// +/// 修复器 +/// +[JsonObject] +public class Fixer +{ + public Settings Settings { get; set; } + + public void Fix() + { + var window = GetWar3Window(); + if (window == IntPtr.Zero) + { + return; + } + + switch (Settings.WindowMode) + { + case WindowMode.FullScreen: + { + SetBorderless(window); + FixFullScreenWindow(window); + break; + } + case WindowMode.Maximum: + { + SetBorder(window); + FixMaxWindow(window); + break; + } + case WindowMode.Ratio43: + { + SetBorderless(window); + FixRatio43(window); + break; + } + case WindowMode.Custom: + { + SetBorder(window); + FixCustomWindow(window); + break; + } + default: + break; + } + + LockCursor(); + } + + public void Apply() + { + var window = GetWar3Window(); + if (window == IntPtr.Zero) + { + return; + } + + switch (Settings.WindowMode) + { + case WindowMode.FullScreen: + { + SetBorderless(window); + SetFullScreenWindow(window); + break; + } + case WindowMode.Maximum: + { + SetBorder(window); + SetMaxWindow(window); + break; + } + case WindowMode.Ratio43: + { + SetBorderless(window); + SetRatio43(window); + break; + } + case WindowMode.Custom: + { + SetBorder(window); + SetCustomWindow(window); + break; + } + default: + break; + } + + LockCursor(); + } + + /// + /// 获取魔兽3窗口句柄 + /// + /// + public static IntPtr GetWar3Window() + { + var window = API.FindWindowA("Warcraft III", "Warcraft III"); + if (window != IntPtr.Zero) + { + return window; + } + + window = API.FindWindowA("Black Warcraft III", "Warcraft III"); + if (window == IntPtr.Zero) + { + return IntPtr.Zero; + } + + var child = API.GetWindow(window, API.GW_CHILD); + return child; + } + + private static IntPtr Get5211War3Window() + { + return API.FindWindowA("Black Warcraft III", "Warcraft III"); + } + + /// + /// 设置窗口无边框 + /// + private static void SetBorderless(IntPtr window) + { + var wndStyle = API.GetWindowLong(window, API.GWL_STYLE); + wndStyle &= ~(API.WS_BORDER | API.WS_THICKFRAME | API.WS_CAPTION); + API.SetWindowLong(window, API.GWL_STYLE, wndStyle); + + var exStyle = API.GetWindowLong(window, API.GWL_EXSTYLE); + exStyle &= ~(API.WS_EX_WINDOWEDGE | API.WS_EX_DLGMODALFRAME); + API.SetWindowLong(window, API.GWL_EXSTYLE, exStyle); + } + + /// + /// 设置窗口边框 + /// + private void SetBorder(IntPtr window) + { + var wndStyle = API.GetWindowLong(window, API.GWL_STYLE); + wndStyle |= API.WS_BORDER | API.WS_THICKFRAME | API.WS_CAPTION; + API.SetWindowLong(window, API.GWL_STYLE, wndStyle); + + var exStyle = API.GetWindowLong(window, API.GWL_EXSTYLE); + exStyle |= API.WS_EX_WINDOWEDGE | API.WS_EX_DLGMODALFRAME; + API.SetWindowLong(window, API.GWL_EXSTYLE, exStyle); + } + + /// + /// 应用全屏窗口 + /// + private void SetFullScreenWindow(IntPtr window) + { + var width = Screen.PrimaryScreen.Bounds.Width; + var height = Screen.PrimaryScreen.Bounds.Height; + + API.SetWindowPos(window, IntPtr.Zero, 0, 0, width, height, 0); + } + + /// + /// 修复全屏窗口 + /// + private void FixFullScreenWindow(IntPtr window) + { + if (window == IntPtr.Zero) + { + return; + } + + Task.Run( + async () => + { + var width = Screen.PrimaryScreen.Bounds.Width; + var height = Screen.PrimaryScreen.Bounds.Height; + + API.SetWindowPos(window, IntPtr.Zero, 0, 0, width + 1, height, 0); + await Task.Delay(1000); + API.SetWindowPos(window, IntPtr.Zero, 0, 0, width, height, 0); + }); + } + + /// + /// 应用自定义窗口 + /// + private void SetCustomWindow(IntPtr window) + { + var width = Settings.Width; + var height = Settings.Height; + int x; + int y; + if (Settings.UseCustomPosition) + { + x = Settings.X; + y = Settings.Y; + } + else + { + x = Screen.PrimaryScreen.Bounds.Width / 2 - width / 2; + y = Screen.PrimaryScreen.Bounds.Height / 2 - height / 2; + } + + var border = API.GetBorder(); + API.ShowWindow(window, API.SW_SHOWNORMAL); + API.SetWindowPos(window, IntPtr.Zero, x - border, y, width, height, 0); + } + + /// + /// 修复自定义窗口 + /// + private void FixCustomWindow(IntPtr window) + { + if (window == IntPtr.Zero) + { + return; + } + + Task.Run( + async () => + { + var width = Settings.Width; + var height = Settings.Height; + int x; + int y; + if (Settings.UseCustomPosition) + { + x = Settings.X; + y = Settings.Y; + } + else + { + x = Screen.PrimaryScreen.Bounds.Width / 2 - width / 2; + y = Screen.PrimaryScreen.Bounds.Height / 2 - height / 2; + } + + var border = API.GetBorder(); + API.SetWindowPos(window, IntPtr.Zero, x - border, y, width + 1, height, 0); + await Task.Delay(1000); + API.SetWindowPos(window, IntPtr.Zero, x - border, y, width, height, 0); + }); + } + + /// + /// 应用最大化窗口 + /// + private void SetMaxWindow(IntPtr window) + { + API.ShowWindow(window, API.SW_MAXIMIZE); + } + + /// + /// 修复最大化窗口 + /// + private void FixMaxWindow(IntPtr window) + { + Task.Run( + async () => + { + API.ShowWindow(window, API.SW_SHOWNORMAL); + await Task.Delay(100); + API.ShowWindow(window, API.SW_MAXIMIZE); + }); + } + + /// + /// 应用4:3窗口 + /// + /// + private void SetRatio43(IntPtr window) + { + API.SystemParametersInfo(API.SPI_GETWORKAREA, 0, out var rect, 0); + var width = rect.Right; + var height = rect.Bottom; + width = Math.Min(height / 3 * 4, width); + + var x = Screen.PrimaryScreen.Bounds.Width / 2 - width / 2; + API.ShowWindow(window, API.SW_SHOWNORMAL); + API.SetWindowPos(window, IntPtr.Zero, x, 0, width, height, 0); + } + + /// + /// 修复4:3窗口 + /// + /// + private void FixRatio43(IntPtr window) + { + API.SystemParametersInfo(API.SPI_GETWORKAREA, 0, out var rect, 0); + var width = rect.Right; + var height = rect.Bottom; + width = Math.Min(height / 3 * 4, width); + + var x = Screen.PrimaryScreen.Bounds.Width / 2 - width / 2; + API.ShowWindow(window, API.SW_SHOWNORMAL); + Task.Run( + async () => + { + API.SetWindowPos(window, IntPtr.Zero, x, 0, width + 1, height, 0); + await Task.Delay(1000); + API.SetWindowPos(window, IntPtr.Zero, x, 0, width, height, 0); + }); + } + + /// + /// 锁定鼠标范围 + /// + public void LockCursor() + { + if (!Settings.LockCursor) + { + return; + } + + var war3Window = GetWar3Window(); + if (war3Window == IntPtr.Zero) + { + return; + } + + var handle = API.GetForegroundWindow(); + if (handle != war3Window) + { + // 11对战平台的窗口是嵌套的 + var war35211 = Get5211War3Window(); + if (handle == war35211 && handle != IntPtr.Zero) + { + handle = API.GetWindow(handle, API.GW_CHILD); + } + } + + if (handle == war3Window) + { + API.GetWindowRect(war3Window, out var windowRect); + if (windowRect.Top == -32000) + { + // 窗口已最小化 + return; + } + + if (Settings.WindowMode is WindowMode.Maximum or WindowMode.Custom) + { + var height = API.GetTitleBarHeight(); + var border = API.GetBorder(); + var rect = new Rect { Top = windowRect.Top + height, Bottom = windowRect.Bottom - border, Left = windowRect.Left + border, Right = windowRect.Right - border }; + API.ClipCursor(ref rect); + } + else + { + API.ClipCursor(ref windowRect); + } + } + } +} \ No newline at end of file diff --git a/src/War3FixFont/HotKey.cs b/src/War3FixFont/HotKey.cs index 485787c..cbde025 100644 --- a/src/War3FixFont/HotKey.cs +++ b/src/War3FixFont/HotKey.cs @@ -176,6 +176,36 @@ public override bool Equals(object obj) return false; } - return h!.Modifier == Modifier && h.KeyCode == KeyCode; + return Equals(h); + } + + protected bool Equals(HotKey other) + { + return KeyCode == other.KeyCode + && Control == other.Control + && Alt == other.Alt + && Shift == other.Shift; + } + + public override int GetHashCode() + { + unchecked + { + var hashCode = (int)KeyCode; + hashCode = (hashCode * 397) ^ Control.GetHashCode(); + hashCode = (hashCode * 397) ^ Alt.GetHashCode(); + hashCode = (hashCode * 397) ^ Shift.GetHashCode(); + return hashCode; + } + } + + public static bool operator ==(HotKey key1, HotKey key2) + { + return key1 != null && key2 != null && key1.Equals(key2); + } + + public static bool operator !=(HotKey key1, HotKey key2) + { + return !(key1 == key2); } } \ No newline at end of file diff --git a/src/War3FixFont/Main.Designer.cs b/src/War3FixFont/Main.Designer.cs index d1da45e..c11c17b 100644 --- a/src/War3FixFont/Main.Designer.cs +++ b/src/War3FixFont/Main.Designer.cs @@ -37,8 +37,6 @@ private void InitializeComponent() this.EnableHotKeyCheckBox = new System.Windows.Forms.CheckBox(); this.label1 = new System.Windows.Forms.Label(); this.LinkLabel = new System.Windows.Forms.LinkLabel(); - this.BorderMaxWindowButton = new System.Windows.Forms.Button(); - this.FullScreenButton = new System.Windows.Forms.Button(); this.VersionLabel = new System.Windows.Forms.Label(); this.EnableTimerFixCheckBox = new System.Windows.Forms.CheckBox(); this.IntervalInput = new System.Windows.Forms.NumericUpDown(); @@ -48,15 +46,25 @@ private void InitializeComponent() this.PanelMenu = new System.Windows.Forms.ContextMenuStrip(this.components); this.ShowWindowMenuItem = new System.Windows.Forms.ToolStripMenuItem(); this.ExitAppMenuItem = new System.Windows.Forms.ToolStripMenuItem(); - this.WindowModeSelect = new System.Windows.Forms.ComboBox(); - this.WindowModeLabel = new System.Windows.Forms.Label(); - this.AutoWindowCheckBox = new System.Windows.Forms.CheckBox(); + this.AutoApplyCheckBox = new System.Windows.Forms.CheckBox(); this.LockCursorCheckBox = new System.Windows.Forms.CheckBox(); - this.HotKeyInputBox = new War3FixFont.HotKeyInputBox(); - this.ShowMeHotKeyInputBox = new War3FixFont.HotKeyInputBox(); this.label3 = new System.Windows.Forms.Label(); + this.WidthInput = new System.Windows.Forms.NumericUpDown(); + this.HeightInput = new System.Windows.Forms.NumericUpDown(); + this.CustomPositionY = new System.Windows.Forms.NumericUpDown(); + this.CustomPositionX = new System.Windows.Forms.NumericUpDown(); + this.CustomPositionCheckBox = new System.Windows.Forms.CheckBox(); + this.WindowModeComboBox = new System.Windows.Forms.ComboBox(); + this.label4 = new System.Windows.Forms.Label(); + this.CustomSizeLabel = new System.Windows.Forms.Label(); + this.ShowMeHotKeyInputBox = new War3FixFont.HotKeyInputBox(); + this.HotKeyInputBox = new War3FixFont.HotKeyInputBox(); ((System.ComponentModel.ISupportInitialize)(this.IntervalInput)).BeginInit(); this.PanelMenu.SuspendLayout(); + ((System.ComponentModel.ISupportInitialize)(this.WidthInput)).BeginInit(); + ((System.ComponentModel.ISupportInitialize)(this.HeightInput)).BeginInit(); + ((System.ComponentModel.ISupportInitialize)(this.CustomPositionY)).BeginInit(); + ((System.ComponentModel.ISupportInitialize)(this.CustomPositionX)).BeginInit(); this.SuspendLayout(); // // FixButton @@ -75,7 +83,7 @@ private void InitializeComponent() this.EnableHotKeyCheckBox.AutoSize = true; this.EnableHotKeyCheckBox.Checked = true; this.EnableHotKeyCheckBox.CheckState = System.Windows.Forms.CheckState.Checked; - this.EnableHotKeyCheckBox.Location = new System.Drawing.Point(12, 108); + this.EnableHotKeyCheckBox.Location = new System.Drawing.Point(14, 185); this.EnableHotKeyCheckBox.Margin = new System.Windows.Forms.Padding(3, 2, 3, 2); this.EnableHotKeyCheckBox.Name = "EnableHotKeyCheckBox"; this.EnableHotKeyCheckBox.Size = new System.Drawing.Size(84, 16); @@ -88,7 +96,7 @@ private void InitializeComponent() // this.label1.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Left))); this.label1.AutoSize = true; - this.label1.Location = new System.Drawing.Point(10, 218); + this.label1.Location = new System.Drawing.Point(10, 315); this.label1.Name = "label1"; this.label1.Size = new System.Drawing.Size(77, 12); this.label1.TabIndex = 2; @@ -98,7 +106,7 @@ private void InitializeComponent() // this.LinkLabel.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Left))); this.LinkLabel.AutoSize = true; - this.LinkLabel.Location = new System.Drawing.Point(10, 238); + this.LinkLabel.Location = new System.Drawing.Point(10, 335); this.LinkLabel.Name = "LinkLabel"; this.LinkLabel.Size = new System.Drawing.Size(227, 12); this.LinkLabel.TabIndex = 3; @@ -106,34 +114,10 @@ private void InitializeComponent() this.LinkLabel.Text = "https://github.com/Zonciu/War3FixFont"; this.LinkLabel.LinkClicked += new System.Windows.Forms.LinkLabelLinkClickedEventHandler(this.LinkLabel_LinkClicked); // - // BorderMaxWindowButton - // - this.BorderMaxWindowButton.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Right))); - this.BorderMaxWindowButton.Location = new System.Drawing.Point(281, 39); - this.BorderMaxWindowButton.Margin = new System.Windows.Forms.Padding(3, 2, 3, 2); - this.BorderMaxWindowButton.Name = "BorderMaxWindowButton"; - this.BorderMaxWindowButton.Size = new System.Drawing.Size(75, 23); - this.BorderMaxWindowButton.TabIndex = 4; - this.BorderMaxWindowButton.Text = "有边框全屏"; - this.BorderMaxWindowButton.UseVisualStyleBackColor = true; - this.BorderMaxWindowButton.Click += new System.EventHandler(this.BorderMaxWindowButton_Click); - // - // FullScreenButton - // - this.FullScreenButton.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Right))); - this.FullScreenButton.Location = new System.Drawing.Point(281, 12); - this.FullScreenButton.Margin = new System.Windows.Forms.Padding(3, 2, 3, 2); - this.FullScreenButton.Name = "FullScreenButton"; - this.FullScreenButton.Size = new System.Drawing.Size(75, 23); - this.FullScreenButton.TabIndex = 5; - this.FullScreenButton.Text = "无边框全屏"; - this.FullScreenButton.UseVisualStyleBackColor = true; - this.FullScreenButton.Click += new System.EventHandler(this.FullScreenButton_Click); - // // VersionLabel // this.VersionLabel.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Right))); - this.VersionLabel.Location = new System.Drawing.Point(281, 238); + this.VersionLabel.Location = new System.Drawing.Point(281, 335); this.VersionLabel.Name = "VersionLabel"; this.VersionLabel.Size = new System.Drawing.Size(75, 12); this.VersionLabel.TabIndex = 11; @@ -143,7 +127,7 @@ private void InitializeComponent() // EnableTimerFixCheckBox // this.EnableTimerFixCheckBox.AutoSize = true; - this.EnableTimerFixCheckBox.Location = new System.Drawing.Point(12, 52); + this.EnableTimerFixCheckBox.Location = new System.Drawing.Point(14, 49); this.EnableTimerFixCheckBox.Margin = new System.Windows.Forms.Padding(3, 2, 3, 2); this.EnableTimerFixCheckBox.Name = "EnableTimerFixCheckBox"; this.EnableTimerFixCheckBox.Size = new System.Drawing.Size(72, 16); @@ -154,7 +138,7 @@ private void InitializeComponent() // // IntervalInput // - this.IntervalInput.Location = new System.Drawing.Point(93, 50); + this.IntervalInput.Location = new System.Drawing.Point(93, 47); this.IntervalInput.Margin = new System.Windows.Forms.Padding(0); this.IntervalInput.Name = "IntervalInput"; this.IntervalInput.Size = new System.Drawing.Size(54, 21); @@ -169,7 +153,7 @@ private void InitializeComponent() // label2 // this.label2.AutoSize = true; - this.label2.Location = new System.Drawing.Point(154, 54); + this.label2.Location = new System.Drawing.Point(154, 51); this.label2.Margin = new System.Windows.Forms.Padding(0); this.label2.Name = "label2"; this.label2.Size = new System.Drawing.Size(17, 12); @@ -179,7 +163,7 @@ private void InitializeComponent() // ManualButton // this.ManualButton.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Right))); - this.ManualButton.Location = new System.Drawing.Point(281, 207); + this.ManualButton.Location = new System.Drawing.Point(281, 304); this.ManualButton.Name = "ManualButton"; this.ManualButton.Size = new System.Drawing.Size(75, 23); this.ManualButton.TabIndex = 19; @@ -217,39 +201,21 @@ private void InitializeComponent() this.ExitAppMenuItem.Text = "退出"; this.ExitAppMenuItem.Click += new System.EventHandler(this.ExitApplication); // - // WindowModeSelect - // - this.WindowModeSelect.FormattingEnabled = true; - this.WindowModeSelect.Location = new System.Drawing.Point(69, 78); - this.WindowModeSelect.Name = "WindowModeSelect"; - this.WindowModeSelect.Size = new System.Drawing.Size(121, 20); - this.WindowModeSelect.TabIndex = 20; - this.WindowModeSelect.SelectionChangeCommitted += new System.EventHandler(this.WindowModeSelect_SelectionChangeCommitted); - // - // WindowModeLabel - // - this.WindowModeLabel.AutoSize = true; - this.WindowModeLabel.Location = new System.Drawing.Point(12, 82); - this.WindowModeLabel.Name = "WindowModeLabel"; - this.WindowModeLabel.Size = new System.Drawing.Size(53, 12); - this.WindowModeLabel.TabIndex = 21; - this.WindowModeLabel.Text = "窗口模式"; - // - // AutoWindowCheckBox + // AutoApplyCheckBox // - this.AutoWindowCheckBox.AutoSize = true; - this.AutoWindowCheckBox.Location = new System.Drawing.Point(196, 80); - this.AutoWindowCheckBox.Name = "AutoWindowCheckBox"; - this.AutoWindowCheckBox.Size = new System.Drawing.Size(96, 16); - this.AutoWindowCheckBox.TabIndex = 22; - this.AutoWindowCheckBox.Text = "自动设置窗口"; - this.AutoWindowCheckBox.UseVisualStyleBackColor = true; - this.AutoWindowCheckBox.CheckedChanged += new System.EventHandler(this.AutoWindowCheckBox_CheckedChanged); + this.AutoApplyCheckBox.AutoSize = true; + this.AutoApplyCheckBox.Location = new System.Drawing.Point(193, 49); + this.AutoApplyCheckBox.Name = "AutoApplyCheckBox"; + this.AutoApplyCheckBox.Size = new System.Drawing.Size(96, 16); + this.AutoApplyCheckBox.TabIndex = 22; + this.AutoApplyCheckBox.Text = "自动设置窗口"; + this.AutoApplyCheckBox.UseVisualStyleBackColor = true; + this.AutoApplyCheckBox.CheckedChanged += new System.EventHandler(this.AutoWindowCheckBox_CheckedChanged); // // LockCursorCheckBox // this.LockCursorCheckBox.AutoSize = true; - this.LockCursorCheckBox.Location = new System.Drawing.Point(12, 138); + this.LockCursorCheckBox.Location = new System.Drawing.Point(14, 220); this.LockCursorCheckBox.Name = "LockCursorCheckBox"; this.LockCursorCheckBox.Size = new System.Drawing.Size(96, 16); this.LockCursorCheckBox.TabIndex = 23; @@ -257,27 +223,128 @@ private void InitializeComponent() this.LockCursorCheckBox.UseVisualStyleBackColor = true; this.LockCursorCheckBox.CheckedChanged += new System.EventHandler(this.LockCursorCheckBox_CheckedChanged); // - // HotKeyInputBox + // label3 // - this.HotKeyInputBox.Alt = false; - this.HotKeyInputBox.BackColor = System.Drawing.SystemColors.Window; - this.HotKeyInputBox.Control = false; - this.HotKeyInputBox.KeyCode = System.Windows.Forms.Keys.None; - this.HotKeyInputBox.Location = new System.Drawing.Point(102, 106); - this.HotKeyInputBox.Name = "HotKeyInputBox"; - this.HotKeyInputBox.Shift = false; - this.HotKeyInputBox.ShortcutsEnabled = false; - this.HotKeyInputBox.Size = new System.Drawing.Size(153, 21); - this.HotKeyInputBox.TabIndex = 12; - this.HotKeyInputBox.WordWrap = false; - this.HotKeyInputBox.HotKeyChanged += new System.EventHandler(this.HotKeyInputBox_HotKeyChanged); + this.label3.AutoSize = true; + this.label3.Location = new System.Drawing.Point(14, 255); + this.label3.Name = "label3"; + this.label3.Size = new System.Drawing.Size(65, 12); + this.label3.TabIndex = 25; + this.label3.Text = "显示本窗口"; + // + // WidthInput + // + this.WidthInput.Location = new System.Drawing.Point(112, 113); + this.WidthInput.Margin = new System.Windows.Forms.Padding(0); + this.WidthInput.Maximum = new decimal(new int[] { + 2147483647, + 0, + 0, + 0}); + this.WidthInput.Name = "WidthInput"; + this.WidthInput.Size = new System.Drawing.Size(54, 21); + this.WidthInput.TabIndex = 27; + this.WidthInput.Value = new decimal(new int[] { + 1920, + 0, + 0, + 0}); + this.WidthInput.ValueChanged += new System.EventHandler(this.WidthInput_ValueChanged); + // + // HeightInput + // + this.HeightInput.Location = new System.Drawing.Point(175, 113); + this.HeightInput.Margin = new System.Windows.Forms.Padding(0); + this.HeightInput.Maximum = new decimal(new int[] { + 2147483647, + 0, + 0, + 0}); + this.HeightInput.Name = "HeightInput"; + this.HeightInput.Size = new System.Drawing.Size(54, 21); + this.HeightInput.TabIndex = 28; + this.HeightInput.Value = new decimal(new int[] { + 1080, + 0, + 0, + 0}); + this.HeightInput.ValueChanged += new System.EventHandler(this.HeightInput_ValueChanged); + // + // CustomPositionY + // + this.CustomPositionY.Location = new System.Drawing.Point(175, 148); + this.CustomPositionY.Margin = new System.Windows.Forms.Padding(0); + this.CustomPositionY.Maximum = new decimal(new int[] { + 2147483647, + 0, + 0, + 0}); + this.CustomPositionY.Name = "CustomPositionY"; + this.CustomPositionY.Size = new System.Drawing.Size(54, 21); + this.CustomPositionY.TabIndex = 32; + this.CustomPositionY.ValueChanged += new System.EventHandler(this.CustomPositionY_ValueChanged); + // + // CustomPositionX + // + this.CustomPositionX.Location = new System.Drawing.Point(112, 148); + this.CustomPositionX.Margin = new System.Windows.Forms.Padding(0); + this.CustomPositionX.Maximum = new decimal(new int[] { + 2147483647, + 0, + 0, + 0}); + this.CustomPositionX.Name = "CustomPositionX"; + this.CustomPositionX.Size = new System.Drawing.Size(54, 21); + this.CustomPositionX.TabIndex = 31; + this.CustomPositionX.ValueChanged += new System.EventHandler(this.CustomPositionX_ValueChanged); + // + // CustomPositionCheckBox + // + this.CustomPositionCheckBox.AutoSize = true; + this.CustomPositionCheckBox.Checked = true; + this.CustomPositionCheckBox.CheckState = System.Windows.Forms.CheckState.Checked; + this.CustomPositionCheckBox.Location = new System.Drawing.Point(14, 150); + this.CustomPositionCheckBox.Margin = new System.Windows.Forms.Padding(3, 2, 3, 2); + this.CustomPositionCheckBox.Name = "CustomPositionCheckBox"; + this.CustomPositionCheckBox.Size = new System.Drawing.Size(84, 16); + this.CustomPositionCheckBox.TabIndex = 33; + this.CustomPositionCheckBox.Text = "自定义位置"; + this.CustomPositionCheckBox.UseVisualStyleBackColor = true; + this.CustomPositionCheckBox.CheckedChanged += new System.EventHandler(this.CustomPositionCheckBox_CheckedChanged); + // + // WindowModeComboBox + // + this.WindowModeComboBox.FormattingEnabled = true; + this.WindowModeComboBox.Location = new System.Drawing.Point(112, 80); + this.WindowModeComboBox.Name = "WindowModeComboBox"; + this.WindowModeComboBox.Size = new System.Drawing.Size(121, 20); + this.WindowModeComboBox.TabIndex = 37; + this.WindowModeComboBox.SelectedIndexChanged += new System.EventHandler(this.WindowModeComboBox_SelectedIndexChanged); + // + // label4 + // + this.label4.AutoSize = true; + this.label4.Location = new System.Drawing.Point(12, 84); + this.label4.Name = "label4"; + this.label4.Size = new System.Drawing.Size(53, 12); + this.label4.TabIndex = 38; + this.label4.Text = "窗口模式"; + // + // CustomSizeLabel + // + this.CustomSizeLabel.AutoSize = true; + this.CustomSizeLabel.Location = new System.Drawing.Point(12, 117); + this.CustomSizeLabel.Name = "CustomSizeLabel"; + this.CustomSizeLabel.Size = new System.Drawing.Size(65, 12); + this.CustomSizeLabel.TabIndex = 39; + this.CustomSizeLabel.Text = "自定义大小"; // // ShowMeHotKeyInputBox // this.ShowMeHotKeyInputBox.Alt = false; this.ShowMeHotKeyInputBox.Control = false; this.ShowMeHotKeyInputBox.KeyCode = System.Windows.Forms.Keys.None; - this.ShowMeHotKeyInputBox.Location = new System.Drawing.Point(83, 164); + this.ShowMeHotKeyInputBox.Location = new System.Drawing.Point(112, 251); this.ShowMeHotKeyInputBox.Name = "ShowMeHotKeyInputBox"; this.ShowMeHotKeyInputBox.Shift = false; this.ShowMeHotKeyInputBox.ShortcutsEnabled = false; @@ -286,34 +353,44 @@ private void InitializeComponent() this.ShowMeHotKeyInputBox.WordWrap = false; this.ShowMeHotKeyInputBox.HotKeyChanged += new System.EventHandler(this.ShowMeHotKeyInputBox_HotKeyChanged); // - // label3 + // HotKeyInputBox // - this.label3.AutoSize = true; - this.label3.Location = new System.Drawing.Point(12, 168); - this.label3.Name = "label3"; - this.label3.Size = new System.Drawing.Size(65, 12); - this.label3.TabIndex = 25; - this.label3.Text = "显示本窗口"; + this.HotKeyInputBox.Alt = false; + this.HotKeyInputBox.BackColor = System.Drawing.SystemColors.Window; + this.HotKeyInputBox.Control = false; + this.HotKeyInputBox.KeyCode = System.Windows.Forms.Keys.None; + this.HotKeyInputBox.Location = new System.Drawing.Point(112, 183); + this.HotKeyInputBox.Name = "HotKeyInputBox"; + this.HotKeyInputBox.Shift = false; + this.HotKeyInputBox.ShortcutsEnabled = false; + this.HotKeyInputBox.Size = new System.Drawing.Size(153, 21); + this.HotKeyInputBox.TabIndex = 12; + this.HotKeyInputBox.WordWrap = false; + this.HotKeyInputBox.HotKeyChanged += new System.EventHandler(this.HotKeyInputBox_HotKeyChanged); // // Main // this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 12F); this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; - this.ClientSize = new System.Drawing.Size(368, 259); + this.ClientSize = new System.Drawing.Size(368, 356); + this.Controls.Add(this.CustomSizeLabel); + this.Controls.Add(this.label4); + this.Controls.Add(this.WindowModeComboBox); + this.Controls.Add(this.CustomPositionCheckBox); + this.Controls.Add(this.CustomPositionY); + this.Controls.Add(this.CustomPositionX); + this.Controls.Add(this.HeightInput); + this.Controls.Add(this.WidthInput); this.Controls.Add(this.label3); this.Controls.Add(this.ShowMeHotKeyInputBox); this.Controls.Add(this.LockCursorCheckBox); - this.Controls.Add(this.AutoWindowCheckBox); - this.Controls.Add(this.WindowModeLabel); - this.Controls.Add(this.WindowModeSelect); + this.Controls.Add(this.AutoApplyCheckBox); this.Controls.Add(this.ManualButton); this.Controls.Add(this.EnableTimerFixCheckBox); this.Controls.Add(this.IntervalInput); this.Controls.Add(this.label2); this.Controls.Add(this.HotKeyInputBox); this.Controls.Add(this.VersionLabel); - this.Controls.Add(this.FullScreenButton); - this.Controls.Add(this.BorderMaxWindowButton); this.Controls.Add(this.LinkLabel); this.Controls.Add(this.label1); this.Controls.Add(this.EnableHotKeyCheckBox); @@ -325,6 +402,10 @@ private void InitializeComponent() this.SizeChanged += new System.EventHandler(this.Main_SizeChanged); ((System.ComponentModel.ISupportInitialize)(this.IntervalInput)).EndInit(); this.PanelMenu.ResumeLayout(false); + ((System.ComponentModel.ISupportInitialize)(this.WidthInput)).EndInit(); + ((System.ComponentModel.ISupportInitialize)(this.HeightInput)).EndInit(); + ((System.ComponentModel.ISupportInitialize)(this.CustomPositionY)).EndInit(); + ((System.ComponentModel.ISupportInitialize)(this.CustomPositionX)).EndInit(); this.ResumeLayout(false); this.PerformLayout(); @@ -338,8 +419,6 @@ private void InitializeComponent() private Button FixButton; private Label label1; private LinkLabel LinkLabel; - private Button BorderMaxWindowButton; - private Button FullScreenButton; private Label VersionLabel; private CheckBox EnableTimerFixCheckBox; private NumericUpDown IntervalInput; @@ -349,10 +428,16 @@ private void InitializeComponent() private ContextMenuStrip PanelMenu; private ToolStripMenuItem ShowWindowMenuItem; private ToolStripMenuItem ExitAppMenuItem; - private ComboBox WindowModeSelect; - private Label WindowModeLabel; - private CheckBox AutoWindowCheckBox; + private CheckBox AutoApplyCheckBox; private CheckBox LockCursorCheckBox; private HotKeyInputBox ShowMeHotKeyInputBox; private Label label3; + private NumericUpDown WidthInput; + private NumericUpDown HeightInput; + private NumericUpDown CustomPositionY; + private NumericUpDown CustomPositionX; + private CheckBox CustomPositionCheckBox; + private ComboBox WindowModeComboBox; + private Label label4; + private Label CustomSizeLabel; } \ No newline at end of file diff --git a/src/War3FixFont/Main.cs b/src/War3FixFont/Main.cs index 6e010ab..e190c67 100644 --- a/src/War3FixFont/Main.cs +++ b/src/War3FixFont/Main.cs @@ -52,8 +52,6 @@ public partial class Main : Form /// private readonly Timer _war3RunningMonitor = new(); - private bool _isSetAutoWindow; - private const int FixHotKeyId = 1; private int _fixHotKeyId; @@ -66,9 +64,14 @@ public partial class Main : Form public Settings Settings => SettingsManager.Settings; + public readonly Fixer Fixer; + + private readonly bool _inited; + public Main() { SettingsManager.Load(); + Fixer = new() { Settings = SettingsManager.Settings }; _fixThresholdTicks = Settings.FixThreshold * 1000 * 10000; InitializeComponent(); @@ -84,8 +87,8 @@ public Main() EnableTimerFixCheckBox.Checked = Settings.UseTimer; // 读取窗口配置 - WindowModeSelect.DisplayMember = "Name"; - WindowModeSelect.ValueMember = "Value"; + WindowModeComboBox.DisplayMember = "Name"; + WindowModeComboBox.ValueMember = "Value"; var windowModeSource = Enum.GetValues(typeof(WindowMode)) .Cast() .Select( @@ -96,8 +99,11 @@ public Main() }) .OrderBy(item => item.Value) .ToList(); - WindowModeSelect.DataSource = windowModeSource; - WindowModeSelect.SelectedItem = windowModeSource.Single(e => e.Value == Settings.WindowMode); + WindowModeComboBox.SelectedIndexChanged -= WindowModeComboBox_SelectedIndexChanged; + WindowModeComboBox.DataSource = windowModeSource; + var mode = windowModeSource.Single(e => e.Value == Settings.WindowMode); + WindowModeComboBox.SelectedItem = mode; + WindowModeComboBox.SelectedIndexChanged += WindowModeComboBox_SelectedIndexChanged; // 读取修复快捷键配置 var hotKey = Settings.HotKey; @@ -109,7 +115,6 @@ public Main() { Settings.HotKey = HotKey.DefaultFixHotKey; HotKeyInputBox.HotKey = Settings.HotKey; - SettingsManager.Save(); } HotKeyInputBox.HotKeyEditing += (_, _) => @@ -123,6 +128,17 @@ public Main() EnableHotKeyCheckBox.Checked = Settings.UseHotKey; UpdateFixHotKey(); + // 读取窗口模式 + var useCustomMode = Settings.WindowMode == WindowMode.Custom; + WidthInput.Enabled = useCustomMode; + WidthInput.Value = Settings.Width; + HeightInput.Enabled = useCustomMode; + HeightInput.Value = Settings.Height; + CustomPositionCheckBox.Enabled = useCustomMode; + CustomPositionCheckBox.Checked = Settings.UseCustomPosition; + CustomPositionX.Enabled = useCustomMode && CustomPositionCheckBox.Checked; + CustomPositionY.Enabled = useCustomMode && CustomPositionCheckBox.Checked; + // 读取显示窗口快捷键配置 if (Settings.ShowMeHotKey.IsValid) { @@ -132,7 +148,6 @@ public Main() { Settings.ShowMeHotKey = HotKey.DefaultShowMeHotKey; ShowMeHotKeyInputBox.HotKey = Settings.ShowMeHotKey; - SettingsManager.Save(); } ShowMeHotKeyInputBox.HotKeyEditing += (_, _) => @@ -153,13 +168,16 @@ public Main() } // 扫描魔兽3进程 - AutoWindowCheckBox.Checked = Settings.UseAutoWindow; + AutoApplyCheckBox.Checked = Settings.AutoApplyWindow; _war3RunningMonitor.Interval = 2000; _war3RunningMonitor.Elapsed += CheckWar3Process; - if (Settings.UseAutoWindow) + if (Settings.AutoApplyWindow) { _war3RunningMonitor.Start(); } + + SettingsManager.Save(); + _inited = true; } /// @@ -258,22 +276,7 @@ private void FixFont(bool resetTimer) if (nowTicks - _lastFixTicks >= _fixThresholdTicks) { _lastFixTicks = nowTicks; - - switch (Settings.WindowMode) - { - case WindowMode.KeepCurrent: - FixHelper.FixCurrentWindow(); - break; - case WindowMode.MaxWindows: - FixHelper.Border(); - FixHelper.FixMaxWindow(); - break; - case WindowMode.FullScreenWindow: - default: - FixHelper.Borderless(); - FixHelper.FixFullScreenWindow(); - break; - } + Fixer.Fix(); } } catch (Exception e) @@ -332,29 +335,6 @@ private void LinkLabel_LinkClicked(object sender, LinkLabelLinkClickedEventArgs Process.Start(ps); } - /// - /// 有边框全屏 - /// - /// - /// - private void BorderMaxWindowButton_Click(object sender, EventArgs e) - { - FixHelper.Border(); - FixHelper.NormalWindow(); - FixHelper.MaxWindow(); - } - - /// - /// 无边框全屏 - /// - /// - /// - private void FullScreenButton_Click(object sender, EventArgs e) - { - FixHelper.Borderless(); - FixHelper.FullScreen(); - } - /// /// 更新定时间隔 /// @@ -362,6 +342,11 @@ private void FullScreenButton_Click(object sender, EventArgs e) /// private void IntervalInput_ValueChanged(object sender, EventArgs e) { + if (!_inited || Settings.TimerInterval == (int)IntervalInput.Value) + { + return; + } + Settings.TimerInterval = (int)IntervalInput.Value; SettingsManager.Save(); if (_timer.Enabled) @@ -379,6 +364,11 @@ private void IntervalInput_ValueChanged(object sender, EventArgs e) /// private void EnableTimerFixCheckBox_CheckedChanged(object sender, EventArgs e) { + if (!_inited || Settings.UseTimer == EnableTimerFixCheckBox.Checked) + { + return; + } + Settings.UseTimer = EnableTimerFixCheckBox.Checked; SettingsManager.Save(); if (!EnableTimerFixCheckBox.Checked) @@ -407,6 +397,11 @@ private void EnableTimerFixCheckBox_CheckedChanged(object sender, EventArgs e) /// private void EnableHotKeyCheckBox_CheckedChanged(object sender, EventArgs e) { + if (!_inited || Settings.UseHotKey == EnableHotKeyCheckBox.Checked) + { + return; + } + Settings.UseHotKey = EnableHotKeyCheckBox.Checked; SettingsManager.Save(); UpdateFixHotKey(); @@ -420,7 +415,13 @@ private void EnableHotKeyCheckBox_CheckedChanged(object sender, EventArgs e) private void HotKeyInputBox_HotKeyChanged(object sender, EventArgs e) { var hotkey = HotKeyInputBox.HotKey; - Settings.HotKey = hotkey.IsValid ? hotkey : HotKey.Empty; + hotkey = hotkey.IsValid ? hotkey : HotKey.Empty; + if (!_inited || Settings.HotKey == hotkey) + { + return; + } + + Settings.HotKey = hotkey; SettingsManager.Save(); UpdateFixHotKey(); } @@ -437,22 +438,6 @@ private void ManualButton_Click(object sender, EventArgs e) manual.ShowDialog(); } - /// - /// 窗口模式改变 - /// - /// - /// - private void WindowModeSelect_SelectionChangeCommitted(object sender, EventArgs e) - { - var mode = (ComboBoxItem)WindowModeSelect.SelectedItem; - Settings.WindowMode = mode.Value; - SettingsManager.Save(); - if (Settings.UseAutoWindow) - { - ApplyWindowMode(); - } - } - #region 系统托盘 /// @@ -528,7 +513,8 @@ private void ToggleWindow() if (nowTicks - _lastToggleWindowTicks >= ToggleWindowThresholdTicks) { _lastToggleWindowTicks = nowTicks; - if (Visible) + var foregroundWindow = API.GetForegroundWindow(); + if (Visible && Handle == foregroundWindow) { HideWindow(); } @@ -547,7 +533,13 @@ private void ToggleWindow() private void ShowMeHotKeyInputBox_HotKeyChanged(object sender, EventArgs e) { var hotkey = ShowMeHotKeyInputBox.HotKey; - Settings.ShowMeHotKey = hotkey.IsValid ? hotkey : HotKey.DefaultShowMeHotKey; + hotkey = hotkey.IsValid ? hotkey : HotKey.DefaultShowMeHotKey; + if (!_inited || Settings.ShowMeHotKey == hotkey) + { + return; + } + + Settings.ShowMeHotKey = hotkey; SettingsManager.Save(); UpdateShowMeHotKey(); } @@ -590,15 +582,16 @@ private void UpdateShowMeHotKey() /// private void AutoWindowCheckBox_CheckedChanged(object sender, EventArgs e) { - Settings.UseAutoWindow = AutoWindowCheckBox.Checked; - SettingsManager.Save(); - if (Settings.UseAutoWindow) + if (!_inited || Settings.AutoApplyWindow == AutoApplyCheckBox.Checked) { - if (_isSetAutoWindow) - { - ApplyWindowMode(); - } + return; + } + Settings.AutoApplyWindow = AutoApplyCheckBox.Checked; + SettingsManager.Save(); + if (Settings.AutoApplyWindow) + { + Apply(); _war3RunningMonitor.Start(); } else @@ -614,53 +607,31 @@ private void AutoWindowCheckBox_CheckedChanged(object sender, EventArgs e) /// private void CheckWar3Process(object sender, ElapsedEventArgs e) { - if (!Settings.UseAutoWindow) + if (!Settings.AutoApplyWindow) { - _isSetAutoWindow = false; return; } - var window = FixHelper.GetWar3Window(); + var window = Fixer.GetWar3Window(); if (window == IntPtr.Zero) { - _isSetAutoWindow = false; + return; } - else - { - if (!_isSetAutoWindow) + + Task.Run( + async () => { - _isSetAutoWindow = true; - Task.Run( - async () => - { - await Task.Delay(800); - ApplyWindowMode(); - }); - } - } + await Task.Delay(800); + Apply(); + }); } /// /// 应用窗口模式 /// - private void ApplyWindowMode() + private void Apply() { - switch (Settings.WindowMode) - { - case WindowMode.FullScreenWindow: - FixHelper.Borderless(); - FixHelper.FullScreen(); - break; - case WindowMode.MaxWindows: - FixHelper.Border(); - FixHelper.MaxWindow(); - break; - case WindowMode.KeepCurrent: - default: - break; - } - - SetCursor(); + Fixer.Apply(); } #endregion @@ -674,52 +645,13 @@ private void ApplyWindowMode() /// private void LockCursorCheckBox_CheckedChanged(object sender, EventArgs e) { - Settings.LockCursor = LockCursorCheckBox.Checked; - SettingsManager.Save(); - } - - /// - /// 锁定鼠标范围 - /// - private void SetCursor() - { - var war3Window = FixHelper.GetWar3Window(); - if (war3Window == IntPtr.Zero) + if (!_inited || Settings.LockCursor == LockCursorCheckBox.Checked) { return; } - var handle = API.GetForegroundWindow(); - if (handle != war3Window) - { - var war35211 = FixHelper.Get5211War3Window(); - if (handle == war35211 && handle != IntPtr.Zero) - { - handle = API.GetWindow(handle, API.GW_CHILD); - } - } - - if (handle == war3Window && Settings.LockCursor) - { - API.GetWindowRect(war3Window, out var windowRect); - if (windowRect.Top == -32000) - { - // 窗口已最小化 - return; - } - - if (Settings.WindowMode != WindowMode.FullScreenWindow) - { - var height = API.GetTitleBarHeight(); - var border = API.GetBorder(); - var rect = new Rect { Top = windowRect.Top + height, Bottom = windowRect.Bottom - border, Left = windowRect.Left + border, Right = windowRect.Right - border }; - API.ClipCursor(ref rect); - } - else - { - API.ClipCursor(ref windowRect); - } - } + Settings.LockCursor = LockCursorCheckBox.Checked; + SettingsManager.Save(); } /// @@ -734,7 +666,7 @@ private void SetCursor() /// public void LockCursorEventProc(IntPtr hWinEventHook, uint eventType, IntPtr hwnd, int idObject, int idChild, uint dwEventThread, uint dwmsEventTime) { - SetCursor(); + Fixer.LockCursor(); } /// @@ -758,4 +690,116 @@ private void UnlockCursor() } #endregion + + /// + /// 自定义宽度 + /// + /// + /// + private void WidthInput_ValueChanged(object sender, EventArgs e) + { + if (!_inited || Settings.Width == (int)WidthInput.Value) + { + return; + } + + Settings.Width = (int)WidthInput.Value; + SettingsManager.Save(); + } + + /// + /// 自定义高度 + /// + /// + /// + private void HeightInput_ValueChanged(object sender, EventArgs e) + { + if (!_inited || Settings.Height == (int)HeightInput.Value) + { + return; + } + + Settings.Height = (int)HeightInput.Value; + SettingsManager.Save(); + } + + /// + /// 自定义位置X + /// + /// + /// + private void CustomPositionX_ValueChanged(object sender, EventArgs e) + { + if (!_inited || Settings.X == (int)CustomPositionX.Value) + { + return; + } + + Settings.X = (int)CustomPositionX.Value; + SettingsManager.Save(); + } + + /// + /// 自定义位置Y + /// + /// + /// + private void CustomPositionY_ValueChanged(object sender, EventArgs e) + { + if (!_inited || Settings.Y == (int)CustomPositionY.Value) + { + return; + } + + Settings.Y = (int)CustomPositionY.Value; + SettingsManager.Save(); + } + + /// + /// 启用/停用自定义位置 + /// + /// + /// + private void CustomPositionCheckBox_CheckedChanged(object sender, EventArgs e) + { + if (!_inited || Settings.UseCustomPosition == CustomPositionCheckBox.Checked) + { + return; + } + + Settings.UseCustomPosition = CustomPositionCheckBox.Checked; + SettingsManager.Save(); + var enableCustomPosition = Settings.WindowMode == WindowMode.Custom && CustomPositionCheckBox.Checked; + CustomPositionX.Enabled = enableCustomPosition; + CustomPositionY.Enabled = enableCustomPosition; + } + + /// + /// 窗口模式改变 + /// + /// + /// + private void WindowModeComboBox_SelectedIndexChanged(object sender, EventArgs e) + { + var mode = (ComboBoxItem)WindowModeComboBox.SelectedItem; + if (!_inited || Settings.WindowMode == mode.Value) + { + return; + } + + Settings.WindowMode = mode.Value; + SettingsManager.Save(); + + var useCustomMode = mode.Value == WindowMode.Custom; + WidthInput.Enabled = useCustomMode; + HeightInput.Enabled = useCustomMode; + CustomPositionCheckBox.Enabled = useCustomMode; + CustomPositionX.Enabled = useCustomMode && CustomPositionCheckBox.Checked; + CustomPositionY.Enabled = useCustomMode && CustomPositionCheckBox.Checked; + + if (Settings.AutoApplyWindow) + { + Apply(); + } + } } \ No newline at end of file diff --git a/src/War3FixFont/Manual.Designer.cs b/src/War3FixFont/Manual.Designer.cs index 3b5dab7..cacf424 100644 --- a/src/War3FixFont/Manual.Designer.cs +++ b/src/War3FixFont/Manual.Designer.cs @@ -53,7 +53,7 @@ private void InitializeComponent() this.Controls.Add(this.ManualContent); this.Icon = ((System.Drawing.Icon)(resources.GetObject("$this.Icon"))); this.Name = "Manual"; - this.Text = "Manual"; + this.Text = "使用说明"; this.ResumeLayout(false); this.PerformLayout(); diff --git a/src/War3FixFont/Program.cs b/src/War3FixFont/Program.cs index c18f6ee..1fa84ca 100644 --- a/src/War3FixFont/Program.cs +++ b/src/War3FixFont/Program.cs @@ -1,4 +1,5 @@ using System; +using System.Diagnostics; using System.Threading; using System.Windows.Forms; @@ -15,6 +16,19 @@ static void Main() using var mutex = new Mutex(true, "War3FixFont", out var mutexCreated); if (mutexCreated) { + if (!Debugger.IsAttached) + { + // Add the event handler for handling UI thread exceptions to the event. + Application.ThreadException += UIThreadException; + + // Set the unhandled exception mode to force all Windows Forms errors to go through + // our handler. + Application.SetUnhandledExceptionMode(UnhandledExceptionMode.CatchException); + + // Add the event handler for handling non-UI thread exceptions to the event. + AppDomain.CurrentDomain.UnhandledException += CurrentDomain_UnhandledException; + } + Application.EnableVisualStyles(); Application.SetCompatibleTextRenderingDefault(false); Application.Run(new Main()); @@ -24,5 +38,92 @@ static void Main() MessageBox.Show("程序已经运行", "魔兽争霸3叠字修复", MessageBoxButtons.OK, MessageBoxIcon.Information); } } + + // Handle the UI exceptions by showing a dialog box, and asking the user whether + // or not they wish to abort execution. + private static void UIThreadException(object sender, ThreadExceptionEventArgs t) + { + var result = DialogResult.Cancel; + try + { + result = ShowThreadExceptionDialog("程序异常", t.Exception); + } + catch + { + try + { + MessageBox.Show( + "程序异常", + "程序出错", + MessageBoxButtons.AbortRetryIgnore, + MessageBoxIcon.Stop); + } + finally + { + Application.Exit(); + } + } + + if (result == DialogResult.Abort) + { + Application.Exit(); + } + } + + private static void LogToEventLog(string message) + { + const string SourceName = "War3FixFont"; + if (!EventLog.SourceExists(SourceName)) + { + EventLog.CreateEventSource(SourceName, "Application"); + } + + var eventLog = new EventLog(); + eventLog.Source = SourceName; + eventLog.WriteEntry(message); + } + + // Handle the UI exceptions by showing a dialog box, and asking the user whether + // or not they wish to abort execution. + // NOTE: This exception cannot be kept from terminating the application - it can only + // log the event, and inform the user about it. + private static void CurrentDomain_UnhandledException(object sender, UnhandledExceptionEventArgs e) + { + try + { + var ex = (Exception)e.ExceptionObject; + const string ErrorMsg = "程序异常:\n\n"; + LogToEventLog(ErrorMsg + ex.Message + "\n\nStack Trace:\n" + ex.StackTrace); + } + catch (Exception exc) + { + try + { + MessageBox.Show( + "日志异常", + "无法记录错误到日志: " + + exc.Message, + MessageBoxButtons.OK, + MessageBoxIcon.Stop); + } + finally + { + Application.Exit(); + } + } + } + + // Creates the error message and displays it. + private static DialogResult ShowThreadExceptionDialog(string title, Exception e) + { + var errorMsg = "程序异常:\n\n"; + errorMsg = errorMsg + e.Message + "\n\nStack Trace:\n" + e.StackTrace; + LogToEventLog(errorMsg); + return MessageBox.Show( + errorMsg, + title, + MessageBoxButtons.AbortRetryIgnore, + MessageBoxIcon.Stop); + } } } \ No newline at end of file diff --git a/src/War3FixFont/Properties/AssemblyInfo.cs b/src/War3FixFont/Properties/AssemblyInfo.cs index 0820e85..013ba5f 100644 --- a/src/War3FixFont/Properties/AssemblyInfo.cs +++ b/src/War3FixFont/Properties/AssemblyInfo.cs @@ -10,7 +10,7 @@ [assembly: AssemblyConfiguration("")] [assembly: AssemblyCompany("Zonciu Studio")] [assembly: AssemblyProduct("War3FixFont")] -[assembly: AssemblyCopyright("Copyright © 2022")] +[assembly: AssemblyCopyright("Copyright © 2023")] [assembly: AssemblyTrademark("")] [assembly: AssemblyCulture("")] @@ -32,5 +32,5 @@ // You can specify all the values or you can default the Build and Revision Numbers // by using the '*' as shown below: // [assembly: AssemblyVersion("1.0.*")] -[assembly: AssemblyVersion("1.5")] -[assembly: AssemblyFileVersion("1.5")] \ No newline at end of file +[assembly: AssemblyVersion("1.7")] +[assembly: AssemblyFileVersion("1.7")] \ No newline at end of file diff --git a/src/War3FixFont/Properties/Resources.Designer.cs b/src/War3FixFont/Properties/Resources.Designer.cs index abb0cfd..cf6b290 100644 --- a/src/War3FixFont/Properties/Resources.Designer.cs +++ b/src/War3FixFont/Properties/Resources.Designer.cs @@ -1,9 +1,10 @@ //------------------------------------------------------------------------------ // -// This code was generated by a tool. +// 此代码由工具生成。 +// 运行时版本:4.0.30319.42000 // -// Changes to this file may cause incorrect behavior and will be lost if -// the code is regenerated. +// 对此文件的更改可能会导致不正确的行为,并且如果 +// 重新生成代码,这些更改将会丢失。 // //------------------------------------------------------------------------------ @@ -12,12 +13,12 @@ namespace War3FixFont.Properties { /// - /// A strongly-typed resource class, for looking up localized strings, etc. + /// 一个强类型的资源类,用于查找本地化的字符串等。 /// - // This class was auto-generated by the StronglyTypedResourceBuilder - // class via a tool like ResGen or Visual Studio. - // To add or remove a member, edit your .ResX file then rerun ResGen - // with the /str option, or rebuild your VS project. + // 此类是由 StronglyTypedResourceBuilder + // 类通过类似于 ResGen 或 Visual Studio 的工具自动生成的。 + // 若要添加或移除成员,请编辑 .ResX 文件,然后重新运行 ResGen + // (以 /str 作为命令选项),或重新生成 VS 项目。 [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "17.0.0.0")] [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] @@ -32,7 +33,7 @@ internal Resources() { } /// - /// Returns the cached ResourceManager instance used by this class. + /// 返回此类使用的缓存的 ResourceManager 实例。 /// [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] internal static global::System.Resources.ResourceManager ResourceManager { @@ -46,8 +47,8 @@ internal Resources() { } /// - /// Overrides the current thread's CurrentUICulture property for all - /// resource lookups using this strongly typed resource class. + /// 重写当前线程的 CurrentUICulture 属性,对 + /// 使用此强类型资源类的所有资源查找执行重写。 /// [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] internal static global::System.Globalization.CultureInfo Culture { @@ -60,20 +61,24 @@ internal Resources() { } /// - /// Looks up a localized string similar to 窗口模式: - ///1. 保持当前: 游戏是普通窗口或无边框窗口时,每次修复增加1像素宽度,再减1像素宽度。 - /// 游戏是窗口最大化时,会让窗口缩放一次来完成修复。 + /// 查找类似 窗口模式: + /// + ///1. 无边框全屏: 把游戏设为无边框全屏,每次修复增加1像素宽度,再减1像素宽度。 /// - ///2. 无边框全屏: 把游戏设为无边框全屏,每次修复增加1像素宽度,再减1像素宽度。 - /// - ///3. 有边框最大化: 把游戏设为有边框最大化窗口,会让窗口缩放一次来完成修复。 + ///2. 最大化窗口: 把游戏设为有边框最大化窗口,会让窗口缩放一次来完成修复。 + /// + ///3. 4:3模式: 把游戏设为4:3比例窗口。 + /// + ///4. 自定义窗口: 手动设置窗口宽高和位置。 /// + ///自定义位置: 未勾选时默认为屏幕中间,勾选后以屏幕左上角为原点设置窗口位置。 + /// ///限制修复的间隔时间,默认CD 1秒,触发一次修复后,至少经过1秒才能触发下一次修复。 /// ///勾选自动设置窗口后,游戏启动时会自动设置窗口状态。 /// ///勾选锁定鼠标范围后,鼠标会自动限定在游戏窗口范围内。 - /// . + /// 的本地化字符串。 /// internal static string Manual { get { diff --git a/src/War3FixFont/Properties/Resources.resx b/src/War3FixFont/Properties/Resources.resx index d9e7572..5ef8ce5 100644 --- a/src/War3FixFont/Properties/Resources.resx +++ b/src/War3FixFont/Properties/Resources.resx @@ -119,13 +119,17 @@ 窗口模式: -1. 保持当前: 游戏是普通窗口或无边框窗口时,每次修复增加1像素宽度,再减1像素宽度。 - 游戏是窗口最大化时,会让窗口缩放一次来完成修复。 - -2. 无边框全屏: 把游戏设为无边框全屏,每次修复增加1像素宽度,再减1像素宽度。 + +1. 无边框全屏: 把游戏设为无边框全屏,每次修复增加1像素宽度,再减1像素宽度。 -3. 有边框最大化: 把游戏设为有边框最大化窗口,会让窗口缩放一次来完成修复。 +2. 最大化窗口: 把游戏设为有边框最大化窗口,会让窗口缩放一次来完成修复。 + +3. 4:3模式: 把游戏设为4:3比例窗口。 + +4. 自定义窗口: 手动设置窗口宽高和位置。 +自定义位置: 未勾选时默认为屏幕中间,勾选后以屏幕左上角为原点设置窗口位置。 + 限制修复的间隔时间,默认CD 1秒,触发一次修复后,至少经过1秒才能触发下一次修复。 勾选自动设置窗口后,游戏启动时会自动设置窗口状态。 diff --git a/src/War3FixFont/Settings.cs b/src/War3FixFont/Settings.cs index 0f9e1b5..a21704e 100644 --- a/src/War3FixFont/Settings.cs +++ b/src/War3FixFont/Settings.cs @@ -1,5 +1,4 @@ using Newtonsoft.Json; -using Newtonsoft.Json.Converters; namespace War3FixFont; @@ -16,13 +15,13 @@ public class Settings public bool UseHotKey { get; set; } = true; /// - /// 快捷键 + /// 修复快捷键 /// [JsonProperty("HotKey")] public string HotKeyString { get; set; } = "0,1,1,D"; /// - /// 快捷键 + /// 修复快捷键 /// [JsonIgnore] public HotKey HotKey @@ -51,7 +50,7 @@ public HotKey ShowMeHotKey /// 窗口模式 /// [JsonProperty] - public WindowMode WindowMode { get; set; } = WindowMode.FullScreenWindow; + public WindowMode WindowMode { get; set; } = WindowMode.FullScreen; /// /// 使用定时修复 @@ -75,11 +74,41 @@ public HotKey ShowMeHotKey /// 自动应用窗口模式 /// [JsonProperty] - public bool UseAutoWindow { get; set; } = true; + public bool AutoApplyWindow { get; set; } = true; /// /// 锁定鼠标 /// [JsonProperty] public bool LockCursor { get; set; } = true; + + /// + /// 自定义宽度 + /// + [JsonProperty] + public int Width { get; set; } + + /// + /// 自定义高度 + /// + [JsonProperty] + public int Height { get; set; } + + /// + /// 启用自定义位置 + /// + [JsonProperty] + public bool UseCustomPosition { get; set; } + + /// + /// 自定义位置X + /// + [JsonProperty] + public int X { get; set; } + + /// + /// 自定义位置Y + /// + [JsonProperty] + public int Y { get; set; } } \ No newline at end of file diff --git a/src/War3FixFont/War3FixFont.csproj b/src/War3FixFont/War3FixFont.csproj index 1b6c64e..e7ca816 100644 --- a/src/War3FixFont/War3FixFont.csproj +++ b/src/War3FixFont/War3FixFont.csproj @@ -60,7 +60,7 @@ false - true + false app.manifest @@ -89,8 +89,8 @@ + - Component @@ -167,7 +167,7 @@ all - runtime; build; native; contentfiles; analyzers; buildtransitive + runtime; compile; build; native; contentfiles; analyzers; buildtransitive all diff --git a/src/War3FixFont/WinAPI/API.cs b/src/War3FixFont/WinAPI/API.cs index 728d246..004ff06 100644 --- a/src/War3FixFont/WinAPI/API.cs +++ b/src/War3FixFont/WinAPI/API.cs @@ -99,6 +99,17 @@ public static class API [DllImport("user32.dll")] public static extern int GetSystemMetrics(int nIndex); + /// + /// 获取系统信息 + /// + /// + /// + /// + /// + /// + [DllImport("user32.dll", SetLastError = true)] + public static extern bool SystemParametersInfo(int uiAction, int uiParam, out Rect pvParam, int fWinIni); + public delegate void WinEventProc(IntPtr hWinEventHook, uint eventType, IntPtr hwnd, int idObject, int idChild, uint dwEventThread, uint dwmsEventTime); /// @@ -170,6 +181,8 @@ public static class API public const uint EVENT_SYSTEM_FOREGROUND = 3; + public const int SPI_GETWORKAREA = 0x0030; + public static int GetTitleBarHeight() => GetSystemMetrics(SM_CYFRAME) + GetSystemMetrics(SM_CYCAPTION) diff --git a/src/War3FixFont/WindowMode.cs b/src/War3FixFont/WindowMode.cs index 2bee802..7a891fe 100644 --- a/src/War3FixFont/WindowMode.cs +++ b/src/War3FixFont/WindowMode.cs @@ -7,21 +7,27 @@ namespace War3FixFont; /// public enum WindowMode { - /// - /// 保持当前窗口 - /// - [Description("保持当前")] - KeepCurrent, - /// /// 全屏窗口 /// [Description("无边框全屏")] - FullScreenWindow, + FullScreen, /// /// 最大化窗口 /// - [Description("有边框最大化")] - MaxWindows + [Description("最大化窗口")] + Maximum, + + /// + /// 4:3窗口 + /// + [Description("4:3窗口")] + Ratio43, + + /// + /// 自定义窗口尺寸 + /// + [Description("自定义窗口")] + Custom } \ No newline at end of file