2011년 8월 4일 목요일

멀티모니터 열거하기 - Multiple Monitor Enumeration

모니터가 여러 개인 경우 directdraw api 를 사용해 모니터별로 열거할수 있다.
getScreen() 함수는 지정한 RECT 에 해당하는 모니터를 찾고 모니터 오프셋 값을 RECT 에 넣어줌

//----------------------------------------------------------------------------------
#define  MAX_MONITOR (4)

struct Monitor {
    HMONITOR hMon;
    GUID guid; 
};

class MonitorManager {
    Monitor monitor[MAX_MONITOR];
    int nScreen;
    ...
    int getScreen(RECT *rect);
};

// Enumerate Monitor
struct EnumInfo
{
    BOOL bMultimonSupported;
    HRESULT hr;
};

BOOL WINAPI DDEnumCallbackEx( GUID* pGuid, LPTSTR pszDesc, LPTSTR pszDriverName,
                              VOID* pContext, HMONITOR hmon )
{
MONITORINFO mi;
if (pGuid != NULL && hmon != NULL) {
mi.cbSize = sizeof(mi);
GetMonitorInfo(hmon, &mi);

MonitorManager *manager = (MonitorManager *)pContext;
manager->monitor[manager->nScreen].guid = *pGuid;
manager->monitor[manager->nScreen].hMon = hmon;
manager->nScreen++;
}
    return TRUE; // Keep enumerating
}

BOOL WINAPI DDEnumCallback( GUID* pGuid, LPTSTR pszDesc, LPTSTR pszDriverName,
                            VOID* pContext )
{
    DDEnumCallbackEx(pGuid, pszDesc, pszDriverName, pContext, NULL);
    return FALSE; // Stop enumerating -- For this sample, we don't want any non-display devices
}

HRESULT EnumerateScreens(MonitorManager *manager)
{
    HRESULT hr;
    HMODULE hModule = NULL;
    LPDIRECTDRAWENUMERATEEX pDDEnumEx = NULL;
    EnumInfo enumInfo;

    ZeroMemory(&enumInfo, sizeof(enumInfo));

    hModule = LoadLibrary( TEXT("ddraw.dll") );
    // If ddraw.dll doesn't exist in the search path,
    // then DirectX probably isn't installed, so fail.
    if (hModule == NULL)
        return E_FAIL;
 
    pDDEnumEx = (LPDIRECTDRAWENUMERATEEX) GetProcAddress(hModule,
#ifdef UNICODE
        "DirectDrawEnumerateExW"
#else
        "DirectDrawEnumerateExA"
#endif
        );

manager->nScreen = 0;

    if (pDDEnumEx == NULL)
    {
        // We must be running on an old version of DirectDraw.
        // Therefore MultiMon isn't supported. Fall back on
        // DirectDrawEnumerate to enumerate standard devices on a
        // single-monitor system.
        enumInfo.bMultimonSupported = FALSE;
        hr = DirectDrawEnumerate(DDEnumCallback, manager);
    }
    else
    {
        enumInfo.bMultimonSupported = TRUE;
        hr = pDDEnumEx(DDEnumCallbackEx, manager, DDENUM_ATTACHEDSECONDARYDEVICES);
    }

    // If something failed inside the enumeration, be sure to return that HRESULT

    FreeLibrary(hModule);
    return hr;
}

int MonitorManager::getScreen(RECT *rect)
{
MONITORINFO mi;
HMONITOR hMon = MonitorFromRect(rect, MONITOR_DEFAULTTONEAREST);
for (int i=0; i < nScreen; i++) {
if (hMon == monitor[i].hMon) {
mi.cbSize = sizeof(mi);
GetMonitorInfo(hMon, &mi);
OffsetRect(rect, -mi.rcMonitor.left, -mi.rcMonitor.top);
return i;
}
}

return -1;
}

댓글 없음:

댓글 쓰기