简体   繁体   中英

Alternative to GetWindowRect() for multi-monitor usage?

I am trying to reposition a form to bottom/right point of a control.

public void SetAutoLocation()
{
    Rect rect;
    GetWindowRect(referenceControl.Handle, out rect);
    Point targetPoint;
    targetPoint = new Point(rect.left, rect.top + referenceControl.Height);

    if (rect.left + referenceControl.Width - this.Width < 0) //Outside left border
    {
        targetPoint.X = 0;
    }
    else
    {
        targetPoint.X = rect.left - this.Width + referenceControl.Width;
    }
    if (targetPoint.X + this.Width > System.Windows.Forms.SystemInformation.WorkingArea.Right) //Outside right border
    {
        targetPoint.X = System.Windows.Forms.SystemInformation.WorkingArea.Right - this.Width;
    }
    else if (targetPoint.X < 0)
        targetPoint.X = 0;

    if (targetPoint.Y + this.Height > System.Windows.Forms.SystemInformation.WorkingArea.Bottom) //Outside below border
    {
        targetPoint.Y = rect.top - this.Height;
    }
    if (targetPoint.Y < 0)
    {
        targetPoint.Y = 0;
    }
    if (targetPoint.X < 0)
    {
        targetPoint.X = 0;
    }

    this.Location = targetPoint;
    this.Refresh();

}

The above code works well in single monitor display. But when the parent form is opened in dual monitor display, the form positions itself on the 1st monitor, as GetWindowRect() returns the rectangle inside the primary display.

So looking for some alternative to GetWindowRect() that might work on multi-display.

Use the Screen class to get the WorkingArea for the monitor that the control is on:

    var screen = Screen.FromControl(referenceControl);
    var area = screen.WorkingArea;
    var rect = referenceControl.RectangleToScreen(
        new Rectangle(0, 0, referenceControl.Width, referenceControl.Height));
    // etc..

Note how RectangleToScreen can help you avoid having to pinvoke GetWindowRect().

If you consult MSDN it's clearly stated that SystemInformation.WorkingArea returns informations only for primary monitor :

WorkingArea always returns the work area of the primary monitor. If you need the work area of a monitor in a multiple display environment, you can call one of the overloads of Screen.GetWorkingArea.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM