구리의 창고

멀티모니터 정보 구해오기 본문

Programming

멀티모니터 정보 구해오기

구리z 2010. 3. 25. 10:27

응용 프로그램이 다중 모니터 환경을 직접 다루거나 다중 모니터로 인한 문제점을 해결하려면 먼저 시스템에 장착된 모니터에 대한 정보를 조사해야 한다. 다음 함수는 시스템의 모든 모니터 또는 특정 DC와 관련된 모니터를 열거한다.

BOOL EnumDisplayMonitors(HDC hdc, LPCRECT lprcClip, MONITORENUMPROC lpfnEnum, LPARAM dwData);

hdc와 lprcClip 인수에 대해서는 잠시 후 따로 정리해 보기로 하되 이 값이 둘 다 NULL이면 모든 모니터가 열거된다. lpfnEnum 인수는 모니터가 발견될 때마다 호출될 콜백 함수이며 dwData는 이 함수로 전달될 사용자 정의값이다. 콜백 함수는 다음과 같은 원형을 가진다.

BOOL CALLBACK MonitorEnumProc(HMONITOR hMonitor, HDC hdcMonitor, LPRECT lprcMonitor, LPARAM dwData);

첫번째 인수 hMonitor는 발견된 모니터의 핸들인데 이 핸들로부터 모니터의 상세한 정보를 조사할 수 있다. hdcMonitor는 이 모니터 영역에 그리기를 할 때 사용할 DC 핸들이며 lprcMonitor는 모니터의 좌표값인데 잠시 후 따로 정리하도록 하자. 열거를 계속하려면 TRUE를 리턴하고 열거를 중지하려면 FALSE를 리턴하면 된다. 원하는 모니터를 찾았을 때 FALSE를 리턴하면 모니터 열거가 끝난다. 모니터의 핸들로부터 모니터의 정보를 조사할 때는 다음 함수를 사용한다.

BOOL GetMonitorInfo(HMONITOR hMonitor, LPMONITORINFO lpmi);

MONITORINFO(EX) 구조체를 선언한 후 이 구조체의 포인터를 전달하면 모니터 관련 정보를 구조체에 채워준다. 이 구조체는 다음과 같이 선언되어 있다.

typedef struct tagMONITORINFOEX { 
  DWORD  cbSize;
  RECT   rcMonitor;
  RECT   rcWork;
  DWORD  dwFlags;
  TCHAR  szDevice[CCHDEVICENAME];
} MONITORINFOEX, *LPMONITORINFOEX;
 
맴버 설명
cbSize 구조체의 크기이며, GetMonitorInfo를 호출하기 전에 대입 해줘야 한다.
rcMonitor 가상 화면상의 모니터좌표이다.
rcWork 가상 화면상 작업공간 좌표이다.
dwFlags 주 모니터의 경우, MONITORINFOF_PRIMARY
szDevice 모니터 이름

다음 예제는 모든 모니터 정보를 읽어온다.

#define WINVER 0x0500
#include <windows.h>
....
int y;
BOOL CALLBACK MonitorEnumProc(HMONITOR hMonitor,HDC hdcMonitor,LPRECT lprcMonitor,LPARAM dwData)
{
   TCHAR sInfo[256];
   MONITORINFOEX mi;
 
   mi.cbSize=sizeof(MONITORINFOEX);
   GetMonitorInfo(hMonitor,&mi);
   wsprintf(sInfo,"모니터 핸들 = %x, 좌표=(%d,%d)-(%d,%d) %s",hMonitor,
      lprcMonitor->left,lprcMonitor->top,lprcMonitor->right,lprcMonitor->bottom,
      (mi.dwFlags & MONITORINFOF_PRIMARY)==0 ? "":"주 모니터");
   TextOut((HDC)dwData,10,y,sInfo,lstrlen(sInfo));
   y+=20;
   return TRUE;
}
 
LRESULT CALLBACK WndProc(HWND hWnd,UINT iMessage,WPARAM wParam,LPARAM lParam)
{
   HDC hdc;
   PAINTSTRUCT ps;
   TCHAR Mes[256];
   int cMon;
   RECT rcVirt;
 
   switch(iMessage) {
   case WM_LBUTTONDOWN:
   case WM_DISPLAYCHANGE:
      InvalidateRect(hWnd,NULL,TRUE);
      UpdateWindow(hWnd);
      return 0;
   case WM_PAINT:
      hdc=BeginPaint(hWnd, &ps);
      cMon=GetSystemMetrics(SM_CMONITORS);
      if (cMon == 0) {
          lstrcpy(Mes,"다중 모니터를 지원하지 않는 시스템입니다");
          TextOut(hdc,10,10,Mes,lstrlen(Mes));
      } else {
          wsprintf(Mes,"모니터 개수 = %d, 색상 포맷=%s",cMon,
             GetSystemMetrics(SM_SAMEDISPLAYFORMAT) ? "모두 동일":"다름");
          TextOut(hdc,10,10,Mes,lstrlen(Mes));
 
          rcVirt.left=GetSystemMetrics(SM_XVIRTUALSCREEN);
          rcVirt.top=GetSystemMetrics(SM_YVIRTUALSCREEN);
          rcVirt.right=rcVirt.left+GetSystemMetrics(SM_CXVIRTUALSCREEN);
          rcVirt.bottom=rcVirt.top+GetSystemMetrics(SM_CYVIRTUALSCREEN);
          wsprintf(Mes,"가상 화면=(%d,%d)-(%d,%d)",rcVirt.left,rcVirt.top,
             rcVirt.right,rcVirt.bottom);
          TextOut(hdc,10,30,Mes,lstrlen(Mes));
 
          y=50;
          EnumDisplayMonitors(NULL,NULL,MonitorEnumProc,(LPARAM)hdc);
      }
      EndPaint(hWnd, &ps);
      return 0;
   case WM_DESTROY:
      PostQuitMessage(0);
      return 0;
   }
   return(DefWindowProc(hWnd,iMessage,wParam,lParam));
}
 
출처 : http://www.winapi.co.kr/win32lec/lecnew/25-4-3.htm
Comments