Flutter框架高阶——Window应用程序设置窗体窗口背景完全透明

news2024/10/6 8:35:15

文章目录

    • 1.修改 main.cpp
      • 1)C++ 与 Win32 API
      • 2)EnableTransparency()
      • 3)中文注释
    • 2.编写 Flutter 代码
      • 1)bitsdojo_window
      • 2)window_manager
      • 3)区别对比
      • 4)同时使用
        • (1)设置初始化代码
        • (2)处理冲突和集成

Flutter的文件结构如下,找到图中的main.cpp的文件
在这里插入图片描述

1.修改 main.cpp

main.cpp文件中的代码应该和下面差不多:

#include <flutter/dart_project.h>
#include <flutter/flutter_view_controller.h>
#include <windows.h>

#include "flutter_window.h"
#include "utils.h"

int APIENTRY wWinMain(_In_ HINSTANCE instance, _In_opt_ HINSTANCE prev,
                      _In_ wchar_t *command_line, _In_ int show_command) {
  // Attach to console when present (e.g., 'flutter run') or create a
  // new console when running with a debugger.
  if (!::AttachConsole(ATTACH_PARENT_PROCESS) && ::IsDebuggerPresent()) {
    CreateAndAttachConsole();
  }

  // Initialize COM, so that it is available for use in the library and/or
  // plugins.
  ::CoInitializeEx(nullptr, COINIT_APARTMENTTHREADED);

  flutter::DartProject project(L"data");

  std::vector<std::string> command_line_arguments =
      GetCommandLineArguments();

  project.set_dart_entrypoint_arguments(std::move(command_line_arguments));

  FlutterWindow window(project);
  Win32Window::Point origin(10, 10);
  Win32Window::Size size(1280, 720);
  if (!window.Create(L"untitled", origin, size)) {
    return EXIT_FAILURE;
  }

  window.SetQuitOnClose(true);

  ::MSG msg;
  while (::GetMessage(&msg, nullptr, 0, 0)) {
    ::TranslateMessage(&msg);
    ::DispatchMessage(&msg);
  }

  ::CoUninitialize();
  return EXIT_SUCCESS;
}

1)C++ 与 Win32 API

由上面的代码不难看出flutterwindow应用程序使用的是C++语言,通过 Win32 API 与 Windows 操作系统进行交互实现。所以让窗口变得透明,对窗口的背景颜色进行设置,并启用层叠窗口样式。就要在main.cpp文件中做一些更改:

  • 在创建窗口时,设置窗口的样式为层叠窗口。
  • 使用SetLayeredWindowAttributes函数设置窗口透明度。
#include <flutter/dart_project.h>
// 省略代码...
#include "utils.h"


// 下面是新加的代码---------------------------------------------------------
#include<bitsdojo_window_windows/bitsdojo_window_plugin.h>
auto bdw = bitsdojo_window_configure(BDW_CUSTOM_FRAME | BDW_HIDE_ON_STARTUP);

void EnableTransparency(HWND hwnd) {
    SetWindowLong(hwnd, GWL_EXSTYLE, GetWindowLong(hwnd, GWL_EXSTYLE) | WS_EX_LAYERED);
    COLORREF colorKey = RGB(255, 255, 255); 
    BYTE alpha = 0;
    SetLayeredWindowAttributes(hwnd, colorKey, alpha, LWA_ALPHA);
} 
// 到这里结束---------------------------------------------------------------


int APIENTRY wWinMain(_In_ HINSTANCE instance, _In_opt_ HINSTANCE prev,                      _In_ wchar_t *command_line, _In_ int show_command) {
	// 省略代码...
	if (!window.Create(L"untitled", origin, size)) {
    	return EXIT_FAILURE;
 	 }
    
    
    // 下面是新加的代码------------------------------------------------------
	EnableTransparency(window.GetHandle());     
    // 到这里结束-----------------------------------------------------------
    
    
    window.SetQuitOnClose(true);
	// 省略代码...
    return EXIT_SUCCESS;
}               

2)EnableTransparency()

// 启用透明度的函数
void EnableTransparency(HWND hwnd) {
    // 设置窗口样式为分层
    SetWindowLong(hwnd, GWL_EXSTYLE, GetWindowLong(hwnd, GWL_EXSTYLE) | WS_EX_LAYERED);
    // 设置透明色和alpha
    COLORREF colorKey = RGB(255, 255, 255); // The color to make transparent
    // 透明程度:透明度水平(0 - 255,0完全透明,255完全不透明)
    BYTE alpha = 0;
    SetLayeredWindowAttributes(hwnd, colorKey, alpha, LWA_ALPHA);
}

EnableTransparency函数:这是一个新的函数,函数名随意,它接收窗口句柄作为参数,并设置窗口为层叠样式(WS_EX_LAYERED),然后通过SetLayeredWindowAttributes函数设置窗口的透明度。这里的透明度由alpha参数决定,取值范围是0到255,其中0表示完全透明,255表示完全不透明。

EnableTransparency(window.GetHandle());     

window.Create之后调用EnableTransparency:在创建窗口之后,我们调用EnableTransparency函数并传递窗口句柄,以使窗口透明。

GetHandle函数属于Win32Window类,它返回后台窗口句柄,使客户端能够设置图标和其他窗口属性。如果窗口已被销毁,则返回nullptr。

3)中文注释

使用Android Studiomain.cpp文件中使用中文注释容易报文件编码的错误,在文件中指定编码格式或者在编辑器中修改编码格式都能解决,不过不用中文注释应该是最简单直接的做法。

// 错误信息示例
P:\FlutterProject\flutter_clock-master\untitled\windows\runner\main.cpp(1,1): error C2220: 以下警告被视为错误 [P:\FlutterProject\flutter_clock-master\untitled\build\windows\x64\runner\untitled.vcxproj]
P:\FlutterProject\flutter_clock-master\untitled\windows\runner\main.cpp(1,1): warning C4819: 该文件包含不能在当前代码页(936)中表示的字符。请将该文件保存为 Unicode 格式以防止数据丢失 [P:\FlutterProject\flutter_clock-master\untitled\build\windows\x64\runner\untitled.vcxproj]
Exception: Build process failed.

2.编写 Flutter 代码

网上有两个包bitsdojo_windowwindow_manager进行Flutterwindow应用程序编程,bitsdojo_windowwindow_manager 是两个用于 Flutter 桌面应用开发的包,咱们已经修改了main.cpp,只要在组件中设置背景即可,这两个包都能实现,下面列出bitsdojo_window的实现:

import 'package:flutter/material.dart';
import 'package:bitsdojo_window/bitsdojo_window.dart';

void main() {
  runApp(const MyApp());
  doWhenWindowReady(() {
    appWindow.show();
  });
}

class MyApp extends StatelessWidget {
  const MyApp({super.key});

  
  Widget build(BuildContext context) {
    return MaterialApp(
      color: Colors.transparent,
      theme: ThemeData(
        // 设置窗口的背景颜色
        scaffoldBackgroundColor: Colors.transparent,
      ),
      home: Container(color: Colors.transparent),
    );
  }
}

上面几乎把存在的组件都设置成了transparent,所以现在窗口的透明与否完全由组件说了算,两个包只要写一条让窗体显示的代码(如上面的 appWindow.show();)即可。既然提到这两个包,这里说明一下它们两个的区别:

1)bitsdojo_window

功能

  1. 自定义窗口边框:允许开发者自定义窗口的边框和标题栏,可以实现无边框窗口并完全控制窗口的外观和行为。
  2. 窗口拖动:提供简单的 API 用于实现自定义标题栏的拖动。
  3. 窗口按钮:允许自定义最小化、最大化和关闭按钮的行为。
  4. 窗口透明度:支持设置窗口的透明度。
  5. 多平台支持:支持 Windows、macOS 和 Linux。

典型用例

  • 需要高度自定义窗口外观和行为的应用。
  • 希望实现无边框窗口并自行处理窗口标题栏和按钮。

示例代码

import 'package:bitsdojo_window/bitsdojo_window.dart';

void main() {
  runApp(MyApp());

  // Initialize bitsdojo_window
  doWhenWindowReady(() {
    final initialSize = Size(600, 450);
    appWindow.minSize = initialSize;
    appWindow.size = initialSize;
    appWindow.alignment = Alignment.center;
    appWindow.show();
  });
}

2)window_manager

功能

  1. 窗口管理:提供多种窗口管理功能,包括窗口最小化、最大化、恢复、隐藏、显示等。
  2. 窗口信息:可以获取窗口的位置、大小、标题等信息。
  3. 窗口事件:支持窗口的各种事件监听,如窗口关闭、聚焦、失焦等事件。
  4. 多平台支持:支持 Windows、macOS 和 Linux。

典型用例

  • 需要对窗口进行全面控制和管理的应用。
  • 需要监听窗口事件或获取窗口状态信息的应用。

示例代码

import 'package:window_manager/window_manager.dart';

void main() async {
  WidgetsFlutterBinding.ensureInitialized();
  await windowManager.ensureInitialized();

  WindowOptions windowOptions = WindowOptions(
    size: Size(800, 600),
    center: true,
    title: 'My Flutter App',
  );

  windowManager.waitUntilReadyToShow(windowOptions, () async {
    await windowManager.show();
    await windowManager.focus();
  });

  runApp(MyApp());
}

3)区别对比

  • bitsdojo_window:侧重于窗口外观的高度自定义,特别是无边框窗口的实现和自定义窗口控制按钮。
  • window_manager:提供全面的窗口管理功能,适合需要对窗口进行各种操作和事件处理的应用。

选择哪个包取决于你的具体需求:如果你需要自定义窗口的外观和行为,bitsdojo_window 是一个很好的选择;如果你需要全面的窗口管理功能,window_manager 可能更适合你。

4)同时使用

当然有大聪明就想了,我都用可不可以呢?在同一个 Flutter 项目中同时使用 bitsdojo_windowwindow_manager 当然是可以的,但需要注意它们可能在某些功能上存在冲突或重叠,因此需要谨慎管理。方法如下,仅供参考:

(1)设置初始化代码

main.dart 文件中初始化 bitsdojo_windowwindow_manager,确保它们不互相干扰:

import 'package:flutter/material.dart';
import 'package:bitsdojo_window/bitsdojo_window.dart';
import 'package:window_manager/window_manager.dart';

void main() async {
  WidgetsFlutterBinding.ensureInitialized();

  // Initialize window_manager
  await windowManager.ensureInitialized();

  WindowOptions windowOptions = WindowOptions(
    size: Size(800, 600),
    center: true,
    title: 'My Flutter App',
  );

  windowManager.waitUntilReadyToShow(windowOptions, () async {
    await windowManager.show();
    await windowManager.focus();
  });

  runApp(MyApp());

  // Initialize bitsdojo_window
  doWhenWindowReady(() {
    final initialSize = Size(800, 600);
    appWindow.minSize = initialSize;
    appWindow.size = initialSize;
    appWindow.alignment = Alignment.center;
    appWindow.show();
  });
}

class MyApp extends StatelessWidget {
  
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Flutter Demo',
      theme: ThemeData(
        primarySwatch: Colors.blue,
      ),
      home: MyHomePage(),
    );
  }
}

class MyHomePage extends StatelessWidget {
  
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text('Flutter Demo Home Page'),
      ),
      body: WindowBorder(
        color: Colors.black,
        width: 1,
        child: Center(
          child: Column(
            mainAxisAlignment: MainAxisAlignment.center,
            children: <Widget>[
              Text(
                'You have pushed the button this many times:',
              ),
            ],
          ),
        ),
      ),
    );
  }
}
(2)处理冲突和集成

在整合过程中,注意以下几点:

  1. 窗口初始化:确保 window_managerbitsdojo_window 的初始化代码不互相干扰。window_manager 用于窗口管理,bitsdojo_window 用于自定义窗口外观。
  2. 窗口事件:如果需要监听窗口事件,如最小化、最大化等,优先使用 window_manager 提供的事件处理机制。
  3. 自定义边框和按钮:使用 bitsdojo_window 自定义窗口边框和按钮时,确保这些自定义不会影响 window_manager 的功能。

以下是一个实现透明窗口并管理窗口事件的示例:

import 'package:flutter/material.dart';
import 'package:bitsdojo_window/bitsdojo_window.dart';
import 'package:window_manager/window_manager.dart';

void main() async {
  WidgetsFlutterBinding.ensureInitialized();

  // Initialize window_manager
  await windowManager.ensureInitialized();

  WindowOptions windowOptions = WindowOptions(
    size: Size(800, 600),
    center: true,
    title: 'My Flutter App',
  );

  windowManager.waitUntilReadyToShow(windowOptions, () async {
    await windowManager.show();
    await windowManager.focus();
  });

  runApp(MyApp());

  // Initialize bitsdojo_window
  doWhenWindowReady(() {
    final initialSize = Size(800, 600);
    appWindow.minSize = initialSize;
    appWindow.size = initialSize;
    appWindow.alignment = Alignment.center;

    // Set the window to be transparent
    appWindow.setEffect(
      effect: WindowEffect.transparent,
      color: Colors.transparent,
    );

    appWindow.show();
  });
}

class MyApp extends StatelessWidget {
  
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Flutter Demo',
      theme: ThemeData(
        primarySwatch: Colors.blue,
      ),
      home: MyHomePage(),
    );
  }
}

class MyHomePage extends StatelessWidget {
  
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text('Flutter Demo Home Page'),
      ),
      body: WindowBorder(
        color: Colors.black,
        width: 1,
        child: Center(
          child: Column(
            mainAxisAlignment: MainAxisAlignment.center,
            children: <Widget>[
              Text(
                'You have pushed the button this many times:',
              ),
            ],
          ),
        ),
      ),
    );
  }
}

如果觉得文章写的不错,就随手点个赞再走吧!😊

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1842160.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

做金蝶BI数据分析?后悔没早遇到这套方案

金蝶ERP是企业信息化管理的核心平台&#xff0c;在企业管理上有着十分重要的地位&#xff1b;而BI数据可视化工具同样在企业管理中扮演着至关重要的角色&#xff0c;通过将复杂数据转化为直观、易懂的图形和报表&#xff0c;推动企业高效、精准科学化决策。金蝶、BI两者结合&am…

使用二进制安装安装docker

在一些情况下无法使用yum安装docker下面写了一个使用二进制安装docker的文档 官网下载地址https://download.docker.com/linux/static/stable/x86_64/ 可以按需求下载 wget https://download.docker.com/linux/static/stable/x86_64/docker-20.10.10.tgz 下载包 tar xf dcker…

JAVA小知识27:异常与异常处理全解

一、异常 异常就是代表程序出现了问题&#xff0c;像我们之前学数组的时候碰到的数组越界异常&#xff0c;以及空指针异常等等都属于开发中经常能碰到的异常。 我们学习异常不是为了在以后中避免异常&#xff0c;而是学习碰到了异常以后该如何的处理。 1.1、异常的分类 Java…

InPixio Photo Cutter v10 解锁版安装教程 (懒人抠图工具)

前言 InPixio Photo Cutter是一款懒人抠图工具&#xff0c;采用了增强的算法切割技术&#xff0c;可以在不影响图像质量的情况下&#xff0c;允许用户从照片中删除任何物体或人物&#xff0c;并且保持其完整的质量。你只需点击几下鼠标&#xff0c;便可从照片中剪下任何细节、…

Linux驱动开发(二)--字符设备驱动开发提升 LED驱动开发实验

1、地址映射 在编写驱动之前&#xff0c;需要知道MMU&#xff0c;也就是内存管理单元&#xff0c;在老版本的 Linux 中要求处理器必须有 MMU&#xff0c;但是现在Linux 内核已经支持无 MMU 的处理器了。 MMU的功能如下&#xff1a; 完成虚拟空间到物理空间的映射 内存保护&…

安卓手机删除的照片怎么恢复?3个方法,小技巧大作用

你是否曾经不小心删除了手机里的珍贵照片&#xff0c;却不知道怎么恢复&#xff1f;别担心&#xff0c;今天我们就来分享几个简单的小技巧&#xff0c;帮助你轻松找回那些丢失的照片。这些技巧虽然简单&#xff0c;但却能发挥大作用&#xff0c;让你不再为丢失照片而烦恼。手机…

delphi 如何使用TEdgeBrowser组件以及打包环境在其他主机上运行

不管开发环境还是第三方环境先安装运行时库&#xff1a;Microsoft Edge WebView2 | Microsoft Edge Developer 开发环境可以直接通过&#xff1a; delphi IDE安装 安装完毕后进入到指定路径&#xff0c;复制里面的WebView2Loader.dll到你要开发的程序根目录&#xff1a; 大致路…

南开大学漏洞报送证书【文尾有福利】

证书介绍 获取来源&#xff1a;edusrc&#xff08;教育漏洞报告平台&#xff09; url&#xff1a;教育漏洞报告平台(EDUSRC) 兑换价格&#xff1a;30金币​ 获取条件&#xff1a;南开大学任意中危或以上级别漏洞 证书规格&#xff1a;证书做了木框装裱&#xff0c;显得很高…

C++设计模式——Flyweight享元模式

一&#xff0c;享元模式简介 享元模式是一种结构型设计模式&#xff0c;它将每个对象中各自保存一份数据的方式改为多个对象共享同一份数据&#xff0c;该模式可以有效减少应用程序的内存占用。 享元模式的核心思想是共享和复用&#xff0c;通过设置共享资源来避免创建过多的实…

反激开关电源输入电解电容选型及计算

输入电解电容波形如下 计算 1、输入电解电容经验选取法 当输入电压为220V20%&#xff08;AC176-264V&#xff09;时 按照输出功率选取&#xff1a;W/μF 耐压&#xff08;400V&#xff0c;输入176-264V最高DC峰值373V&#xff09; 当输入电压为11020%时&#xff08;AC88-132V…

进销存系统哪个好?2024最新进销存系统推荐(持续更新中)

现在市面上的进销存系统太多了&#xff0c;企业的选择越多&#xff0c;越容易踩坑。那企业在选择进销存系统时&#xff0c;需要考虑哪些因素&#xff1f; 1、系统的适配性 在进行选择之前&#xff0c;就应该先清楚自己的企业是重财务流管理、还是生产业务流管理、还是销售订单…

NSSCTF-Web题目8

目录 [LitCTF 2023]Http pro max plus 1、题目 2、知识点 3、思路 [NSSCTF 2022 Spring Recruit]babyphp 1、题目 2、知识点 3、思路 [LitCTF 2023]Http pro max plus 1、题目 2、知识点 http数据包头部字段 3、思路 打开题目 第一想法就是加上X-forwarded-for字段 …

ABAP程序示例:交互式ALV演示程序

这个程序是一个用于显示和刷新事务代码&#xff08;TCode&#xff09;列表的报表程序。它使用ALV&#xff08;ABAP List Viewer&#xff09;来显示数据&#xff0c;并提供了一个刷新功能&#xff0c;以便用户可以查看新的事务代码。以下是程序的主要部分及其功能&#xff1a; 数…

拉普拉斯矩阵对称归一化理解,通过一个简单的例子进行说明

拉普拉斯矩阵&#xff08;Laplacian Matrix&#xff09;是一个与图相关的矩阵&#xff0c;通常用于图分析、机器学习和信号处理等领域。它是由图的邻接矩阵或关联矩阵计算得出的。 对于一个无向图 G ( V , E ) G(V,E) G(V,E)&#xff0c;它的拉普拉斯矩阵 L L L 可以表示为…

springBoot高校宿舍交电费系统-计算机毕业设计源码031552

摘 要 科技进步的飞速发展引起人们日常生活的巨大变化&#xff0c;电子信息技术的飞速发展使得电子信息技术的各个领域的应用水平得到普及和应用。信息时代的到来已成为不可阻挡的时尚潮流&#xff0c;人类发展的历史正进入一个新时代。在现实运用中&#xff0c;应用软件的工作…

大数据-数据分析师利用excel绘图

你会用excel&#xff0c;统计数据吗&#xff1f;我是大数据工程师&#xff0c;但是我不会excel。那咋办&#xff1f; 用sql&#xff0c;统计&#xff0c;导出到excel&#xff0c;在用excel统计。本文主要讨论的是导出到excel后&#xff0c;画图。 图是什么&#xff1f; x和y…

视频画面大小裁剪怎么弄?这3种剪辑方法轻松解决

视频画面大小裁剪怎么弄&#xff1f;视频画面大小裁剪&#xff0c;是视频编辑中常见且实用的操作之一。它不仅能帮助我们精准地去除视频中的多余内容&#xff0c;还能根据实际需求调整画面大小&#xff0c;使之适应不同的播放平台和场景需求。通过裁剪&#xff0c;我们可以让视…

WordPress主题 酱茄免费主题

酱茄free主题由酱茄开发的一款免费开源的WordPress主题&#xff0c;主题专为WordPress博客、资讯、自媒体网站而设计&#xff0c;遵循GPL V2.0开源协议发布。 运行环境 酱茄Free主题当前版本&#xff1a;2020.11.25 V1.0.0 支持WordPress版本&#xff1a;5.4 兼容Chrome、Fire…

git知识域

知识体系 FAQ git clone与git pull区别 git clone&#xff1a;从无到有&#xff0c;包含分支信息&#xff0c;日志信息。 git pull&#xff1a;在已有项目基础上操作&#xff0c;针对特定分支。

React实现H5手势密码

监测应用进入前后台 在JavaScript中,监听H5页面是否在前台或后台运行,主要依赖于Page Visibility API。这个API在大多数现代浏览器中都是支持的,包括苹果的Safari和谷歌的Chrome(也就基本覆盖了Android和iOS平台)。下面是一个简单的示例代码,展示如何使用这个API来判断页…