Flutter框架高阶——Window应用程序设置窗体窗口背景完全透明
文章目录
- 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
由上面的代码不难看出flutter的window应用程序使用的是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);// 设置透明色和alphaCOLORREF 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 Studio在main.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_window和window_manager进行Flutter的window应用程序编程,bitsdojo_window 和 window_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
功能:
- 自定义窗口边框:允许开发者自定义窗口的边框和标题栏,可以实现无边框窗口并完全控制窗口的外观和行为。
- 窗口拖动:提供简单的 API 用于实现自定义标题栏的拖动。
- 窗口按钮:允许自定义最小化、最大化和关闭按钮的行为。
- 窗口透明度:支持设置窗口的透明度。
- 多平台支持:支持 Windows、macOS 和 Linux。
典型用例:
- 需要高度自定义窗口外观和行为的应用。
- 希望实现无边框窗口并自行处理窗口标题栏和按钮。
示例代码:
import 'package:bitsdojo_window/bitsdojo_window.dart';void main() {runApp(MyApp());// Initialize bitsdojo_windowdoWhenWindowReady(() {final initialSize = Size(600, 450);appWindow.minSize = initialSize;appWindow.size = initialSize;appWindow.alignment = Alignment.center;appWindow.show();});
}
2)window_manager
功能:
- 窗口管理:提供多种窗口管理功能,包括窗口最小化、最大化、恢复、隐藏、显示等。
- 窗口信息:可以获取窗口的位置、大小、标题等信息。
- 窗口事件:支持窗口的各种事件监听,如窗口关闭、聚焦、失焦等事件。
- 多平台支持:支持 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_window 和 window_manager 当然是可以的,但需要注意它们可能在某些功能上存在冲突或重叠,因此需要谨慎管理。方法如下,仅供参考:
(1)设置初始化代码
在 main.dart 文件中初始化 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_managerawait 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_windowdoWhenWindowReady(() {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)处理冲突和集成
在整合过程中,注意以下几点:
- 窗口初始化:确保
window_manager和bitsdojo_window的初始化代码不互相干扰。window_manager用于窗口管理,bitsdojo_window用于自定义窗口外观。 - 窗口事件:如果需要监听窗口事件,如最小化、最大化等,优先使用
window_manager提供的事件处理机制。 - 自定义边框和按钮:使用
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_managerawait 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_windowdoWhenWindowReady(() {final initialSize = Size(800, 600);appWindow.minSize = initialSize;appWindow.size = initialSize;appWindow.alignment = Alignment.center;// Set the window to be transparentappWindow.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:',),],),),),);}
}
如果觉得文章写的不错,就随手点个赞再走吧!😊
相关文章:
Flutter框架高阶——Window应用程序设置窗体窗口背景完全透明
文章目录 1.修改 main.cpp1)C 与 Win32 API2)EnableTransparency()3)中文注释 2.编写 Flutter 代码1)bitsdojo_window2)window_manager3)区别对比4)同时使用(1)设置初始化…...
HJ39判断两个IP是否属于同一子网
提示:文章 文章目录 前言一、背景二、 2.1 2.2 总结 前言 HJ39判断两个IP是否属于同一子网 一、 代码: 第一版代码没有对掩码网络号进行处理。一开始对非法字段的理解就是value大于255。然后执行示例, 254.255.0.0 85.122.52.249 10.57.…...
opencv学习笔记(2)
设置鼠标回调函数 setMouseCallback(winname, callback, userdata) winname:窗口名字 callback:回调函数 userdata:传回callback中 callback(event, x, y, flags,userdata) event:鼠标事件 x: 鼠标的x坐标 y: 鼠标的y坐标 flags:鼠标键和组合键 userdata:setMouseCallback传回…...
分享vs code十大好用的插件
1.Chinese (Simplified) (简体中文) Language Pack for Visual Studio Code 将 VS Code 界面改成简体中文。 2.PDF Viewer 在VS Code 中打开 PDF文件。 3.TODO Highlight 这个扩展会突出显示您的待办事项注释,并提醒存在未完成的注释或任务。 该扩展附带了内…...
MySQL支持哪些特殊字符
MySQL支持多种特殊字符,这些字符在SQL语句中具有特定的含义,需要在使用时特别注意。以下是一些MySQL中的特殊字符及其相关信息: 引号: 单引号():用于定义字符串。如果字符串中包含单引号本身&…...
c语言中的宏是什么?
宏的定义及用途 C语言中的宏是一种预处理指令,它允许程序员定义一个名称,该名称可以代表一段代码或一个值。宏的主要用途是简化代码的编写,提高代码的可读性和可维护性,以及实现代码的重复利用。 宏的定义使用#define指令&#…...
采购信息记录标准编码范围维护以及如何开发获取编码范围
上图是配置的点,在这里可以获取到对应的编号范围以及对象名称 下面的话是官方就如何取编号的技术文档 SAP Help Portal...
渗透测试基础(四) MS08-067 漏洞攻击
1. 漏洞介绍 漏洞描述 Microsoft Windows Server服务RPC请求缓冲区溢出漏洞Windows的Server服务在处理特质RPC请求时存在缓冲区溢出漏洞,远程攻击者可以通过发送恶意的RPC请求触发这个溢出,导致完全入侵用户系统,以SYSTEM权限执行任意指令。…...
vmware 虚拟机保留数据扩展C盘
1,在默认安装系统的时候,VMWARE一般给C盘50G,很多人想着够用了,但是后面慢慢的安装各种大型软件,游戏,才发现,悔时已晚。 2,有很多人虚拟机其实就是拿来游戏多开,但是当…...
vscode cmake c++ include 设置
在这里设置编译器路径,include路径等等。 一个奇怪的现象是同一项目放在VS中可以cmake生成,并正常运行,但是放在VSCODE中cmake生成时会报错,如iostream、limits等头文件找不到。当在VS中运行执行完成调试后,在运行VSC…...
2024-06-19 高等数学(统计学和概率论-高等工科数学)
学习数学时,有效的笔记方法可以帮助你更好地理解和记忆概念、公式和解题技巧。下面是一个数学笔记的基本模本,你可以根据自己的需求进行调整: 1. **标题**:写上日期和课程名称,例如“2024-06-19 高等数学”。 2. **课…...
idea 创建properties文件,解决乱码
设置properties文件编码 点击file->Settings File Encodings->设置utf-8 重新创建.properties文件才生效...
树莓派4B学习笔记11:PC端网线SSH连接树莓派_网线连接请求超时问题解决
今日继续学习树莓派4B 4G:(Raspberry Pi,简称RPi或RasPi) 本人所用树莓派4B 装载的系统与版本如下: 版本可用命令 (lsb_release -a) 查询: Opencv 版本是4.5.1: 今日学习使用网线连接树莓派,网线可以提供更…...
适合营销的叙事可视化
背景 数据可视化与数据故事化的差异和相似点,以及它们如何协同工作,将你的数据转化为清晰、简洁、可操作的信息,以便您的组织使用。 什么是数据可视化? 数据可视化通过图像传达信息——这是你所收集数据的视觉表示。通过提供原…...
Spring Cloud全家桶(上)【Nacos、OpenFeign、LoadBalancer、GateWay、金丝雀灰色发布】
0.零基础入门微服务实战课 1.微服务和 Spring Cloud1.1 什么是微服务?1.2 什么是 Spring Cloud?1.3 微服务 VS Spring Cloud 2.为什么要学微服务?3.Spring Cloud 组件介绍1.什么是 Nacos?1.1 Nacos 功能1.1.1 配置中心1.1.2 注册中心 1.2 Na…...
GPRS与4G网络:技术差异与应用选择
在移动通信的发展历程中,GPRS(General Packet Radio Service)和4G(Fourth-Generation)技术都扮演着举足轻重的角色。虽然两者都旨在提供无线数据传输服务,但在数据传输速率、延迟和覆盖范围等方面ÿ…...
【Spring】1. Maven项目管理
📚博客主页:爱敲代码的小杨. ✨专栏:《Java SE语法》 | 《数据结构与算法》 | 《C生万物》 |《MySQL探索之旅》 |《Web世界探险家》 ❤️感谢大家点赞👍🏻收藏⭐评论✍🏻,您的三连就是我持续更…...
工业制造领涉及的8大常见管理系统,如mes、scada、aps、wms等
在工业生产和制造领域有一些常见的管理系统,很多小伙伴分不清,这次大美B端工场带领大家了解清楚。 MES(Manufacturing Execution System,制造执行系统): MES是一种用于监控、控制和优化生产过程的软件系统…...
Lianwei 安全周报|2024.06.17
新的一周又开始了,以下是本周「Lianwei周报」,我们总结推荐了本周的政策/标准/指南最新动态、热点资讯和安全事件,保证大家不错过本周的每一个重点! 政策/标准/指南最新动态 01 IDC:2024 第一季度中国安全硬件市场规模…...
海量数据处理利器 Roaring BitMap 原理介绍
作者:来自 vivo 互联网服务器团队- Zheng Rui 本文结合个人理解梳理了BitMap及Roaring BitMap的原理及使用,分别主要介绍了Roaring BitMap的存储方式及三种container类型及Java中Roaring BitMap相关API使用。 一、引言 在进行大数据开发时,…...
反向工程与模型迁移:打造未来商品详情API的可持续创新体系
在电商行业蓬勃发展的当下,商品详情API作为连接电商平台与开发者、商家及用户的关键纽带,其重要性日益凸显。传统商品详情API主要聚焦于商品基本信息(如名称、价格、库存等)的获取与展示,已难以满足市场对个性化、智能…...
【人工智能】神经网络的优化器optimizer(二):Adagrad自适应学习率优化器
一.自适应梯度算法Adagrad概述 Adagrad(Adaptive Gradient Algorithm)是一种自适应学习率的优化算法,由Duchi等人在2011年提出。其核心思想是针对不同参数自动调整学习率,适合处理稀疏数据和不同参数梯度差异较大的场景。Adagrad通…...
三体问题详解
从物理学角度,三体问题之所以不稳定,是因为三个天体在万有引力作用下相互作用,形成一个非线性耦合系统。我们可以从牛顿经典力学出发,列出具体的运动方程,并说明为何这个系统本质上是混沌的,无法得到一般解…...
ArcGIS Pro制作水平横向图例+多级标注
今天介绍下载ArcGIS Pro中如何设置水平横向图例。 之前我们介绍了ArcGIS的横向图例制作:ArcGIS横向、多列图例、顺序重排、符号居中、批量更改图例符号等等(ArcGIS出图图例8大技巧),那这次我们看看ArcGIS Pro如何更加快捷的操作。…...
安宝特案例丨Vuzix AR智能眼镜集成专业软件,助力卢森堡医院药房转型,赢得辉瑞创新奖
在Vuzix M400 AR智能眼镜的助力下,卢森堡罗伯特舒曼医院(the Robert Schuman Hospitals, HRS)凭借在无菌制剂生产流程中引入增强现实技术(AR)创新项目,荣获了2024年6月7日由卢森堡医院药剂师协会࿰…...
【VLNs篇】07:NavRL—在动态环境中学习安全飞行
项目内容论文标题NavRL: 在动态环境中学习安全飞行 (NavRL: Learning Safe Flight in Dynamic Environments)核心问题解决无人机在包含静态和动态障碍物的复杂环境中进行安全、高效自主导航的挑战,克服传统方法和现有强化学习方法的局限性。核心算法基于近端策略优化…...
日常一水C
多态 言简意赅:就是一个对象面对同一事件时做出的不同反应 而之前的继承中说过,当子类和父类的函数名相同时,会隐藏父类的同名函数转而调用子类的同名函数,如果要调用父类的同名函数,那么就需要对父类进行引用&#…...
适应性Java用于现代 API:REST、GraphQL 和事件驱动
在快速发展的软件开发领域,REST、GraphQL 和事件驱动架构等新的 API 标准对于构建可扩展、高效的系统至关重要。Java 在现代 API 方面以其在企业应用中的稳定性而闻名,不断适应这些现代范式的需求。随着不断发展的生态系统,Java 在现代 API 方…...
数据结构:递归的种类(Types of Recursion)
目录 尾递归(Tail Recursion) 什么是 Loop(循环)? 复杂度分析 头递归(Head Recursion) 树形递归(Tree Recursion) 线性递归(Linear Recursion)…...
客户案例 | 短视频点播企业海外视频加速与成本优化:MediaPackage+Cloudfront 技术重构实践
01技术背景与业务挑战 某短视频点播企业深耕国内用户市场,但其后台应用系统部署于东南亚印尼 IDC 机房。 随着业务规模扩大,传统架构已较难满足当前企业发展的需求,企业面临着三重挑战: ① 业务:国内用户访问海外服…...
