HCURSOR MakeCursor()

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