我在这里找到了一个屏幕捕获代码,但是当我尝试构建它时,它无法构建,所以我自己修复了代码,现在它构建了,但我认为它不起作用,因为在调试 VS 时说它无法从 hBitmap 读取(没有数据?)。我是新手程序员,所以我现在真的不知道该怎么做......而且我可能没有正确修复代码......
感谢您的帮助。
#include <Windows.h>
int main()
{
// get the device context of the screen
HDC hScreenDC = CreateDC(L"DISPLAY", NULL, NULL, NULL);
// and a device context to put it in
HDC hMemoryDC = CreateCompatibleDC(hScreenDC);
int x = GetDeviceCaps(hScreenDC, HORZRES);
int y = GetDeviceCaps(hScreenDC, VERTRES);
// maybe worth checking these are positive values
HBITMAP hBitmap = CreateCompatibleBitmap(hScreenDC, x, y);
// get a new bitmap
HBITMAP hOldBitmap = (HBITMAP)SelectObject(hMemoryDC, hBitmap);
BitBlt(hMemoryDC, 0, 0, 640, 480, hScreenDC, 0, 0, SRCCOPY);
hBitmap = (HBITMAP)SelectObject(hMemoryDC, hOldBitmap);
// now your image is held in hBitmap. You can save it or do whatever with it
}
最佳答案
简短回答:没有问题。
hBitmap
包含位图的句柄,该位图具有通过 BitBlt
检索的截屏数据。当您在 Visual Studio 中将鼠标悬停在 hBitmap
上时,它只是通知您 hBitmap
不是指向内存的有效指针,这是一个正确的报告 - 窗口句柄只是标记解析为内存位置和实现由 Windows API 私下管理的结构。
为了证明您的代码确实从屏幕上提取了一些内容,请尝试将其写入文件。使用 GDI+ 写入文件很有帮助,因为它会为您节省大量必须手动编写的初始化代码。
这是一个快速的控制台应用程序,它将使用您的代码和 a helper function GetEncoderClsid
to get the PNG encoder 发出一个 PNG 文件。 .
#include "stdafx.h"
#include <Windows.h>
#include <gdiplus.h>
using namespace Gdiplus;
int GetEncoderClsid(const WCHAR* format, CLSID* pClsid)
{
UINT num = 0; // number of image encoders
UINT size = 0; // size of the image encoder array in bytes
ImageCodecInfo* pImageCodecInfo = NULL;
GetImageEncodersSize(&num, &size);
if (size == 0)
return -1; // Failure
pImageCodecInfo = (ImageCodecInfo*)(malloc(size));
if (pImageCodecInfo == NULL)
return -1; // Failure
GetImageEncoders(num, size, pImageCodecInfo);
for (UINT j = 0; j < num; ++j)
{
if (wcscmp(pImageCodecInfo[j].MimeType, format) == 0)
{
*pClsid = pImageCodecInfo[j].Clsid;
free(pImageCodecInfo);
return j; // Success
}
}
free(pImageCodecInfo);
return -1; // Failure
}
int _tmain(int argc, _TCHAR* argv[])
{
GdiplusStartupInput gdiplusStartupInput;
ULONG_PTR gdiplusToken;
GdiplusStartup(&gdiplusToken, &gdiplusStartupInput, NULL);
// get the device context of the screen
HDC hScreenDC = CreateDC(L"DISPLAY", NULL, NULL, NULL);
// and a device context to put it in
HDC hMemoryDC = CreateCompatibleDC(hScreenDC);
int x = GetDeviceCaps(hScreenDC, HORZRES);
int y = GetDeviceCaps(hScreenDC, VERTRES);
// maybe worth checking these are positive values
HBITMAP hBitmap = CreateCompatibleBitmap(hScreenDC, x, y);
// get a new bitmap
HBITMAP hOldBitmap = (HBITMAP)SelectObject(hMemoryDC, hBitmap);
BitBlt(hMemoryDC, 0, 0, 640, 480, hScreenDC, 0, 0, SRCCOPY);
hBitmap = (HBITMAP)SelectObject(hMemoryDC, hOldBitmap);
// now your image is held in hBitmap. You can save it or do whatever with it
CLSID pngClsid;
GetEncoderClsid(L"image/png", &pngClsid);
Bitmap *bmp = new Bitmap(hBitmap, NULL);
bmp->Save(L"desktop_slice.png", &pngClsid, NULL);
delete bmp;
GdiplusShutdown(gdiplusToken);
return 0;
}
确保将 gdiplus.lib
添加到项目设置中的源库列表中。运行它会创建一个名为“desktop_slice.png”的文件。
如果您在检索包含屏幕数据的位图后需要做额外的工作,您应该将它选择到兼容的 DC 中并使用该 DC 调用额外的 GDI 函数,或者在交换之前对 hMemoryDC
进行其他修改使用 SelectObject
输出位图。
如果您需要在像素级别进行较低级别的工作,您应该考虑创建一个具有满足您需要的已知像素格式的 DIB 部分,并使用从 ppvBits
返回的指针> 争论。
关于c++ - 这个屏幕截图代码有什么问题?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/21592454/