Files
lity3d/Engine/Window/window.c
T
shuiyu1123 7a0533d21a sync: user's Lity3D_source.zip changes
- Engine core: improved initialization and lifecycle
- Renderer: camera and rendering pipeline updates
- Editor: updated editor code
- Window: improved window handling
- Demo/main.c: scene demo with AssetManager + scene loading
- build.bat: updated build script
- 11 files modified from user's manual edits
2026-07-12 12:13:50 +08:00

199 lines
6.3 KiB
C

// ============================================================================
// window.c - Win32 窗口实现
// ============================================================================
#include "window.h"
#include "../Core/logger.h"
#include <stdlib.h>
#include <string.h>
// 窗口类名
static const wchar_t* WINDOW_CLASS = L"Lity3DEngineWindow";
// 全局回调
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:
SetCapture(hwnd);
if (g_mouse_button_callback) g_mouse_button_callback(0, 1);
return 0;
case WM_RBUTTONDOWN:
SetCapture(hwnd);
if (g_mouse_button_callback) g_mouse_button_callback(1, 1);
return 0;
case WM_MBUTTONDOWN:
SetCapture(hwnd);
if (g_mouse_button_callback) g_mouse_button_callback(2, 1);
return 0;
case WM_LBUTTONUP:
if (GetCapture() == hwnd) ReleaseCapture();
if (g_mouse_button_callback) g_mouse_button_callback(0, 0);
return 0;
case WM_RBUTTONUP:
if (GetCapture() == hwnd) ReleaseCapture();
if (g_mouse_button_callback) g_mouse_button_callback(1, 0);
return 0;
case WM_MBUTTONUP:
if (GetCapture() == hwnd) ReleaseCapture();
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; }