diff --git a/WitcherScriptMerger/Forms/MainForm.cs b/WitcherScriptMerger/Forms/MainForm.cs index 8897f40..06a9cb9 100644 --- a/WitcherScriptMerger/Forms/MainForm.cs +++ b/WitcherScriptMerger/Forms/MainForm.cs @@ -882,18 +882,19 @@ void HideProgressScreen() public DialogResult ShowMessage(string text, string title = "", MessageBoxButtons buttons = MessageBoxButtons.OK, - MessageBoxIcon icon = MessageBoxIcon.None) + MessageBoxIcon icon = MessageBoxIcon.None, + MessageBoxDefaultButton defaultButton = MessageBoxDefaultButton.Button1) { this.ActivateSafely(); if (this.InvokeRequired) { return (DialogResult)this.Invoke(new Func( - () => { return MessageBox.Show(this, text, title, buttons, icon); })); + () => { return MessageBox.Show(this, text, title, buttons, icon, defaultButton); })); } else { - return MessageBox.Show(this, text, title, buttons, icon); + return MessageBox.Show(this, text, title, buttons, icon, defaultButton); } } diff --git a/WitcherScriptMerger/HeadlessMergeNotifier.cs b/WitcherScriptMerger/HeadlessMergeNotifier.cs index 8212f24..a76ce0b 100644 --- a/WitcherScriptMerger/HeadlessMergeNotifier.cs +++ b/WitcherScriptMerger/HeadlessMergeNotifier.cs @@ -14,10 +14,19 @@ class HeadlessMergeNotifier : IMergeNotifier public DialogResult ShowMessage(string text, string title = "", MessageBoxButtons buttons = MessageBoxButtons.OK, - MessageBoxIcon icon = MessageBoxIcon.None) + MessageBoxIcon icon = MessageBoxIcon.None, + MessageBoxDefaultButton defaultButton = MessageBoxDefaultButton.Button1) { Write(text, title, icon); + // defaultButton is intentionally unused here: it only affects which + // button has interactive UI focus (Enter-key behavior), and headless + // mode has no UI to focus. The DialogResult below is chosen per + // buttons set instead, per this class's own fixed, non-destructive + // default for each verb - not by the caller's requested default + // button. A call site relying on defaultButton to signal "this is the + // safe answer" for a MessageBoxButtons combination not covered below + // will get whatever the catch-all case returns instead. return buttons switch { MessageBoxButtons.OK => DialogResult.OK, diff --git a/WitcherScriptMerger/IMergeNotifier.cs b/WitcherScriptMerger/IMergeNotifier.cs index c66d0dd..0eb3034 100644 --- a/WitcherScriptMerger/IMergeNotifier.cs +++ b/WitcherScriptMerger/IMergeNotifier.cs @@ -9,7 +9,8 @@ interface IMergeNotifier DialogResult ShowMessage(string text, string title = "", MessageBoxButtons buttons = MessageBoxButtons.OK, - MessageBoxIcon icon = MessageBoxIcon.None); + MessageBoxIcon icon = MessageBoxIcon.None, + MessageBoxDefaultButton defaultButton = MessageBoxDefaultButton.Button1); DialogResult ShowError(string text, string title = "Error"); diff --git a/WitcherScriptMerger/LoadOrder/LoadOrderValidator.cs b/WitcherScriptMerger/LoadOrder/LoadOrderValidator.cs index 29e88b5..d99f184 100644 --- a/WitcherScriptMerger/LoadOrder/LoadOrderValidator.cs +++ b/WitcherScriptMerger/LoadOrder/LoadOrderValidator.cs @@ -21,8 +21,11 @@ public static void ValidateAndFix(CustomLoadOrder loadOrder) { PrioritizeMergedMod(loadOrder, mergedMod); } - else if (choice == DialogResult.Cancel) // Never + else if (choice == DialogResult.Cancel && Program.Notifier.IsInteractive) // Never { + // IsInteractive guard: HeadlessMergeNotifier's fixed default for + // YesNoCancel is Cancel, which would otherwise persist this setting + // on every headless run that reaches here. Program.Settings.Set("ValidateCustomLoadOrder", false); Program.Settings.Save(); } @@ -30,10 +33,20 @@ public static void ValidateAndFix(CustomLoadOrder loadOrder) static DialogResult PromptToPrioritizeMergedMod(string modsSettingsPath) { - MessageBoxManager.Cancel = "Ne&ver"; - MessageBoxManager.Register(); - - var choice = MessageBox.Show( + // Known, accepted regression: the Cancel button used to be relabeled + // "Ne&ver" via MessageBoxManager.Register()/Unregister(), which worked + // only because the old MessageBox.Show call ran on the same background + // thread (Register()'s SetWindowsHookEx is thread-affine) as this + // method. Program.Notifier.ShowMessage (MainForm.ShowMessage) Invokes + // the actual MessageBox.Show onto the UI thread, so that hook can no + // longer see the dialog's window messages - relabeling can't be + // preserved without adding custom button-text support to + // IMergeNotifier, which is out of scope here. The Cancel button now + // reads "Cancel"; clicking it still permanently disables this check + // (see the IsInteractive-guarded branch above), just without a label + // saying so. DialogResult semantics and this method's return value are + // otherwise unchanged. + return Program.Notifier.ShowMessage( $"{modsSettingsPath}\n\n" + "Detected custom load order in the file above, and merged files aren't configured to load first.\n\n" + "Would you like Script Merger to modify your custom load order so that your merged files have top priority?", @@ -41,9 +54,6 @@ static DialogResult PromptToPrioritizeMergedMod(string modsSettingsPath) MessageBoxButtons.YesNoCancel, MessageBoxIcon.Exclamation, MessageBoxDefaultButton.Button2); - - MessageBoxManager.Unregister(); - return choice; } static void PrioritizeMergedMod(CustomLoadOrder loadOrder, ModLoadSetting mergedModSetting)