问题
I am trying to get bitmap from mouse cursor, but with next code, i just can't get colors.
CURSORINFO cursorInfo = { 0 };
cursorInfo.cbSize = sizeof(cursorInfo);
if (GetCursorInfo(&cursorInfo)) {
ICONINFO ii = {0};
int p = GetIconInfo(cursorInfo.hCursor, &ii);
// get screen
HDC dc = GetDC(NULL);
HDC memDC = CreateCompatibleDC(dc);
//SelectObject(memDC, ii.hbmColor);
int counter = 0;
//
byte* bits[1000];// = new byte[w * 4];
BITMAPINFO bmi;
memset(&bmi, 0, sizeof(BITMAPINFO));
bmi.bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
bmi.bmiHeader.biWidth = 16;
bmi.bmiHeader.biHeight = 16;
bmi.bmiHeader.biBitCount = 32;
bmi.bmiHeader.biPlanes = 1;
bmi.bmiHeader.biCompression = BI_RGB;
bmi.bmiHeader.biSizeImage = 0;
bmi.bmiHeader.biXPelsPerMeter = 0;
bmi.bmiHeader.biYPelsPerMeter = 0;
bmi.bmiHeader.biClrUsed = 0;
bmi.bmiHeader.biClrImportant = 0;
int rv = ::GetDIBits(memDC, ii.hbmColor, 0, 1, (void**)&bits, &bmi, DIB_RGB_COLORS);
}
回答1:
Start by getting the parameters of the bitmap as recorded by Windows:
BITMAP bitmap = {0};
GetObject(ii.hbmColor, sizeof(bitmap), &bitmap);
You can use the returned values to populate the bmi
structure.
And about the bmi
structure: BITMAPINFO
does not reserve enough space for a palette. You should create your own structure for this:
struct BitmapPlusPalette
{
BITMAPINFOHEADER bmiHeader;
RGBQUAD palette[256];
};
Calculating the number of bytes needed for the bitmap is a bit tricky because it needs to be rounded up:
w = ((bitmap.bmWidth * bitmap.bmBitsPixel) + 31) / 8;
byte* bits = new byte[w * bitmap.bmHeight];
And here's a corrected version of your final line:
int rv = ::GetDIBits(dc, ii.hbmColor, 0, bitmap.bmHeight, bits, (BITMAPINFO *)&bmi, DIB_RGB_COLORS);
回答2:
The problem with your code I think is in the way you allocated memory for 'bits' variable and how you used it then in GetDIBits function.
Firstly, the commented part byte* bits = new byte[w*4]
was better than byte* bits[1000]
. When you write byte* bits[1000]
computer allocates 1000 POINTERS to byte. Each of these pointers doesn't point to anything.
Secondly, GetDIBits accepts LPVOID lpvBits as a 5th param. So, its a pointer to void. In most platforms sizeof(void *) > sizeof(byte), so you can't just pass it a byte array, probably it would be better to pass a pointer to int or unsigned int (I'm not good at Windows types, so maybe something more appropriate should be better, sorry).
So, my guess is this:
unsigned bits[1000];
memset(bits, 0, sizeof(bits));
//...
int tv = GetDIBits(memDC, ii.hmbColor, 0, 1, (LPVOID)bits, /* ... */);
来源:https://stackoverflow.com/questions/3830698/mouse-cursor-bitmap