我目前正在为连接到系统的每个屏幕开发一个需要HDC
的应用程序。
我目前正在使用这样的代码:
std::vector<HDC> dcs;
HDC dcMain = ::GetDC(nullptr); // <-- don't understand this
::EnumDisplayMonitors(dcMain, nullptr, MONITORENUMPROC(&DisplayMonitorCallback), LPARAM(&dcs));
我的回调如下:
BOOL DisplayMonitorCallback(const HMONITOR monitor, const HDC hdcMonitor, const LPRECT lprcMonitor, std::vector<HDC>& dcs)
{
dcs.push_back(hdcMonitor);
// here is where it gets weird!
HBRUSH br = CreateSolidBrush(RGB(0, 255, 0));
auto rst = FillRect(hdcMonitor, lprcMonitor, br);
// Process all monitors
return TRUE;
}
请注意,我目前正在每个屏幕上渲染绿色画笔。这在 THIS 上下文中完全有效(即在回调中)。
现在,问题是,我正在捕获稍后要使用的HDC
。
之后几行,我正在迭代我的dcs
向量:
for (HDC dc : dcs)
{
HBRUSH br = CreateSolidBrush(RGB(255, 255, 0));
RECT x = { 100, 100, 500, 500 };
auto rst = FillRect(dc, &x, br);
printf("%d", rst);
}
所以,我的问题是:
对于dcMain
,我必须通过这个,这是获得一个的好方法吗?
为什么渲染在回调中起作用,但是当我捕获HDC
并稍后迭代它们时它们不起作用?
答案 0 :(得分:2)
是的,EnumDisplayMonitors()
文档中提到了这一点:
要为每个显示器最佳地绘制整个虚拟屏幕,您可以使用以下代码:
hdc = GetDC(NULL); EnumDisplayMonitors(hdc, NULL, MyPaintScreenEnumProc, 0); ReleaseDC(NULL, hdc);
{@ 1}}只在回调中有效,正如@andlabs建议的那样。这是有道理的,因为必须获取然后释放HDC
,但只有HDC
知道如何获得每个EnumDisplayMonitors()
,因此只有它知道如何正确发布每一个。由于没有用于释放枚举HDC
的API函数,这意味着HDC
在枚举之外无效。
MSDN告诉您如何获取给定监视器的HDC
:
HMONITOR and the Device Context
每个物理显示由
HDC
类型的监视器句柄表示。有效的HMONITOR
保证为非NULL。只要它是桌面的一部分,物理显示就具有相同的HMONITOR
。发送HMONITOR
消息时,可能会从桌面删除任何监视器,因此其WM_DISPLAYCHANGE
变为无效或其设置已更改。因此,应用程序应检查发送此消息时是否所有HMONITOR
都有效。任何返回显示设备上下文(DC)的函数通常都会返回主监视器的DC。要获取另一台显示器的DC,请使用
HMONITORS
功能。 或者,您可以使用EnumDisplayMonitors
功能中的设备名称创建一个GetMonitorInfo
的DC。但是,如果函数(例如CreateDC
或GetWindowDC
)获得跨越多个显示器的窗口的DC,则DC也将跨越两个显示器。
例如:
BeginPaint
typedef std::vector<HDC> hdc_vector;
BOOL CALLBACK DisplayMonitorCallback(HMONITOR hMonitor, HDC hdcMonitor, LPRECT lprcMonitor, LPARAM dwData)
{
MONITORINFOEX mi = {0};
mi.cbSize = sizeof(mi);
if (GetMonitorInfo(hMonitor, &mi))
{
HDC dc = CreateDC(NULL, mi.szDevice, NULL, NULL);
if (dc)
reinterpret_cast<hdc_vector*>(dwData)->push_back(dc);
}
...
return TRUE;
}
由于您显然正在使用C ++ 11,我建议使用hdc_vector dcs;
EnumDisplayMonitors(dcMain, nullptr, DisplayMonitorCallback, reinterpret_cast<LPARAM>(&dcs));
...
for (HDC dc : dcs)
{
...
}
...
for (HDC dc : dcs)
DeleteDC(dc);
进行std::unique_ptr
的内存管理,这样您就不必手动调用HDC
。我会使用lambda进行回调,并将DeleteDC()
更改为std::vector
(这样您就可以在需要时查找任何特定监视器的std::map
):
HDC