// Format of the mouse cursor header. typedef struct tagCURSORHEADER { WORD wHotSpotX; WORD wHotSpotY; WORD wExtentX; WORD wExtentY; WORD wFunnyNumber; BYTE ucNumberOfPlanes; BYTE ucBitsPerPixel; } CURSORHEADER; typedef CURSORHEADER FAR * LPCURSORHEADER; // This code may be added to GENERIC's MainWndProc message switch. case WM_KEYDOWN: switch ( wParam ) { case VK_SPACE: { // Capture the client area to memory, BitBlt the mouse cursor // onto it, and then BitBlt it all back to the screen. // Several of the function calls should really be checked // for error returns. HCURSOR hCursor; POINT pCurPos; LPSTR lpGMemCursor; LPSTR lpBits; LPCURSORHEADER lpCursorHdr; WORD wBitsOffset, wHotX, wHotY, wExtX, wExtY; HDC hDCClient, hDCMemory, hDCTemp; RECT rClient; HBITMAP hBMCursorAND, hBMCursorXOR; HBITMAP hBMOldTemp, hBMOldMem, hBMMemory; // Get the current cursor position in client coords. GetCursorPos( &pCurPos ); ScreenToClient( hWnd, &pCurPos ); // Get the current cursor handle. hCursor = SetCursor( LoadCursor( NULL, IDC_ARROW ) ); // Put the cursor back like we found it. SetCursor( hCursor ); // Lock the cursor handle down. lpGMemCursor = GlobalLock( hCursor ); // Cast the structure pointer to the cursor address. lpCursorHdr = (LPCURSORHEADER)lpGMemCursor; wHotX = lpCursorHdr->wHotSpotX; wHotY = lpCursorHdr->wHotSpotY; wExtX = lpCursorHdr->wExtentX; wExtY = lpCursorHdr->wExtentY; // Build a pointer to the first bitmap. wBitsOffset = sizeof( CURSORHEADER ); lpBits = lpGMemCursor + wBitsOffset; hBMCursorAND = CreateBitmap( wExtX, wExtY, lpCursorHdr->ucNumberOfPlanes, lpCursorHdr->ucBitsPerPixel, lpBits ); // Build a pointer to the second bitmap. // NOTE: This calculation will be wrong if the cursor // bitmap width is not a multiple of 8! wBitsOffset = sizeof( CURSORHEADER ) + (( wExtX / 8 ) * wExtY ); lpBits = lpGMemCursor + wBitsOffset; hBMCursorXOR = CreateBitmap( wExtX, wExtY, lpCursorHdr->ucNumberOfPlanes, lpCursorHdr->ucBitsPerPixel, lpBits ); // We're done with the orginal cursor, so unlock it. GlobalUnlock( hCursor ); // Create DCs. hDCClient = GetDC( hWnd ); hDCMemory = CreateCompatibleDC( hDCClient ); hDCTemp = CreateCompatibleDC( hDCClient ); // Build a bitmap the same size as the client rectangle. GetClientRect( hWnd, &rClient ); hBMMemory = CreateCompatibleBitmap( hDCClient, rClient.right, rClient.bottom ); // Select the new bitmap into the memory device context. hBMOldMem = SelectObject( hDCMemory, hBMMemory ); // BitBlt the client window to the memory DC. BitBlt( hDCMemory, 0, 0, rClient.right, rClient.bottom, hDCClient, 0, 0, SRCCOPY ); // Select the first cursor bitmap into the temp DC. hBMOldTemp = SelectObject( hDCTemp, hBMCursorAND ); // BitBlt the first (AND) cursor bitmap to the memory DC. BitBlt( hDCMemory, pCurPos.x - wHotX, pCurPos.y - wHotY, wExtX, wExtY, hDCTemp, 0, 0, SRCAND ); // Select the other cursor bitmap into the temp DC. // NOTE: Don't overwrite the original bitmap handle! SelectObject( hDCTemp, hBMCursorXOR ); // BitBlt the second (XOR) cursor bitmap to the memory DC. BitBlt( hDCMemory, pCurPos.x - wHotX, pCurPos.y - wHotY, wExtX, wExtY, hDCTemp, 0, 0, SRCINVERT ); // This is where you would save the memory bitmap or print it. // For this test we'll just blast it back onto the client area. BitBlt( hDCClient, 0, 0, rClient.right, rClient.bottom, hDCMemory, 0, 0, SRCCOPY ); // Select the orginal bitmaps back into the DCs. SelectObject( hDCMemory, hBMOldMem ); SelectObject( hDCTemp, hBMOldTemp ); // Delete DCs. DeleteDC( hDCMemory ); DeleteDC( hDCTemp ); ReleaseDC( hWnd, hDCClient ); // Delete the created bitmaps. DeleteObject( hBMCursorAND ); DeleteObject( hBMCursorXOR ); DeleteObject( hBMMemory ); break; } } break;