mirror of
https://github.com/SFML/SFML.git
synced 2024-11-25 04:41:05 +08:00
Added Win32 implementation
This commit is contained in:
parent
f65459d0e1
commit
b0b1f13269
@ -56,18 +56,18 @@ public:
|
||||
/// Type | Linux | Mac OS X | Windows
|
||||
/// ------------------------------------|:-----:|:--------:|:--------:
|
||||
/// sf::Cursor::Arrow | yes | yes | yes
|
||||
/// sf::Cursor::ArrowWait | no | no | no
|
||||
/// sf::Cursor::Wait | no | no | no
|
||||
/// sf::Cursor::Text | no | yes | no
|
||||
/// sf::Cursor::Hand | no | yes | no
|
||||
/// sf::Cursor::SizeHorizontal | no | yes | no
|
||||
/// sf::Cursor::SizeVertical | no | yes | no
|
||||
/// sf::Cursor::SizeTopLeftBottomRight | no | no | no
|
||||
/// sf::Cursor::SizeBottomLeftTopRight | no | no | no
|
||||
/// sf::Cursor::SizeAll | no | no | no
|
||||
/// sf::Cursor::Cross | no | yes | no
|
||||
/// sf::Cursor::Help | no | no | no
|
||||
/// sf::Cursor::NotAllowed | no | yes | no
|
||||
/// sf::Cursor::ArrowWait | no | no | yes
|
||||
/// sf::Cursor::Wait | no | no | yes
|
||||
/// sf::Cursor::Text | no | yes | yes
|
||||
/// sf::Cursor::Hand | no | yes | yes
|
||||
/// sf::Cursor::SizeHorizontal | no | yes | yes
|
||||
/// sf::Cursor::SizeVertical | no | yes | yes
|
||||
/// sf::Cursor::SizeTopLeftBottomRight | no | no | yes
|
||||
/// sf::Cursor::SizeBottomLeftTopRight | no | no | yes
|
||||
/// sf::Cursor::SizeAll | no | no | yes
|
||||
/// sf::Cursor::Cross | no | yes | yes
|
||||
/// sf::Cursor::Help | no | no | yes
|
||||
/// sf::Cursor::NotAllowed | no | yes | yes
|
||||
///
|
||||
////////////////////////////////////////////////////////////
|
||||
enum Type
|
||||
@ -195,8 +195,8 @@ private:
|
||||
/// with either loadFromPixels() or loadFromSystem(), the
|
||||
/// cursor can be changed with sf::Window::setMouseCursor().
|
||||
///
|
||||
/// \todo Does Windows or Linux requires the Cursor instance
|
||||
/// to outlive it's usage?
|
||||
/// The behaviour is undefined if the cursor is destroyed while
|
||||
/// in use by the window.
|
||||
///
|
||||
/// Usage example:
|
||||
/// \code
|
||||
|
@ -367,6 +367,9 @@ public:
|
||||
///
|
||||
/// Upon window creation, the arrow cursor is used by default.
|
||||
///
|
||||
/// \warning The cursor must not be destroyed while in use by
|
||||
/// the window.
|
||||
///
|
||||
/// \warning Features related to Cursor are not supported on
|
||||
/// iOS and Android.
|
||||
///
|
||||
|
127
src/SFML/Window/Win32/CursorImpl.cpp
Normal file → Executable file
127
src/SFML/Window/Win32/CursorImpl.cpp
Normal file → Executable file
@ -26,6 +26,8 @@
|
||||
// Headers
|
||||
////////////////////////////////////////////////////////////
|
||||
#include <SFML/Window/Win32/CursorImpl.hpp>
|
||||
#include <SFML/System/Err.hpp>
|
||||
#include <cstring>
|
||||
|
||||
namespace sf
|
||||
{
|
||||
@ -33,33 +35,148 @@ namespace priv
|
||||
{
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
CursorImpl::CursorImpl()
|
||||
CursorImpl::CursorImpl() :
|
||||
m_cursor(NULL)
|
||||
{
|
||||
// TODO
|
||||
// That's it.
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
CursorImpl::~CursorImpl()
|
||||
{
|
||||
// TODO
|
||||
release();
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
bool CursorImpl::loadFromPixels(const Uint8* pixels, Vector2u size, Vector2u hotspot)
|
||||
{
|
||||
// TODO
|
||||
release();
|
||||
|
||||
// Create the bitmap that will hold our color data
|
||||
BITMAPV5HEADER bitmapHeader;
|
||||
std::memset(&bitmapHeader, 0, sizeof(BITMAPV5HEADER));
|
||||
|
||||
bitmapHeader.bV5Size = sizeof(BITMAPV5HEADER);
|
||||
bitmapHeader.bV5Width = size.x;
|
||||
bitmapHeader.bV5Height = -static_cast<int>(size.y); // Negative indicates origin is in upper-left corner
|
||||
bitmapHeader.bV5Planes = 1;
|
||||
bitmapHeader.bV5BitCount = 32;
|
||||
bitmapHeader.bV5Compression = BI_BITFIELDS;
|
||||
bitmapHeader.bV5RedMask = 0x00ff0000;
|
||||
bitmapHeader.bV5GreenMask = 0x0000ff00;
|
||||
bitmapHeader.bV5BlueMask = 0x000000ff;
|
||||
bitmapHeader.bV5AlphaMask = 0xff000000;
|
||||
|
||||
Uint8* bitmapData = NULL;
|
||||
|
||||
HDC screenDC = GetDC(NULL);
|
||||
HBITMAP color = CreateDIBSection(
|
||||
screenDC,
|
||||
reinterpret_cast<const BITMAPINFO*>(&bitmapHeader),
|
||||
DIB_RGB_COLORS,
|
||||
reinterpret_cast<void**>(&bitmapData),
|
||||
NULL,
|
||||
0
|
||||
);
|
||||
ReleaseDC(NULL, screenDC);
|
||||
|
||||
if (!color)
|
||||
{
|
||||
err() << "Failed to create cursor color bitmap" << std::endl;
|
||||
return false;
|
||||
}
|
||||
|
||||
// Fill our bitmap with the cursor color data
|
||||
std::memcpy(bitmapData, pixels, size.x * size.y * 4);
|
||||
|
||||
// Create a dummy mask bitmap (it won't be used)
|
||||
HBITMAP mask = CreateBitmap(size.x, size.y, 1, 1, NULL);
|
||||
|
||||
if (!mask)
|
||||
{
|
||||
DeleteObject(color);
|
||||
err() << "Failed to create cursor mask bitmap" << std::endl;
|
||||
return false;
|
||||
}
|
||||
|
||||
// Create the structure that describes our cursor
|
||||
ICONINFO cursorInfo;
|
||||
std::memset(&cursorInfo, 0, sizeof(ICONINFO));
|
||||
|
||||
cursorInfo.fIcon = FALSE; // This is a cursor and not an icon
|
||||
cursorInfo.xHotspot = hotspot.x;
|
||||
cursorInfo.yHotspot = hotspot.y;
|
||||
cursorInfo.hbmColor = color;
|
||||
cursorInfo.hbmMask = mask;
|
||||
|
||||
// Create the cursor
|
||||
m_cursor = reinterpret_cast<HCURSOR>(CreateIconIndirect(&cursorInfo));
|
||||
|
||||
// The data has been copied into the cursor, so get rid of these
|
||||
DeleteObject(color);
|
||||
DeleteObject(mask);
|
||||
|
||||
if (m_cursor)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
err() << "Failed to create cursor from bitmaps" << std::endl;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
bool CursorImpl::loadFromSystem(Cursor::Type type)
|
||||
{
|
||||
// TODO
|
||||
release();
|
||||
|
||||
LPCTSTR shape;
|
||||
switch (type)
|
||||
{
|
||||
case Cursor::Arrow: shape = IDC_ARROW; break;
|
||||
case Cursor::ArrowWait: shape = IDC_APPSTARTING; break;
|
||||
case Cursor::Wait: shape = IDC_WAIT; break;
|
||||
case Cursor::Text: shape = IDC_IBEAM; break;
|
||||
case Cursor::Hand: shape = IDC_HAND; break;
|
||||
case Cursor::SizeHorizontal: shape = IDC_SIZEWE; break;
|
||||
case Cursor::SizeVertical: shape = IDC_SIZENS; break;
|
||||
case Cursor::SizeTopLeftBottomRight: shape = IDC_SIZENWSE; break;
|
||||
case Cursor::SizeBottomLeftTopRight: shape = IDC_SIZENESW; break;
|
||||
case Cursor::SizeAll: shape = IDC_SIZEALL; break;
|
||||
case Cursor::Cross: shape = IDC_CROSS; break;
|
||||
case Cursor::Help: shape = IDC_HELP; break;
|
||||
case Cursor::NotAllowed: shape = IDC_NO; break;
|
||||
}
|
||||
|
||||
// Create a copy of the shared system cursor that we can destroy later
|
||||
m_cursor = CopyCursor(LoadCursor(NULL, shape));
|
||||
|
||||
if (m_cursor)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
err() << "Could not create copy of a system cursor" << std::endl;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
void CursorImpl::release()
|
||||
{
|
||||
if (m_cursor) {
|
||||
DestroyCursor(m_cursor);
|
||||
m_cursor = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace priv
|
||||
|
||||
} // namespace sf
|
||||
|
8
src/SFML/Window/Win32/CursorImpl.hpp
Normal file → Executable file
8
src/SFML/Window/Win32/CursorImpl.hpp
Normal file → Executable file
@ -32,6 +32,7 @@
|
||||
#include <SFML/System/NonCopyable.hpp>
|
||||
#include <SFML/System/Vector2.hpp>
|
||||
|
||||
#include <windows.h>
|
||||
|
||||
namespace sf
|
||||
{
|
||||
@ -82,9 +83,16 @@ private:
|
||||
|
||||
friend class WindowImplWin32;
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
/// \brief Release the cursor, if we have loaded one.
|
||||
///
|
||||
////////////////////////////////////////////////////////////
|
||||
void release();
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
// Member data
|
||||
////////////////////////////////////////////////////////////
|
||||
HCURSOR m_cursor;
|
||||
};
|
||||
|
||||
} // namespace priv
|
||||
|
121
src/SFML/Window/Win32/WindowImplWin32.cpp
Normal file → Executable file
121
src/SFML/Window/Win32/WindowImplWin32.cpp
Normal file → Executable file
@ -132,8 +132,8 @@ namespace priv
|
||||
WindowImplWin32::WindowImplWin32(WindowHandle handle) :
|
||||
m_handle (handle),
|
||||
m_callback (0),
|
||||
m_cursor (NULL),
|
||||
m_loadedCursor (NULL),
|
||||
m_cursorVisible (true), // might need to call GetCursorInfo
|
||||
m_lastCursor (LoadCursor(NULL, IDC_ARROW)),
|
||||
m_icon (NULL),
|
||||
m_keyRepeatEnabled(true),
|
||||
m_lastSize (0, 0),
|
||||
@ -165,8 +165,8 @@ m_cursorGrabbed (false)
|
||||
WindowImplWin32::WindowImplWin32(VideoMode mode, const String& title, Uint32 style, const ContextSettings& /*settings*/) :
|
||||
m_handle (NULL),
|
||||
m_callback (0),
|
||||
m_cursor (NULL),
|
||||
m_loadedCursor (NULL),
|
||||
m_cursorVisible (true), // might need to call GetCursorInfo
|
||||
m_lastCursor (LoadCursor(NULL, IDC_ARROW)),
|
||||
m_icon (NULL),
|
||||
m_keyRepeatEnabled(true),
|
||||
m_lastSize (mode.width, mode.height),
|
||||
@ -241,9 +241,7 @@ m_cursorGrabbed (m_fullscreen)
|
||||
////////////////////////////////////////////////////////////
|
||||
WindowImplWin32::~WindowImplWin32()
|
||||
{
|
||||
// Destroy the cursor
|
||||
if (m_loadedCursor)
|
||||
DestroyCursor(m_loadedCursor);
|
||||
// TODO should we restore the cursor shape and visibility?
|
||||
|
||||
// Destroy the custom icon, if any
|
||||
if (m_icon)
|
||||
@ -396,16 +394,14 @@ void WindowImplWin32::setVisible(bool visible)
|
||||
////////////////////////////////////////////////////////////
|
||||
void WindowImplWin32::setMouseCursorVisible(bool visible)
|
||||
{
|
||||
// Set the default mouse cursor if none has been loaded yet
|
||||
if (!m_loadedCursor)
|
||||
setMouseCursor(Window::Arrow);
|
||||
|
||||
if (visible)
|
||||
m_cursor = m_loadedCursor;
|
||||
else
|
||||
m_cursor = NULL;
|
||||
|
||||
SetCursor(m_cursor);
|
||||
// Don't call twice ShowCursor with the same parameter value;
|
||||
// we don't want to increment/decrement the internal counter
|
||||
// more than once.
|
||||
if (visible != m_cursorVisible)
|
||||
{
|
||||
m_cursorVisible = visible;
|
||||
ShowCursor(visible);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -420,93 +416,8 @@ void WindowImplWin32::setMouseCursorGrabbed(bool grabbed)
|
||||
////////////////////////////////////////////////////////////
|
||||
void WindowImplWin32::setMouseCursor(const CursorImpl& cursor)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
void WindowImplWin32::setMouseCursor(const Uint8* pixels, unsigned int width, unsigned int height, Uint16 hotspotX, Uint16 hotspotY)
|
||||
{
|
||||
// Create the bitmap that will hold our color data
|
||||
BITMAPV5HEADER bitmapHeader;
|
||||
std::memset(&bitmapHeader, 0, sizeof(BITMAPV5HEADER));
|
||||
|
||||
bitmapHeader.bV5Size = sizeof(BITMAPV5HEADER);
|
||||
bitmapHeader.bV5Width = width;
|
||||
bitmapHeader.bV5Height = -height; // Negative indicates origin is in upper-left corner
|
||||
bitmapHeader.bV5Planes = 1;
|
||||
bitmapHeader.bV5BitCount = 32;
|
||||
bitmapHeader.bV5Compression = BI_BITFIELDS;
|
||||
bitmapHeader.bV5RedMask = 0x00ff0000;
|
||||
bitmapHeader.bV5GreenMask = 0x0000ff00;
|
||||
bitmapHeader.bV5BlueMask = 0x000000ff;
|
||||
bitmapHeader.bV5AlphaMask = 0xff000000;
|
||||
|
||||
Uint8* bitmapData = NULL;
|
||||
|
||||
HDC screenDC = GetDC(NULL);
|
||||
HBITMAP color = CreateDIBSection(
|
||||
screenDC,
|
||||
reinterpret_cast<const BITMAPINFO*>(&bitmapHeader),
|
||||
DIB_RGB_COLORS,
|
||||
reinterpret_cast<void**>(&bitmapData),
|
||||
NULL,
|
||||
0
|
||||
);
|
||||
ReleaseDC(NULL, screenDC);
|
||||
|
||||
if (!color)
|
||||
{
|
||||
err() << "Failed to create cursor color bitmap" << std::endl;
|
||||
return;
|
||||
}
|
||||
|
||||
// Fill our bitmap with the cursor color data
|
||||
std::memcpy(bitmapData, pixels, width * height * 4);
|
||||
|
||||
// Create a dummy mask bitmap (it won't be used)
|
||||
HBITMAP mask = CreateBitmap(width, height, 1, 1, NULL);
|
||||
|
||||
if (!mask)
|
||||
{
|
||||
DeleteObject(color);
|
||||
err() << "Failed to create cursor mask bitmap" << std::endl;
|
||||
return;
|
||||
}
|
||||
|
||||
// Create the structure that describes our cursor
|
||||
ICONINFO cursorInfo;
|
||||
std::memset(&cursorInfo, 0, sizeof(ICONINFO));
|
||||
|
||||
cursorInfo.fIcon = FALSE; // This is a cursor and not an icon
|
||||
cursorInfo.xHotspot = hotspotX;
|
||||
cursorInfo.yHotspot = hotspotY;
|
||||
cursorInfo.hbmColor = color;
|
||||
cursorInfo.hbmMask = mask;
|
||||
|
||||
// Create the cursor
|
||||
HCURSOR newCursor = reinterpret_cast<HCURSOR>(CreateIconIndirect(&cursorInfo));
|
||||
|
||||
// The data has been copied into the cursor, so get rid of these
|
||||
DeleteObject(color);
|
||||
DeleteObject(mask);
|
||||
|
||||
if (!newCursor)
|
||||
{
|
||||
err() << "Failed to create cursor from bitmaps" << std::endl;
|
||||
return;
|
||||
}
|
||||
|
||||
HCURSOR oldCursor = m_loadedCursor;
|
||||
m_loadedCursor = newCursor;
|
||||
|
||||
if (m_cursor)
|
||||
{
|
||||
m_cursor = m_loadedCursor;
|
||||
SetCursor(m_cursor);
|
||||
}
|
||||
|
||||
if (oldCursor)
|
||||
DestroyCursor(oldCursor);
|
||||
m_lastCursor = cursor.m_cursor;
|
||||
SetCursor(m_lastCursor);
|
||||
}
|
||||
|
||||
|
||||
@ -671,7 +582,7 @@ void WindowImplWin32::processEvent(UINT message, WPARAM wParam, LPARAM lParam)
|
||||
{
|
||||
// The mouse has moved, if the cursor is in our window we must refresh the cursor
|
||||
if (LOWORD(lParam) == HTCLIENT)
|
||||
SetCursor(m_cursor);
|
||||
SetCursor(m_lastCursor);
|
||||
|
||||
break;
|
||||
}
|
||||
|
4
src/SFML/Window/Win32/WindowImplWin32.hpp
Normal file → Executable file
4
src/SFML/Window/Win32/WindowImplWin32.hpp
Normal file → Executable file
@ -274,8 +274,8 @@ private:
|
||||
////////////////////////////////////////////////////////////
|
||||
HWND m_handle; ///< Win32 handle of the window
|
||||
LONG_PTR m_callback; ///< Stores the original event callback function of the control
|
||||
HCURSOR m_cursor; ///< The system cursor currently displayed into the window, NULL if hidden
|
||||
HCURSOR m_loadedCursor; ///< The system cursor selected to be displayed into the window
|
||||
bool m_cursorVisible; ///< Is the cursor visible or hidden?
|
||||
HCURSOR m_lastCursor; ///< Last cursor used -- this data is not owned by the window and is required to be always valid
|
||||
HICON m_icon; ///< Custom icon assigned to the window
|
||||
bool m_keyRepeatEnabled; ///< Automatic key-repeat state for keydown events
|
||||
Vector2u m_lastSize; ///< The last handled size of the window
|
||||
|
Loading…
Reference in New Issue
Block a user