WinForms sous macOS
Cette page est une traduction. En cas de divergence, la version anglaise fait foi. English
Pourquoi WinForms seul n’y arrive pas
System.Windows.Forms vit dans le runtime Windows Desktop et enveloppe user32.dll et GDI+. Il
n’en existe aucune version pour macOS et il n’y en a jamais eu — un projet net10.0-windows ne
compile même pas sur un Mac. Les contournements habituels ne tiennent pas non plus : le portage
WinForms de Mono n’a jamais atteint le .NET moderne, System.Drawing.Common lève une
PlatformNotSupportedException hors de Windows depuis .NET 7, et faire tourner l’application dans
une VM Windows ou sous CrossOver signifie que vous livrez toujours une application Windows.
Ce que Majorsilence.Forms fait à la place
Il réimplémente l’API WinForms sur SkiaSharp et l’héberge dans une vraie NSWindow via Avalonia.
Une simple compilation net10.0 — sans TFM -windows — produit une application qui se lance
nativement sur les Mac Apple Silicon (arm64) et Intel (x64).
dotnet new install Majorsilence.Forms.Templates
dotnet new majorsilenceforms
dotnet run --project MajorsilenceFormsApp
Le modèle produit une bibliothèque d’interface partagée plus une tête de bureau ; le même code source compile sans modification sous Windows et Linux.
Ce qui fonctionne réellement sous macOS
| Domaine | Sous macOS |
|---|---|
| Fenêtrage et entrées | NSWindow native via le backend Avalonia, avec les boutons « feux tricolores » standard de macOS et le déplacement/redimensionnement natifs |
| Apple Silicon | arm64 natif — osx-arm64 et osx-x64 sont tous deux des cibles de publication normales |
| Rendu, Retina | SkiaSharp, accéléré par le GPU et compatible HiDPI — le même code de dessin que sous Windows et Linux |
| Polices et texte | Résolus via CoreText par SkiaSharp, avec un jeu de polices de secours embarqué pour tout ce qui manque |
Code GDI+ / System.Drawing |
Remplacé par Majorsilence.Forms.Drawing — Bitmap, Font, Pen, Brush, Region, Drawing2D, Imaging, lecture EMF/WMF |
| Boîtes de dialogue courantes | Boîtes de dialogue natives d’ouverture/enregistrement/dossier/couleur/police via le backend |
| Impression | PrintDocument rend via Skia vers un PDF, à l’identique sur chaque OS |
| Contrôles WebView | Vraie WKWebView, y compris le rendu PDF intégré |
| Son | Joué via afplay |
| Stockage sécurisé et synthèse vocale | Majorsilence.Forms.Essentials : SecureStorage écrit dans Keychain Services, Speech utilise la voix système say ; les deux exposent IsSupported et se dégradent en no-ops plutôt que de lever une exception |
| Thèmes et mode sombre | Les thèmes sont des fichiers CSS (un sous-ensemble documenté) ; BuiltInTheme.Default suit l’apparence clair/sombre de l’OS, et Theme.SetBuiltInTheme/Theme.ApplyTheme basculent à l’exécution. L’exemple Theme Studio est un éditeur CSS en direct avec aperçu, et des binaires précompilés sont joints aux GitHub Releases |
| Gestes du trackpad | Pinch, Swipe, LongPress et ScrollGesture avec inertie sont des événements de premier ordre ; ScrollableControl les applique déjà, donc Panel/ListBox/TreeView se déplacent sans aucune modification de l’application |
| Handle de fenêtre natif | Un vrai pointeur NSWindow via WindowBase.PlatformHandle (les handles par contrôle valent IntPtr.Zero partout — voir Interopérabilité native) |
| Backend Uno | Également pris en charge, et vérifié démarrant et rendant un formulaire complet sous macOS, si vous préférez héberger dans Uno |
| Backend GTK 4 | Compile et s’exécute sous macOS avec le runtime GTK de Homebrew (brew install gtk4) — un backend pensé d’abord pour Linux, attendez-vous donc à une fenêtre GTK plutôt qu’AppKit ; utile surtout pour tester la tête GTK sur un Mac |
Là où l’application ne fera pas très « Mac »
À connaître avant une revue de design, parce que ce sont des conséquences du modèle de compatibilité et non des bogues :
- La barre de menus est dans la fenêtre.
MenuStripest une vraie barre ancrée en haut à l’intérieur du formulaire, comme WinForms la dessine — elle n’est pas projetée sur la barre de menus globale de macOS en haut de l’écran. - Les contrôles sont dessinés, pas natifs. Un
Buttonest du code de dessin Skia thématisé par le framework ; il correspond donc à votre application sous Windows et Linux plutôt qu’à AppKit. La cohérence entre plateformes et l’apparence native sur chacune sont des objectifs réellement opposés ; ce projet choisit le premier. Le thème CSS vous permet de vous approcher d’une palette et d’une typographie Mac, mais cela reste votre thème, pas celui d’AppKit. - Les conventions Windows voyagent avec le code. Les raccourcis clavier, l’ordre des boutons des boîtes de dialogue et la sémantique de fermeture des fenêtres viennent de votre conception WinForms existante. Les adapter aux habitudes macOS est un travail au niveau de l’application.
- Pas de pont UI Automation. La prise en charge des lecteurs d’écran
(
Majorsilence.Forms.WindowsUIAutomation) est aujourd’hui réservée à Windows ; un pontNSAccessibilityest sur la feuille de route, pas câblé. L’arbre d’automatisation indépendant du backend pilote tout de même les tests, Selenium et le serveur MCP sous macOS.
Livrer un .app
L’empaquetage est le même que pour toute application de bureau Avalonia ou .NET — le framework n’ajoute aucune étape supplémentaire :
dotnet publish -c Release -r osx-arm64 --self-contained
À partir de là, les corvées macOS habituelles s’appliquent : envelopper la sortie publiée dans une
arborescence de bundle YourApp.app/Contents/MacOS avec un Info.plist et un .icns, puis la
signer avec codesign, et la faire notariser par Apple si vous distribuez en dehors de l’App Store.
Construisez un binaire universel en publiant osx-arm64 et osx-x64 et en les réunissant avec
lipo.
Vérifié sous macOS
L’exemple Explorer et la galerie de contrôles complète
tournent tous deux sous macOS, et la tête Uno de la galerie y a aussi été vérifiée :

Ensuite
- Démarrer — première application, depuis un modèle ou de zéro.
- Migrer une application WinForms existante — la réécriture automatisée.
- WinForms sous Linux — la même histoire sous Ubuntu, Fedora et Debian.
- WinForms multiplateforme — l’architecture et ses compromis.