2025-02-22 13:38:11 -07:00
|
|
|
#include <SFML/Window/WindowHandle.hpp>
|
|
|
|
|
|
|
|
// Other 1st party headers
|
|
|
|
#include <SFML/Window/Window.hpp>
|
|
|
|
#include <SFML/Window/WindowBase.hpp>
|
|
|
|
|
|
|
|
#include <catch2/catch_test_macros.hpp>
|
2025-02-25 21:07:50 +01:00
|
|
|
#include <catch2/generators/catch_generators.hpp>
|
2025-02-22 13:38:11 -07:00
|
|
|
|
|
|
|
#include <SystemUtil.hpp>
|
|
|
|
#include <optional>
|
|
|
|
|
|
|
|
#ifndef NOMINMAX
|
|
|
|
#define NOMINMAX
|
|
|
|
#endif
|
|
|
|
#ifndef WIN32_LEAN_AND_MEAN
|
|
|
|
#define WIN32_LEAN_AND_MEAN
|
|
|
|
#endif
|
|
|
|
#include <Windows.h>
|
|
|
|
|
|
|
|
namespace
|
|
|
|
{
|
|
|
|
bool gotWmShowWindow = false;
|
|
|
|
|
|
|
|
LRESULT WINAPI wndProc(HWND handle, UINT message, WPARAM wParam, LPARAM lParam)
|
|
|
|
{
|
|
|
|
switch (message)
|
|
|
|
{
|
|
|
|
case WM_SHOWWINDOW:
|
|
|
|
gotWmShowWindow = true;
|
|
|
|
assert(wParam == TRUE); // If wParam is TRUE, the window is being shown
|
|
|
|
assert(lParam == 0); // If lParam is zero, the message was sent because of a call to the ShowWindow function
|
|
|
|
break;
|
|
|
|
case WM_CLOSE:
|
|
|
|
PostQuitMessage(0);
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
return DefWindowProcW(handle, message, wParam, lParam);
|
|
|
|
}
|
2025-02-25 21:07:50 +01:00
|
|
|
|
|
|
|
sf::WindowHandle createWindowWrapper(LPWSTR className, HINSTANCE hInstance, DWORD dwExStyle, bool withMenu)
|
|
|
|
{
|
|
|
|
HMENU hMenu = nullptr;
|
|
|
|
if (withMenu)
|
|
|
|
{
|
|
|
|
hMenu = CreateMenu();
|
|
|
|
AppendMenuW(hMenu, MF_STRING, 1, L"Test");
|
|
|
|
}
|
|
|
|
return CreateWindowExW(dwExStyle,
|
|
|
|
className,
|
|
|
|
L"WindowHandle Tests",
|
|
|
|
WS_OVERLAPPEDWINDOW,
|
|
|
|
CW_USEDEFAULT,
|
|
|
|
CW_USEDEFAULT,
|
|
|
|
640,
|
|
|
|
480,
|
|
|
|
nullptr,
|
|
|
|
hMenu,
|
|
|
|
hInstance,
|
|
|
|
nullptr);
|
|
|
|
}
|
|
|
|
|
2025-02-22 13:38:11 -07:00
|
|
|
} // namespace
|
|
|
|
|
|
|
|
TEST_CASE("[Window] sf::WindowHandle (Win32)")
|
|
|
|
{
|
2025-02-25 21:07:50 +01:00
|
|
|
const auto exStyle = GENERATE(DWORD{0}, WS_EX_TOOLWINDOW | WS_EX_CLIENTEDGE);
|
|
|
|
const auto withMenu = GENERATE(false, true);
|
|
|
|
INFO("ExStyle: " << std::hex << exStyle << ", withMenu: " << withMenu);
|
|
|
|
|
2025-02-22 13:38:11 -07:00
|
|
|
const WNDCLASSW classInfo{{}, wndProc, {}, {}, GetModuleHandleW(nullptr), {}, {}, {}, {}, L"sfml_WindowHandleTests"};
|
|
|
|
|
|
|
|
const ATOM winClassId = RegisterClassW(&classInfo);
|
|
|
|
REQUIRE(winClassId);
|
|
|
|
|
2025-02-25 21:07:50 +01:00
|
|
|
const sf::WindowHandle handle = createWindowWrapper(reinterpret_cast<LPWSTR>(static_cast<ULONG_PTR>(winClassId)),
|
|
|
|
classInfo.hInstance,
|
|
|
|
exStyle,
|
|
|
|
withMenu);
|
2025-02-22 13:38:11 -07:00
|
|
|
REQUIRE(handle);
|
|
|
|
REQUIRE(!gotWmShowWindow);
|
|
|
|
REQUIRE(IsWindow(handle));
|
|
|
|
|
|
|
|
RECT windowRect{};
|
|
|
|
REQUIRE(GetWindowRect(handle, &windowRect));
|
|
|
|
const auto position = sf::Vector2i(sf::Vector2(windowRect.left, windowRect.top));
|
|
|
|
|
|
|
|
RECT clientRect{};
|
|
|
|
REQUIRE(GetClientRect(handle, &clientRect));
|
2025-02-25 21:07:50 +01:00
|
|
|
const auto initialSize = sf::Vector2u(
|
|
|
|
sf::Vector2(clientRect.right - clientRect.left, clientRect.bottom - clientRect.top));
|
|
|
|
constexpr sf::Vector2u newSize(640, 480);
|
2025-02-22 13:38:11 -07:00
|
|
|
|
|
|
|
SECTION("sf::WindowBase")
|
|
|
|
{
|
|
|
|
std::optional<sf::WindowBase> windowBase;
|
|
|
|
|
|
|
|
SECTION("WindowHandle constructor")
|
|
|
|
{
|
|
|
|
windowBase.emplace(handle);
|
|
|
|
}
|
|
|
|
|
|
|
|
SECTION("create(WindowHandle)")
|
|
|
|
{
|
|
|
|
windowBase.emplace().create(handle);
|
|
|
|
}
|
|
|
|
|
2025-02-25 21:07:50 +01:00
|
|
|
INFO("ExStyle: " << std::hex << exStyle << ", withMenu: " << withMenu);
|
2025-02-22 13:38:11 -07:00
|
|
|
CHECK(windowBase->isOpen());
|
|
|
|
CHECK(windowBase->getPosition() == position);
|
2025-02-25 21:07:50 +01:00
|
|
|
CHECK(windowBase->getSize() == initialSize);
|
2025-02-22 13:38:11 -07:00
|
|
|
CHECK(windowBase->getNativeHandle() == handle);
|
2025-02-25 21:07:50 +01:00
|
|
|
|
|
|
|
CHECK(windowBase->getSize() != newSize);
|
|
|
|
windowBase->setSize(newSize);
|
|
|
|
|
|
|
|
REQUIRE(GetClientRect(handle, &clientRect));
|
|
|
|
const auto size = sf::Vector2u(sf::Vector2(clientRect.right - clientRect.left, clientRect.bottom - clientRect.top));
|
|
|
|
CHECK(size == newSize); // Validate that the actual client rect is indeed what we asked for
|
|
|
|
CHECK(windowBase->getSize() == size); // Validate that the `getSize` also returns the _actual_ client size
|
2025-02-22 13:38:11 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
SECTION("sf::Window")
|
|
|
|
{
|
|
|
|
std::optional<sf::Window> window;
|
|
|
|
|
|
|
|
SECTION("Default context settings")
|
|
|
|
{
|
|
|
|
SECTION("WindowHandle constructor")
|
|
|
|
{
|
|
|
|
window.emplace(handle);
|
|
|
|
}
|
|
|
|
|
|
|
|
SECTION("create(WindowHandle)")
|
|
|
|
{
|
|
|
|
window.emplace().create(handle);
|
|
|
|
}
|
|
|
|
|
2025-02-25 21:07:50 +01:00
|
|
|
INFO("ExStyle: " << std::hex << exStyle << ", withMenu: " << withMenu);
|
2025-02-22 13:38:11 -07:00
|
|
|
CHECK(window->getSettings().attributeFlags == sf::ContextSettings::Default);
|
|
|
|
}
|
|
|
|
|
|
|
|
SECTION("Custom context settings")
|
|
|
|
{
|
|
|
|
static constexpr sf::ContextSettings contextSettings{/* depthBits*/ 1, /* stencilBits */ 1, /* antiAliasingLevel */ 1};
|
|
|
|
|
|
|
|
SECTION("WindowHandle constructor")
|
|
|
|
{
|
|
|
|
window.emplace(handle, contextSettings);
|
|
|
|
}
|
|
|
|
|
|
|
|
SECTION("create(WindowHandle)")
|
|
|
|
{
|
|
|
|
window.emplace().create(handle, contextSettings);
|
|
|
|
}
|
|
|
|
|
2025-02-25 21:07:50 +01:00
|
|
|
INFO("ExStyle: " << std::hex << exStyle << ", withMenu: " << withMenu);
|
2025-02-22 13:38:11 -07:00
|
|
|
CHECK(window->getSettings().depthBits >= 1);
|
|
|
|
CHECK(window->getSettings().stencilBits >= 1);
|
|
|
|
CHECK(window->getSettings().antiAliasingLevel >= 1);
|
|
|
|
}
|
|
|
|
|
2025-02-25 21:07:50 +01:00
|
|
|
INFO("ExStyle: " << std::hex << exStyle << ", withMenu: " << withMenu);
|
2025-02-22 13:38:11 -07:00
|
|
|
CHECK(window->isOpen());
|
|
|
|
CHECK(window->getPosition() == position);
|
2025-02-25 21:07:50 +01:00
|
|
|
CHECK(window->getSize() == initialSize);
|
2025-02-22 13:38:11 -07:00
|
|
|
CHECK(window->getNativeHandle() == handle);
|
2025-02-25 21:07:50 +01:00
|
|
|
|
|
|
|
CHECK(window->getSize() != newSize);
|
|
|
|
window->setSize(newSize);
|
|
|
|
|
|
|
|
REQUIRE(GetClientRect(handle, &clientRect));
|
|
|
|
const auto size = sf::Vector2u(sf::Vector2(clientRect.right - clientRect.left, clientRect.bottom - clientRect.top));
|
|
|
|
CHECK(size == newSize); // Validate that the actual client rect is indeed what we asked for
|
|
|
|
CHECK(window->getSize() == size); // Validate that the `getSize` also returns the _actual_ client size
|
2025-02-22 13:38:11 -07:00
|
|
|
}
|
|
|
|
|
2025-02-25 21:07:50 +01:00
|
|
|
INFO("ExStyle: " << std::hex << exStyle << ", withMenu: " << withMenu);
|
|
|
|
|
2025-02-22 13:38:11 -07:00
|
|
|
CHECK(gotWmShowWindow);
|
|
|
|
CHECK(IsWindow(handle)); // The window is not destroyed
|
|
|
|
|
|
|
|
CHECK(DestroyWindow(handle));
|
|
|
|
CHECK(UnregisterClassW(classInfo.lpszClassName, classInfo.hInstance));
|
|
|
|
gotWmShowWindow = false;
|
|
|
|
|
|
|
|
CHECK(!IsWindow(handle)); // Now it is gone
|
|
|
|
}
|