跳到主要内容

Windows Surface、DPI 与输入

Windows 专用接口位于 litheview_win.h,用于将 View 接入 HWND 并同步原生窗口状态。

绑定 HWND

ltv_win_view_attach(view, reinterpret_cast<uintptr_t>(render_hwnd));

一个 View 同一时间只能绑定到一个原生窗口。切换宿主窗口前先调用:

ltv_win_view_detach(view);

尺寸与 DPI

ltv_win_set_device_scale_factor(scale_factor);
ltv_win_view_resize(view,
width_dip,
height_dip,
width_pixels,
height_pixels);

width_dip / height_dip 是逻辑页面尺寸,pixel 参数是 GPU 合成的物理尺寸。per-monitor DPI 变化后应更新 scale factor,并用同一次布局结果同步两套尺寸。

交互式原生 resize 开始前调用 ltv_win_view_prepare_native_resize();操作取消时调用 ltv_win_view_cancel_native_resize()

鼠标与键盘

将 Win32 消息原值转发给当前 View:

ltv_win_view_forward_mouse_message(
view, message, wparam, lparam, screen_position);

ltv_win_view_forward_keyboard_message(
view, message, wparam, lparam);

鼠标位置使用物理像素。宿主仍负责命中测试、焦点和 capture 等窗口策略。

文件拖拽

Windows 宿主可以把本地文件拖拽序列转发给页面:

const char* files[] = {"C:\\Users\\me\\Desktop\\report.pdf"};
ltv_win_view_drag_files_enter(
view, files, 1, x_pixels, y_pixels, screen_x_pixels, screen_y_pixels,
LTV_WIN_DRAG_OPERATION_COPY);
ltv_win_view_drag_files_over(
view, x_pixels, y_pixels, screen_x_pixels, screen_y_pixels,
LTV_WIN_DRAG_OPERATION_COPY);
ltv_win_view_drag_files_drop(
view, files, 1, x_pixels, y_pixels, screen_x_pixels, screen_y_pixels);

路径必须是 UTF-8 绝对本地文件路径。坐标与鼠标转发接口一致,使用 view-local 物理像素和 screen 物理像素。拖动取消或离开 View 时调用 ltv_win_view_drag_files_leave()

光标

ltv_cursor_type_t cursor = LTV_CURSOR_ARROW;
if (ltv_win_view_get_cursor(view, x_dip, y_dip, &cursor) == LTV_OK) {
ApplyNativeCursor(cursor);
}

返回值覆盖箭头、文本、手型、等待、缩放、禁止和隐藏等常见光标类型。

IME

宿主需要把平台 IME 组合过程翻译为结构化 UTF-16 调用:

  • ltv_win_view_ime_set_composition() 更新组合文本、下划线 span 和选择区间。
  • ltv_win_view_ime_commit_text() 提交最终文本。
  • ltv_win_view_ime_finish_composition() 完成当前组合。
  • ltv_win_view_ime_cancel_composition() 取消当前组合。
  • ltv_win_view_get_ime_caret_rect() 返回 View 内的 DIP 坐标,用于定位候选窗口。

所有 offset 都是 UTF-16 code unit 下标,不是 Unicode code point 下标。

原生模态循环

会进入 Win32 嵌套消息循环的 API 前后必须成对调用:

ltv_win_set_os_modal_loop(1);
DefWindowProc(hwnd, WM_SYSCOMMAND, wparam, lparam);
ltv_win_set_os_modal_loop(0);

这两个调用必须位于 LitheView UI 线程,并且严格配对。