1

I think the extra wrinkles here make this question not a duplicate of other centering questions.

I would like to use the approach of @BSharp given here for a self-closing message box:

var w = new Form() { Size = new Size(0, 0) };
Task.Delay(TimeSpan.FromSeconds(10))
    .ContinueWith((t) => w.Close(), TaskScheduler.FromCurrentSynchronizationContext());

MessageBox.Show(w, message, caption);

However, in my two-monitor setup, the application is running on the right monitor and the message box is being displayed on the left monitor. How to get it to display in the same location but on the right monitor?

Tim
  • 8,669
  • 31
  • 105
  • 183
  • 1
    Add `var sc = Screen.FromHandle(this.Handle);` to determine the current Screen, then, e.g.`var w = new Form() { Size = new Size(0, 0), StartPosition = FormStartPosition.Manual, Location = new Point([Left], [Top]) };`, where [Left] and [Top] are calculated based on the Screen Bounds. In case you need it, see the notes here: [Using SetWindowPos with multiple monitors](https://stackoverflow.com/a/53026765/7444103) about the VirtualScreen and other stuff (consider the DpiAwaress part). – Jimi Sep 08 '20 at 21:19
  • Why are you passing in `w` as a new form? If you pass in your program's main window to the `Show(...)` method then the message box should display automatically on the correct screen. – Loathing Sep 09 '20 at 01:56
  • 1
    @Loathing The main reason is because you have to close the Owner Window to close the MessageBox. You probably don't want to close the currently displayed Form. Yes, of course there are other means, but this is quite simplified: no P/Invoking, not UI Automation, no risky `SendKeys` in a threaded Timer, etc. Also, you can show the MessageBox in any other screen, no matter where you main app's Forms are displayed. – Jimi Sep 09 '20 at 10:50
  • 1
    You're welcome :) As a side note, you don't need to set the Size of a Window you never show (which would not hide it anyway): what counts here is `StartPosition = FormStartPosition.Manual`, so you can set a specific `Location`. – Jimi Sep 09 '20 at 12:33

1 Answers1

0
private static Form CreateDummyForm(Form mainForm) {
    Form dummy = new Form(); // { Opacity = 0, ShowInTaskbar = false };
    dummy.Location = mainForm.Location;
    IntPtr hwnd = dummy.Handle; // force handle creation
    mainForm.Load += delegate {
        IntPtr blah = dummy.Handle;
    };
    mainForm.LocationChanged += delegate {
        dummy.Location = mainForm.Location;
    };
    return dummy;
}

[STAThread]
static void Main() {
    Application.EnableVisualStyles();
    Application.SetCompatibleTextRenderingDefault(false);
    Form mf = new Form() { Size = new Size(400, 400) };
    Button btn = new Button { Text = "Button" };
    Form dummy = CreateDummyForm(mf);
    btn.Click += delegate {
        Task.Delay(TimeSpan.FromSeconds(5)).ContinueWith((t) => { dummy.Close(); }, TaskScheduler.FromCurrentSynchronizationContext());
        MessageBox.Show(dummy, "blah", "blah", MessageBoxButtons.OKCancel);
        dummy = CreateDummyForm(mf); // Close disposes the dummy form
    };
    mf.Controls.Add(btn);
    Application.Run(mf);
}
Loathing
  • 5,109
  • 3
  • 24
  • 35