void Texture::SetAsHardwareCursor(const Vector2 & hotSpot) { if (id) { LPDIRECT3DSURFACE9 textureMainSurface; HRESULT hr = id->GetSurfaceLevel(0, &textureMainSurface); RENDER_VERIFY(hr); // Check surface format // D3DSURFACE_DESC desc; ZeroMemory(&desc, sizeof(desc)); RENDER_VERIFY(textureMainSurface->GetDesc(&desc)); LPDIRECT3DDEVICE9 device = RenderManager::Instance()->GetD3DDevice(); hr = device->SetCursorProperties((UINT)hotSpot.x, (UINT)hotSpot.y, textureMainSurface); RENDER_VERIFY(hr); D3DSafeRelease(textureMainSurface); } }
HRESULT HookIDirect3DDevice9::SetCursorProperties(LPVOID _this, UINT XHotSpot,UINT YHotSpot,IDirect3DSurface9* pCursorBitmap) { LOG_API(); return pD3Dev->SetCursorProperties(XHotSpot, YHotSpot, pCursorBitmap); }
//----------------------------------------------------------------------------- // Name: D3DUtil_SetDeviceCursor // Desc: Gives the D3D device a cursor with image and hotspot from hCursor. //----------------------------------------------------------------------------- HRESULT D3DUtil_SetDeviceCursor( LPDIRECT3DDEVICE9 pd3dDevice, HCURSOR hCursor, BOOL bAddWatermark ) { HRESULT hr = E_FAIL; ICONINFO iconinfo; BOOL bBWCursor; LPDIRECT3DSURFACE9 pCursorSurface = NULL; HDC hdcColor = NULL; HDC hdcMask = NULL; HDC hdcScreen = NULL; BITMAP bm; DWORD dwWidth; DWORD dwHeightSrc; DWORD dwHeightDest; COLORREF crColor; COLORREF crMask; UINT x; UINT y; BITMAPINFO bmi; COLORREF* pcrArrayColor = NULL; COLORREF* pcrArrayMask = NULL; DWORD* pBitmap; HGDIOBJ hgdiobjOld; ZeroMemory( &iconinfo, sizeof(iconinfo) ); if( !GetIconInfo( hCursor, &iconinfo ) ) goto End; if (0 == GetObject((HGDIOBJ)iconinfo.hbmMask, sizeof(BITMAP), (LPVOID)&bm)) goto End; dwWidth = bm.bmWidth; dwHeightSrc = bm.bmHeight; if( iconinfo.hbmColor == NULL ) { bBWCursor = TRUE; dwHeightDest = dwHeightSrc / 2; } else { bBWCursor = FALSE; dwHeightDest = dwHeightSrc; } // Create a surface for the fullscreen cursor if( FAILED( hr = pd3dDevice->CreateOffscreenPlainSurface( dwWidth, dwHeightDest, D3DFMT_A8R8G8B8, D3DPOOL_SCRATCH, &pCursorSurface, 0 ) ) ) { goto End; } pcrArrayMask = new DWORD[dwWidth * dwHeightSrc]; ZeroMemory(&bmi, sizeof(bmi)); bmi.bmiHeader.biSize = sizeof(bmi.bmiHeader); bmi.bmiHeader.biWidth = dwWidth; bmi.bmiHeader.biHeight = dwHeightSrc; bmi.bmiHeader.biPlanes = 1; bmi.bmiHeader.biBitCount = 32; bmi.bmiHeader.biCompression = BI_RGB; hdcScreen = GetDC( NULL ); hdcMask = CreateCompatibleDC( hdcScreen ); if( hdcMask == NULL ) { hr = E_FAIL; goto End; } hgdiobjOld = SelectObject(hdcMask, iconinfo.hbmMask); GetDIBits(hdcMask, iconinfo.hbmMask, 0, dwHeightSrc, pcrArrayMask, &bmi, DIB_RGB_COLORS); SelectObject(hdcMask, hgdiobjOld); if (!bBWCursor) { pcrArrayColor = new DWORD[dwWidth * dwHeightDest]; hdcColor = CreateCompatibleDC( hdcScreen ); if( hdcColor == NULL ) { hr = E_FAIL; goto End; } SelectObject(hdcColor, iconinfo.hbmColor); GetDIBits(hdcColor, iconinfo.hbmColor, 0, dwHeightDest, pcrArrayColor, &bmi, DIB_RGB_COLORS); } // Transfer cursor image into the surface D3DLOCKED_RECT lr; pCursorSurface->LockRect( &lr, NULL, 0 ); pBitmap = (DWORD*)lr.pBits; for( y = 0; y < dwHeightDest; y++ ) { for( x = 0; x < dwWidth; x++ ) { if (bBWCursor) { crColor = pcrArrayMask[dwWidth*(dwHeightDest-1-y) + x]; crMask = pcrArrayMask[dwWidth*(dwHeightSrc-1-y) + x]; } else { crColor = pcrArrayColor[dwWidth*(dwHeightDest-1-y) + x]; crMask = pcrArrayMask[dwWidth*(dwHeightDest-1-y) + x]; } if (crMask == 0) pBitmap[dwWidth*y + x] = 0xff000000 | crColor; else pBitmap[dwWidth*y + x] = 0x00000000; // It may be helpful to make the D3D cursor look slightly // different from the Windows cursor so you can distinguish // between the two when developing/testing code. When // bAddWatermark is TRUE, the following code adds some // small grey "D3D" characters to the upper-left corner of // the D3D cursor image. if( bAddWatermark && x < 12 && y < 5 ) { // 11.. 11.. 11.. .... CCC0 // 1.1. ..1. 1.1. .... A2A0 // 1.1. .1.. 1.1. .... A4A0 // 1.1. ..1. 1.1. .... A2A0 // 11.. 11.. 11.. .... CCC0 const WORD wMask[5] = { 0xccc0, 0xa2a0, 0xa4a0, 0xa2a0, 0xccc0 }; if( wMask[y] & (1 << (15 - x)) ) { pBitmap[dwWidth*y + x] |= 0xff808080; } } } } pCursorSurface->UnlockRect(); // Set the device cursor if( FAILED( hr = pd3dDevice->SetCursorProperties( iconinfo.xHotspot, iconinfo.yHotspot, pCursorSurface ) ) ) { goto End; } hr = S_OK; End: if( iconinfo.hbmMask != NULL ) DeleteObject( iconinfo.hbmMask ); if( iconinfo.hbmColor != NULL ) DeleteObject( iconinfo.hbmColor ); if( hdcScreen != NULL ) ReleaseDC( NULL, hdcScreen ); if( hdcColor != NULL ) DeleteDC( hdcColor ); if( hdcMask != NULL ) DeleteDC( hdcMask ); SAFE_DELETE_ARRAY( pcrArrayColor ); SAFE_DELETE_ARRAY( pcrArrayMask ); SAFE_RELEASE( pCursorSurface ); return hr; }