首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >Win32:显示监视器的捕获句柄

Win32:显示监视器的捕获句柄
EN

Stack Overflow用户
提问于 2016-09-01 16:08:01
回答 1查看 2.7K关注 0票数 0

我目前正在开发一个应用程序,它需要为连接到系统的每个屏幕提供一个HDC

我目前使用的代码如下:

代码语言:javascript
复制
std::vector<HDC> dcs;
HDC dcMain = ::GetDC(nullptr); // <-- don't understand this

::EnumDisplayMonitors(dcMain, nullptr, MONITORENUMPROC(&DisplayMonitorCallback), LPARAM(&dcs));

我的回访如下:

代码语言:javascript
复制
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;
}

注意,我目前正在每个屏幕上呈现一个绿色画笔。在这种情况下(即在回调中),这是非常有效的。

现在,问题是,我正在捕获那些HDC,以便稍后使用。

因此,几行之后,我将迭代我的dcs向量:

代码语言:javascript
复制
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);
}

所以,我的问题是:

  1. 对于dcMain,我必须传递这个,这是获得一个的好方法吗?
  2. 为什么呈现在回调中工作,但当我捕获HDC并在以后迭代它们时却不能工作?
EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2016-09-01 22:49:45

  1. 是的,在EnumDisplayMonitors()文档中提到了这一点: 要最优地为每个显示监视器绘制整个虚拟屏幕,可以使用如下代码: hdc = GetDC(NULL);EnumDisplayMonitors(hdc,NULL,MyPaintScreenEnumProc,0);ReleaseDC(NULL,hdc);
  2. 正如@andlabs所建议的,HDCs仅在回调的内部有效。这是有意义的,因为必须获得一个HDC,然后发布,但是只有EnumDisplayMonitors()知道是如何获得每个HDC的,所以只有它知道如何正确地释放每个HDC。由于没有发布枚举HDC的API函数,这意味着HDC在枚举之外无效。 MSDN告诉您如何为给定的监视器获取HDC HMONITOR与设备上下文 每个物理显示都由HMONITOR类型的监视器句柄表示。有效的HMONITOR保证为非空。只要物理显示器是桌面的一部分,它就具有相同的HMONITOR。发送WM_DISPLAYCHANGE消息时,任何监视器都可能从桌面上移除,因此其HMONITOR无效或其设置发生更改。因此,当发送此消息时,应用程序应检查所有HMONITORS是否有效。 任何返回显示设备上下文( DC )的函数通常都会返回主监视器的DC。若要获得另一个监视器的DC,请使用EnumDisplayMonitors函数。或者,您可以使用来自GetMonitorInfo CreateDC.函数的函数的设备名称来使用创建DC。但是,如果函数(如GetWindowDCBeginPaint )为跨越多个显示的窗口获取DC,则DC也将跨越这两种显示。

例如:

向量hdc_vector;BOOL回调DisplayMonitorCallback(HMONITOR hMonitor,HDC hdcMonitor,LPRECT lprcMonitor,LPARAM dwData) { MONITORINFOEX = {0};mi.cbSize =相当大的( mi );if (GetMonitorInfo(hMonitor,&mi)) { HDC dc = CreateDC(NULL,mi.szDevice,NULL,NULL);if (dc) lprcMonitor}.返回TRUE;}

hdc_vector dcs;EnumDisplayMonitors(dcMain,nullptr,DisplayMonitorCallback,reinterpret_cast(&dcs));用于(HDC dc : dcs) {.}(HDC dc :dc) DeleteDC(dc);

由于您显然在使用C++11,所以我建议使用std::unique_ptr来管理HDC的内存,这样您就不必手动调用DeleteDC()了。我将使用lambda进行回调,并将std::vector更改为std::map (因此在需要时可以查找任何特定监视器的HDC ):

std::unique_ptr device_hdc;std::map device_hdc_map;device_hdc_map dcs;EnumDisplayMonitors(dcMain,nullptr,HMONITOR hMonitor,HDC hdcMonitor,LPRECT lprcMonitor,LPARAM dwData -> BOOL { MONITORINFOEX = {0};mi.cbSize = sizeof( mi );如果(GetMonitorInfo(hMonitor,&mi)) { HDC dc =CreateDC(空,mi.szDevice,空,空);if (dc) hMonitor= device_hdc(dc,&:DeleteDC);}.返回TRUE;},reinterpret_cast(&dcs );.对于(device_hdc_map::value_type &dc : dcs) { //根据需要使用dc.second.get(实际的HDC) .}

票数 3
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/39276282

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档