win32_runner 0.2.2 copy "win32_runner: ^0.2.2" to clipboard
win32_runner: ^0.2.2 copied to clipboard

Compile and run a Flutter app without needing any C/C++ code. Just Dart!

example/win32_runner.dart

// Copyright (c) 2023, Halil Durmus. Please see the AUTHORS file for details.
// All rights reserved. Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

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) {
    // Give Flutter an opportunity to handle window messages.
    if (engineInitialized) {
      final result = engine.handleTopLevelWindowProc(hwnd, msg, wParam, lParam);
      if (result != FALSE) return result;
    }

    // Otherwise, we address host window messages.
    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);
    }

    // Set up Flutter view controller. The size must match the window dimensions
    // to avoid unnecessary surface creation / destruction in the startup path.
    engine = FlutterEmbedder(hostWindow.dimensions, project, flutterLibrary);
    engineInitialized = true;

    Window(engine.hwnd)
      ..setParent(hostWindow)
      ..move(hostWindow.dimensions)
      ..setFocus()
      ..runMessageLoop();

    windowProc.close();
    CoUninitialize();
  }
}
25
likes
160
pub points
20%
popularity

Publisher

verified publisherhalildurmus.dev

Compile and run a Flutter app without needing any C/C++ code. Just Dart!

Repository (GitHub)
View/report issues

Topics

#win32 #ffi #windows

Documentation

API reference

License

BSD-3-Clause (license)

Dependencies

args, ffi, path, win32, win32_registry

More

Packages that depend on win32_runner