// ============================================================================ // window.c - Win32 窗口实现 // ============================================================================ #include "window.h" #include "../Core/logger.h" #include #include // 窗口类名 static const wchar_t* WINDOW_CLASS = L"MiMoEngineWindow"; // 全局回调 static WindowKeyCallback g_key_callback = NULL; static WindowResizeCallback g_resize_callback = NULL; static WindowMouseMoveCallback g_mouse_move_callback = NULL; static WindowMouseButtonCallback g_mouse_button_callback = NULL; // 窗口过程 static LRESULT CALLBACK window_proc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) { Window* window = NULL; if (msg == WM_NCCREATE) { CREATESTRUCT* cs = (CREATESTRUCT*)lParam; window = (Window*)cs->lpCreateParams; SetWindowLongPtrW(hwnd, GWLP_USERDATA, (LONG_PTR)window); } else { window = (Window*)GetWindowLongPtrW(hwnd, GWLP_USERDATA); } if (window) { switch (msg) { case WM_SIZE: window->width = LOWORD(lParam); window->height = HIWORD(lParam); window->minimized = (wParam == SIZE_MINIMIZED); if (g_resize_callback && !window->minimized) { g_resize_callback(window->width, window->height); } return 0; case WM_PAINT: ValidateRect(hwnd, NULL); return 0; case WM_ERASEBKGND: return 1; case WM_KEYDOWN: if (g_key_callback) g_key_callback((int)wParam); return 0; case WM_KEYUP: return 0; case WM_MOUSEMOVE: if (g_mouse_move_callback) g_mouse_move_callback(LOWORD(lParam), HIWORD(lParam)); return 0; case WM_LBUTTONDOWN: if (g_mouse_button_callback) g_mouse_button_callback(0, 1); return 0; case WM_RBUTTONDOWN: if (g_mouse_button_callback) g_mouse_button_callback(1, 1); return 0; case WM_MBUTTONDOWN: if (g_mouse_button_callback) g_mouse_button_callback(2, 1); return 0; case WM_LBUTTONUP: if (g_mouse_button_callback) g_mouse_button_callback(0, 0); return 0; case WM_RBUTTONUP: if (g_mouse_button_callback) g_mouse_button_callback(1, 0); return 0; case WM_MBUTTONUP: if (g_mouse_button_callback) g_mouse_button_callback(2, 0); return 0; case WM_DESTROY: PostQuitMessage(0); return 0; } } return DefWindowProcW(hwnd, msg, wParam, lParam); } // 注册窗口类 static void register_window_class(void) { WNDCLASSEXW wc = {0}; wc.cbSize = sizeof(WNDCLASSEXW); wc.style = CS_HREDRAW | CS_VREDRAW | CS_OWNDC; wc.lpfnWndProc = window_proc; wc.hInstance = GetModuleHandleW(NULL); wc.hIcon = LoadIcon(NULL, IDI_APPLICATION); wc.hCursor = LoadCursor(NULL, IDC_ARROW); wc.hbrBackground = NULL; wc.lpszClassName = WINDOW_CLASS; wc.hIconSm = LoadIcon(NULL, IDI_APPLICATION); if (!RegisterClassExW(&wc)) { LOG_ERROR("Failed to register window class!"); } } Window* window_create(const char* title, int width, int height, int fullscreen) { Window* window = (Window*)calloc(1, sizeof(Window)); if (!window) return NULL; window->title = title; window->width = width; window->height = height; window->fullscreen = fullscreen; register_window_class(); DWORD style = WS_OVERLAPPEDWINDOW; DWORD ex_style = WS_EX_APPWINDOW; RECT rect = {0, 0, width, height}; AdjustWindowRectEx(&rect, style, FALSE, ex_style); int adjusted_width = rect.right - rect.left; int adjusted_height = rect.bottom - rect.top; int screen_w = GetSystemMetrics(SM_CXSCREEN); int screen_h = GetSystemMetrics(SM_CYSCREEN); int pos_x = (screen_w - adjusted_width) / 2; int pos_y = (screen_h - adjusted_height) / 2; // 转换标题为宽字符 wchar_t w_title[256]; MultiByteToWideChar(CP_UTF8, 0, title, -1, w_title, 256); window->hwnd = CreateWindowExW( ex_style, WINDOW_CLASS, w_title, style, pos_x, pos_y, adjusted_width, adjusted_height, NULL, NULL, GetModuleHandleW(NULL), window ); if (!window->hwnd) { LOG_ERROR("Failed to create window! Error: %lu", GetLastError()); free(window); return NULL; } ShowWindow(window->hwnd, SW_SHOW); UpdateWindow(window->hwnd); LOG_INFO("Window created: %dx%d", width, height); return window; } void window_destroy(Window* window) { if (window) { if (window->hwnd) { DestroyWindow(window->hwnd); window->hwnd = NULL; } free(window); } } void window_show(Window* window) { if (window && window->hwnd) ShowWindow(window->hwnd, SW_SHOW); } void window_hide(Window* window) { if (window && window->hwnd) ShowWindow(window->hwnd, SW_HIDE); } int window_process_messages(Window* window) { MSG msg = {0}; while (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE)) { if (msg.message == WM_QUIT) return 0; TranslateMessage(&msg); DispatchMessage(&msg); } return 1; } int window_get_width(Window* window) { return window ? window->width : 0; } int window_get_height(Window* window) { return window ? window->height : 0; } HWND window_get_handle(Window* window) { return window ? window->hwnd : NULL; } int window_is_fullscreen(Window* window) { return window ? window->fullscreen : 0; } int window_is_minimized(Window* window) { return window ? window->minimized : 0; } void window_set_key_callback(Window* window, WindowKeyCallback callback) { g_key_callback = callback; } void window_set_resize_callback(Window* window, WindowResizeCallback callback) { g_resize_callback = callback; } void window_set_mouse_move_callback(Window* window, WindowMouseMoveCallback callback) { g_mouse_move_callback = callback; } void window_set_mouse_button_callback(Window* window, WindowMouseButtonCallback callback) { g_mouse_button_callback = callback; }