Host-side window records + message queue; WM_SIZE/WM_MOVE/WM_DESTROY sent synchronously as Win32 does; PostQuitMessage also queues WM_QUIT. 64-bit pointer casts ADAPTED. port.ms_window. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
92 lines
3.6 KiB
C++
92 lines
3.6 KiB
C++
// 40250 CMSWindow / CMSApplication over the <winuser.h> subset of platform/Win32User.cpp.
|
|
#include "EterLib/StdAfx.h"
|
|
#include "EterLib/MSApplication.h"
|
|
#include "../../src/platform/EterLib/HostCursor.h"
|
|
|
|
#include <cstdio>
|
|
#include <vector>
|
|
|
|
namespace {
|
|
struct App : CMSApplication
|
|
{
|
|
std::vector<UINT> seen;
|
|
LRESULT WindowProcedure(HWND hWnd, UINT uiMsg, WPARAM wParam, LPARAM lParam) override
|
|
{
|
|
seen.push_back(uiMsg);
|
|
return CMSApplication::WindowProcedure(hWnd, uiMsg, wParam, lParam);
|
|
}
|
|
bool Active() const { return m_isActive; }
|
|
const char* Register() { return RegisterWindowClass(0, BLACK_BRUSH, DefWindowProc); }
|
|
};
|
|
}
|
|
|
|
int main()
|
|
{
|
|
int failures = 0;
|
|
auto check = [&failures](bool ok, const char *name) {
|
|
if (!ok) {
|
|
std::fprintf(stderr, "FAIL %s\n", name);
|
|
++failures;
|
|
}
|
|
};
|
|
|
|
App app;
|
|
app.Initialize(reinterpret_cast<HINSTANCE>(0x400000));
|
|
check(app.GetInstance() == reinterpret_cast<HINSTANCE>(0x400000), "Initialize sets the shared instance");
|
|
check(app.GetWindowHandle() == NULL && !app.IsVisible(), "constructor: no window, hidden");
|
|
|
|
const char* first = app.Register();
|
|
check(first[0] != '\0' && app.Register() == first, "RegisterWindowClass reuses the class name");
|
|
|
|
check(app.Create("Metin2") && IsWindow(app.GetWindowHandle()), "Create");
|
|
check(!app.IsVisible(), "Create leaves the window hidden");
|
|
|
|
// SetSize: Win32 sends WM_SIZE (SIZE_RESTORED) synchronously -> OnSize marks the window active and visible.
|
|
app.SetSize(800, 600);
|
|
RECT rc;
|
|
app.GetClientRect(&rc);
|
|
check(rc.left == 0 && rc.top == 0 && rc.right == 800 && rc.bottom == 600, "SetSize client rect");
|
|
check(app.IsActive() && app.IsVisible(), "WM_SIZE restored -> active, visible");
|
|
check(!app.seen.empty() && app.seen.back() == WM_SIZE, "WM_SIZE reaches the window procedure");
|
|
|
|
app.SetCenterPosition();
|
|
app.GetWindowRect(&rc);
|
|
check(rc.left == (1920 - 800) / 2 && rc.top == (1080 - 600) / 2 && rc.right - rc.left == 800, "SetCenterPosition");
|
|
|
|
// The host cursor is in client coordinates; GetCursorPos + ScreenToClient round-trips it.
|
|
MtHostSetCursor(5, 7);
|
|
POINT pt;
|
|
app.GetMousePosition(&pt);
|
|
check(pt.x == 5 && pt.y == 7, "GetMousePosition");
|
|
|
|
app.AdjustSize(640, 480);
|
|
app.GetWindowRect(&rc);
|
|
check(rc.left == 0 && rc.top == 0 && rc.right == 640 && rc.bottom == 480, "AdjustSize moves to 0,0 at the client size");
|
|
|
|
app.Hide();
|
|
check(!app.IsVisible(), "Hide");
|
|
app.SetVisibleMode(true);
|
|
check(app.IsVisible(), "SetVisibleMode");
|
|
|
|
// The message queue: IsMessage peeks, MessageProcess dispatches to CMSWindow::WindowProcedure.
|
|
check(!app.IsMessage(), "IsMessage on an empty queue");
|
|
PostMessage(app.GetWindowHandle(), WM_ACTIVATEAPP, WA_INACTIVE, 0);
|
|
check(app.IsMessage() && app.IsMessage(), "IsMessage does not remove");
|
|
check(app.MessageProcess() && !app.Active(), "WM_ACTIVATEAPP inactive");
|
|
PostMessage(app.GetWindowHandle(), WM_ACTIVATEAPP, WA_CLICKACTIVE, 0);
|
|
check(app.MessageProcess() && app.Active(), "WM_ACTIVATEAPP click-active");
|
|
PostMessage(app.GetWindowHandle(), WM_SIZE, SIZE_MINIMIZED, 0);
|
|
check(app.MessageProcess() && !app.Active() && !app.IsVisible(), "WM_SIZE minimized -> inactive, hidden");
|
|
|
|
// WM_CLOSE: CMSApplication posts WM_QUIT, DefWindowProc destroys the window, MessageLoop ends on WM_QUIT.
|
|
HWND hWnd = app.GetWindowHandle();
|
|
PostMessage(hWnd, WM_CLOSE, 0, 0);
|
|
app.seen.clear();
|
|
app.MessageLoop();
|
|
check(app.seen.size() == 2 && app.seen[0] == WM_CLOSE && app.seen[1] == WM_DESTROY, "WM_CLOSE then WM_DESTROY");
|
|
check(!IsWindow(hWnd) && !app.IsMessage(), "window destroyed, queue drained");
|
|
app.Destroy();
|
|
check(app.GetWindowHandle() == NULL, "Destroy clears the handle");
|
|
return failures ? 1 : 0;
|
|
}
|