| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229 |
- #include "CmCursor.h"
- #include "CmRenderWindow.h"
- #include "CmWindowEventUtilities.h"
- #include "CmPixelUtil.h"
- #include "CmApplication.h"
- #include <windows.h>
- namespace CamelotFramework
- {
- struct NativeCursorData::Pimpl
- {
- HCURSOR cursor;
- };
- NativeCursorData::NativeCursorData()
- {
- data = cm_new<Pimpl>();
- }
- NativeCursorData::~NativeCursorData()
- {
- cm_delete(data);
- }
- bool Cursor::mIsHidden = false;
- NativeCursorData Cursor::mCursor;
- bool Cursor::mUsingCustom = false;
- void Cursor::setPosition(const Int2& screenPos)
- {
- SetCursorPos(screenPos.x, screenPos.y);
- }
- void Cursor::hide()
- {
- mIsHidden = true;
- // ShowCursor(FALSE) doesn't work. Presumably because we're in the wrong thread, and using
- // WM_SETCURSOR in message loop to hide the cursor is smarter solution anyway.
- RenderWindowPtr primaryWindow = gApplication().getPrimaryWindow();
- HWND hwnd;
- primaryWindow->getCustomAttribute("WINDOW", &hwnd);
- PostMessage(hwnd, WM_SETCURSOR, WPARAM(hwnd), (LPARAM)MAKELONG(HTCLIENT, WM_MOUSEMOVE));
- }
- void Cursor::show()
- {
- mIsHidden = false;
- // ShowCursor(FALSE) doesn't work. Presumably because we're in the wrong thread, and using
- // WM_SETCURSOR in message loop to hide the cursor is smarter solution anyway.
- RenderWindowPtr primaryWindow = gApplication().getPrimaryWindow();
- HWND hwnd;
- primaryWindow->getCustomAttribute("WINDOW", &hwnd);
- PostMessage(hwnd, WM_SETCURSOR, WPARAM(hwnd), (LPARAM)MAKELONG(HTCLIENT, WM_MOUSEMOVE));
- }
- void Cursor::clipToWindow(const RenderWindow& window)
- {
- HWND hwnd;
- window.getCustomAttribute("WINDOW", &hwnd);
- // Clip cursor to the window
- RECT clipWindowRect;
- if(GetWindowRect(hwnd, &clipWindowRect))
- {
- ClipCursor(&clipWindowRect);
- }
- }
- void Cursor::clipToRect(const Rect& screenRect)
- {
- RECT clipWindowRect;
- clipWindowRect.left = screenRect.x;
- clipWindowRect.top = screenRect.y;
- clipWindowRect.right = screenRect.x + screenRect.width;
- clipWindowRect.bottom = screenRect.y + screenRect.height;
- ClipCursor(&clipWindowRect);
- }
- void Cursor::clipDisable()
- {
- ClipCursor(NULL);
- }
- void Cursor::setCursor(CursorType type)
- {
- if(mUsingCustom)
- {
- SetCursor(0);
- DestroyIcon(mCursor.data->cursor);
- mUsingCustom = false;
- }
- switch(type)
- {
- case CursorType::Arrow:
- mCursor.data->cursor = LoadCursor(0, IDC_ARROW);
- break;
- case CursorType::Wait:
- mCursor.data->cursor = LoadCursor(0, IDC_WAIT);
- break;
- case CursorType::IBeam:
- mCursor.data->cursor = LoadCursor(0, IDC_IBEAM);
- break;
- case CursorType::Help:
- mCursor.data->cursor = LoadCursor(0, IDC_HELP);
- break;
- case CursorType::Hand:
- mCursor.data->cursor = LoadCursor(0, IDC_HAND);
- break;
- case CursorType::SizeAll:
- mCursor.data->cursor = LoadCursor(0, IDC_SIZEALL);
- break;
- case CursorType::SizeNESW:
- mCursor.data->cursor = LoadCursor(0, IDC_SIZENESW);
- break;
- case CursorType::SizeNS:
- mCursor.data->cursor = LoadCursor(0, IDC_SIZENS);
- break;
- case CursorType::SizeNWSE:
- mCursor.data->cursor = LoadCursor(0, IDC_SIZENWSE);
- break;
- case CursorType::SizeWE:
- mCursor.data->cursor = LoadCursor(0, IDC_SIZEWE);
- break;
- }
- // Make sure we notify the message loop to perform the actual cursor update
- RenderWindowPtr primaryWindow = gApplication().getPrimaryWindow();
- HWND hwnd;
- primaryWindow->getCustomAttribute("WINDOW", &hwnd);
- PostMessage(hwnd, WM_SETCURSOR, WPARAM(hwnd), (LPARAM)MAKELONG(HTCLIENT, WM_MOUSEMOVE));
- }
- // TODO - Add support for animated custom cursor
- void Cursor::setCustomCursor(PixelData& pixelData, const Int2& hotSpot)
- {
- if(mUsingCustom)
- {
- SetCursor(0);
- DestroyIcon(mCursor.data->cursor);
- }
- mUsingCustom = true;
- BITMAPV5HEADER bi;
- ZeroMemory(&bi,sizeof(BITMAPV5HEADER));
- bi.bV5Size = sizeof(BITMAPV5HEADER);
- bi.bV5Width = pixelData.getWidth();
- bi.bV5Height = pixelData.getHeight();
- bi.bV5Planes = 1;
- bi.bV5BitCount = 32;
- bi.bV5Compression = BI_BITFIELDS;
- bi.bV5RedMask = 0x00FF0000;
- bi.bV5GreenMask = 0x0000FF00;
- bi.bV5BlueMask = 0x000000FF;
- bi.bV5AlphaMask = 0xFF000000;
- HDC hDC = GetDC(NULL);
- void* data = nullptr;
- HBITMAP hBitmap = CreateDIBSection(hDC, (BITMAPINFO *)&bi, DIB_RGB_COLORS,
- (void**)&data, NULL, (DWORD)0);
- HDC hBitmapDC = CreateCompatibleDC(hDC);
- ReleaseDC(NULL, hDC);
- // Create an empty mask bitmap.
- HBITMAP hMonoBitmap = CreateBitmap(pixelData.getWidth(), pixelData.getHeight(), 1, 1, NULL);
- //Select the bitmaps to DC
- HBITMAP hOldBitmap = (HBITMAP)SelectObject(hBitmapDC, hBitmap);
- //Scan each pixel of the source bitmap and create the masks
- Color pixel;
- DWORD *dst = (DWORD*)data;
- for(UINT32 y = 0; y < pixelData.getHeight(); ++y)
- {
- for(UINT32 x = 0; x < pixelData.getWidth(); ++x)
- {
- pixel = pixelData.getColorAt(x, pixelData.getHeight() - y - 1);
- *dst = pixel.getAsBGRA();
- dst++;
- }
- }
- SelectObject(hBitmapDC, hOldBitmap);
- DeleteDC(hBitmapDC);
- ICONINFO iconinfo = {0};
- iconinfo.fIcon = FALSE;
- iconinfo.xHotspot = (DWORD)hotSpot.x;
- iconinfo.yHotspot = (DWORD)hotSpot.y;
- iconinfo.hbmMask = hMonoBitmap;
- iconinfo.hbmColor = hBitmap;
- mCursor.data->cursor = CreateIconIndirect(&iconinfo);
- DeleteObject(hBitmap);
- DeleteObject(hMonoBitmap);
- // Make sure we notify the message loop to perform the actual cursor update
- RenderWindowPtr primaryWindow = gApplication().getPrimaryWindow();
- HWND hwnd;
- primaryWindow->getCustomAttribute("WINDOW", &hwnd);
- PostMessage(hwnd, WM_SETCURSOR, WPARAM(hwnd), (LPARAM)MAKELONG(HTCLIENT, WM_MOUSEMOVE));
- }
- void Cursor::_win32ShowCursor()
- {
- SetCursor(mCursor.data->cursor);
- }
- void Cursor::_win32HideCursor()
- {
- SetCursor(nullptr);
- }
- }
|