0

If the MainWindow is too close to the edge of the screen, opening a New Window with relative positioning can go off screen.

I'd like to have it detect that it's off screen and reposition itself close to the edge, even overlapping the MainWindow. For Top, Bottom, Left and Right.

Example Project Source
https://www.dropbox.com/s/3r2guvssiakcz6f/WindowReposition.zip?dl=0

private Boolean IsWindowOpened = false;


// Info Button
//
private void buttonInfo_Click(object sender, RoutedEventArgs e)
{
    MainWindow mainwindow = this;

    // Start Info Window
    InfoWindow info = new InfoWindow(mainwindow);

    // Only Allow 1 Window Instance
    if (IsWindowOpened) return;
    info.ContentRendered += delegate { IsWindowOpened = true; };
    info.Closed += delegate { IsWindowOpened = false; };

    // Position Relative to MainWindow
    info.Left = mainwindow.Left - 270;
    info.Top = mainwindow.Top + 0;

    // Open Info Window
    info.Show();
}

Example of 1280x720 screen

MainWindow Center Screen
InfoWindow -270px Left, 0px Top

Example 01


Off Screen

MainWindow Top Left of Screen
InfoWindow -270px Left, 0px Top

Example 02


Reposition In Screen

MainWindow Top Left of Screen
InfoWindow -160px Left, 0px Top

Example 03

Camilo Terevinto
  • 31,141
  • 6
  • 88
  • 120
Matt McManis
  • 4,475
  • 5
  • 38
  • 93

2 Answers2

1

To Place Dialog to Left

The quick-n-dirty way of doing this is to simply use Math.Max (i.e. the right-most value) to use the offset or 0, whichever is larger. Using System.Windows.Forms.Screen allows us to accommodate for multiple monitors.

    private void btnInfoToLeft_Click(object sender, RoutedEventArgs e)
    {
        // Figure out which screen we're on
        var allScreens = Screen.AllScreens.ToList();
        var thisScreen = allScreens.SingleOrDefault(s => this.Left >= s.WorkingArea.Left && this.Left < s.WorkingArea.Right);

        // Place dialog to left of window, but not past screen border
        InfoWindow info= new InfoWindow();
        info.Left = Math.Max(this.Left - info.Width - 10, thisScreen.WorkingArea.Left);
        info.Top = Math.Max(this.Top - info.Height - 10, thisScreen.WorkingArea.Top);
        info.Show();
    }

Note that we use the Width of the dialog - it's ActualWidth will be 0 before it is shown on the screen.

To Place Dialog to Right

Similarly, we need to figure out the right-most boundaries of the screen, and account for the width of the main window and dialog, and take the Math.Min value (i.e. the left-most value).

    private void btnInfoToRight_Click(object sender, RoutedEventArgs e)
    {
        // Figure out which screen we're on
        var allScreens = Screen.AllScreens.ToList();
        var thisScreen = allScreens.SingleOrDefault(s => this.Left >= s.WorkingArea.Left && this.Left < s.WorkingArea.Right);

        // Place dialog to right of window, but not past screen border
        InfoWindow info = new InfoWindow();
        info.Left = Math.Min(this.Left + this.ActualWidth + 10, thisScreen.WorkingArea.Right - info.Width);
        info.Top = Math.Min(this.Top + this.ActualHeight + 10, thisScreen.WorkingArea.Bottom - info.Height);
        info.Show();
    }

This time, we still use the Width of the dialog, but the ActualWidth of the main window, which will be the width after it has been drawn (and possibly resized).

In these examples, I've also placed the dialog above/below the main window. You can set the top of the dialog to be equal to the top of the main window, or play around to get it to line up with the bottom, etc., using this example as a guide.

Matt McManis
  • 4,475
  • 5
  • 38
  • 93
Wonko the Sane
  • 10,623
  • 8
  • 67
  • 92
0

There are no shortcuts for this kind of problem. You'll have to figure out the dimensions of the screen you're using, then adjust the position of the info window manually.

Take a look at this StackOverflow post: How to get the size of the current screen in WPF?

tyson
  • 166
  • 1
  • 9