diff --git a/GW Launcher/Forms/MainForm.cs b/GW Launcher/Forms/MainForm.cs index 3023d66..c345dd9 100644 --- a/GW Launcher/Forms/MainForm.cs +++ b/GW Launcher/Forms/MainForm.cs @@ -15,21 +15,74 @@ public partial class MainForm : Form public MainForm(bool launchMinimized = false) { - if (!launchMinimized) - { - _allowVisible = true; - var position = new Point - { - X = Screen.PrimaryScreen!.Bounds.Width / 2, - Y = Screen.PrimaryScreen.Bounds.Height / 2 - }; - Location = position; - } InitializeComponent(); _selectedItems = new ListView.SelectedIndexCollection(listViewAccounts); _instance = this; + if(!launchMinimized) + { + RepositionAndShow(); + } } + protected void RepositionAndShow() + { + _allowVisible = true; + // get Windows screen scale factor (system -> display -> scale): + // to get real resolution from virtual one, we need to multiply with scale factor: virtual resolution * scale = native unscaled resolution + float scale = ScreenScaling.GetScreenScalingFactor(); + + bool IsVisible(Point p) + { + return Screen.AllScreens.Any(s => + p.X < s.Bounds.Right * scale && p.X > s.Bounds.Left * scale && p.Y > s.Bounds.Top * scale && p.Y < s.Bounds.Bottom * scale); + } + + var rect = NotifyIconHelper.GetIconRect(notifyIcon); + var position = new Point(rect.Left, rect.Top); + + RefreshUI(); + + position.X -= Width / 2; + if (position.Y > Screen.FromPoint(Cursor.Position).WorkingArea.Height * scale / 2) + { + position.Y -= 5 + Height; + } + else + { + position.Y += 5; + } + + if (!IsVisible(position)) + { + position.Y = (int)(Cursor.Position.Y * scale); + } + + Debug.Assert(Screen.PrimaryScreen != null, "Screen.PrimaryScreen != null"); + + if (!IsVisible(position)) + { + position.X = (int)(Screen.PrimaryScreen.Bounds.Width * scale) / 2; + position.Y = (int)(Screen.PrimaryScreen.Bounds.Height * scale) / 2; + } + + //divide out scaling factor as DPI-unaware windows app works with a virtual resolution of 100% scaling: + position.X = (int)(position.X / scale); + position.Y = (int)(position.Y / scale); + + //if bottom right corner is out of screen (scaling was already divided out), move window back into screen: + if (position.X + Width > Screen.PrimaryScreen.Bounds.Width) + position.X -= position.X + Width - Screen.PrimaryScreen.Bounds.Width; + + if (position.Y + Height > Screen.PrimaryScreen.Bounds.Height) + position.Y -= position.Y + Height - Screen.PrimaryScreen.Bounds.Height; + + + Location = position; + + Visible = !Visible; + Activate(); + } + protected override void OnFormClosing(FormClosingEventArgs e) { _instance = null; @@ -297,61 +350,9 @@ private void NotifyIcon_MouseClick(object sender, MouseEventArgs e) _allowVisible = true; _keepOpen = e.Button == MouseButtons.Right && Visible == false; - // get Windows screen scale factor (system -> display -> scale): - // to get real resolution from virtual one, we need to multiply with scale factor: virtual resolution * scale = native unscaled resolution - float scale = ScreenScaling.GetScreenScalingFactor(); - - bool IsVisible(Point p) - { - return Screen.AllScreens.Any(s => - p.X < s.Bounds.Right * scale && p.X > s.Bounds.Left * scale && p.Y > s.Bounds.Top * scale && p.Y < s.Bounds.Bottom * scale); - } - - var rect = NotifyIconHelper.GetIconRect(notifyIcon); - var position = new Point(rect.Left, rect.Top); - - RefreshUI(); - - position.X -= Width / 2; - if (position.Y > Screen.FromPoint(Cursor.Position).WorkingArea.Height * scale / 2) - { - position.Y -= 5 + Height; - } - else - { - position.Y += 5; - } - - if (!IsVisible(position)) - { - position.Y = (int) (Cursor.Position.Y * scale); - } - - Debug.Assert(Screen.PrimaryScreen != null, "Screen.PrimaryScreen != null"); - - if (!IsVisible(position)) - { - position.X = (int) (Screen.PrimaryScreen.Bounds.Width * scale) / 2; - position.Y = (int) (Screen.PrimaryScreen.Bounds.Height * scale) / 2; - } + RepositionAndShow(); - //divide out scaling factor as DPI-unaware windows app works with a virtual resolution of 100% scaling: - position.X = (int) (position.X / scale); - position.Y = (int) (position.Y / scale); - - //if bottom right corner is out of screen (scaling was already divided out), move window back into screen: - if (position.X + Width > Screen.PrimaryScreen.Bounds.Width) - position.X -= position.X + Width - Screen.PrimaryScreen.Bounds.Width; - - if (position.Y + Height > Screen.PrimaryScreen.Bounds.Height) - position.Y -= position.Y + Height - Screen.PrimaryScreen.Bounds.Height; - - - Location = position; - - Visible = !Visible; - Activate(); - } + } private async void ToolStripMenuItemUpdateAllClients_Click(object sender, EventArgs e) { diff --git a/GW Launcher/MulticlientPatch.cs b/GW Launcher/MulticlientPatch.cs index 48f2f8b..8cd22b1 100644 --- a/GW Launcher/MulticlientPatch.cs +++ b/GW Launcher/MulticlientPatch.cs @@ -129,18 +129,9 @@ private static IntPtr GetProcessModuleBase(IntPtr process) memory = new GWCAMemory(process); - foreach (var dll in ModManager.GetDlls(account)) - { - var load_module_result = memory.LoadModule(dll); - if (load_module_result != GWCAMemory.LoadModuleResult.SUCCESSFUL) - { - err = GetErrorMessage($"memory.LoadModule({dll})", Marshal.GetLastWin32Error()); - goto cleanup; - } - } - + var VK_SHIFT = 0x10; //NB: Because account launching is done on another thread, we can't rely on WPF/WinForms API to tell us if shift is pressed - if ((GetAsyncKeyState(0x10) & 0x8000) != 0) { + if ((GetAsyncKeyState(VK_SHIFT) & 0x8000) != 0) { DialogResult result = MessageBox.Show("Guild Wars is in a suspended state, plugins are not yet loaded.\n\nContinue?", "Launching paused", MessageBoxButtons.OKCancel); @@ -151,6 +142,16 @@ private static IntPtr GetProcessModuleBase(IntPtr process) } } + foreach (var dll in ModManager.GetDlls(account)) + { + var loadModuleResult = memory.LoadModule(dll); + if (loadModuleResult != GWCAMemory.LoadModuleResult.SUCCESSFUL) + { + err = GetErrorMessage($"memory.LoadModule({dll})", Marshal.GetLastWin32Error()); + goto cleanup; + } + } + if (procinfo.hThread != IntPtr.Zero) { try @@ -176,7 +177,7 @@ private static IntPtr GetProcessModuleBase(IntPtr process) cleanup: if (err != null) { - process?.Kill(); + // process?.Kill(); memory = null; } // Make sure to restore the modfile.txt file (blank string if in the gwlauncher dir, whatever was there before if in the gw dir) diff --git a/GW Launcher/Program.cs b/GW Launcher/Program.cs index 4809fc4..afb1b3d 100644 --- a/GW Launcher/Program.cs +++ b/GW Launcher/Program.cs @@ -504,7 +504,7 @@ private static bool IsDotNet8DesktopInstalled() }; using var process = Process.Start(processInfo); - using var reader = process.StandardOutput; + using var reader = process!.StandardOutput; var output = reader.ReadToEnd(); process.WaitForExit();