从Electron迁移至Wry/Tauri后,如何拦截window.resizeTo实现窗口调整?
在Wry/Tauri中拦截并实现window.resizeTo功能
为什么window.resizeTo在Wry/Tauri中无效
Wry/Tauri为了沙箱安全和权限控制,默认禁用了window.resizeTo这类直接操作窗口的DOM API,所以直接调用不会生效。但可以通过前端重写API + 后端IPC调用的方式实现等价功能。
实现步骤
1. 前端拦截window.resizeTo调用
重写全局的window.resizeTo方法,将尺寸参数通过Tauri的IPC发送给Rust后端处理:
import { invoke } from '@tauri-apps/api/tauri'; // 重写window.resizeTo,替换为IPC调用 window.resizeTo = async function (targetWidth, targetHeight) { // 可选:添加尺寸合法性校验,避免过小窗口 const validWidth = Math.max(targetWidth, 300); const validHeight = Math.max(targetHeight, 200); // 调用后端注册的resize命令 await invoke('resize_window', { width: validWidth, height: validHeight }); };
2. Rust后端实现窗口调整逻辑
在Tauri的主程序中注册resize_window命令,接收前端参数后调用窗口API调整尺寸:
use tauri::{Manager, Window}; // 定义IPC命令 #[tauri::command] async fn resize_window(window: Window, width: f64, height: f64) -> Result<(), String> { // 转换为整数尺寸(窗口尺寸通常以物理像素整数为单位) let physical_width = width as u32; let physical_height = height as u32; // 调用Tauri窗口API设置尺寸 window .set_size(tauri::Size::Physical(tauri::PhysicalSize { width: physical_width, height: physical_height, })) .map_err(|err| err.to_string()) } fn main() { tauri::Builder::default() .invoke_handler(tauri::generate_handler![resize_window]) .run(tauri::generate_context!()) .expect("Failed to run Tauri application"); }
纯Wry环境下的实现(不使用Tauri上层框架)
如果是直接使用Wry而非Tauri,需要通过WebView的IPC监听实现:
use wry::{ application::{window::Window, dpi::PhysicalSize}, webview::WebViewBuilder, serde_json::Value, }; fn main() -> wry::Result<()> { let app = wry::application::Application::new()?; let window = app.create_window( "Wry Resize Demo", wry::application::window::WindowBuilder::new() .with_inner_size(PhysicalSize::new(800, 600)), )?; let _webview = WebViewBuilder::new(window)? // 注入JS重写resizeTo .with_initialization_script( r#" window.resizeTo = function(width, height) { // 通过IPC发送 resize 消息及参数 window.ipc.postMessage(JSON.stringify({ type: 'resize', width: width, height: height })); }; "#, ) // 处理IPC消息 .with_ipc_handler(|window, message| { let msg: Value = serde_json::from_str(&message).unwrap(); if msg["type"].as_str() == Some("resize") { let width = msg["width"].as_f64().unwrap_or(800.0) as u32; let height = msg["height"].as_f64().unwrap_or(600.0) as u32; // 调整窗口尺寸 window.set_inner_size(PhysicalSize::new(width, height)); } Ok(()) }) .build()?; app.run() }
注意事项
- 参数校验:建议在前端或后端添加尺寸范围限制,避免窗口被调整到无法操作的大小
- 多窗口场景:如果应用存在多个窗口,需要在IPC调用时传递窗口标识,后端通过
window.get_window("window_label")获取对应窗口实例后调整尺寸 - DPI适配:如果需要处理高DPI屏幕,可使用
Size::Logical替代Physical,并通过Tauri的window.scale_factor()获取缩放比例进行转换
内容的提问来源于stack exchange,提问作者TheGr8_Nik
相关产品推荐
相关产品推荐

