Positioning Objects on Multiple Screens

Placing a window or menu on more than one screen causes visual disruption for a user. To minimize this problem, the OS displays menus and new or maximized windows within one screen. The following table shows the screens on which the OS places windows and other user interface elements.

Object Location
window Appears on the screen that contains the largest part of the window when you create the window by calling the CreateWindow or CreateWindowEx function.

Maximizes on the screen that contained the largest part of the window before the user minimized the window.

owned window Appears on the same screen as its owner.
submenu Appears on the screen that contains the largest part of the corresponding menu item.
context menu Appears on the screen on which the user right-clicked.
drop-down list Appears on the screen that contains the rectangle of the combo box.
dialog box Appears on the screen of the window that owns it.

If the dialog box has no owner and the active window is not in the same application as the dialog box, the dialog box appears on the primary screen.

message box Appears on the screen of the window that owns it.

An application typically also needs to position objects. For example, an application may need to create a window on the same screen as another window.

To position an object on a multiple screen system

  1. Determine the appropriate screen for the object.

    Typically, you want to position an object either on the primary screen or on a screen that already contains another object. To identify the screen that contains a given point, rectangle, or window, use the MonitorFromPoint, MonitorFromRect, or MonitorFromWindow function.

  2. Get the coordinates to the screen by calling the GetMonitorInfo function, which provides both the work area and the entire screen rectangle.

    The SM_CXSCREEN and SM_CYSCREEN system metrics used by the GetSystemMetrics function always refer to the primary screen and not necessarily to the screen that displays your application. Also, avoid using the SM_CXVIRTUALSCREEN and SM_CYVIRTUALSCREEN system metrics because these values refer to the virtual screen, not to a physical screen.

  3. Position the object using these coordinates.

To center a dialog box in the work area of a window, use the DS_CENTER style. To center the dialog box in an application window, use the GetWindowRect function. Windows CE automatically restricts menus and dialog boxes to a single screen. This restriction, however, can be a problem for custom menus, custom drop-down boxes, custom tool palettes, and the saved position of an application.

Using the SM_CXSCREEN and SM_CYSCREEN system metrics to determine the location of an application toolbar restricts the location of the toolbar to the primary screen. To place the toolbar on any edge of any screen, use the appropriate system metrics to calculate the edges of the screens.

A maximized window does not cover a taskbar that has the Always on top property. In contrast, a full-screen window covers the taskbar, for example, in Microsoft PowerPoint® slide shows and games.

The OS tries to start an application on the screen that contains the shortcut for the application. Therefore, one way to position an application is to place the shortcut on the desired screen.

If you use the ShellExecuteEx function, supply a window handle**so the OS opens any new windows on the same screen as the calling application.

The following sample code demonstrates how applications can correctly position objects on multiple screens. Do not assume that the coordinates in the RECT structure are based on the origin (0,0).

#include <windows.h>

#define MONITOR_CENTER   0x0001        // Center rectangle on screen.
#define MONITOR_CLIP     0x0000        // Clip rectangle to screen.
#define MONITOR_WORKAREA 0x0002        // Use work area of screen.
#define MONITOR_AREA     0x0000        // Use entire area of screen.

//
// ClipOrCenterRectToMonitor
//
// The most common problem applications have when running on a
// multiple screen system is that the applications clip or center windows
// based on the SM_CXSCREEN and SM_CYSCREEN system metrics.
// For compatibility with existing applications, these system metrics
// return the size of the primary screen.
//
// This function shows how you use the multimonitor functions
// to clip or center windows.
//
void ClipOrCenterRectToMonitor(LPRECT prc, UINT flags)
{
    HMONITOR hMonitor;
    MONITORINFO mi;
    RECT        rc;
    int         w = prc->right  - prc->left;
    int         h = prc->bottom - prc->top;

    //
    // Get the nearest screen to the passed rectangle.
    //
    hMonitor = MonitorFromRect(prc, MONITOR_DEFAULTTONEAREST);

    //
    // Get the work area or entire screen rectangle.
    //
    mi.cbSize = sizeof(mi);
    GetMonitorInfo(hMonitor, &mi);

    if (flags & MONITOR_WORKAREA)
        rc = mi.rcWork;
    else
        rc = mi.rcMonitor;

    //
    // Center or clip the passed rectangle to the screen rectangle.
    //
    if (flags & MONITOR_CENTER)
    {
        prc->left   = rc.left + (rc.right  - rc.left - w) / 2;
        prc->top    = rc.top  + (rc.bottom - rc.top  - h) / 2;
        prc->right  = prc->left + w;
        prc->bottom = prc->top  + h;
    }
    else
    {
        prc->left   = max(rc.left, min(rc.right-w,  prc->left));
        prc->top    = max(rc.top,  min(rc.bottom-h, prc->top));
        prc->right  = prc->left + w;
        prc->bottom = prc->top  + h;
    }
}

void ClipOrCenterWindowToMonitor(HWND hwnd, UINT flags)
{
    RECT rc;
    GetWindowRect(hwnd, &rc);
    ClipOrCenterRectToMonitor(&rc, flags);
    SetWindowPos(hwnd, NULL, rc.left, rc.top, 0, 0, SWP_NOSIZE | 
                 SWP_NOZORDER | SWP_NOACTIVATE);
}

 Last updated on Friday, April 09, 2004

© 1992-2003 Microsoft Corporation. All rights reserved.