我正在尝试创建一个与windows ()函数等价的函数,但我希望创建屏幕的位图,然后读取该缓冲区。
这就是我所得到的(主要是从谷歌搜索中粘贴的拷贝),当我运行它时,它只打印0。我认为我的大部分都是正确的,我的问题是我不知道如何读取字节变量。
所以我的问题是,我需要做什么才能让它用我的for循环打印出一些随机的颜色(R,G或B)?
#include <Windows.h>
#include <iostream>
#include <math.h>
#include <stdio.h>
using namespace std;
int main() {
HDC hdc,hdcMem;
hdc = GetDC(NULL);
hdcMem = CreateCompatibleDC(hdc);
HBITMAP hBitmap = CreateCompatibleBitmap(hdc, 1680, 1050);
BITMAPINFO MyBMInfo = {0};
MyBMInfo.bmiHeader.biSize = sizeof(MyBMInfo.bmiHeader);
// Get the BITMAPINFO structure from the bitmap
if(0 == GetDIBits(hdcMem, hBitmap, 0, 0, NULL, &MyBMInfo, DIB_RGB_COLORS)) {
cout << "error" << endl;
}
// create the bitmap buffer
BYTE* lpPixels = new BYTE[MyBMInfo.bmiHeader.biSizeImage];
MyBMInfo.bmiHeader.biSize = sizeof(MyBMInfo.bmiHeader);
MyBMInfo.bmiHeader.biBitCount = 32;
MyBMInfo.bmiHeader.biCompression = BI_RGB;
MyBMInfo.bmiHeader.biHeight = abs(MyBMInfo.bmiHeader.biHeight);
// get the actual bitmap buffer
if(0 == GetDIBits(hdc, hBitmap, 0, MyBMInfo.bmiHeader.biHeight, (LPVOID)lpPixels, &MyBMInfo, DIB_RGB_COLORS)) {
cout << "error2" << endl;
}
for(int i = 0; i < 100; i++) {
cout << (int)lpPixels[i] << endl;
}
return 0;
}发布于 2014-10-07 14:27:49
按照约定,我将使用工作代码片段添加一个新的答案(我添加了缺少的lpPixels清理)。请参阅我先前回答的讨论和@enhzflep所做的讨论。
#include <Windows.h>
#include <iostream>
#include <math.h>
#include <stdio.h>
using namespace std;
HBITMAP GetScreenBmp( HDC hdc) {
// Get screen dimensions
int nScreenWidth = GetSystemMetrics(SM_CXSCREEN);
int nScreenHeight = GetSystemMetrics(SM_CYSCREEN);
// Create compatible DC, create a compatible bitmap and copy the screen using BitBlt()
HDC hCaptureDC = CreateCompatibleDC(hdc);
HBITMAP hBitmap = CreateCompatibleBitmap(hdc, nScreenWidth, nScreenHeight);
HGDIOBJ hOld = SelectObject(hCaptureDC, hBitmap);
BOOL bOK = BitBlt(hCaptureDC,0,0,nScreenWidth, nScreenHeight, hdc,0,0,SRCCOPY|CAPTUREBLT);
SelectObject(hCaptureDC, hOld); // always select the previously selected object once done
DeleteDC(hCaptureDC);
return hBitmap;
}
int main() {
HDC hdc = GetDC(0);
HBITMAP hBitmap = GetScreenBmp(hdc);
BITMAPINFO MyBMInfo = {0};
MyBMInfo.bmiHeader.biSize = sizeof(MyBMInfo.bmiHeader);
// Get the BITMAPINFO structure from the bitmap
if(0 == GetDIBits(hdc, hBitmap, 0, 0, NULL, &MyBMInfo, DIB_RGB_COLORS)) {
cout << "error" << endl;
}
// create the bitmap buffer
BYTE* lpPixels = new BYTE[MyBMInfo.bmiHeader.biSizeImage];
// Better do this here - the original bitmap might have BI_BITFILEDS, which makes it
// necessary to read the color table - you might not want this.
MyBMInfo.bmiHeader.biCompression = BI_RGB;
// get the actual bitmap buffer
if(0 == GetDIBits(hdc, hBitmap, 0, MyBMInfo.bmiHeader.biHeight, (LPVOID)lpPixels, &MyBMInfo, DIB_RGB_COLORS)) {
cout << "error2" << endl;
}
for(int i = 0; i < 100; i++) {
cout << (int)lpPixels[i];
}
DeleteObject(hBitmap);
ReleaseDC(NULL, hdc);
delete[] lpPixels;
return 0;
}发布于 2014-10-07 11:23:32
基本上,您需要绘制一些像素才能返回除0以外的结果。
目前,主目录中的第4行代码创建了一个空(空白,0初始化)映像。然后,在第一次调用GetDIBits时,您将获得有关此映像大小的信息。然后,通过第二次调用GetDIBits获得实际(空白)像素。
要修复,只需将一个位图文件从磁盘加载到您的hBitmap中,并选择此位图到您的hdcMem中。
即改变
HBITMAP hBitmap = CreateCompatibleBitmap(hdc, 1680, 1050);像这样的事。
HBITMAP hBitmap = (HBITMAP)LoadImage(NULL, "xpButton.bmp", IMAGE_BITMAP, 0,0, LR_LOADFROMFILE);
HBITMAP old = (HBITMAP) SelectObject(hdcMem, hBitmap);(确保使用有效的bmp文件名。我的目录与.cpp文件存在于同一个文件夹中,因为这是通过IDE运行时的“当前”目录。如果希望通过资源管理器运行,请将bmp的另一份副本放在与exe相同的文件夹中)
下面是我使用过的bmp (上传到SO后已转换为png ):

下面是循环的前10次迭代。
255
5
253
0
255
5
253
0
255
5注意,0,0像素的颜色为: rgb(253,5,255),它是一个8位的图像,因此没有alpha通道,因此它的值为0。像素存储为BGRA等,我将留给您来修复程序的(不存在的)清理部分。Windows将取消您在这里使用的内存,但是您绝对不应该养成不释放任何已分配内存的习惯。:)
发布于 2014-10-07 11:08:32
你的代码似乎有点混乱。太多的片段,我猜:)。尽管如此,您仍然非常接近:第一个GetDIBits()调用是为了得到填充位图的属性,正如代码中的注释所示。为此,您将使用一个不必要的MemDC --这可能是来自一个希望在屏幕上执行BitBlt的片段。
然后,您可以使用填充结构获得第二个GetDIBits()调用的实际位图像素,但是您要做的是再次用硬编码值替换属性,从而使第一个GetDIBits()调用变得无用。
因此:删除MemDC --您不需要它--并在第一个对GetDIBits()的调用中用hdc替换hdcMem,然后删除在第一个GetDIBits调用之后覆盖bmiHeader成员的所有语句,然后得到像素。
哦,当然,不要忘记在dc上调用ReleaseDC()/DeleteObject(),并在位图上调用delete[]缓冲区:)
https://stackoverflow.com/questions/26233848
复制相似问题