简答:没什么错。
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,并呼吁更多的GDI函数与DC,或SelectObject
换出位图前进行其他修改hMemoryDC
。
如果您需要在像素级别执行较低级的工作,您应该查看创建一个已知像素格式的DIB部分以满足您的需求,并使用从ppvBits
参数返回的指针。
CreateDIBSection @ MSDN
我有一个问题,用的#include “stdafx.h中”(没有这样的文件或目录) 。 (我创建了一个空的Win32项目...) – Tez
如果我评论stdafx,我仍然得到一个diff错误:错误C2061:语法错误:标识符'_TCHAR'。如果我包含tchar.h,我得到一个diff错误:错误LNK2019:无法解析的外部符号_WinMain @ 16在函数中引用___tmainCRTStartup – Tez
'int main()'可以代替int _tmain(int argc,_TCHAR * argv [])',但你应该看看在UNICODE下编译,你是对的,如果你创建一个空的Win32项目(尝试创建一个控制台项目),“stdafx.h”将不存在 – meklarian