in tools/ExeView/iconcur.cpp [520:790]
HCURSOR MakeCursor ( LPRESPACKET lprp )
{
LPBITMAPINFOHEADER lpbihdr;
LPBITMAPINFO lpbinfo;
LPCURSORIMAGE lpci;
HCURSOR hCursor = NULL;
WORD wH, wW, wXORSize, wANDSize, wScans, wColorTableSize;
WORD wCursorW, wCursorH;
LPSTR lpANDbits;
LPSTR lpXORbits;
HDC hDC, hSrcDC, hDestDC;
HBITMAP hbmpXOR, hbmpAND;
HBITMAP hbmpDestXOR, hbmpDestAND;
HBITMAP hbmpOldSrc, hbmpOldDest;
BITMAP bmp;
HANDLE hXORbits, hANDbits;
lpci = (LPCURSORIMAGE)lprp->lpMem;
lpbinfo = &lpci->bi;
lpbihdr = (LPBITMAPINFOHEADER)lpbinfo;
wW = (WORD)lpbihdr->biWidth;
wH = (WORD)lpbihdr->biHeight / 2;
wXORSize = (wW * wH) / 8;
wANDSize = (wW * wH) / 8;
wColorTableSize = sizeof(RGBQUAD) * (0x0001<<lpbihdr->biBitCount);
lpXORbits = ((LPSTR)lpbihdr)+wColorTableSize+(WORD)lpbihdr->biSize;
lpANDbits = lpXORbits + wXORSize;
// Now we need to make a bitmap and convert these to DDB
// Get a screen DC
hDC = GetDC( NULL );
if (!hDC)
return NULL;
// XOR BITMAP
// create MONO device-dependent bitmap for XOR mask
hbmpXOR= CreateBitmap( wW, wH, 1, 1, NULL );
if (!hbmpXOR)
{
ReleaseDC( NULL, hDC );
return NULL;
}
else
{
RGBQUAD rgbBlack = { 0x00, 0x00, 0x00, 0x00 };
RGBQUAD rgbWhite = { 0xFF, 0xFF, 0xFF, 0x00 };
// modify BITMAPINFOHEADER structure for monochrome bitmap
lpbihdr->biHeight = wH;
lpbihdr->biSizeImage = wXORSize;
lpbihdr->biBitCount = 1;
lpbinfo->bmiColors[0] = rgbBlack;
lpbinfo->bmiColors[1] = rgbWhite;
// convert XOR mask from DIB to DDB
wScans = SetDIBits(hDC,hbmpXOR,0,wH,lpXORbits,lpbinfo,DIB_RGB_COLORS);
if (wScans == 0)
{
DeleteObject( hbmpXOR );
ReleaseDC( NULL, hDC );
return NULL;
}
}
// AND BITMAP
// create MONO device-dependent bitmap for AND mask
hbmpAND= CreateBitmap( wW, wH, 1, 1, NULL );
if (!hbmpAND)
{
DeleteObject( hbmpXOR );
ReleaseDC( NULL, hDC );
return NULL;
}
else
{
RGBQUAD rgbBlack = { 0x00, 0x00, 0x00, 0x00 };
RGBQUAD rgbWhite = { 0xFF, 0xFF, 0xFF, 0x00 };
// modify BITMAPINFOHEADER structure for monochrome bitmap
lpbihdr->biHeight = wH;
lpbihdr->biSizeImage = wANDSize;
lpbihdr->biBitCount = 1;
lpbinfo->bmiColors[0] = rgbBlack;
lpbinfo->bmiColors[1] = rgbWhite;
// convert AND mask from DIB to DDB
wScans = SetDIBits(hDC,hbmpAND,0,wH,lpANDbits,lpbinfo,DIB_RGB_COLORS);
if (wScans == 0)
{
DeleteObject( hbmpXOR );
DeleteObject( hbmpAND );
ReleaseDC( NULL, hDC );
return NULL;
}
}
// Now that we have a AND bitmap and a XOR bitmap, we need to
// convert the cursor size to that of the display by using StretchBlt.
hSrcDC = CreateCompatibleDC( hDC );
if (!hSrcDC)
{
DeleteObject( hbmpXOR );
DeleteObject( hbmpAND );
ReleaseDC( NULL, hDC );
return NULL;
}
hDestDC = CreateCompatibleDC( hDC );
if (!hDestDC)
{
DeleteDC( hSrcDC );
DeleteObject( hbmpXOR );
DeleteObject( hbmpAND );
ReleaseDC( NULL, hDC );
return NULL;
}
wCursorW = GetSystemMetrics( SM_CXCURSOR );
wCursorH = GetSystemMetrics( SM_CYCURSOR );
hbmpDestXOR = CreateBitmap( wCursorW, wCursorH, 1, 1, NULL );
if (!hbmpDestXOR)
{
DeleteObject( hbmpXOR );
DeleteObject( hbmpAND );
DeleteDC( hSrcDC );
DeleteDC( hDestDC );
ReleaseDC( NULL, hDC );
return NULL;
}
hbmpDestAND = CreateBitmap( wCursorW, wCursorH, 1, 1, NULL );
if (!hbmpDestAND)
{
DeleteObject( hbmpDestXOR );
DeleteObject( hbmpXOR );
DeleteObject( hbmpAND );
DeleteDC( hSrcDC );
DeleteDC( hDestDC );
ReleaseDC( NULL, hDC );
return NULL;
}
hbmpOldSrc = (HBITMAP)SelectObject( hSrcDC, hbmpXOR );
hbmpOldDest = (HBITMAP)SelectObject( hDestDC, hbmpDestXOR );
SetStretchBltMode( hDestDC, WHITEONBLACK );
StretchBlt(hDestDC,0,0,wCursorW,wCursorH,hSrcDC,0,0,wW,wH,SRCCOPY);
SelectObject( hSrcDC, hbmpAND );
SelectObject( hDestDC, hbmpDestAND );
SetStretchBltMode( hDestDC, BLACKONWHITE );
StretchBlt(hDestDC,0,0,wCursorW,wCursorH,hSrcDC,0,0,wW,wH,SRCCOPY);
// Clean up all but the two new bitmaps
SelectObject( hSrcDC, hbmpOldSrc );
SelectObject( hDestDC, hbmpOldDest );
DeleteDC( hSrcDC );
DeleteDC( hDestDC );
ReleaseDC( NULL, hDC );
DeleteObject( hbmpXOR );
DeleteObject( hbmpAND );
// Now that the bitmaps are the correct size, we need to retrieve
// the DDB bits again so we can CreateCursor
GetObject( hbmpDestXOR, sizeof(BITMAP), (LPSTR)&bmp );
wXORSize = (bmp.bmWidth * bmp.bmHeight) *
(bmp.bmPlanes * bmp.bmBitsPixel) / 8;
hXORbits = GlobalAlloc( GHND, wXORSize );
if (hXORbits == NULL)
{
DeleteObject( hbmpDestAND );
DeleteObject( hbmpDestXOR );
return NULL;
}
if ((lpXORbits = (LPSTR)GlobalLock( hXORbits )) == NULL)
{
GlobalFree( hXORbits );
DeleteObject( hbmpDestAND );
DeleteObject( hbmpDestXOR );
return NULL;
}
if (!GetBitmapBits( hbmpDestXOR, wXORSize, lpXORbits))
{
GlobalUnlock( hXORbits );
GlobalFree( hXORbits );
DeleteObject( hbmpDestAND );
DeleteObject( hbmpDestXOR );
return NULL;
}
GetObject( hbmpDestAND, sizeof(BITMAP), (LPSTR)&bmp );
wANDSize = (bmp.bmWidth * bmp.bmHeight) / 8;
hANDbits = GlobalAlloc( GHND, wANDSize );
if (hANDbits == NULL)
{
GlobalUnlock( hXORbits );
GlobalFree( hXORbits );
DeleteObject( hbmpDestAND );
DeleteObject( hbmpDestXOR );
return NULL;
}
if ((lpANDbits = (LPSTR)GlobalLock( hANDbits )) == NULL)
{
GlobalFree( hANDbits );
GlobalUnlock( hXORbits );
GlobalFree( hXORbits );
DeleteObject( hbmpDestAND );
DeleteObject( hbmpDestXOR );
return NULL;
}
if (!GetBitmapBits( hbmpDestAND,wANDSize,lpANDbits))
{
GlobalUnlock( hANDbits );
GlobalFree( hANDbits );
GlobalUnlock( hXORbits );
GlobalFree( hXORbits );
DeleteObject( hbmpDestAND );
DeleteObject( hbmpDestXOR );
return NULL;
}
// Now after all this we can finally make an cursor.
GetObject( hbmpDestXOR, sizeof(BITMAP), (LPSTR)&bmp );
hCursor = CreateCursor( ghInst, lpci->xHotSpot, lpci->yHotSpot,
wCursorW, wCursorH, lpANDbits, lpXORbits );
GlobalUnlock( hANDbits );
GlobalFree( hANDbits );
GlobalUnlock( hXORbits );
GlobalFree( hXORbits );
DeleteObject( hbmpDestAND );
DeleteObject( hbmpDestXOR );
return hCursor;
} //*** MakeCursor