我尝试使用Windows API GetCursorInfo
捕获鼠标光标,并在使用CURSORINFO
阅读ICONINFO
之后进入GetIconInfo
结构,因此我将获得hbmMask
和hbmColor
位图
首先使用hbmMask
栅格操作来应用AND
位图,然后使用hbmColor
栅格操作来应用XOR
位图。这样会导致光标不透明和背景透明,但是在下面的示例中,这在我的POC完整代码中没有发生。
在对遮罩数据进行AND
光栅和对彩色数据进行XOR
光栅之后,最终结果将是光标,并覆盖有32 * 32白色矩形。
void save_as_bitmap(unsigned char *bitmap_data, int rowPitch, int width, int height, char *filename)
{
// A file is created, this is where we will save the screen capture.
FILE *f;
BITMAPFILEHEADER bmfHeader;
BITMAPINFOHEADER bi;
bi.biSize = sizeof(BITMAPINFOHEADER);
bi.biWidth = width;
//Make the size negative if the image is upside down.
bi.biHeight = -height;
//There is only one plane in RGB color space where as 3 planes in YUV.
bi.biPlanes = 1;
//In windows RGB, 8 bit - depth for each of R, G, B and alpha.
bi.biBitCount = 32;
//We are not compressing the image.
bi.biCompression = BI_RGB;
// The size, in bytes, of the image. This may be set to zero for BI_RGB bitmaps.
bi.biSizeImage = 0;
bi.biXPelsPerMeter = 0;
bi.biYPelsPerMeter = 0;
bi.biClrUsed = 0;
bi.biClrImportant = 0;
// rowPitch = the size of the row in bytes.
DWORD dwSizeofImage = rowPitch * height;
// Add the size of the headers to the size of the bitmap to get the total file size
DWORD dwSizeofDIB = dwSizeofImage + sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFOHEADER);
//Offset to where the actual bitmap bits start.
bmfHeader.bfOffBits = (DWORD)sizeof(BITMAPFILEHEADER) + (DWORD)sizeof(BITMAPINFOHEADER);
//Size of the file
bmfHeader.bfSize = dwSizeofDIB;
//bfType must always be BM for Bitmaps
bmfHeader.bfType = 0x4D42; //BM
// TODO: Handle getting current directory
fopen_s(&f, filename, "wb");
DWORD dwBytesWritten = 0;
dwBytesWritten += fwrite(&bmfHeader, sizeof(BITMAPFILEHEADER), 1, f);
dwBytesWritten += fwrite(&bi, sizeof(BITMAPINFOHEADER), 1, f);
dwBytesWritten += fwrite(bitmap_data, 1, dwSizeofImage, f);
fclose(f);
}
//ST484 : HBIMAPtoBYTE : Convert BITMAP to BYTE array.
std::vector<BYTE> HBIMAPtoBYTE( HBITMAP hBitmap,
int &hBitmapSize,
bool &bResult,
int &nWidth,
int &nHeight )
{
bResult = true;
BITMAP bmp;
if (!GetObject(hBitmap, sizeof(BITMAP), (LPVOID)&bmp))
{
DeleteObject(hBitmap);
bResult = false;
}
int rpcbiPlanes = 32;
BITMAPINFO info;
memset(&info, 0, sizeof(BITMAPINFO));
info.bmiHeader.biSize = sizeof(info.bmiHeader);
info.bmiHeader.biWidth = bmp.bmWidth;
info.bmiHeader.biHeight = -bmp.bmHeight;
info.bmiHeader.biPlanes = 1;
info.bmiHeader.biBitCount = rpcbiPlanes;
info.bmiHeader.biCompression= BI_RGB;
size_t pixelSize = info.bmiHeader.biBitCount / 8;
size_t scanlineSize = (pixelSize * info.bmiHeader.biWidth + 3) & ~3;
size_t bitmapSize = bmp.bmHeight * scanlineSize;
hBitmapSize = bitmapSize;
nWidth = bmp.bmWidth;
nHeight = bmp.bmHeight;
std::vector<BYTE> pixels(bitmapSize);
HDC hdc = ::GetDC(NULL);
if(!GetDIBits(hdc, hBitmap, 0, bmp.bmHeight, &pixels[0], &info, DIB_RGB_COLORS))
{
hBitmapSize = 0;
bResult = false;
}
return pixels;
}
// getHCursor : Capture cursor.
CURSORINFO getHCursor()
{
CURSORINFO cursorInfo;
cursorInfo.cbSize = sizeof(CURSORINFO);
if (GetCursorInfo(&cursorInfo) == 0)
{
MessageBox(NULL, _T("Exception : GetCursorInfo creation failed"),_T("message"),MB_OK|MB_SYSTEMMODAL);
cursorInfo.hCursor = NULL;
return cursorInfo;
}
return cursorInfo;
}
//Main Call
int _tmain(int argc, _TCHAR* argv[])
{
int CountP = 0;
while (true)
{
CURSORINFO CursorInfo = getHCursor();
if (CursorInfo.hCursor == NULL)
{
::Sleep(MinSleep);
continue;
}
ICONINFO iconInfo;
if (!GetIconInfo(CursorInfo.hCursor, &iconInfo))
{
MessageBox(NULL, _T("Exception : GetIconInfo creation failed"),_T("message"),MB_OK|MB_SYSTEMMODAL);
::Sleep(MinSleep);
}
std::vector<BYTE> bColorBitmap;
std::vector<BYTE> bMaskBitmap;
std::vector<BYTE> bDestBitmap;
int sz_hbmColor = 0;
int sz_hbmMask = 0;
int sz_hbDest = 0;
int nWidth = 0;
int nHeight = 0;
bool hbmColor_result = false;
bool hbmMask_result = false;
bool hbmDest_result = false;
int rpcbiPlanes = 32;
bool isColorShape = (iconInfo.hbmColor != NULL);
// read mask and color in to byte vector.
bColorBitmap = HBIMAPtoBYTE(iconInfo.hbmColor,sz_hbmColor,hbmColor_result,nWidth,nHeight);
bMaskBitmap = HBIMAPtoBYTE(iconInfo.hbmMask,sz_hbmMask,hbmMask_result,nWidth,nHeight);
//Create Dummy bitmap using width and height filled with black color.
HBITMAP desBitmap = CreateBitmap(nWidth,nHeight,1,rpcbiPlanes,NULL);
if(desBitmap != NULL)
{
// read dummy bitmap in to byte vector.
bDestBitmap = HBIMAPtoBYTE(desBitmap,sz_hbDest,hbmDest_result,nWidth,nHeight);
}
//the mask bitmap is first applied with an AND raster operation.
for(int i = 0; i < nHeight ; i++)
{
for(int j = 0; j < nWidth; j++)
{
bDestBitmap[i*4*nWidth + j*4 ] &= bMaskBitmap[i*4*nWidth + j*4 ];
bDestBitmap[i*4*nWidth + j*4 + 1] &= bMaskBitmap[i*4*nWidth + j*4 + 1];
bDestBitmap[i*4*nWidth + j*4 + 2] &= bMaskBitmap[i*4*nWidth + j*4 + 2];
bDestBitmap[i*4*nWidth + j*4 + 3] &= bMaskBitmap[i*4*nWidth + j*4 + 3];
}
}
//then the color bitmap is applied with an XOR raster operation.
for(int i = 0; i < nHeight ; i++)
{
for(int j = 0; j < nWidth; j++)
{
bDestBitmap[i*4*nWidth + j*4 ] ^= bColorBitmap[i*4*nWidth + j*4 ];
bDestBitmap[i*4*nWidth + j*4 + 1] ^= bColorBitmap[i*4*nWidth + j*4 + 1];
bDestBitmap[i*4*nWidth + j*4 + 2] ^= bColorBitmap[i*4*nWidth + j*4 + 2];
bDestBitmap[i*4*nWidth + j*4 + 3] ^= bColorBitmap[i*4*nWidth + j*4 + 3];
}
}
//Save Color bitmap.
sprintf_s(file_name,"C:\\Test\\captured\\Cursor_%d.bmp", CountP);
save_as_bitmap(&(bDestBitmap[0]), nWidth*4, nWidth, nHeight, file_name);
CountP++;
Sleep(MaxSleep);
}
return 0;
}
答案 0 :(得分:0)
最后,我发现使用Windows API可获得出色的结果。
在项目中加入comctl32.lib
HIMAGELIST iCursorList=ImageList_Create(nWidth,nHeight,ILC_COLOR32|ILC_MASK,8,8);
ImageList_AddMasked(iCursorList,iconInfo.hbmColor,000000);
DeleteObject(iconInfo.hbmColor);
TRANSPARENT_HICON = ImageList_GetIcon(iCursorList,0,ILD_TRANSPARENT);
1)使用width
,height
,ILC_COLOR32|ILC_MASK
2)将位图添加到ImageList_AddMasked中,并应用您想要使其透明的颜色,000000
在我的代码中为黑色。
3)从ImageList_GetIcon获取透明图标。