我的任务是修改我们的一个 c++ 产品以在 Windows 操作系统的特定显示器上生成一个新窗口。这适用于需要能够配置平铺多显示器可视化的客户,其中每个显示器由单台计算机上的单独显卡驱动。
在 linux 中,我可以通过在每个显示器上启动一个 X 服务器来轻松地做到这一点,然后在适当设置 DISPLAY env var 的情况下启动可视化软件的多个实例。但是,在 Windows 中执行此操作时,我迷失了。任何指针/建议/示例?
您需要枚举所有监视器并在虚拟屏幕 (MSDN)上检查它们的映射。
通过调用EnumDisplayMonitors (MSDN)枚举监视器。这将枚举一系列HMONITOR
句柄,您可以将这些句柄传递给GetMonitorInfo (MSDN)以获取监视器在虚拟屏幕上的位置。
还有一个完整的多显示器支持指南,可能也值得一读。
一些注意事项:因为虚拟屏幕是用户控制的映射,所以没有什么能阻止用户在虚拟坐标空间中放置监视器的另一物理侧设置监视器,反之亦然,以及任意数量的其他奇怪的放置场景。此外,一些显卡在检测到插件时会尝试假设显示器在哪里,这从您的软件的角度来看可能是错误的,但可能是由于用户没有注意哪个显示端口映射到左侧(如果它甚至被标记)。
您可以使用EnumDisplayMonitors
Win32 API 中的函数来获取每个显示器的信息。
一旦你有了所需显示的矩形,你就知道该怎么做了 =)
我很确定显示器是按顺序列举的。但是如果你正在平铺,你可以获得所有显示矩形的向量,然后对它们进行排序。
我有一个方便的包装器,我写了一段时间来获取所有监视器信息:
宣言
class CMonitorInfoEx : public MONITORINFOEX
{
public:
CMonitorInfoEx();
LPCRECT GetRect() const { return &rcMonitor; }
LPCRECT GetWorkRect() const { return &rcWork; }
LPCTSTR DeviceName() const { return szDevice; }
bool IsPrimary() const { return (dwFlags & MONITORINFOF_PRIMARY) ? true : false; }
int Width() const { return rcMonitor.right - rcMonitor.left; }
int Height() const { return rcMonitor.bottom - rcMonitor.top; }
int WorkWidth() const { return rcWork.right - rcWork.left; }
int WorkHeight() const { return rcWork.bottom - rcWork.top; }
};
class CSysDisplays
{
public:
CSysDisplays();
void Update();
int Count() const;
const CMonitorInfoEx& Get( int i ) const;
private:
std::vector<CMonitorInfoEx> mInfo;
};
执行
BOOL CALLBACK MonitorEnumProc( __in HMONITOR hMonitor, __in HDC hdcMonitor, __in LPRECT lprcMonitor, __in LPARAM dwData )
{
std::vector<CMonitorInfoEx>& infoArray = *reinterpret_cast< std::vector<CMonitorInfoEx>* >( dwData );
CMonitorInfoEx info;
GetMonitorInfo( hMonitor, &info );
infoArray.push_back( info );
return TRUE;
}
CMonitorInfoEx::CMonitorInfoEx()
{
cbSize = sizeof(MONITORINFOEX);
}
CSysDisplays::CSysDisplays()
{
Update();
}
void CSysDisplays::Update()
{
mInfo.clear();
mInfo.reserve( ::GetSystemMetrics(SM_CMONITORS) );
EnumDisplayMonitors( NULL, NULL, MonitorEnumProc, reinterpret_cast<LPARAM>(&mInfo) );
}
int CSysDisplays::Count() const
{
return (int)mInfo.size();
}
const CMonitorInfoEx& CSysDisplays::Get( int i ) const
{
return mInfo[i];
}