mirror of
https://github.com/SFML/SFML.git
synced 2024-11-25 12:51: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
|
/// Type | Linux | Mac OS X | Windows
|
||||||
/// ------------------------------------|:-----:|:--------:|:--------:
|
/// ------------------------------------|:-----:|:--------:|:--------:
|
||||||
/// sf::Cursor::Arrow | yes | yes | yes
|
/// sf::Cursor::Arrow | yes | yes | yes
|
||||||
/// sf::Cursor::ArrowWait | no | no | no
|
/// sf::Cursor::ArrowWait | no | no | yes
|
||||||
/// sf::Cursor::Wait | no | no | no
|
/// sf::Cursor::Wait | no | no | yes
|
||||||
/// sf::Cursor::Text | no | yes | no
|
/// sf::Cursor::Text | no | yes | yes
|
||||||
/// sf::Cursor::Hand | no | yes | no
|
/// sf::Cursor::Hand | no | yes | yes
|
||||||
/// sf::Cursor::SizeHorizontal | no | yes | no
|
/// sf::Cursor::SizeHorizontal | no | yes | yes
|
||||||
/// sf::Cursor::SizeVertical | no | yes | no
|
/// sf::Cursor::SizeVertical | no | yes | yes
|
||||||
/// sf::Cursor::SizeTopLeftBottomRight | no | no | no
|
/// sf::Cursor::SizeTopLeftBottomRight | no | no | yes
|
||||||
/// sf::Cursor::SizeBottomLeftTopRight | no | no | no
|
/// sf::Cursor::SizeBottomLeftTopRight | no | no | yes
|
||||||
/// sf::Cursor::SizeAll | no | no | no
|
/// sf::Cursor::SizeAll | no | no | yes
|
||||||
/// sf::Cursor::Cross | no | yes | no
|
/// sf::Cursor::Cross | no | yes | yes
|
||||||
/// sf::Cursor::Help | no | no | no
|
/// sf::Cursor::Help | no | no | yes
|
||||||
/// sf::Cursor::NotAllowed | no | yes | no
|
/// sf::Cursor::NotAllowed | no | yes | yes
|
||||||
///
|
///
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
enum Type
|
enum Type
|
||||||
@ -195,8 +195,8 @@ private:
|
|||||||
/// with either loadFromPixels() or loadFromSystem(), the
|
/// with either loadFromPixels() or loadFromSystem(), the
|
||||||
/// cursor can be changed with sf::Window::setMouseCursor().
|
/// cursor can be changed with sf::Window::setMouseCursor().
|
||||||
///
|
///
|
||||||
/// \todo Does Windows or Linux requires the Cursor instance
|
/// The behaviour is undefined if the cursor is destroyed while
|
||||||
/// to outlive it's usage?
|
/// in use by the window.
|
||||||
///
|
///
|
||||||
/// Usage example:
|
/// Usage example:
|
||||||
/// \code
|
/// \code
|
||||||
|
@ -367,6 +367,9 @@ public:
|
|||||||
///
|
///
|
||||||
/// Upon window creation, the arrow cursor is used by default.
|
/// 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
|
/// \warning Features related to Cursor are not supported on
|
||||||
/// iOS and Android.
|
/// 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
|
// Headers
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
#include <SFML/Window/Win32/CursorImpl.hpp>
|
#include <SFML/Window/Win32/CursorImpl.hpp>
|
||||||
|
#include <SFML/System/Err.hpp>
|
||||||
|
#include <cstring>
|
||||||
|
|
||||||
namespace sf
|
namespace sf
|
||||||
{
|
{
|
||||||
@ -33,33 +35,148 @@ namespace priv
|
|||||||
{
|
{
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
CursorImpl::CursorImpl()
|
CursorImpl::CursorImpl() :
|
||||||
|
m_cursor(NULL)
|
||||||
{
|
{
|
||||||
// TODO
|
// That's it.
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
CursorImpl::~CursorImpl()
|
CursorImpl::~CursorImpl()
|
||||||
{
|
{
|
||||||
// TODO
|
release();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
bool CursorImpl::loadFromPixels(const Uint8* pixels, Vector2u size, Vector2u hotspot)
|
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)
|
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 priv
|
||||||
|
|
||||||
} // namespace sf
|
} // 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/NonCopyable.hpp>
|
||||||
#include <SFML/System/Vector2.hpp>
|
#include <SFML/System/Vector2.hpp>
|
||||||
|
|
||||||
|
#include <windows.h>
|
||||||
|
|
||||||
namespace sf
|
namespace sf
|
||||||
{
|
{
|
||||||
@ -82,9 +83,16 @@ private:
|
|||||||
|
|
||||||
friend class WindowImplWin32;
|
friend class WindowImplWin32;
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
/// \brief Release the cursor, if we have loaded one.
|
||||||
|
///
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
void release();
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
// Member data
|
// Member data
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
|
HCURSOR m_cursor;
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace priv
|
} // 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) :
|
WindowImplWin32::WindowImplWin32(WindowHandle handle) :
|
||||||
m_handle (handle),
|
m_handle (handle),
|
||||||
m_callback (0),
|
m_callback (0),
|
||||||
m_cursor (NULL),
|
m_cursorVisible (true), // might need to call GetCursorInfo
|
||||||
m_loadedCursor (NULL),
|
m_lastCursor (LoadCursor(NULL, IDC_ARROW)),
|
||||||
m_icon (NULL),
|
m_icon (NULL),
|
||||||
m_keyRepeatEnabled(true),
|
m_keyRepeatEnabled(true),
|
||||||
m_lastSize (0, 0),
|
m_lastSize (0, 0),
|
||||||
@ -165,8 +165,8 @@ m_cursorGrabbed (false)
|
|||||||
WindowImplWin32::WindowImplWin32(VideoMode mode, const String& title, Uint32 style, const ContextSettings& /*settings*/) :
|
WindowImplWin32::WindowImplWin32(VideoMode mode, const String& title, Uint32 style, const ContextSettings& /*settings*/) :
|
||||||
m_handle (NULL),
|
m_handle (NULL),
|
||||||
m_callback (0),
|
m_callback (0),
|
||||||
m_cursor (NULL),
|
m_cursorVisible (true), // might need to call GetCursorInfo
|
||||||
m_loadedCursor (NULL),
|
m_lastCursor (LoadCursor(NULL, IDC_ARROW)),
|
||||||
m_icon (NULL),
|
m_icon (NULL),
|
||||||
m_keyRepeatEnabled(true),
|
m_keyRepeatEnabled(true),
|
||||||
m_lastSize (mode.width, mode.height),
|
m_lastSize (mode.width, mode.height),
|
||||||
@ -241,9 +241,7 @@ m_cursorGrabbed (m_fullscreen)
|
|||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
WindowImplWin32::~WindowImplWin32()
|
WindowImplWin32::~WindowImplWin32()
|
||||||
{
|
{
|
||||||
// Destroy the cursor
|
// TODO should we restore the cursor shape and visibility?
|
||||||
if (m_loadedCursor)
|
|
||||||
DestroyCursor(m_loadedCursor);
|
|
||||||
|
|
||||||
// Destroy the custom icon, if any
|
// Destroy the custom icon, if any
|
||||||
if (m_icon)
|
if (m_icon)
|
||||||
@ -396,16 +394,14 @@ void WindowImplWin32::setVisible(bool visible)
|
|||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
void WindowImplWin32::setMouseCursorVisible(bool visible)
|
void WindowImplWin32::setMouseCursorVisible(bool visible)
|
||||||
{
|
{
|
||||||
// Set the default mouse cursor if none has been loaded yet
|
// Don't call twice ShowCursor with the same parameter value;
|
||||||
if (!m_loadedCursor)
|
// we don't want to increment/decrement the internal counter
|
||||||
setMouseCursor(Window::Arrow);
|
// more than once.
|
||||||
|
if (visible != m_cursorVisible)
|
||||||
if (visible)
|
{
|
||||||
m_cursor = m_loadedCursor;
|
m_cursorVisible = visible;
|
||||||
else
|
ShowCursor(visible);
|
||||||
m_cursor = NULL;
|
}
|
||||||
|
|
||||||
SetCursor(m_cursor);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -420,93 +416,8 @@ void WindowImplWin32::setMouseCursorGrabbed(bool grabbed)
|
|||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
void WindowImplWin32::setMouseCursor(const CursorImpl& cursor)
|
void WindowImplWin32::setMouseCursor(const CursorImpl& cursor)
|
||||||
{
|
{
|
||||||
}
|
m_lastCursor = cursor.m_cursor;
|
||||||
|
SetCursor(m_lastCursor);
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////
|
|
||||||
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);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -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
|
// The mouse has moved, if the cursor is in our window we must refresh the cursor
|
||||||
if (LOWORD(lParam) == HTCLIENT)
|
if (LOWORD(lParam) == HTCLIENT)
|
||||||
SetCursor(m_cursor);
|
SetCursor(m_lastCursor);
|
||||||
|
|
||||||
break;
|
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
|
HWND m_handle; ///< Win32 handle of the window
|
||||||
LONG_PTR m_callback; ///< Stores the original event callback function of the control
|
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
|
bool m_cursorVisible; ///< Is the cursor visible or hidden?
|
||||||
HCURSOR m_loadedCursor; ///< The system cursor selected to be displayed into the window
|
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
|
HICON m_icon; ///< Custom icon assigned to the window
|
||||||
bool m_keyRepeatEnabled; ///< Automatic key-repeat state for keydown events
|
bool m_keyRepeatEnabled; ///< Automatic key-repeat state for keydown events
|
||||||
Vector2u m_lastSize; ///< The last handled size of the window
|
Vector2u m_lastSize; ///< The last handled size of the window
|
||||||
|
Loading…
Reference in New Issue
Block a user