现在有3个显示器,想要在程序中控制应用程序在某个显示器中显示,如何指定相应的显示器?

解决方案 »

  1.   

    The Virtual Screen
    The bounding rectangle of all the monitors is the virtual screen. The desktop covers the virtual screen instead of a single monitor. The following illustration shows a possible arrangement of three monitors. The primary monitor contains the origin (0,0). This is for compatibility with existing applications that expect a monitor with an origin. However, the primary monitor does not have to be in the upper left of the virtual screen. In Figure 1, it is near the center. When the primary monitor is not in the upper left of the virtual screen, parts of the virtual screen have negative coordinates. Because the arrangement of monitors is set by the user, all applications should be designed to work with negative coordinates. For more information, see Multiple Monitor Considerations for Older Programs. For Windows 98/Me, the primary monitor is the same as the VGA/Boot display. For Windows 2000/XP, the primary monitor can be any monitor.The coordinates of the virtual screen are represented by a signed 16-bit value because of the 16-bit values contained in many existing messages. Thus, the bounds of the virtual screen are:SHORT_MIN    <= rcVirtualScreen.left   <= SHORT_MAX - 1
    SHORT_MIN +1 <= rcVirtualScreen.right  <= SHORT_MAX
    SHORT_MIN    <= rcVirtualScreen.top    <= SHORT_MAX - 1
    SHORT_MIN +1 <= rcVirtualScreen.bottom <= SHORT_MAX
      

  2.   

    HMONITOR and the Device Context
    Each physical display is represented by a monitor handle of type HMONITOR. A valid HMONITOR is guaranteed to be non-NULL. A physical display has the same HMONITOR as long as it is part of the desktop. When a WM_DISPLAYCHANGE message is sent, any monitor may be removed from the desktop—and thus its HMONITOR becomes invalid—or has its settings changed. Therefore, an application should check whether all HMONITORS are valid when this message is sent. Any function that returns a display device context (DC) normally returns a DC for the primary monitor. To obtain the DC for another monitor, use the EnumDisplayMonitors function. Or, you can use the device name from the GetMonitorInfo function to create a DC with CreateDC. However, if the function, such as GetWindowDC or BeginPaint, gets a DC for a window that spans more than one display, the DC will also span the two displays. 
      

  3.   

    Painting on a DC That Spans Multiple Displays
    To respond to a WM_PAINT message, use code like the following.case WM_PAINT:
    hdc = BeginPaint(hwnd, &ps);
    EnumDisplayMonitors(hdc, NULL, MyPaintEnumProc, 0);
    EndPaint(hwnd, &ps);
     
    To paint the top half of a window, use code like the following.GetClient Rect(hwnd, &rc);
    rc.bottom = (rc.bottom - rc.top) / 2;
    hdc = GetDC(hwnd);
    EnumDisplayMonitors(hdc, &rc, MyPaintEnumProc, 0);
    ReleaseDC(hwnd, hdc);To paint the entire virtual screen optimally for each monitor, use code like the following.hdc = GetDC(NULL);
    EnumDisplayMonitors(hdc, NULL, MyPaintScreenEnumProc, 0);
    ReleaseDC(NULL, hdc);
    Positioning Objects on a Multiple Display Setup
    The following sample code demonstrates how applications can correctly position objects on multiple displays. Note, do not assume that the RECT is based on the origin (0,0).#include <windows.h>
    #include "multimon.h"    #define MONITOR_CENTER     0x0001        // center rect to monitor
    #define MONITOR_CLIP     0x0000        // clip rect to monitor
    #define MONITOR_WORKAREA 0x0002        // use monitor work area
    #define MONITOR_AREA     0x0000        // use monitor entire area//
    //  ClipOrCenterRectToMonitor
    //
    //  The most common problem apps have when running on a
    //  multimonitor system is that they "clip" or "pin" windows
    //  based on the SM_CXSCREEN and SM_CYSCREEN system metrics.
    //  Because of app compatibility reasons these system metrics
    //  return the size of the primary monitor.
    //
    //  This shows how you use the multi-monitor functions
    //  to do the same thing.
    //
    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 monitor to the passed rect.
        //
        hMonitor = MonitorFromRect(prc, MONITOR_DEFAULTTONEAREST);    //
        // get the work area or entire monitor rect.
        //
        mi.cbSize = sizeof(mi);
        GetMonitorInfo(hMonitor, &mi);    if (flags & MONITOR_WORKAREA)
            rc = mi.rcWork;
        else
            rc = mi.rcMonitor;    //
        // center or clip the passed rect to the monitor rect
        //
        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);
    }