Flutter Windows平台集成插件win32_runner的使用
Flutter Windows平台集成插件win32_runner的使用
win32_runner
是一个实验性的包,允许你从Dart运行器而不是默认的C++运行器运行Flutter应用程序。这对于希望在没有C++编译器的情况下创建Windows Flutter应用的人来说非常有用。
重要提示
该包目前处于实验阶段,不应用于生产应用程序。它主要是一个概念验证,并且有一些限制,例如不支持插件。
使用方法
以下是将现有Flutter应用程序在Windows上使用Dart运行器运行的步骤:
步骤1:克隆仓库
C:\src> git clone https://github.com/halildurmus/win32_runner.git
C:\src> cd win32_runner
步骤2:安装依赖
C:\src\win32_runner> dart pub get
步骤3:创建示例应用
C:\src\win32_runner> cd ..
C:\src> flutter create simpleapp
C:\src> cd simpleapp
步骤4:编译Flutter代码和资源
C:\src\simpleapp> flutter assemble -dTargetPlatform=windows-x64 --output=build -dBuildMode=release release_bundle_windows-x64_assets
步骤5:编译Dart运行器
C:\src\simpleapp> dart compile exe ..\win32_runner\example\win32_runner.dart -o win32_runner.exe
步骤6:运行Flutter应用
C:\src\simpleapp> .\win32_runner
完成这些步骤后,你应该可以看到你的Flutter应用在Windows上通过Dart运行器运行。
示例代码
以下是从win32_runner
示例中提取的关键代码片段:
import 'dart:ffi';
import 'dart:io';
import 'dart:math' as math;
import 'package:args/args.dart';
import 'package:ffi/ffi.dart';
import 'package:win32/win32.dart';
import 'package:win32_runner/win32_runner.dart';
void main() => initApp(Application.winMain);
class Application {
static late FlutterEmbedder engine;
static bool engineInitialized = false;
static int mainWindowProc(int hwnd, int msg, int wParam, int lParam) {
// 给Flutter处理窗口消息的机会。
if (engineInitialized) {
final result = engine.handleTopLevelWindowProc(hwnd, msg, wParam, lParam);
if (result != FALSE) return result;
}
// 否则,我们处理主机窗口消息。
switch (msg) {
case WM_NCCREATE:
EnableNonClientDpiScaling(hwnd);
case WM_DESTROY:
PostQuitMessage(0);
return 0;
case WM_FONTCHANGE:
engine.reloadSystemFonts();
return 0;
case WM_SIZE:
final hostWindow = Window(hwnd);
Window(engine.hwnd).move(hostWindow.dimensions);
return 0;
case WM_ACTIVATE:
Window(engine.hwnd).setFocus();
return 0;
case WM_SETTINGCHANGE:
if (wParam == 0 && lParam != 0) {
final lParamString =
Pointer.fromAddress(lParam).cast<Utf16>().toDartString();
if (lParamString == 'ImmersiveColorSet') {
Window(hwnd).updateTheme();
}
}
return 0;
case WM_DWMCOLORIZATIONCOLORCHANGED:
Window(hwnd).updateTheme();
return 0;
}
return DefWindowProc(hwnd, msg, wParam, lParam);
}
static String parseArgs(List<String> args) {
final parser = ArgParser()
..addOption('path',
abbr: 'p',
help: 'Relative or absolute path to a Flutter app. ',
defaultsTo: '.')
..addFlag('help', abbr: 'h', help: 'Shows usage information.');
final results = parser.parse(args);
if (results['help'] as bool) {
print('Runs a Flutter app.\n\nSyntax:\n${parser.usage}');
exit(0);
}
final appPath = results['path'] as String;
return Directory(appPath).absolute.path;
}
static void winMain(int hInstance, List<String> args, int nShowCmd) {
final appPath = parseArgs(args);
final iconPath = '$appPath\\windows\\runner\\resources\\app_icon.ico';
if (!File(iconPath).existsSync()) {
print('Icon file not found at "$iconPath".');
exit(WIN32_ERROR.ERROR_FILE_NOT_FOUND);
}
CoInitializeEx(nullptr, COINIT.COINIT_APARTMENTTHREADED);
SetThreadDpiAwarenessContext(DPI_AWARENESS_CONTEXT_PER_MONITOR_AWARE_V2);
final windowProc = NativeCallable<WNDPROC>.isolateLocal(
mainWindowProc,
exceptionalReturn: 0,
);
final hostWindow = Window.create(
hInstance: hInstance,
windowCaption: 'Dart Native Win32 Window',
className: 'FLUTTER_RUNNER_WIN32_WINDOW',
windowProc: windowProc.nativeFunction,
dimensions: const math.Rectangle<int>(10, 10, 1280, 720),
iconPath: iconPath,
)..updateTheme();
final project = DartProject.fromRoot(appPath);
final flutterLibrary =
'$appPath\\windows\\flutter\\ephemeral\\flutter_windows.dll';
if (!File(flutterLibrary).existsSync()) {
print('`flutter_windows.dll` file not found at "$flutterLibrary".');
exit(WIN32_ERROR.ERROR_FILE_NOT_FOUND);
}
// 设置Flutter视图控制器。大小必须与窗口尺寸匹配,以避免启动路径中的不必要表面创建/销毁。
engine = FlutterEmbedder(hostWindow.dimensions, project, flutterLibrary);
engineInitialized = true;
Window(engine.hwnd)
..setParent(hostWindow)
..move(hostWindow.dimensions)
..setFocus()
..runMessageLoop();
windowProc.close();
CoUninitialize();
}
}
更多关于Flutter Windows平台集成插件win32_runner的使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html
更多关于Flutter Windows平台集成插件win32_runner的使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html
当然,下面是一个关于如何在Flutter Windows平台上集成并使用win32_runner
插件的示例代码案例。win32_runner
插件允许你调用Windows原生API来执行一些特定的Windows平台任务。需要注意的是,win32_runner
这个名称可能是一个假设的插件名称,实际中你可能需要找到一个具体的插件或者自己使用dart:ffi
来调用Windows API。
为了演示如何在Flutter Windows平台上集成并使用原生插件,这里我将展示如何调用一个简单的Windows API,比如MessageBox
,这是一个显示消息框的Windows API函数。我们将使用dart:ffi
来实现这个功能,因为dart:ffi
允许Dart代码调用原生C函数。
步骤 1: 设置Flutter项目
首先,确保你已经创建了一个Flutter项目。如果还没有,可以使用以下命令创建:
flutter create flutter_windows_ffi_example
cd flutter_windows_ffi_example
步骤 2: 添加dart:ffi
依赖
在pubspec.yaml
文件中,添加对ffi
包的依赖:
dependencies:
flutter:
sdk: flutter
ffi: ^1.0.0 # 请检查并使用最新版本
然后运行flutter pub get
来获取依赖。
步骤 3: 创建Windows平台插件代码
在windows
目录下创建一个新的Dart文件,比如windows_api.dart
,并编写以下代码:
import 'dart:ffi';
import 'package:ffi/ffi.dart';
typedef MessageBoxFunc = Int32 Function(
Pointer<Utf16> hWnd, Pointer<Utf16> lpText, Pointer<Utf16> lpCaption, Uint32 uType);
typedef MessageBox = int Function(Pointer<Utf16>, Pointer<Utf16>, Pointer<Utf16>, int);
class WindowsApi {
static late DynamicLibrary _user32;
static void loadLibrary() {
_user32 = DynamicLibrary.open('user32.dll');
}
static MessageBox? _messageBox;
static MessageBox get messageBox {
_messageBox ??= _user32
.lookup<NativeFunction<MessageBoxFunc>>('MessageBoxW')
.asFunction<MessageBox>();
return _messageBox!;
}
}
步骤 4: 调用Windows API
在你的Flutter应用的Dart代码中,比如main.dart
,编写以下代码来调用MessageBox
函数:
import 'package:flutter/material.dart';
import 'windows_api.dart';
void main() {
WindowsApi.loadLibrary();
runApp(MyApp());
}
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
home: Scaffold(
appBar: AppBar(
title: Text('Flutter Windows FFI Example'),
),
body: Center(
child: ElevatedButton(
onPressed: () {
showMessageBox();
},
child: Text('Show Message Box'),
),
),
),
);
}
void showMessageBox() {
final hwnd = Pointer<Utf16>.fromAddress(0); // NULL for no parent window
final lpText = 'Hello from Flutter!'.toNativeUtf16();
final lpCaption = 'Flutter MessageBox'.toNativeUtf16();
final uType = 0; // MB_OK
WindowsApi.messageBox(hwnd, lpText, lpCaption, uType);
// Free allocated memory
calloc.free(lpText);
calloc.free(lpCaption);
}
}
步骤 5: 运行应用
确保你的开发环境已经正确配置了Flutter和Dart SDK,然后在终端中运行以下命令来构建并运行你的Flutter应用:
flutter run -d windows
当应用启动后,点击按钮应该会显示一个Windows消息框。
总结
以上代码展示了如何在Flutter Windows平台上集成并使用dart:ffi
来调用Windows原生API。虽然这里使用的是MessageBox
作为示例,但同样的方法可以扩展到调用其他Windows API。如果你需要更复杂的Windows平台功能,可以考虑编写一个更全面的原生插件,或者使用现有的第三方插件。