Mouse cursor bitmap

2019-02-27 20:02发布

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);
}

2条回答
小情绪 Triste *
2楼-- · 2019-02-27 20:29

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, /* ... */);
查看更多
戒情不戒烟
3楼-- · 2019-02-27 20:34

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);
查看更多
登录 后发表回答