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

如何在Flutter桌面应用中禁止截图与屏幕录制?

Flutter桌面应用禁止截图与屏幕录制实现方案

Flutter本身没有跨平台API直接实现禁止截图/录屏的功能,需要结合各桌面平台的原生API,通过MethodChannel与Flutter端通信完成。以下分平台给出具体实现步骤:

一、Flutter端基础配置

先创建MethodChannel,用于调用原生平台的禁止截图方法:

import 'package:flutter/services.dart';

class ScreenProtection {
  static const MethodChannel _channel = MethodChannel('screen_protection');

  // 启用屏幕保护(禁止截图/录屏)
  static Future<void> enableProtection() async {
    try {
      await _channel.invokeMethod('enableProtection');
    } on PlatformException catch (e) {
      print('启用保护失败: ${e.message}');
    }
  }

  // 关闭屏幕保护
  static Future<void> disableProtection() async {
    try {
      await _channel.invokeMethod('disableProtection');
    } on PlatformException catch (e) {
      print('关闭保护失败: ${e.message}');
    }
  }
}

在需要启用保护的页面,直接调用ScreenProtection.enableProtection()即可。

二、各平台原生实现

1. macOS平台

macOS可通过设置窗口的sharingType为NSWindowSharingNone,阻止系统和第三方工具捕获窗口内容:

  1. 打开macos/Runner/AppDelegate.swift
  2. 注册MethodChannel实现动态控制:
import Cocoa
import FlutterMacOS

@NSApplicationMain
class AppDelegate: FlutterAppDelegate {
  override func applicationDidFinishLaunching(_ aNotification: Notification) {
    super.applicationDidFinishLaunching(aNotification)
    
    guard let controller = window?.contentViewController as? FlutterViewController else { return }
    let channel = FlutterMethodChannel(name: "screen_protection", binaryMessenger: controller.engine.binaryMessenger)
    
    channel.setMethodCallHandler { [weak self] call, result in
      guard let window = self?.window else {
        result(FlutterError(code: "NO_WINDOW", message: "无法获取窗口", details: nil))
        return
      }
      
      switch call.method {
      case "enableProtection":
        window.sharingType = .none
        result(nil)
      case "disableProtection":
        window.sharingType = .default
        result(nil)
      default:
        result(FlutterMethodNotImplemented)
      }
    }
  }
}

2. Windows平台

Windows使用Win32 API的SetWindowDisplayAffinity函数,设置窗口显示亲和力为WDA_MONITOR,阻止截图和录屏:

  1. 打开windows/runner/flutter_window.cpp
  2. 在窗口初始化后注册MethodChannel:
#include <windows.h>
#include "flutter_window.h"
#include "flutter/generated_plugin_registrant.h"

FlutterWindow::FlutterWindow() {}
FlutterWindow::~FlutterWindow() {}

bool FlutterWindow::OnCreate() {
  if (!Win32Window::OnCreate()) {
    return false;
  }

  RECT frame = GetClientArea();
  flutter_controller_ = std::make_unique<FlutterEngine>(
      L"flutter_window",
      flutter::DartProject::GetDefaultForCurrentDirectory());
  flutter_controller_->engine()->SetNextFrameCallback([&]() {
    this->Show();
  });
  flutter_controller_->InitializeSize(frame.right - frame.left, frame.bottom - frame.top);
  RegisterPlugins(flutter_controller_->engine());

  HWND hwnd = GetHandle();
  // 注册MethodChannel用于动态控制
  auto channel = std::make_unique<flutter::MethodChannel<flutter::EncodableValue>>(
      flutter_controller_->engine()->messenger(),
      "screen_protection",
      &flutter::StandardMethodCodec::GetInstance());
  
  channel->SetMethodCallHandler(
      [hwnd](const flutter::MethodCall<flutter::EncodableValue>& call,
             std::unique_ptr<flutter::MethodResult<flutter::EncodableValue>> result) {
        if (call.method_name() == "enableProtection") {
          BOOL success = SetWindowDisplayAffinity(hwnd, WDA_MONITOR);
          success ? result->Success() : result->Error("SET_FAILED", "设置窗口保护失败");
        } else if (call.method_name() == "disableProtection") {
          BOOL success = SetWindowDisplayAffinity(hwnd, WDA_NONE);
          success ? result->Success() : result->Error("SET_FAILED", "取消窗口保护失败");
        } else {
          result->NotImplemented();
        }
      });

  return true;
}

注意:SetWindowDisplayAffinity需要Windows 10 1607及以上版本支持。

3. Linux平台

Linux桌面环境(GNOME、KDE等)没有统一的禁止截图/录屏API,实现兼容性较差:
可尝试通过GTK设置窗口私有属性,阻止部分系统级截图工具:

  1. 打开linux/runner/main.cc
  2. 在窗口初始化时添加属性设置:
#include <gtk/gtk.h>
#include "flutter/generated_plugin_registrant.h"

int main(int argc, char** argv) {
  gtk_init(&argc, &argv);

  GtkWidget* window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
  gtk_window_set_default_size(GTK_WINDOW(window), 800, 600);
  
  // 设置窗口私有属性尝试阻止截图
  g_object_set(G_OBJECT(window), "gtk-extended-window-private", TRUE, NULL);

  GtkWidget* flutter_view = flutter_view_new(gtk_window_get_display(GTK_WINDOW(window)));
  gtk_container_add(GTK_CONTAINER(window), flutter_view);

  flutter::FlutterEngine engine;
  engine.Initialize();
  RegisterPlugins(&engine);

  gtk_widget_show_all(window);
  gtk_main();

  return 0;
}

说明:该方案仅对部分系统工具生效,无法覆盖所有第三方截图软件。

三、局限性说明

  • 以上方案仅能阻止软件层面的截图/录屏,无法对抗硬件级别的捕获设备(如外接摄像头拍摄屏幕)。
  • 部分第三方工具可能绕过系统限制,无法完全杜绝截图行为。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.21 11:45:58