这段代码的目的是捕获当前屏幕的图像,并将其保存到一个数据包列表中,以便后续处理或传输。下面是对每一部分的详细解释:
主要功能
获取屏幕设备上下文:
HDC hScreen = ::GetDC(NULL);
- 使用
GetDC
函数获取整个屏幕的设备上下文(HDC),以便后续进行绘制操作。
获取屏幕参数:
int nBitPerPixel = GetDeviceCaps(hScreen, BITSPIXEL);
int nWidth = GetDeviceCaps(hScreen, HORZRES);
int nHeight = GetDeviceCaps(hScreen, VERTRES);
- 获取当前屏幕的色深(每像素位数)、宽度和高度。这些信息在创建图像对象时会用到。
创建 GDI 图像对象:
screen.Create(nWidth, nHeight, nBitPerPixel);
- 使用
CImage
类创建一个与屏幕大小相同、色深相同的新图像对象。
抓取屏幕内容:
BitBlt(screen.GetDC(), 0, 0, nWidth, nHeight, hScreen, 0, 0, SRCCOPY);
- 使用
BitBlt
函数从屏幕设备上下文复制图像数据到之前创建的CImage
对象中,完成对当前显示内容的截图。
释放设备上下文:
ReleaseDC(NULL, hScreen);
- 在完成屏幕抓取之后,释放获得的设备上下文。
分配全局内存块:
HGLOBAL hMem = GlobalAlloc(GMEM_MOVEABLE, 0);
if (hMem == NULL) return -1;
- 使用
GlobalAlloc
分配一个全局可移动内存块,用于存放后续生成的图像数据。如果分配失败则返回错误码-1
。
创建流以保存图像数据:
IStream* pStream = NULL;
HRESULT ret = CreateStreamOnHGlobal(hMem, TRUE, &pStream);
if (ret == S_OK) {
screen.Save(pStream, Gdiplus::ImageFormatPNG);
...
}
保存图像到流:
- 创建成功后,调用
screen.Save()
方法将捕获到的图像以 PNG 格式保存到流中。
- 创建成功后,调用
重新定位流指针并锁定内存:
LARGE_INTEGER bg = { 0 };
pStream->Seek(bg, STREAM_SEEK_SET, NULL); // 重置流位置到起始点
PBYTE pData = (PBYTE)GlobalLock(hMem); // 锁定内存,以便访问内部数据
SIZE_T nSize = GlobalSize(hMem); // 获取内存大小
将数据包添加至列表:
lstPacket.push_back(CPacket(6, pData, nSize));
GlobalUnlock(hMem); // 解锁全局内存块,确保安全访问。
释放资源和清理:
pStream->Release();
GlobalFree(hMem); // 清理分配的内存。
screen.ReleaseDC(); // 如果还有需要的话,释放 DC。
总结
整体而言,这段代码实现了以下功能:它从计算机当前显示器上抓取屏幕快照,使用 GDI(Graphics Device Interface)处理相关操作,然后将该快照以 PNG 格式保存在全局内存中,并最后通过给定的数据包格式将该快照的信息放入传递的数据包列表中,以供进一步使用。这可以用于远程桌面、截图工具等场景。
内容由零声教学AI助手提供,问题来源于学员提问