0

I am trying to send a window to a screen, and place that window in the center of the screen. When the button is clicked, it send / close the window and change button content.

My first issue is I can open and close the Window, but only 1 time. The second time I receive: System.InvalidOperationException: 'Cannot set Visibility or call Show, ShowDialog, or WindowInteropHelper.EnsureHandle after a Window has closed.'

Also, if the button is closed manually, it does not change the button content.

Finally, it does not place the window in the center of the screen. I try to place the window in the center of the screen using:

window.HorizontalAlignment = System.Windows.HorizontalAlignment.Center;
window.VerticalAlignment = VerticalAlignment.Center;

but this does not work, it place the window upper left corner.

Can anyone out there guide me on how this should be handled?

Window1 w1 = new Window1();

private void ShowByCoordinates(Window window, string screenName, int LeftTransform, int TopTransform)
    {

        if (button4.Content.ToString() == "Send")
        {
            Screen s0 = Screen.AllScreens.FirstOrDefault(s => s.DeviceName == screenName) ?? Screen.PrimaryScreen;
            Rectangle bounds = s0.WorkingArea;
            window.Left = bounds.X + LeftTransform;
            window.Top = bounds.Y + TopTransform;
            window.HorizontalAlignment = System.Windows.HorizontalAlignment.Center;
            window.VerticalAlignment = VerticalAlignment.Center;
            window.Show();
            button4.Content = "Stop";
        }
        else
        {
            window.Close();
            button4.Content = "Send";
        }
    }

private void Button4_Click(object sender, RoutedEventArgs e)
    {
        ShowByCoordinates(w1, "DISPLAY2", 1920, 0);
    }
Franck E
  • 629
  • 8
  • 26
  • You can't call `Show()` after `Close()`, it will be disposed. Consider to create new window and then show or don't close it but rather `Hide()/Show()`. – Sinatr Jul 23 '19 at 12:44
  • Possible duplicate of [WPF: Cannot reuse window after it has been closed](https://stackoverflow.com/questions/3568233/wpf-cannot-reuse-window-after-it-has-been-closed) – Sinatr Jul 23 '19 at 12:46
  • I just read the provided link and it does solve half the problem, thank you. So only new window location issue. – Franck E Jul 23 '19 at 13:34

2 Answers2

1

First, once you close the window, it's disposed and you can't show it again. Use Show() and Hide() instead.

When you set WindowStartupLocation to CenterScreen ther is a problem: after the window is shown any programmatical changes to its position will be ignored. So you can only do it once this way.

To do it manually, you need to set WindowStartupLocation to Manual and then set your window's Top and Left properties.

The next problem you'll have to consider is the fact that there may be multiple monitors. If you only need to center the window on the monitor set as primary in the system, then:

w.Left = (SystemParameters.WorkArea.Width - w.ActualWidth) / 2 + SystemParameters.WorkArea.Left;
w.Top = (SystemParameters.WorkArea.Height - w.ActualHeight) / 2 + SystemParameters.WorkArea.Top

is enough. If you want to center the window on the current monitor, then you'll need to do something like this:

(method from here):

public static void PostitionWindowOnScreen(Window window, double horizontalShift = 0, double verticalShift = 0)
{
    Screen screen = Screen.FromHandle(new System.Windows.Interop.WindowInteropHelper(window).Handle);
    window.Left = screen.Bounds.X + ((screen.Bounds.Width - window.ActualWidth) / 2) + horizontalShift;
    window.Top = screen.Bounds.Y + ((screen.Bounds.Height - window.ActualHeight) / 2) + verticalShift;
}

To call it:

TestWindow w;

//....

w = new TestWindow();
w.WindowStartupLocation = WindowStartupLocation.Manual;
w.Closed += w_Closed;

//....

private void w_Closed(object sender, EventArgs e)
{
    // to make sure there is no disposed window to access when user closes it manually
    w = null;
    // or:
    // w = new TestWindow();
}

private void Button_ShowWindow_Click(object sender, RoutedEventArgs e)
{
      if (w == null) return;
      PostitionWindowOnScreen(w, 0, 0);
      w.Show();
}

private void Button_HideWindow_Click(object sender, RoutedEventArgs e)
{
    if (w == null) return;
    w.Hide();
}
Arie
  • 5,251
  • 2
  • 33
  • 54
  • Arie, thanks in advance for your reply. I will test and confirm. – Franck E Jul 23 '19 at 13:44
  • @FranckE just small note: the screen selected here is "current" for the window that is being hidden and shown. You may want to consider using its parent or your System.Windows.Application.Current.MainWindow if this behavior is not what you want – Arie Jul 23 '19 at 13:49
  • Ok, all works ok, except the first time I click on the button to display windows1, it open on main screen. If I hide and show again, it will go on the correct screen. Any suggestions? – Franck E Jul 23 '19 at 15:38
  • After playing with it I finally got it working. Thanks a lot Arie for putting me on the right track.. :) – Franck E Jul 23 '19 at 18:17
0

First, if you Close window, you cannot Show it again as already mentioned. You need to use Hide instead of Close.

To center your screen, just use this line:

this.WindowStartupLocation = WindowStartupLocation.CenterScreen;
Michał Turczyn
  • 32,028
  • 14
  • 47
  • 69
  • This does not work because it then starts the window on the main screen and completely ignores the X and Y I am giving it. – Franck E Jul 23 '19 at 13:32