2016-03-11 14:57:17 +01:00
|
|
|
/* Copyright (c) 2002-2012 Croteam Ltd. All rights reserved. */
|
|
|
|
|
2016-03-29 03:03:54 +02:00
|
|
|
#include "Engine/StdH.h"
|
|
|
|
|
|
|
|
#ifdef PLATFORM_WIN32
|
2016-03-11 14:57:17 +01:00
|
|
|
#include <tchar.h>
|
2016-03-29 03:03:54 +02:00
|
|
|
#endif
|
|
|
|
|
2016-03-11 14:57:17 +01:00
|
|
|
#include <Engine/Graphics/MultiMonitor.h>
|
|
|
|
#include <Engine/Base/Console.h>
|
|
|
|
#include <Engine/Base/ErrorReporting.h>
|
|
|
|
#include <Engine/Base/Translation.h>
|
|
|
|
|
|
|
|
// Win9x multimonitor enabling/disabling code,
|
|
|
|
// idea and original code courtesy of Christian Studer <cstuder@realtimesoft.com>
|
|
|
|
// added dynamic function loading and exception throwing
|
|
|
|
|
|
|
|
extern INDEX gfx_bDisableMultiMonSupport;
|
|
|
|
extern INDEX gfx_ctMonitors;
|
|
|
|
extern INDEX gfx_bMultiMonDisabled;
|
|
|
|
|
2016-03-29 03:03:54 +02:00
|
|
|
#ifdef PLATFORM_WIN32
|
|
|
|
#pragma comment(lib, "advapi32.lib")
|
|
|
|
|
2016-03-11 14:57:17 +01:00
|
|
|
typedef BOOL EnumDisplayDevices_t(
|
|
|
|
PVOID Unused, // not used; must be NULL
|
|
|
|
DWORD iDevNum, // specifies display device
|
|
|
|
PDISPLAY_DEVICE lpDisplayDevice, // pointer to structure to
|
|
|
|
// receive display device information
|
|
|
|
DWORD dwFlags // flags to condition function behavior
|
|
|
|
);
|
|
|
|
|
|
|
|
typedef LONG ChangeDisplaySettingsEx_t(
|
|
|
|
LPCSTR lpszDeviceName,
|
|
|
|
LPDEVMODE lpDevMode,
|
|
|
|
HWND hwnd,
|
|
|
|
DWORD dwflags,
|
|
|
|
LPVOID lParam
|
|
|
|
);
|
|
|
|
|
|
|
|
static HINSTANCE _hUser32Lib = NULL;
|
|
|
|
static EnumDisplayDevices_t *_pEnumDisplayDevices = NULL;
|
|
|
|
static ChangeDisplaySettingsEx_t *_pChangeDisplaySettingsEx = NULL;
|
|
|
|
|
|
|
|
// disables or enables secondary monitors on Win98/Me
|
|
|
|
void Mon_DisableEnable9x_t(BOOL bDisable)
|
|
|
|
{
|
|
|
|
// load user32
|
|
|
|
if (_hUser32Lib==NULL) {
|
|
|
|
_hUser32Lib = ::LoadLibraryA( "user32.dll");
|
|
|
|
if( _hUser32Lib == NULL) {
|
|
|
|
ThrowF_t(TRANS("Cannot load user32.dll."));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (_pEnumDisplayDevices==NULL) {
|
|
|
|
_pEnumDisplayDevices = (EnumDisplayDevices_t*)GetProcAddress(_hUser32Lib, "EnumDisplayDevicesA");
|
|
|
|
if (_pEnumDisplayDevices==NULL) {
|
|
|
|
ThrowF_t(TRANS("Cannot find EnumDisplayDevices()."));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (_pChangeDisplaySettingsEx==NULL) {
|
|
|
|
_pChangeDisplaySettingsEx = (ChangeDisplaySettingsEx_t*)GetProcAddress(_hUser32Lib, "ChangeDisplaySettingsExA");
|
|
|
|
if (_pChangeDisplaySettingsEx==NULL) {
|
|
|
|
ThrowF_t(TRANS("Cannot find ChangeDisplaySettingsEx()."));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
HKEY key;
|
|
|
|
LONG ret = RegOpenKeyEx(HKEY_CURRENT_CONFIG, _T("Display\\Settings"), 0, KEY_ENUMERATE_SUB_KEYS |
|
|
|
|
KEY_SET_VALUE, &key);
|
|
|
|
if (ret != ERROR_SUCCESS) {
|
|
|
|
ThrowF_t(TRANS("Cannot enumerate display settings from registry\n"));
|
|
|
|
}
|
|
|
|
|
|
|
|
TCHAR attach[2];
|
|
|
|
if (bDisable)
|
|
|
|
lstrcpy(attach, _T("0"));
|
|
|
|
else
|
|
|
|
lstrcpy(attach, _T("1"));
|
|
|
|
|
|
|
|
// enumerate all subkeys. there is at least one subkey for each secondary monitor, maybe more.
|
|
|
|
DWORD index = 0;
|
|
|
|
while (ret == ERROR_SUCCESS)
|
|
|
|
{
|
|
|
|
TCHAR keyName[500];
|
|
|
|
DWORD keyNameSize = 500;
|
|
|
|
|
|
|
|
ret = RegEnumKeyEx(key, index, keyName, &keyNameSize, 0, 0, 0, 0);
|
|
|
|
if (ret == ERROR_SUCCESS)
|
|
|
|
{
|
|
|
|
// open the subkey and set the AttachToDesktop value (0 or 1)
|
|
|
|
HKEY subKey;
|
|
|
|
ret = RegOpenKeyEx(key, keyName, 0, KEY_SET_VALUE, &subKey);
|
|
|
|
if (ret == ERROR_SUCCESS)
|
|
|
|
{
|
|
|
|
ret = RegSetValueEx(subKey, _T("AttachToDesktop"), 0, REG_SZ,
|
|
|
|
reinterpret_cast<const BYTE*>(attach), sizeof(TCHAR) * 2);
|
|
|
|
RegCloseKey(subKey);
|
|
|
|
++index;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
RegCloseKey(key);
|
|
|
|
|
|
|
|
bool failed = FALSE;
|
|
|
|
DWORD dev = 0;
|
|
|
|
DISPLAY_DEVICE dd;
|
|
|
|
dd.cb = sizeof(dd);
|
|
|
|
while (_pEnumDisplayDevices(0, dev, &dd, 0))
|
|
|
|
{
|
|
|
|
if (!(dd.StateFlags & DISPLAY_DEVICE_MIRRORING_DRIVER) && !(dd.StateFlags & DISPLAY_DEVICE_PRIMARY_DEVICE))
|
|
|
|
{
|
|
|
|
// this is a secondary monitor, change display settings to what's currently stored in the registry
|
|
|
|
ret = _pChangeDisplaySettingsEx((const char*)dd.DeviceName, 0, 0, 0, 0);
|
|
|
|
// we get DISP_CHANGE_BADPARAM if we try to set settings for a monitor that doesn't exist
|
|
|
|
if (ret != DISP_CHANGE_SUCCESSFUL && ret != DISP_CHANGE_BADPARAM)
|
|
|
|
failed = TRUE;
|
|
|
|
}
|
|
|
|
|
|
|
|
dev++;
|
|
|
|
}
|
|
|
|
if (failed) {
|
|
|
|
ThrowF_t(TRANS("Cannot change settings for at least one secondary monitor\n"));
|
|
|
|
}
|
|
|
|
}
|
2016-03-29 03:03:54 +02:00
|
|
|
#endif
|
2016-03-11 14:57:17 +01:00
|
|
|
|
|
|
|
void MonitorsOff(void)
|
|
|
|
{
|
|
|
|
extern BOOL _bDedicatedServer;
|
|
|
|
if (_bDedicatedServer) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2016-03-29 03:03:54 +02:00
|
|
|
#ifdef PLATFORM_WIN32
|
2016-03-11 14:57:17 +01:00
|
|
|
// check for WinNT or Win2k
|
|
|
|
BOOL bNT = FALSE;
|
|
|
|
OSVERSIONINFO osv;
|
|
|
|
memset(&osv, 0, sizeof(osv));
|
|
|
|
osv.dwOSVersionInfoSize = sizeof(osv);
|
|
|
|
if (GetVersionEx(&osv) && osv.dwPlatformId==VER_PLATFORM_WIN32_NT) {
|
|
|
|
bNT = TRUE;
|
|
|
|
}
|
|
|
|
|
|
|
|
// if there is more than one monitor, and OS is not WinNT
|
|
|
|
if (gfx_ctMonitors>1 && !bNT) {
|
2016-03-29 05:21:44 +02:00
|
|
|
CPrintF(TRANSV("Multimonitor configuration detected...\n"));
|
2016-03-11 14:57:17 +01:00
|
|
|
// if multimon is not allowed
|
|
|
|
if (gfx_bDisableMultiMonSupport) {
|
2016-03-29 05:21:44 +02:00
|
|
|
CPrintF(TRANSV(" Multimonitor support disallowed.\n"));
|
|
|
|
CPrintF(TRANSV(" Disabling multimonitor..."));
|
2016-03-11 14:57:17 +01:00
|
|
|
// disable all but primary
|
|
|
|
try {
|
|
|
|
Mon_DisableEnable9x_t(/*bDisable = */ TRUE);
|
2016-03-29 05:21:44 +02:00
|
|
|
CPrintF(TRANSV(" disabled\n"));
|
2016-03-11 14:57:17 +01:00
|
|
|
} catch(char *strError) {
|
2016-03-29 05:21:44 +02:00
|
|
|
CPrintF(TRANSV(" error: %s\n"), strError);
|
2016-03-11 14:57:17 +01:00
|
|
|
}
|
|
|
|
gfx_bMultiMonDisabled = TRUE;
|
|
|
|
// if multimon is allowed
|
|
|
|
} else {
|
2016-03-29 05:21:44 +02:00
|
|
|
CPrintF(TRANSV(" Multimonitor support was allowed.\n"));
|
2016-03-11 14:57:17 +01:00
|
|
|
}
|
|
|
|
}
|
2016-03-29 03:03:54 +02:00
|
|
|
#else
|
2016-03-29 05:21:44 +02:00
|
|
|
CPrintF(TRANSV("Multimonitor is not supported on this platform.\n"));
|
2016-03-29 03:03:54 +02:00
|
|
|
#endif
|
2016-03-11 14:57:17 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
void MonitorsOn(void)
|
|
|
|
{
|
2016-03-29 03:03:54 +02:00
|
|
|
#ifdef PLATFORM_WIN32
|
2016-03-11 14:57:17 +01:00
|
|
|
// if multimon was disabled
|
|
|
|
if (gfx_bMultiMonDisabled) {
|
2016-03-29 05:21:44 +02:00
|
|
|
CPrintF(TRANSV("Multimonitor support was disabled.\n"));
|
|
|
|
CPrintF(TRANSV(" re-enabling multimonitor..."));
|
2016-03-11 14:57:17 +01:00
|
|
|
// enable all secondary
|
|
|
|
try {
|
|
|
|
Mon_DisableEnable9x_t(/*bDisable = */ FALSE);
|
2016-03-29 05:21:44 +02:00
|
|
|
CPrintF(TRANSV(" enabled\n"));
|
2016-03-11 14:57:17 +01:00
|
|
|
} catch(char *strError) {
|
2016-03-29 05:21:44 +02:00
|
|
|
CPrintF(TRANSV(" error: %s\n"), strError);
|
2016-03-11 14:57:17 +01:00
|
|
|
}
|
|
|
|
}
|
2016-03-29 03:03:54 +02:00
|
|
|
#else
|
2016-03-29 05:21:44 +02:00
|
|
|
CPrintF(TRANSV("Multimonitor is not supported on this platform.\n"));
|
2016-03-29 03:03:54 +02:00
|
|
|
#endif
|
2016-03-11 14:57:17 +01:00
|
|
|
}
|
2016-03-29 03:03:54 +02:00
|
|
|
|