You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用desktop_multi_window包时,如何完全禁用Flutter桌面应用主窗口?

实现主窗口在表单窗口打开期间禁用的方案

要实现主窗口在表单窗口打开时完全禁用,直到表单关闭,可以通过模态子窗口配置 + 主窗口交互拦截的组合方式,结合desktop_multi_window包的特性来实现,具体步骤如下:

1. 将主窗口改为StatefulWidget

因为需要维护表单窗口的打开状态,把MyMainApp从StatelessWidget改为StatefulWidget,用于控制主窗口的交互状态:

class MyMainApp extends StatefulWidget {
  const MyMainApp({super.key});

  @override
  State<MyMainApp> createState() => _MyMainAppState();
}

class _MyMainAppState extends State<MyMainApp> {
  // 标记表单窗口是否处于打开状态
  bool _isFormWindowOpen = false;

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: Scaffold(
        body: Stack(
          children: [
            // 原主窗口内容
            Center(
              child: ElevatedButton(
                onPressed: _isFormWindowOpen ? null : _openFormWindow,
                child: const Text('Open Form'),
              ),
            ),
            // 表单打开时,添加全屏透明拦截层,阻止主窗口交互
            if (_isFormWindowOpen)
              Positioned.fill(
                child: AbsorbPointer(
                  absorbing: true,
                  child: Container(color: Colors.transparent),
                ),
              ),
          ],
        ),
      ),
    );
  }

  // 打开表单窗口的方法
  Future<void> _openFormWindow() async {
    // 获取主窗口ID,用于关联子窗口
    final mainWindowId = DesktopMultiWindow.getCurrentWindowId();
    // 创建表单子窗口,并指定父窗口
    final formWindow = await DesktopMultiWindow.createWindow(
      jsonEncode({'args1': 'v1'}),
      parentWindowId: mainWindowId,
    );

    // 配置子窗口属性
    formWindow
      ..setFrame(const Offset(0, 0) & const Size(400, 600))
      ..center()
      ..setTitle('Form')
      // 设置子窗口为模态窗口(系统层面禁用主窗口)
      ..setModal(true)
      ..show();

    // 标记表单窗口已打开,更新UI显示拦截层
    setState(() {
      _isFormWindowOpen = true;
    });

    // 监听子窗口关闭事件,关闭后恢复主窗口状态
    formWindow.onClose.listen((_) {
      setState(() {
        _isFormWindowOpen = false;
      });
    });
  }
}

2. 关键细节说明

  • 模态窗口配置:通过parentWindowId关联主窗口,并调用setModal(true),让系统原生层面将表单窗口设为主窗口的模态对话框,这会自动让主窗口失去焦点且无法被激活(符合Windows原生模态窗口的行为)。
  • 交互拦截层:使用AbsorbPointer在主窗口内容上方添加全屏透明层,确保即使系统层面的禁用失效,Flutter层面也能拦截所有点击操作。
  • 窗口关闭监听:通过formWindow.onClose监听表单窗口的关闭事件,及时更新主窗口的状态,恢复交互能力。

3. 跨平台适配注意事项

  • Windows:setModal(true)会自动触发原生模态窗口行为,主窗口会被完全禁用,且表单窗口会保持激活状态。
  • macOS:同样支持模态窗口配置,主窗口会被锁定,直到表单窗口关闭。

内容的提问来源于stack exchange,提问作者Ryan

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.13 00:16:03