需求的提出:
最近做了个三维的程序,部署到客户机器上,客户看了后,现场提出这样的一个需求:程序能智能探测接入的显示器个数,当有新的显示器接入时,现有的只在一个显示器上显示的三维场景能投递到新插入的显示器上显示。类似在桌面上点击鼠标右键,选择“显示设置”菜单,弹出的如下界面:
然后在此界面,对显示器进行复制、横向、纵向等处理。
可以在程序中开启一个线程,进行探测,探测到显示器个数增加后,调用SetDisplayConfig(0, NULL, 0, NULL, SDC_TOPOLOGY_CLONE | SDC_APPLY);函数进行复制显示器,一旦显示器复制成功,三维程序就会投递到新插入的显示器上,代码如下:
void checkDisplayNumsChangedFun();
// 获取本机显卡接入的显示器个数
int getAllMonitors();
// 上次查询时显示器的个数
int g_nMonitorCount = 0;
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
std::thread* pDisplay = new std::thread(checkDisplayNumsChangedFun);
return a.exec();
}
// 检测显示器个数是否变化了,如果检测到显示器数目增多了,就复制显示器
void checkDisplayNumsChangedFun()
{
while (true)
{
std::this_thread::sleep_for(std::chrono::milliseconds(5000));
int nMonitorCount = getAllMonitors();
// 显示器个数减少了,直接返回,不处理显示器减少的情况,也许是某个显示器被人拨掉了
if (g_nMonitorCount >= nMonitorCount)
{
continue;
}
CLogToolKits::getInstance()->writeLog(L"有新的显示器插入到主机!");
//change to the clone topology
SetDisplayConfig(0, NULL, 0, NULL, SDC_TOPOLOGY_CLONE | SDC_APPLY);
g_nMonitorCount = nMonitorCount;
}
}
int getAllMonitors()
{
std::list<DISPLAY_DEVICE> devices;
std::list<DEVMODE> modes;
int devId = 0;
bool ret = false;
bool isPrimary = false;
int nPrimaryNum = 0;
//list all DisplayDevices (Monitors)
do
{
DISPLAY_DEVICE displayDevice;
ZeroMemory(&displayDevice, sizeof(DISPLAY_DEVICE));
displayDevice.cb = sizeof(displayDevice);
ret = EnumDisplayDevices(NULL, devId, &displayDevice, 0);
if (ret == true)
{
if ((displayDevice.StateFlags & DISPLAY_DEVICE_ATTACHED_TO_DESKTOP) == DISPLAY_DEVICE_ATTACHED_TO_DESKTOP)
{
devices.push_back(displayDevice);
isPrimary = ((displayDevice.StateFlags & DISPLAY_DEVICE_PRIMARY_DEVICE) == DISPLAY_DEVICE_PRIMARY_DEVICE);
if (isPrimary)
{
nPrimaryNum = devId;
}
}
}
devId++;
} while (ret);
list<DISPLAY_DEVICE> dev_list;
dev_list = devices;
std::list<DISPLAY_DEVICE>::iterator it;
for (it = dev_list.begin(); it != dev_list.end(); it++)
{
DEVMODE deviceMode;
deviceMode.dmSize = sizeof(DEVMODE);
deviceMode.dmFields = DM_PELSWIDTH | DM_PELSHEIGHT | DM_BITSPERPEL | DM_POSITION | DM_DISPLAYFREQUENCY | DM_DISPLAYFLAGS; // | DM_DISPLAYORIENTATION;
EnumDisplaySettings(it->DeviceName, (int)ENUM_REGISTRY_SETTINGS, &deviceMode);
modes.push_back(deviceMode);
}
return modes.size();
}
setDisplayConfig是Windows API函数,搞过MFC开发就童鞋就应该知道,或者装个MSDN查下,在Winuser.h头文件中。
更多对显示器的操作,请参考《VC++编程实现多显示器控制(复制、横屏、纵屏,显示器个数)》