1 #if !defined(_WIN32_WINNT) || (_WIN32_WINNT < 0x0500)
2 
3 //=============================================================================
4 //
5 // MULTIMON
6 // stub module that "stubs" multiple monitor APIs on pre-Memphis Win32 OSes
7 //
8 // By using this header your code will work unchanged on Win95,
9 // you will get back correct values from GetSystemMetrics() for new metrics
10 // and the new APIs will act like only one display is present.
11 //
12 // exactly one source must include this with COMPILE_MULTIMON_STUBS defined
13 //
14 //=============================================================================
15 
16 #ifdef __cplusplus
17 extern "C" {            /* Assume C declarations for C++ */
18 #endif  /* __cplusplus */
19 
20 //
21 // if we are building on Win95/NT4 headers we need to declare this stuff ourselves
22 //
23 #ifndef SM_CMONITORS
24 
25 #define SM_XVIRTUALSCREEN       76
26 #define SM_YVIRTUALSCREEN       77
27 #define SM_CXVIRTUALSCREEN      78
28 #define SM_CYVIRTUALSCREEN      79
29 #define SM_CMONITORS            80
30 #define SM_SAMEDISPLAYFORMAT    81
31 
32 DECLARE_HANDLE(HMONITOR);
33 
34 #define MONITOR_DEFAULTTONULL       0x00000000
35 #define MONITOR_DEFAULTTOPRIMARY    0x00000001
36 #define MONITOR_DEFAULTTONEAREST    0x00000002
37 
38 #define MONITORINFOF_PRIMARY        0x00000001
39 
40 typedef struct tagMONITORINFO
41 {
42     DWORD   cbSize;
43     RECT    rcMonitor;
44     RECT    rcWork;
45     DWORD   dwFlags;
46 } MONITORINFO, *LPMONITORINFO;
47 
48 #define CCHDEVICENAME 32
49 
50 #ifdef __cplusplus
51 typedef struct tagMONITORINFOEX : public tagMONITORINFO
52 {
53   TCHAR       szDevice[CCHDEVICENAME];
54 } MONITORINFOEX, *LPMONITORINFOEX;
55 #else
56 typedef struct
57 {
58   MONITORINFO;
59   TCHAR       szDevice[CCHDEVICENAME];
60 } MONITORINFOEX, *LPMONITORINFOEX;
61 #endif
62 
63 typedef BOOL (CALLBACK* MONITORENUMPROC)(HMONITOR, HDC, LPRECT, LPARAM);
64 
65 #endif  // SM_CMONITORS
66 
67 #ifndef DISPLAY_DEVICE_ATTACHED_TO_DESKTOP
68 
69 typedef struct {
70     DWORD  cb;
71     CHAR   DeviceName[32];
72     CHAR   DeviceString[128];
73     DWORD  StateFlags;
74 } DISPLAY_DEVICE;
75 
76 #define DISPLAY_DEVICE_ATTACHED_TO_DESKTOP 0x00000001
77 #define DISPLAY_DEVICE_MULTI_DRIVER        0x00000002
78 #define DISPLAY_DEVICE_PRIMARY_DEVICE      0x00000004
79 #define DISPLAY_DEVICE_MIRRORING_DRIVER    0x00000008
80 
81 #endif
82 #define DISPLAY_DEVICE_VGA                 0x00000010
83 
84 #ifndef ENUM_CURRENT_SETTINGS
85 #define ENUM_CURRENT_SETTINGS       ((DWORD)-1)
86 #define ENUM_REGISTRY_SETTINGS      ((DWORD)-2)
87 #endif
88 
89 #undef GetMonitorInfo
90 #undef GetSystemMetrics
91 #undef MonitorFromWindow
92 #undef MonitorFromRect
93 #undef MonitorFromPoint
94 #undef EnumDisplayMonitors
95 #undef EnumDisplayDevices
96 
97 //
98 // define this to compile the stubs
99 // otherwise you get the declarations
100 //
101 #ifdef COMPILE_MULTIMON_STUBS
102 
103     //---------------------------------------------------------------------------
104     //
105     // Implement the API stubs.
106     //
107     //---------------------------------------------------------------------------
108 
109     int      (WINAPI* g_pfnGetSystemMetrics)(int);
110     HMONITOR (WINAPI* g_pfnMonitorFromWindow)(HWND, BOOL);
111     HMONITOR (WINAPI* g_pfnMonitorFromRect)(LPCRECT, BOOL);
112     HMONITOR (WINAPI* g_pfnMonitorFromPoint)(POINT, BOOL);
113     BOOL     (WINAPI* g_pfnGetMonitorInfo)(HMONITOR, LPMONITORINFO);
114     BOOL     (WINAPI* g_pfnEnumDisplayMonitors)(HDC, LPCRECT,
115               MONITORENUMPROC, LPARAM);
116     BOOL     (WINAPI *g_pfnEnumDisplayDevices)(LPVOID, int,
117               DISPLAY_DEVICE *,DWORD);
118 
InitMultipleMonitorStubs(void)119     BOOL InitMultipleMonitorStubs(void)
120     {
121         HMODULE hUser32;
122         static BOOL fInitDone;
123 
124         if (fInitDone)
125         {
126             return g_pfnGetMonitorInfo != NULL;
127         }
128 
129         if ((hUser32 = GetModuleHandle(TEXT("USER32"))) &&
130             (*(FARPROC*)&g_pfnGetSystemMetrics    = GetProcAddress(hUser32,"GetSystemMetrics")) &&
131             (*(FARPROC*)&g_pfnMonitorFromWindow   = GetProcAddress(hUser32,"MonitorFromWindow")) &&
132             (*(FARPROC*)&g_pfnMonitorFromRect     = GetProcAddress(hUser32,"MonitorFromRect")) &&
133             (*(FARPROC*)&g_pfnMonitorFromPoint    = GetProcAddress(hUser32,"MonitorFromPoint")) &&
134             (*(FARPROC*)&g_pfnEnumDisplayMonitors = GetProcAddress(hUser32,"EnumDisplayMonitors")) &&
135     #ifdef UNICODE
136             (*(FARPROC*)&g_pfnGetMonitorInfo      = GetProcAddress(hUser32,"GetMonitorInfoW")) &&
137             (*(FARPROC*)&g_pfnEnumDisplayDevices  = GetProcAddress(hUser32,"EnumDisplayDevicesW")) &&
138     #else
139             (*(FARPROC*)&g_pfnGetMonitorInfo      = GetProcAddress(hUser32,"GetMonitorInfoA")) &&
140             (*(FARPROC*)&g_pfnEnumDisplayDevices  = GetProcAddress(hUser32,"EnumDisplayDevicesA")) &&
141     #endif
142             (GetSystemMetrics(SM_CXVIRTUALSCREEN) >= GetSystemMetrics(SM_CXSCREEN)) &&
143             (GetSystemMetrics(SM_CYVIRTUALSCREEN) >= GetSystemMetrics(SM_CYSCREEN)) )
144         {
145             fInitDone = TRUE;
146             return TRUE;
147         }
148         else
149         {
150             g_pfnGetSystemMetrics    = NULL;
151             g_pfnMonitorFromWindow   = NULL;
152             g_pfnMonitorFromRect     = NULL;
153             g_pfnMonitorFromPoint    = NULL;
154             g_pfnGetMonitorInfo      = NULL;
155             g_pfnEnumDisplayMonitors = NULL;
156             g_pfnEnumDisplayDevices  = NULL;
157 
158             fInitDone = TRUE;
159             return FALSE;
160         }
161     }
162 
163     //---------------------------------------------------------------------------
164     //
165     // "stubbed" implementations of Monitor APIs that work with the primary         //  display
166     //
167     //---------------------------------------------------------------------------
168 
169     int WINAPI
xGetSystemMetrics(int nIndex)170     xGetSystemMetrics(int nIndex)
171     {
172         if (InitMultipleMonitorStubs())
173             return g_pfnGetSystemMetrics(nIndex);
174 
175         switch (nIndex)
176         {
177         case SM_CMONITORS:
178         case SM_SAMEDISPLAYFORMAT:
179             return 1;
180 
181         case SM_XVIRTUALSCREEN:
182         case SM_YVIRTUALSCREEN:
183             return 0;
184 
185         case SM_CXVIRTUALSCREEN:
186             nIndex = SM_CXSCREEN;
187             break;
188 
189         case SM_CYVIRTUALSCREEN:
190             nIndex = SM_CYSCREEN;
191             break;
192         }
193 
194         return GetSystemMetrics(nIndex);
195     }
196 
197     #define xPRIMARY_MONITOR ((HMONITOR)0x42)
198 
199     HMONITOR WINAPI
xMonitorFromRect(LPCRECT lprcScreenCoords,UINT uFlags)200     xMonitorFromRect(LPCRECT lprcScreenCoords, UINT uFlags)
201     {
202         if (InitMultipleMonitorStubs())
203             return g_pfnMonitorFromRect(lprcScreenCoords, uFlags);
204 
205         if ((uFlags & (MONITOR_DEFAULTTOPRIMARY | MONITOR_DEFAULTTONEAREST)) ||
206             ((lprcScreenCoords->right > 0) &&
207             (lprcScreenCoords->bottom > 0) &&
208             (lprcScreenCoords->left < GetSystemMetrics(SM_CXSCREEN)) &&
209             (lprcScreenCoords->top < GetSystemMetrics(SM_CYSCREEN))))
210         {
211             return xPRIMARY_MONITOR;
212         }
213 
214         return NULL;
215     }
216 
217     HMONITOR WINAPI
xMonitorFromWindow(HWND hWnd,UINT uFlags)218     xMonitorFromWindow(HWND hWnd, UINT uFlags)
219     {
220         RECT rc;
221 
222         if (InitMultipleMonitorStubs())
223             return g_pfnMonitorFromWindow(hWnd, uFlags);
224 
225         if (uFlags & (MONITOR_DEFAULTTOPRIMARY | MONITOR_DEFAULTTONEAREST))
226             return xPRIMARY_MONITOR;
227 
228         if (GetWindowRect(hWnd, &rc))
229             return xMonitorFromRect(&rc, uFlags);
230 
231         return NULL;
232     }
233 
234     HMONITOR WINAPI
xMonitorFromPoint(POINT ptScreenCoords,UINT uFlags)235     xMonitorFromPoint(POINT ptScreenCoords, UINT uFlags)
236     {
237         if (InitMultipleMonitorStubs())
238             return g_pfnMonitorFromPoint(ptScreenCoords, uFlags);
239 
240         if ((uFlags & (MONITOR_DEFAULTTOPRIMARY | MONITOR_DEFAULTTONEAREST)) ||
241             ((ptScreenCoords.x >= 0) &&
242             (ptScreenCoords.x < GetSystemMetrics(SM_CXSCREEN)) &&
243             (ptScreenCoords.y >= 0) &&
244             (ptScreenCoords.y < GetSystemMetrics(SM_CYSCREEN))))
245         {
246             return xPRIMARY_MONITOR;
247         }
248 
249         return NULL;
250     }
251 
252     BOOL WINAPI
xGetMonitorInfo(HMONITOR hMonitor,LPMONITORINFO lpMonitorInfo)253     xGetMonitorInfo(HMONITOR hMonitor, LPMONITORINFO lpMonitorInfo)
254     {
255         RECT rcWork;
256 
257         if (InitMultipleMonitorStubs())
258             return g_pfnGetMonitorInfo(hMonitor, lpMonitorInfo);
259 
260         if ((hMonitor == xPRIMARY_MONITOR) && lpMonitorInfo &&
261             (lpMonitorInfo->cbSize >= sizeof(MONITORINFO)) &&
262             SystemParametersInfo(SPI_GETWORKAREA, 0, &rcWork, 0))
263         {
264             lpMonitorInfo->rcMonitor.left = 0;
265             lpMonitorInfo->rcMonitor.top  = 0;
266             lpMonitorInfo->rcMonitor.right  = GetSystemMetrics(SM_CXSCREEN);
267             lpMonitorInfo->rcMonitor.bottom = GetSystemMetrics(SM_CYSCREEN);
268             lpMonitorInfo->rcWork = rcWork;
269             lpMonitorInfo->dwFlags = MONITORINFOF_PRIMARY;
270 
271             if (lpMonitorInfo->cbSize >= sizeof(MONITORINFOEX))
272                 lstrcpy(((MONITORINFOEX*)lpMonitorInfo)->szDevice,
273                 TEXT("DISPLAY"));
274 
275             return TRUE;
276         }
277 
278         return FALSE;
279     }
280 
281     BOOL WINAPI
xEnumDisplayMonitors(HDC hdc,LPCRECT lprcIntersect,MONITORENUMPROC lpfnEnumProc,LPARAM lData)282     xEnumDisplayMonitors(
283         HDC hdc,
284         LPCRECT lprcIntersect,
285         MONITORENUMPROC lpfnEnumProc,
286         LPARAM lData)
287     {
288         RECT rcCallback, rcLimit;
289 
290         if (InitMultipleMonitorStubs())
291             return g_pfnEnumDisplayMonitors(hdc, lprcIntersect, lpfnEnumProc,
292                                            lData);
293 
294         if (!lpfnEnumProc)
295             return FALSE;
296 
297         rcLimit.left   = 0;
298         rcLimit.top    = 0;
299         rcLimit.right  = GetSystemMetrics(SM_CXSCREEN);
300         rcLimit.bottom = GetSystemMetrics(SM_CYSCREEN);
301 
302         if (hdc)
303         {
304             RECT rcClip;
305             HWND hWnd;
306 
307             if ((hWnd = WindowFromDC(hdc)) == NULL)
308                 return FALSE;
309 
310             switch (GetClipBox(hdc, &rcClip))
311             {
312             default:
313                 MapWindowPoints(NULL, hWnd, (LPPOINT)&rcLimit, 2);
314                 if (IntersectRect(&rcCallback, &rcClip, &rcLimit))
315                     break;
316                 //fall thru
317             case NULLREGION:
318                  return TRUE;
319             case ERROR:
320                  return FALSE;
321             }
322 
323             rcLimit = rcCallback;
324         }
325 
326         if (!lprcIntersect ||
327             IntersectRect(&rcCallback, lprcIntersect, &rcLimit))
328         {
329             lpfnEnumProc(xPRIMARY_MONITOR, hdc, &rcCallback, lData);
330         }
331 
332         return TRUE;
333     }
334 
335     BOOL WINAPI
xEnumDisplayDevices(LPVOID lpReserved,int iDeviceNum,DISPLAY_DEVICE * pDisplayDevice,DWORD dwFlags)336     xEnumDisplayDevices(LPVOID lpReserved, int iDeviceNum,
337 DISPLAY_DEVICE * pDisplayDevice, DWORD dwFlags)
338     {
339         if (InitMultipleMonitorStubs())
340             return g_pfnEnumDisplayDevices(lpReserved, iDeviceNum,
341                                            pDisplayDevice, dwFlags);
342 
343         return FALSE;
344     }
345 
346     #undef xPRIMARY_MONITOR
347     #undef COMPILE_MULTIMON_STUBS
348 
349 #else    // COMPILE_MULTIMON_STUBS
350 
351     extern int    WINAPI xGetSystemMetrics(int);
352     extern HMONITOR WINAPI xMonitorFromWindow(HWND, UINT);
353     extern HMONITOR WINAPI xMonitorFromRect(LPCRECT, UINT);
354     extern HMONITOR WINAPI xMonitorFromPoint(POINT, UINT);
355     extern BOOL    WINAPI xGetMonitorInfo(HMONITOR, LPMONITORINFO);
356     extern BOOL    WINAPI xEnumDisplayMonitors(HDC, LPCRECT, MONITORENUMPROC,
357                                                LPARAM);
358     extern BOOL WINAPI xEnumDisplayDevices(LPVOID, int, DISPLAY_DEVICE *,DWORD);
359 
360 #endif    // COMPILE_MULTIMON_STUBS
361 
362 //
363 // build defines that replace the regular APIs with our versions
364 //
365 #define GetSystemMetrics    xGetSystemMetrics
366 #define MonitorFromWindow   xMonitorFromWindow
367 #define MonitorFromRect     xMonitorFromRect
368 #define MonitorFromPoint    xMonitorFromPoint
369 #define GetMonitorInfo      xGetMonitorInfo
370 #define EnumDisplayMonitors xEnumDisplayMonitors
371 #define EnumDisplayDevices    xEnumDisplayDevices
372 
373 #ifdef __cplusplus
374 }
375 #endif    /* __cplusplus */
376 
377 #endif  /* !defined(_WIN32_WINNT) || (_WIN32_WINNT < 0x0500) */
378