Chapter 05 · 引擎基础

窗口属性与查询

运行时获取窗口尺寸、动态修改标题、理解 HIGHDPI 下逻辑像素与物理像素的关系。

05

概念:运行时窗口信息

窗口尺寸在运行时可能因用户拖拽而改变(XGE_INIT_RESIZABLE)。你的绘制代码必须每帧查询当前尺寸,而非缓存初始化时的值。XGE 提供了一组轻量查询函数。

API 速查

函数返回值说明
int xgeGetWidth(void)逻辑宽度窗口客户区宽度(逻辑像素)
int xgeGetHeight(void)逻辑高度窗口客户区高度(逻辑像素)
void xgeSetTitle(const char*)—动态修改窗口标题(UTF-8)
void xgeQuit(void)—请求关闭窗口 / 退出主循环

初始化标志对窗口的影响

标志窗口行为
XGE_INIT_WINDOW (0x0000)标准带标题栏窗口
XGE_INIT_FULLSCREEN (0x0001)独占全屏,隐藏任务栏
XGE_INIT_NOFRAME (0x0002)无标题栏、无边框
XGE_INIT_RESIZABLE (0x0004)用户可拖拽边缘调整大小
XGE_INIT_HIGHDPI (0x0008)帧缓冲按 DPI 缩放

HIGHDPI 详解

在 Retina / 4K 显示器上,操作系统使用 DPI 缩放(如 150%、200%)。启用 XGE_INIT_HIGHDPI 后:

  • xgeGetWidth() 返回逻辑像素(如 1280)
  • 实际帧缓冲 = 逻辑 × DPI 缩放(如 1280 × 2 = 2560 物理像素)
  • 所有绘制坐标使用逻辑像素——引擎内部自动乘以 DPI 缩放
  • 通过 xgePlatformRuntimeGet() 可获取 fDpiScale 值

编译本章示例

gcc -O2 -I. -o ch05.exe ch05_main.c build\xge.lib -lm -lws2_32 -liphlpapi -lgdi32 -luser32 -lshell32 -lopengl32 -lole32 -lwinmm -lavrt
.\ch05.exe

示例:自适应绘制

#include "xge.h"
#include <stdio.h>

static int onFrame(void* pUser) {
    int w = xgeGetWidth();
    int h = xgeGetHeight();

    xgeClear(0x0C181CFF);

    // 始终在窗口中心绘制圆形
    float cx = w * 0.5f;
    float cy = h * 0.5f;
    float r  = (w < h ? w : h) * 0.3f;  // 半径 = 短边 30%

    xgeShapeCircleFill(cx, cy, r, 0x4FD8C2FF);
    xgeShapeCircleStroke(cx, cy, r + 10, 3.0f, 0xFFB454FF);

    // 标题栏显示实时尺寸
    char buf[64];
    snprintf(buf, sizeof(buf), "%dx%d | FPS: %d",
             w, h, xgeGetFPS());
    xgeSetTitle(buf);

    // ESC 退出
    if (xgeKeyPressed(XGE_KEY_ESCAPE))
        xgeQuit();

    return XGE_OK;
}

int main(void) {
    xge_desc_t d = {0};
    d.iWidth  = 1024;
    d.iHeight = 768;
    d.sTitle  = "Resize Me";
    d.iFlags  = XGE_INIT_WINDOW | XGE_INIT_RESIZABLE | XGE_INIT_HIGHDPI;

    xgeInit(&d);
    xgeRun(onFrame, NULL);
    xgeUnit();
    return 0;
}

完整代码与可观察结果

可构建的权威源码为 examples/tutorial_capture/ch05_main1.c。它在固定教学画布中绘制居中的主圆、轮廓与十字基准;实际窗口尺寸、帧缓冲尺寸和 DPI 缩放仍应通过下方运行时查询 API 获取。

XGE centered adaptive layout demonstration
图:第 5 章示例的真实离屏输出。青绿色主圆、琥珀色轮廓和十字基准直观展示按当前画布中心布局的结果。
执行效果

可调整大小的窗口,青绿色圆形始终居中,琥珀色描边。标题栏实时显示尺寸和 FPS。拖拽窗口边缘时圆形自动适应。

查询 DPI 缩放

xge_platform_runtime_t rt;
xgePlatformRuntimeGet(&rt);

printf("逻辑尺寸: %dx%d\n", rt.iWindowWidth, rt.iWindowHeight);
printf("帧缓冲:   %dx%d\n", rt.iFramebufferWidth, rt.iFramebufferHeight);
printf("DPI 缩放: %.2f\n", rt.fDpiScale);

要点与陷阱

  • 每帧查询尺寸——不要缓存 xgeGetWidth() 的结果,用户随时可能调整窗口。
  • setTitle 的性能:每帧调用 xgeSetTitle 在 Windows 上有微小开销(Win32 SendMessage)。如果标题不变,避免每帧调用。
  • NOFRAME 窗口无法拖动——如需自定义标题栏拖拽,需自行处理鼠标事件(第 116 章)。
  • FULLSCREEN 下 GetWidth/GetHeight 返回显示器分辨率,而非初始化时指定的值。

进阶练习

  1. 创建一个 NOFRAME 窗口,在帧回调中检测鼠标拖拽实现自定义窗口移动。
  2. 在 HIGHDPI 模式下,用 xgePlatformRuntimeGet 获取 DPI 缩放值并打印。
  3. 监听窗口大小变化(比较前后帧的 GetWidth/GetHeight),在变化时打印日志。