Free Web Hosting Provider - Web Hosting - E-commerce - High Speed Internet - Free Web Page
Search the Web

Windows 2000 Graphics API Black Book
Home | Introduction | Table of Contents | Updates | New Stuff | Links | About the Authors | Ordering
 

Enumerating the Display Monitors
 

New in Windows 98, ME, and 2000 is the ability to attach more than one monitor to a single computer.  These platforms provide support for a virtual desktop that spans multiple display monitors, each with its own unique resolution and color-depth.  From a programming perspective, there is little that you need to do for multiple monitor support—the systems manages most of the details.  In some situations, however, you might want to take advantage of the system’s support for mutiple monitors to increase the functionality of your application.  For example, if you’re creating an application that occupies a large portion of the screen, you might want to implement a feature that allows your application to conform to the dimensions of a particular monitor.
 
Before you begin the enumeration process, you can verify that the system is running with a multiple monitor setup via the GetSystemMetrics function with the SM_CMONITORS metric index:

 

const int num_monitors = GetSystemMetrics(SM_CMONITORS);

 

To enumerate the available display monitors on systems running Windows 98, Me, or 2000, you use the EnumDisplayMonitors function:

 

BOOL EnumDisplayMonitors (

    IN HDC hdc,                      // handle to a display device context

    IN LPCRECT lprcClip,             // pointer to a clipping RECT

    IN MONITORENUMPROC lpfnEnum,     // pointer to a callback function

    IN LPARAM dwData                 // application-defined data that will be

                                     // passed to the callback function

   );

 

The hdc parameter identifies the display device context whose visible area is used as a filter during the enumeration process.  This parameter is useful when you’re interested in enumerating only those monitors that intersect a particular region. This region is formed by the intersection of the visible area of the device context (identified by the hdc parameter) and the clipping rectangle identified by the lprcClip parameter.  For the purpose of enumerating all display monitors, you can simply set both of these parameters to NULL.  The lpfnEnum parameter is a pointer to an application-defined callback function; if you need to supply extra information to this function, you can use the 32-bits available via the dwData parameter.  
 
The EnumDisplayMonitors function will invoke the callback function, indicated by the lpfnEnum parameter, once for each monitor that is found.  This callback function itself is of type MONITORENUMPROC:

 

typedef BOOL (CALLBACK* MONITORENUMPROC)(HMONITOR, HDC, LPRECT, LPARAM);

 

The first parameter is of type HMONITOR, a handle to a display monitor.  From within the callback function, you can pass this value to the GetMonitorInfo function to retrieve monitor-specific information.  For example, the code in Listing 1.6 enumerates all of the display monitors, retreiving the color-depth of each monitor.

Listing 1.6 Enumerating the available monitors under Windows 98, Me, or 2000.

// ------------------------------------------------------------------

// Windows 2000 Graphics API Black Book

// Chapter 1 - Listing 1.6 (EnumDisplayMonitors Demo)

// ------------------------------------------------------------------

 

#define WINVER 0x0500

#include <windows.h>

 

HWND hListBox;

const int ID_BUTTON = 101;

 

HINSTANCE hInst;

LPCSTR WndClassName = TEXT("GMainWnd");

LRESULT CALLBACK MainWndProc(HWND HWnd, UINT Msg, WPARAM WParam,

   LPARAM LParam);

 

int APIENTRY WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,

    LPTSTR lpCmdLine, int nCmdShow)

{

   hInst = hInstance;

 

   WNDCLASS wc;

   memset(&wc, 0, sizeof(WNDCLASS));

   

   wc.lpfnWndProc = MainWndProc;

   wc.hInstance = hInstance;

   wc.hCursor = LoadCursor(NULL, IDC_ARROW);

   wc.hbrBackground = reinterpret_cast<HBRUSH>(COLOR_BTNFACE + 1);

   wc.lpszClassName = WndClassName;

 

   if (RegisterClass(&wc))

   {

      HWND hWnd =

         CreateWindow(WndClassName, TEXT("'EnumDisplayMonitors' Demo"),

                      WS_OVERLAPPEDWINDOW | WS_CAPTION |

                      WS_VISIBLE | WS_CLIPSIBLINGS,

                      CW_USEDEFAULT, CW_USEDEFAULT, 320, 225,

                      NULL, NULL, hInst, NULL);

                                

      if (hWnd)

      {

         ShowWindow(hWnd, nCmdShow);

         UpdateWindow(hWnd);

 

         MSG msg;

         while (GetMessage(&msg, NULL, 0, 0))

         {

              TranslateMessage(&msg);

             DispatchMessage(&msg);

         }     

      }

    }

    return 0;

}

 

//

// this is the application-defined callback function

// 

BOOL CALLBACK EnumMonitorsProc(HMONITOR hMonitor, HDC hdc,

   LPRECT lpRMonitor, LPARAM dwData)

{

   MONITORINFOEX mix;

   memset(&mix, 0, sizeof(MONITORINFOEX));

   mix.cbSize = sizeof(MONITORINFOEX);

 

   if (GetMonitorInfo(hMonitor, &mix))

   {

      HDC hMonitorDC =

         CreateDC("DISPLAY", mix.szDevice, NULL, NULL);

         // for Win98:

         // CreateDC(NULL, mix.szDevice, NULL, NULL);

 

      if (hMonitorDC)

      {

         const int color_depth =

            GetDeviceCaps(hMonitorDC, BITSPIXEL) *

            GetDeviceCaps(hMonitorDC, PLANES);

         DeleteDC(hMonitorDC);

 

         char szColorDepth[2];

         wsprintf(szColorDepth, "%d", color_depth);

 

         HWND hListBox = reinterpret_cast<HWND>(dwData);

         SNDMSG(hListBox, LB_ADDSTRING, 0,

                reinterpret_cast<LPARAM>(mix.szDevice));

         SNDMSG(hListBox, LB_ADDSTRING, 0,

                reinterpret_cast<LPARAM>(szColorDepth));

         SNDMSG(hListBox, LB_ADDSTRING, 0,

                reinterpret_cast<LPARAM>(""));

      }

   }

   return true;

}

 

LRESULT CALLBACK MainWndProc(HWND hWnd, UINT msg, WPARAM wParam,

   LPARAM lParam)

{

   switch (msg)

   {

      case WM_CREATE:

      {

         // create a push button

         CreateWindow(TEXT("BUTTON"), TEXT( "Enumerate"),

                      BS_FLAT | WS_CHILD | WS_VISIBLE,

                      200, 5, 100, 25,

                      hWnd, reinterpret_cast<HMENU>(ID_BUTTON),

                      hInst, NULL);

 

         // create a list box

         hListBox =

            CreateWindowEx(WS_EX_CLIENTEDGE, TEXT( "LISTBOX"), "",

                           WS_CHILD | WS_VISIBLE | WS_VSCROLL,

                           10, 5, 175, 190,

                           hWnd, NULL, hInst, NULL); 

         break;

      }

      case WM_COMMAND:

      {   

         // when the button is clicked...     

         if (wParam == MAKEWPARAM(ID_BUTTON, BN_CLICKED))

         {

            // fill the list box with monitor info

            EnumDisplayMonitors(

               NULL, NULL, EnumMonitorsProc, 

               reinterpret_cast<LPARAM>(hListBox)   

               );

         }

         break;

      }

      case WM_DESTROY:

      { 

         PostQuitMessage(0);

         break;      

      }

   }

   return DefWindowProc(hWnd, msg, wParam, lParam);

 

Copyright © 2001 Damon Chandler and Michael Fötsch