<?xml version="1.0" encoding="utf-8"?>
<feed xmlns="http://www.w3.org/2005/Atom">
  <title>Majorsilence.Forms</title>
  <subtitle>Bibliothèque WinForms multiplateforme open source pour .NET — une couche de compatibilité Windows Forms qui exécute vos applications sous Windows, macOS, Linux et dans le navigateur, sans réécriture.</subtitle>
  <id>https://forms.majorsilence.com/fr/feed.xml</id>
  <link href="https://forms.majorsilence.com/fr/feed.xml" rel="self" type="application/atom+xml"/>
  <link href="https://forms.majorsilence.com/fr/" rel="alternate" type="text/html"/>
  <updated>2026-10-08T14:30:00+00:00</updated>
  <author><name>Majorsilence</name></author>
  <rights>MIT</rights>
  <entry>
    <title>Ce qui a atterri depuis août : 26.9.0, quatre nouveaux backends, thèmes CSS et l&apos;audit de comportement</title>
    <id>https://forms.majorsilence.com/fr/blog/2026/10/08/whats-new-since-august-26-9-0/</id>
    <link href="https://forms.majorsilence.com/fr/blog/2026/10/08/whats-new-since-august-26-9-0/" rel="alternate" type="text/html"/>
    <published>2026-10-08T14:30:00+00:00</published>
    <updated>2026-10-08T14:30:00+00:00</updated>
    <summary type="text">Majorsilence.Forms 26.9.0 : backends GTK 4, Terminal, WinForms et WPF, net48 et netstandard2.0, thèmes CSS, MVVM, l&apos;audit de comportement et les notes de mise à niveau.</summary>
    <content type="html">&lt;p&gt;Le dernier billet publié ici a été écrit à partir de la version 26.0.30. Depuis le 2026-08-17, ledépôt a reçu 557 commits et la version actuelle est &lt;strong&gt;26.9.0&lt;/strong&gt;. Voici un tour d’horizon pour lesutilisateurs existants et ceux qui évaluent le projet : ce qui a changé, le degré de maturité dechaque élément, et la seule chose que vous devez faire lors de la mise à niveau.&lt;/p&gt;&lt;h2 id=&quot;four-new-backends&quot;&gt;Quatre nouveaux backends&lt;/h2&gt;&lt;p&gt;Il y avait trois hôtes — Avalonia, Uno, Headless. Il y en a maintenant sept, qui exécutent tous lemême jeu de contrôles ; la différence tient à qui crée la fenêtre et présente la surface Skia.&lt;/p&gt;&lt;p&gt;&lt;strong&gt;GTK 4&lt;/strong&gt; (&lt;code&gt;Majorsilence.Forms.Gtk4&lt;/code&gt;) est un hôte pensé d’abord pour Linux, construit sur gir.core :une vraie &lt;code&gt;Gtk.Window&lt;/code&gt; par formulaire, la boucle principale GLib, utilisable aussi sous Windows etmacOS avec le runtime GTK 4. Sélectionnez-le explicitement avec &lt;code&gt;Gtk4Application.Use ();&lt;/code&gt; avant&lt;code&gt;Application.Run&lt;/code&gt;. L’intégration fonctionne dans les deux sens (&lt;code&gt;ToGtkWidget()&lt;/code&gt;, &lt;code&gt;ToGtkWindow()&lt;/code&gt;),&lt;code&gt;NativeControlHost&lt;/code&gt; n’a pas de problème d’« airspace » parce que GTK 4 compose un seul arbre de rendu,et &lt;code&gt;WebBrowser&lt;/code&gt; s’appuie sur WebKitGTK 6.0. Vérifié sous Wayland. Lacunes connues : pas de contrôlede la position à l’écran (GTK 4 a supprimé l’API), &lt;code&gt;SetIcon(byte[])&lt;/code&gt; est un no-op, les sélecteurs defichiers natifs renvoient un résultat vide et des boîtes de dialogue de repli sont donc utilisées,facteur d’échelle entier uniquement, non analysé pour l’AOT.&lt;/p&gt;&lt;p&gt;&lt;strong&gt;Terminal&lt;/strong&gt; (&lt;code&gt;Majorsilence.Forms.Terminal&lt;/code&gt;, 2026-10-04) héberge un formulaire dans une console envue unique — le formulaire remplit le terminal, sans barre de titre, comme sur un téléphone. Ilutilise le protocole graphique Kitty ou Sixel à la résolution réelle en pixels lorsque c’estdisponible, sinon des caractères de bloc Unicode ; la détection se fait en interrogeant le terminal,et &lt;code&gt;MF_TERMINAL_GRAPHICS=halfblock|kitty|sixel&lt;/code&gt; fige un mode. La souris et le clavier fonctionnent ;Ctrl+C quitte toujours. Sélectionné avec &lt;code&gt;TerminalApplication.Use (options);&lt;/code&gt;. Vérifié uniquementdans xterm et WezTerm. Pas de sélecteurs natifs, ni de &lt;code&gt;NativeControlHost&lt;/code&gt;, ni de webview.&lt;/p&gt;&lt;p&gt;&lt;strong&gt;WinForms&lt;/strong&gt; (&lt;code&gt;Majorsilence.Forms.WinForms&lt;/code&gt;) est un backend de &lt;em&gt;migration&lt;/em&gt; réservé à Windows : devraies fenêtres &lt;code&gt;System.Windows.Forms&lt;/code&gt; sur la pompe de messages Win32, Skia présenté via un bitmapGDI. Il existe pour que vous puissiez intégrer des contrôles Majorsilence.Forms dans une applicationWinForms existante, un contrôle à la fois — &lt;code&gt;myMfControl.ToWinFormsControl()&lt;/code&gt;,&lt;code&gt;myForm.ToWinFormsForm()&lt;/code&gt;, &lt;code&gt;MajorsilenceFormsPresenter&lt;/code&gt; — puis basculer l’hôte vers Avalonia ou Unoune fois que tout est porté. Pas de gestes, pas d’&lt;code&gt;IWebViewFactory&lt;/code&gt;. Il est distinct de l’ancien&lt;code&gt;WindowsFormsInterop&lt;/code&gt;, qui fait le pont pour des formulaires entiers sur l’hôte Avalonia.&lt;/p&gt;&lt;p&gt;&lt;strong&gt;WPF&lt;/strong&gt; (&lt;code&gt;Majorsilence.Forms.Wpf&lt;/code&gt;) a la même forme et le même objectif pour les applications WPF : unevraie &lt;code&gt;Window&lt;/code&gt; WPF, une présentation par &lt;code&gt;WriteableBitmap&lt;/code&gt;, &lt;code&gt;ToWpfElement()&lt;/code&gt; et &lt;code&gt;ToWpfWindow()&lt;/code&gt;.Sélectionnez-le avec &lt;code&gt;Platform.Backend = new Majorsilence.Forms.Wpf.WpfPlatformBackend ();&lt;/code&gt;.&lt;/p&gt;&lt;p&gt;Avalonia, WinForms et GTK 4 offrent de véritables boîtes de dialogue modales au niveau du système ;Uno ouvre une fenêtre indépendante, utilisez donc &lt;code&gt;Form.ShowDialog(parent)&lt;/code&gt; sur cet hôte.&lt;/p&gt;&lt;h2 id=&quot;net-framework-48-and-netstandard20&quot;&gt;.NET Framework 4.8 et netstandard2.0&lt;/h2&gt;&lt;p&gt;Les paquets cœur — &lt;code&gt;Majorsilence.Forms&lt;/code&gt;, &lt;code&gt;.Drawing.Common&lt;/code&gt;, &lt;code&gt;.Telerik&lt;/code&gt; — ciblent désormais à la fois&lt;code&gt;net8.0&lt;/code&gt;, &lt;code&gt;net10.0&lt;/code&gt; &lt;strong&gt;et &lt;code&gt;netstandard2.0&lt;/code&gt;&lt;/strong&gt;, et les backends WinForms et WPF ajoutent &lt;code&gt;net48&lt;/code&gt;. Uneapplication .NET Framework 4.8 peut donc héberger des contrôles Majorsilence.Forms sans passer d’abordà .NET moderne, ce qui supprime un problème d’ordonnancement que beaucoup de migrationsrencontraient.&lt;/p&gt;&lt;h2 id=&quot;the-behaviour-gap-audit&quot;&gt;L’audit des écarts de comportement&lt;/h2&gt;&lt;p&gt;Les deux plans de couverture de la surface d’API (WinForms et GDI+) sont à &lt;strong&gt;zéro&lt;/strong&gt; : chaque membreprésent en amont est déclaré. C’était de toute façon la moitié la moins intéressante. Un membre quiexiste mais stocke une valeur que personne ne lit, ou déclenche un événement que personne ne lève,compile votre application migrée puis ne fait discrètement rien.&lt;/p&gt;&lt;p&gt;Le 2026-08-25, un audit en douze domaines a donc comparé chaque domaine à l’implémentation en amont etconsigné &lt;strong&gt;483 constats&lt;/strong&gt; où le comportement différait. Depuis, les phases 0 à 4 et la plupart desfamilles de contrôles ont atterri. Éléments concrets désormais réels : la chaîne de prétraitement&lt;code&gt;ProcessCmdKey&lt;/code&gt;, un point de passage unique pour le focus et la validation, la barre de titre hors dela zone cliente, &lt;code&gt;AutoScaleMode.Font&lt;/code&gt; qui met réellement à l’échelle, la liaison de données vivante(&lt;code&gt;CurrencyManager&lt;/code&gt;, &lt;code&gt;BindingNavigator&lt;/code&gt;), &lt;code&gt;ListView.View = Details&lt;/code&gt;, le cycle de vie du formulairedans l’ordre en amont (Load → VisibleChanged → Activated, Shown posté), le réordonnancement descolonnes de DataGridView, Ctrl+Z dans les contrôles de texte, &lt;code&gt;NotifyIcon&lt;/code&gt; dans la zone denotification, &lt;code&gt;Application.AddMessageFilter&lt;/code&gt;, et la libération d’un formulaire qui libère sescontrôles.&lt;/p&gt;&lt;p&gt;La surface creuse est en outre &lt;em&gt;mesurée&lt;/em&gt; maintenant : des fichiers de référence figent les méthodesno-op connues, les événements inertes et les propriétés simplement stockées, de sorte qu’en ajouterrelève d’un acte conscient et non d’un accident. La politique des stubs est inchangée — no-op ouvaleur par défaut, jamais de &lt;code&gt;NotImplementedException&lt;/code&gt;.&lt;/p&gt;&lt;h2 id=&quot;logical-units-the-one-thing-you-must-do&quot;&gt;Unités logiques : la seule chose que vous devez faire&lt;/h2&gt;&lt;p&gt;Le 2026-10-01, &lt;code&gt;ClientRectangle&lt;/code&gt;, &lt;code&gt;ClientSize&lt;/code&gt; et le canvas de peinture (&lt;code&gt;OnPaint&lt;/code&gt;, &lt;code&gt;Paint&lt;/code&gt;,&lt;code&gt;e.ClipRectangle&lt;/code&gt;, &lt;code&gt;e.Canvas&lt;/code&gt;) sont passés en &lt;strong&gt;unités logiques&lt;/strong&gt;, à l’image de&lt;code&gt;Width&lt;/code&gt;/&lt;code&gt;Height&lt;/code&gt;/&lt;code&gt;Bounds&lt;/code&gt; et de &lt;code&gt;MouseEventArgs&lt;/code&gt;. Le framework met le canvas à l’échelle de l’affichagepour vous.&lt;/p&gt;&lt;p&gt;&lt;strong&gt;Si un contrôle personnalisé appelait &lt;code&gt;e.Graphics.ScaleTransform (e.Scaling, e.Scaling)&lt;/code&gt;,supprimez cet appel&lt;/strong&gt; — le dessin est maintenant mis à l’échelle deux fois. Les pixels physiquesrestent accessibles via la famille &lt;code&gt;Scaled*&lt;/code&gt; (&lt;code&gt;ScaledWidth&lt;/code&gt;, &lt;code&gt;ScaledBounds&lt;/code&gt;, …),&lt;code&gt;PaintEventArgs.Scaling&lt;/code&gt; et &lt;code&gt;LogicalToDeviceUnits&lt;/code&gt;. La seule exception concerne les événementsowner-draw (&lt;code&gt;DrawItem&lt;/code&gt;, &lt;code&gt;DrawNode&lt;/code&gt;, &lt;code&gt;CellPainting&lt;/code&gt;), qui vous transmettent toujours des bornes enpixels physiques. Exécutez vos tests avec &lt;code&gt;MF_HEADLESS_SCALE=2&lt;/code&gt; pour attraper tout ce qui dépend del’ancien comportement.&lt;/p&gt;&lt;h2 id=&quot;browser-and-mobile&quot;&gt;Navigateur et mobile&lt;/h2&gt;&lt;p&gt;Sur &lt;code&gt;net10.0-browser&lt;/code&gt;, &lt;code&gt;-android&lt;/code&gt; et &lt;code&gt;-ios&lt;/code&gt;, le backend Avalonia signale &lt;code&gt;CanRunModalLoop = false&lt;/code&gt;,et les appels bloquants — &lt;code&gt;Form.ShowDialog&lt;/code&gt;, &lt;code&gt;MessageBox.Show&lt;/code&gt;, les sélecteurs de fichiers,&lt;code&gt;TaskDialog.ShowDialog&lt;/code&gt;, &lt;code&gt;VbInteraction.MsgBox&lt;/code&gt;/&lt;code&gt;InputBox&lt;/code&gt;, &lt;code&gt;RadMessageBox.Show&lt;/code&gt; — lèvent désormaisune &lt;code&gt;PlatformNotSupportedException&lt;/code&gt; nommant leur jumeau asynchrone &lt;em&gt;avant&lt;/em&gt; que quoi que ce soit nesoit affiché, au lieu de se figer. Les formes asynchrones (&lt;code&gt;ShowDialogAsync&lt;/code&gt;, &lt;code&gt;MessageBox.ShowAsync&lt;/code&gt;,&lt;code&gt;FileDialog.ShowDialogAsync&lt;/code&gt;, …) fonctionnent sur tous les hôtes ; l’idiome est donc un gestionnaire&lt;code&gt;async void&lt;/code&gt; avec &lt;code&gt;await&lt;/code&gt;. Un analyseur Roslyn dans le paquet cœur les repère à l’avance — &lt;code&gt;MFB001&lt;/code&gt;appel modal bloquant, &lt;code&gt;MFB002&lt;/code&gt; attente synchrone sur une Task, &lt;code&gt;MFB003&lt;/code&gt; &lt;code&gt;Thread.Sleep&lt;/code&gt;, chacun avec uncorrectif de code — actif pour les TFM navigateur ou avec &lt;code&gt;majorsilence_forms.browser_target = true&lt;/code&gt;dans &lt;code&gt;.editorconfig&lt;/code&gt;.&lt;/p&gt;&lt;p&gt;La cible navigateur maintient aussi un &lt;strong&gt;DOM d’accessibilité&lt;/strong&gt; à côté du canvas : un élémenttransparent et traversé par les clics par contrôle, avec rôle ARIA, nom, état et bornes, construit àpartir de l’arbre d’automatisation propre au framework. Les lecteurs d’écran, la recherche dans lapage et les outils de test fondés sur le DOM peuvent désormais voir l’interface.&lt;/p&gt;&lt;p&gt;Sur Android et iOS, le clavier à l’écran apparaît quand une &lt;code&gt;TextBox&lt;/code&gt; prend le focus,&lt;code&gt;TextBoxBase.InputKind&lt;/code&gt; choisit le type de clavier, les marges de zone sûre s’appliquent via&lt;code&gt;Form.SafeAreaPadding&lt;/code&gt;, et &lt;code&gt;WindowBase.BackRequested&lt;/code&gt; gère le bouton Retour d’Android. État honnête :Android a eu une première passe sur appareil réel (démarrage, touchers, mise à l’échelle du rendu,défilement tactile confirmés sur matériel) ; le clavier, la zone sûre et la rotation ne sont couvertsque par des tests unitaires. La CI iOS compile la vraie tête et la lance dans un test de fumée sursimulateur, mais personne ne l’a exécutée de manière interactive et le job est toujours en&lt;code&gt;continue-on-error&lt;/code&gt;.&lt;/p&gt;&lt;p&gt;Des contrôles de disposition de type téléphone sont arrivés en même temps : &lt;code&gt;StackPanel&lt;/code&gt;, &lt;code&gt;Card&lt;/code&gt;,&lt;code&gt;RichListBox&lt;/code&gt; (lignes multilignes à modèle) et &lt;code&gt;NavigationHost&lt;/code&gt; (une pile de pages avec un boutonRetour).&lt;/p&gt;&lt;h2 id=&quot;css-theming-and-theme-studio&quot;&gt;Thèmes CSS et Theme Studio&lt;/h2&gt;&lt;p&gt;Les thèmes peuvent désormais s’écrire dans un sous-ensemble strict et documenté de CSS :&lt;code&gt;@theme &quot;Ocean&quot; extends Dark;&lt;/code&gt;, des jetons &lt;code&gt;:root&lt;/code&gt; à raison d’un par propriété de &lt;code&gt;Theme&lt;/code&gt;, des règlespar type de contrôle comme &lt;code&gt;Button:hover { … }&lt;/code&gt;, des parties via &lt;code&gt;Type::part&lt;/code&gt;. L’analyseur n’échouejamais en silence — &lt;code&gt;ThemeStyleSheet.Parse&lt;/code&gt; collecte des diagnostics. Chargez avec&lt;code&gt;Theme.LoadFromCssFile&lt;/code&gt;, ou &lt;code&gt;Theme.RegisterThemeCssFromFile&lt;/code&gt; + &lt;code&gt;Theme.ApplyTheme (&quot;Ocean&quot;)&lt;/code&gt; ; exportezavec &lt;code&gt;Theme.ExportCss&lt;/code&gt;. Chaque contrôle, y compris la couche de compatibilité Telerik, a un sélecteur,et l’ancien XML &lt;code&gt;&amp;lt;Theme&amp;gt;&lt;/code&gt; fonctionne toujours.&lt;/p&gt;&lt;p&gt;Deux paquets compagnons appliquent la &lt;em&gt;même&lt;/em&gt; feuille à d’autres hôtes : &lt;code&gt;Majorsilence.Forms.Theming.WinForms&lt;/code&gt;restyle de vrais contrôles &lt;code&gt;System.Windows.Forms&lt;/code&gt; (Windows uniquement) et &lt;code&gt;Majorsilence.Forms.Theming.Avalonia&lt;/code&gt;restyle les contrôles Fluent natifs d’Avalonia, si bien qu’un seul fichier CSS peut thémer uneapplication de migration mixte. &lt;code&gt;samples/ThemeStudio&lt;/code&gt; est un éditeur en direct avec aperçu etdiagnostics ; des binaires précompilés sont attachés aux GitHub Releases.&lt;/p&gt;&lt;h2 id=&quot;mvvm-essentials-animation&quot;&gt;MVVM, Essentials, animation&lt;/h2&gt;&lt;p&gt;&lt;code&gt;Majorsilence.Forms.Mvvm&lt;/code&gt; est un câblage compatible trimming et AOT au-dessus d’&lt;code&gt;INotifyPropertyChanged&lt;/code&gt;et d’&lt;code&gt;ICommand&lt;/code&gt;, sans réflexion ni dépendance à un toolkit : &lt;code&gt;viewModel.Observe (nameof (VM.Count), vm =&amp;gt; vm.Count, …)&lt;/code&gt;,des liaisons bidirectionnelles &lt;code&gt;BindText&lt;/code&gt;/&lt;code&gt;BindChecked&lt;/code&gt;/&lt;code&gt;BindSelectedIndex&lt;/code&gt;/&lt;code&gt;BindValue&lt;/code&gt;, &lt;code&gt;BindCommand&lt;/code&gt;,et un &lt;code&gt;BindingScope&lt;/code&gt; pour tout libérer. Il fonctionne aux côtés de CommunityToolkit.Mvvm.&lt;/p&gt;&lt;p&gt;&lt;code&gt;Majorsilence.Forms.Essentials&lt;/code&gt; garde les capacités propres à chaque plateforme hors du cœur :&lt;code&gt;SecureStorage&lt;/code&gt;, la synthèse vocale &lt;code&gt;Speech&lt;/code&gt;, &lt;code&gt;Launcher.OpenAsync&lt;/code&gt; (http/https/mailto/tel/sms) et&lt;code&gt;FileSystem.OpenAppPackageFileAsync&lt;/code&gt;. Tout se dégrade en no-op ; vérifiez &lt;code&gt;IsSupported&lt;/code&gt;.&lt;/p&gt;&lt;p&gt;&lt;code&gt;control.RequestAnimationFrame&lt;/code&gt; plus &lt;code&gt;Majorsilence.Forms.Animation&lt;/code&gt; (&lt;code&gt;Tween&amp;lt;T&amp;gt;&lt;/code&gt;, &lt;code&gt;Easing&lt;/code&gt;, &lt;code&gt;Animator&lt;/code&gt;)offrent une animation alignée sur l’affichage sous Avalonia et une horloge manuelle sous Headless.&lt;/p&gt;&lt;h2 id=&quot;tooling&quot;&gt;Outillage&lt;/h2&gt;&lt;ul&gt;  &lt;li&gt;Le serveur MCP est un outil dotnet publié : &lt;code&gt;dotnet tool install -g Majorsilence.Forms.Mcp&lt;/code&gt;, puis&lt;code&gt;claude mcp add majorsilence-ui -- majorsilence-mcp --port 4444&lt;/code&gt;. Il expose &lt;code&gt;ui_snapshot&lt;/code&gt;, &lt;code&gt;ui_find&lt;/code&gt;,&lt;code&gt;ui_click&lt;/code&gt;, &lt;code&gt;ui_type&lt;/code&gt;, &lt;code&gt;ui_wait_for&lt;/code&gt; et &lt;code&gt;ui_screenshot&lt;/code&gt;, en dialoguant avec le &lt;code&gt;WebDriverServer&lt;/code&gt; devotre application.&lt;/li&gt;  &lt;li&gt;&lt;code&gt;samples/AutomationTarget&lt;/code&gt; est une petite application volontairement récalcitrante (des contrôlesqui refusent les clics, un contrôle sans nom) pour apprendre l’outillage. Les contrôles à peinturepersonnalisée publient leur valeur et leur état via &lt;code&gt;IAutomationStateProvider&lt;/code&gt;.&lt;/li&gt;  &lt;li&gt;Le migrateur est désormais livré &lt;strong&gt;uniquement&lt;/strong&gt; sous forme d’outil dotnet(&lt;code&gt;dotnet tool install -g Majorsilence.Forms.Migrator&lt;/code&gt;) ; les binaires autonomes ne sont plus attachésaux releases. Nouvelles options : &lt;code&gt;--map&lt;/code&gt;, &lt;code&gt;--dual-build&lt;/code&gt;, &lt;code&gt;--strict&lt;/code&gt;, &lt;code&gt;--dry-run --diff&lt;/code&gt;.&lt;/li&gt;  &lt;li&gt;&lt;code&gt;Majorsilence.Forms.WinFormsShims.Compat&lt;/code&gt; est un générateur de source à l’état de preuve de conceptqui émet les espaces de noms &lt;code&gt;System.Windows.Forms&lt;/code&gt; et &lt;code&gt;System.Drawing&lt;/code&gt; adossés à Majorsilence.Forms,de sorte qu’un code source WinForms non modifié — y compris &lt;code&gt;Designer.cs&lt;/code&gt; — compile. Destiné auxbibliothèques de contrôles dont l’API publique est typée sur WinForms. Statut PoC ; voir&lt;code&gt;samples/WinFormsCompatDemo&lt;/code&gt;.&lt;/li&gt;&lt;/ul&gt;&lt;h2 id=&quot;upgrade-notes&quot;&gt;Notes de mise à niveau&lt;/h2&gt;&lt;ul&gt;  &lt;li&gt;Figez la version &lt;strong&gt;26.9.0&lt;/strong&gt;. Le projet est toujours en bêta et n’a toujours pas de concepteur visuel.&lt;/li&gt;  &lt;li&gt;Supprimez tout &lt;code&gt;ScaleTransform (e.Scaling, e.Scaling)&lt;/code&gt; dans votre code de peinture personnalisé(voir ci-dessus).&lt;/li&gt;  &lt;li&gt;L’identifiant du paquet de modèles est &lt;code&gt;Majorsilence.Forms.Templates&lt;/code&gt;, installé avec&lt;code&gt;dotnet new install Majorsilence.Forms.Templates&lt;/code&gt;. &lt;code&gt;dotnet new majorsilenceforms&lt;/code&gt; génère désormaisune solution avec une bibliothèque d’interface partagée et une tête bureau ; &lt;code&gt;--IncludeAndroid&lt;/code&gt;,&lt;code&gt;--IncludeiOS&lt;/code&gt; et &lt;code&gt;--IncludeWasm&lt;/code&gt; ajoutent des têtes.&lt;/li&gt;  &lt;li&gt;Les changements cassants sont listés dans &lt;code&gt;MIGRATION.md&lt;/code&gt; : &lt;code&gt;SplitContainer.Orientation&lt;/code&gt;,&lt;code&gt;TreeViewDrawMode.OwnerDrawContent&lt;/code&gt;, les types de délégués d’événements correspondent désormais àWinForms, et les pinceaux dégradés et hachurés ont été déplacés pour correspondre à GDI+.&lt;/li&gt;  &lt;li&gt;Sur navigateur, Android et iOS, remplacez les appels de boîtes de dialogue bloquants par leursjumeaux asynchrones ; laissez &lt;code&gt;MFB001&lt;/code&gt;–&lt;code&gt;MFB003&lt;/code&gt; les trouver.&lt;/li&gt;&lt;/ul&gt;&lt;h2 id=&quot;where-to-read-more&quot;&gt;Pour aller plus loin&lt;/h2&gt;&lt;ul&gt;  &lt;li&gt;&lt;a href=&quot;/fr/backends/&quot;&gt;Backends de plateforme&lt;/a&gt; et&lt;a href=&quot;https://github.com/majorsilence/Majorsilence.Forms/blob/main/docs/backends.md&quot;&gt;&lt;code&gt;docs/backends.md&lt;/code&gt;&lt;/a&gt;&lt;/li&gt;  &lt;li&gt;&lt;a href=&quot;/fr/getting-started/&quot;&gt;Premiers pas&lt;/a&gt; et&lt;a href=&quot;/fr/migration/&quot;&gt;Migration&lt;/a&gt; /&lt;a href=&quot;https://github.com/majorsilence/Majorsilence.Forms/blob/main/MIGRATION.md&quot;&gt;&lt;code&gt;MIGRATION.md&lt;/code&gt;&lt;/a&gt;&lt;/li&gt;  &lt;li&gt;&lt;a href=&quot;https://github.com/majorsilence/Majorsilence.Forms/blob/main/docs/theming.md&quot;&gt;&lt;code&gt;docs/theming.md&lt;/code&gt;&lt;/a&gt;,&lt;a href=&quot;https://github.com/majorsilence/Majorsilence.Forms/blob/main/docs/mvvm.md&quot;&gt;&lt;code&gt;docs/mvvm.md&lt;/code&gt;&lt;/a&gt;,&lt;a href=&quot;https://github.com/majorsilence/Majorsilence.Forms/blob/main/docs/mobile-layout.md&quot;&gt;&lt;code&gt;docs/mobile-layout.md&lt;/code&gt;&lt;/a&gt;,&lt;a href=&quot;https://github.com/majorsilence/Majorsilence.Forms/blob/main/docs/animation.md&quot;&gt;&lt;code&gt;docs/animation.md&lt;/code&gt;&lt;/a&gt;&lt;/li&gt;  &lt;li&gt;&lt;a href=&quot;https://github.com/majorsilence/Majorsilence.Forms/blob/main/docs/behaviour-gap-plan.md&quot;&gt;&lt;code&gt;docs/behaviour-gap-plan.md&lt;/code&gt;&lt;/a&gt;&lt;/li&gt;  &lt;li&gt;&lt;a href=&quot;/fr/automation/&quot;&gt;Automatisation&lt;/a&gt; et&lt;a href=&quot;https://github.com/majorsilence/Majorsilence.Forms/blob/main/docs/automation.md&quot;&gt;&lt;code&gt;docs/automation.md&lt;/code&gt;&lt;/a&gt;&lt;/li&gt;  &lt;li&gt;&lt;a href=&quot;/fr/samples/&quot;&gt;Exemples&lt;/a&gt;&lt;/li&gt;&lt;/ul&gt;</content>
    <author><name>Majorsilence</name></author>
  </entry>
  <entry>
    <title>Présentation de Majorsilence.Forms</title>
    <id>https://forms.majorsilence.com/fr/blog/2026/07/21/introducing-majorsilence-forms/</id>
    <link href="https://forms.majorsilence.com/fr/blog/2026/07/21/introducing-majorsilence-forms/" rel="alternate" type="text/html"/>
    <published>2026-07-21T15:00:00+00:00</published>
    <updated>2026-07-21T15:00:00+00:00</updated>
    <summary type="text">Présentation de Majorsilence.Forms, une bibliothèque WinForms multiplateforme open source pour .NET : conservez vos formulaires, vos contrôles et vos fichiers Designer, et exécutez la même application sous Windows, macOS et Linux sans réécriture.</summary>
    <content type="html">&lt;p&gt;Sortir une application WinForms du bureau Windows a toujours signifié, jusqu’ici, une réécriturecomplète : XAML, une restructuration MVVM imposée, ou le web. C’est coûteux, risqué, et cela jette desannées de logique métier et d’expérience utilisateur qui fonctionnent, pour un code qui n’a souventbesoin que d’un coup de peinture neuve.&lt;/p&gt;&lt;p&gt;&lt;strong&gt;Majorsilence.Forms&lt;/strong&gt; adopte une autre approche : il reproduit la surface d’API de WinForms — les&lt;code&gt;Form&lt;/code&gt;, les contrôles, les gestionnaires d’événements, et même le code-behind &lt;code&gt;*.Designer.cs&lt;/code&gt; — etfournit une couche de compatibilité pour que les formulaires et contrôles existants migrent avec bienmoins de remous. Le modèle de programmation ne change pas ; c’est l’endroit où il s’exécute qui change.&lt;/p&gt;&lt;h2 id=&quot;how-its-built&quot;&gt;Comment c’est construit&lt;/h2&gt;&lt;p&gt;Chaque contrôle est dessiné avec &lt;a href=&quot;https://github.com/mono/SkiaSharp&quot;&gt;SkiaSharp&lt;/a&gt; dans une &lt;code&gt;SKSurface&lt;/code&gt;,au-dessus d’un backend hôte interchangeable :&lt;/p&gt;&lt;ul&gt;  &lt;li&gt;&lt;strong&gt;Avalonia&lt;/strong&gt; (par défaut) — Windows, macOS et Linux pour le bureau, prêts à l’emploi, avec ses proprescibles Android, iOS et Browser (WebAssembly) comme voie vers le mobile et le web également.&lt;/li&gt;  &lt;li&gt;&lt;strong&gt;Uno Platform&lt;/strong&gt; — la portée la plus large : bureau, iOS, Android et WebAssembly.&lt;/li&gt;  &lt;li&gt;&lt;strong&gt;Headless&lt;/strong&gt; — rendu hors écran sans dépendance, pour la CI et les tests automatisés.&lt;/li&gt;&lt;/ul&gt;&lt;p&gt;L’assembly cœur &lt;code&gt;Majorsilence.Forms&lt;/code&gt; ne référence aucun toolkit de fenêtrage — uniquement SkiaSharp.Les backends sont des assemblies séparés qui se branchent sur deux petites interfaces,&lt;code&gt;IPlatformBackend&lt;/code&gt; et &lt;code&gt;IWindowBackend&lt;/code&gt;. C’est cette couture qui permet à la même application, àl’identique, de cibler Avalonia aujourd’hui et Uno demain sans toucher au code applicatif. Pour ensavoir plus, voir &lt;a href=&quot;/fr/backends/&quot;&gt;Backends de plateforme&lt;/a&gt;.&lt;/p&gt;&lt;h2 id=&quot;who-its-for&quot;&gt;À qui cela s’adresse&lt;/h2&gt;&lt;p&gt;Si vous disposez d’une base de code WinForms aujourd’hui limitée à Windows et que vous voulez garderl’élan — réutiliser vos contrôles, les réflexes de votre équipe, votre logique métier — plutôt que devous lancer dans une réécriture de plusieurs années, c’est pour vous que ceci a été conçu.&lt;/p&gt;&lt;p&gt;Le projet en est à ses débuts : l’API se stabilise et tous les recoins de WinForms ne sont pas encorecouverts. Il convient déjà très bien aux nouvelles applications métier multiplateformes, et à lamigration de vraies applications en production si vous figez la version. Consultez la&lt;a href=&quot;https://github.com/majorsilence/Majorsilence.Forms/blob/main/COMPATIBILITY_MATRIX.md&quot;&gt;matrice de compatibilité&lt;/a&gt; pour savoirexactement ce qui est implémenté et ce qui n’est encore qu’un stub aujourd’hui.&lt;/p&gt;&lt;h2 id=&quot;try-it&quot;&gt;Essayez-le&lt;/h2&gt;&lt;pre&gt;&lt;code&gt;dotnet new --install MajorsilenceForms.Templatesdotnet new majorsilenceformsdotnet run&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Ou plongez dans une vraie application — &lt;a href=&quot;https://github.com/majorsilence/Majorsilence.Forms/tree/main/samples/Explorer&quot;&gt;&lt;code&gt;samples/Explorer&lt;/code&gt;&lt;/a&gt;est un clone complet de l’Explorateur Windows, et &lt;a href=&quot;https://github.com/majorsilence/Majorsilence.Forms/tree/main/samples/Outlaw&quot;&gt;&lt;code&gt;samples/Outlaw&lt;/code&gt;&lt;/a&gt;un clone d’Outlook ; tous deux tournent sans modification sur le même jeu de contrôles, sur toutes lesplateformes.&lt;/p&gt;&lt;p&gt;Voir &lt;a href=&quot;/fr/getting-started/&quot;&gt;Premiers pas&lt;/a&gt; pour générer votre première application.&lt;/p&gt;</content>
    <author><name>Majorsilence</name></author>
  </entry>
  <entry>
    <title>Backends de plateforme : Avalonia, Uno et Headless</title>
    <id>https://forms.majorsilence.com/fr/blog/2026/07/21/platform-backends-avalonia-uno-headless/</id>
    <link href="https://forms.majorsilence.com/fr/blog/2026/07/21/platform-backends-avalonia-uno-headless/" rel="alternate" type="text/html"/>
    <published>2026-07-21T11:00:00+00:00</published>
    <updated>2026-07-21T11:00:00+00:00</updated>
    <summary type="text">Comment WinForms multiplateforme s&apos;exécute sur Avalonia, Uno Platform et une surface Skia headless : chaque contrôle est dessiné avec SkiaSharp et le toolkit de fenêtrage en dessous n&apos;est qu&apos;un hôte interchangeable.</summary>
    <content type="html">&lt;p&gt;Majorsilence.Forms effectue &lt;strong&gt;tout son dessin lui-même&lt;/strong&gt; avec SkiaSharp. Chaque contrôle peint dansune &lt;code&gt;SKSurface&lt;/code&gt;/&lt;code&gt;SKCanvas&lt;/code&gt; ; le toolkit de fenêtrage en dessous n’est qu’un &lt;em&gt;hôte&lt;/em&gt; — il crée lesfenêtres natives, fait tourner la boucle de messages, achemine les entrées et présente la surfaceSkia à l’écran. C’est cette séparation qui permet au même jeu de contrôles, à l’identique, de tourneraujourd’hui sur trois toolkits très différents.&lt;/p&gt;&lt;h2 id=&quot;the-seam&quot;&gt;La couture&lt;/h2&gt;&lt;p&gt;Deux interfaces définissent tout ce qu’un hôte doit fournir :&lt;/p&gt;&lt;p&gt;&lt;code&gt;IPlatformBackend&lt;/code&gt; couvre les services au niveau de l’application — le dispatcher (&lt;code&gt;Post&lt;/code&gt;/&lt;code&gt;Invoke&lt;/code&gt;),les timers, le presse-papiers, l’énumération des écrans et la boucle modale. &lt;code&gt;IWindowBackend&lt;/code&gt; couvreune seule fenêtre native — taille et position, afficher/masquer/fermer, curseur, décorations, boîtesde dialogue de fichiers. Les entrées et les demandes de peinture circulent dans &lt;em&gt;l’autre&lt;/em&gt; sens : lebackend appelle directement les méthodes neutres &lt;code&gt;RenderFrame(SKCanvas, …)&lt;/code&gt; et &lt;code&gt;Handle*&lt;/code&gt; de lafenêtre. Aucun type de plateforme — aucun type Avalonia, aucun type WinUI — ne franchit jamais lafrontière vers le code cœur de Majorsilence.Forms.&lt;/p&gt;&lt;h2 id=&quot;three-backends-today&quot;&gt;Trois backends aujourd’hui&lt;/h2&gt;&lt;p&gt;&lt;strong&gt;&lt;code&gt;Majorsilence.Forms.Avalonia&lt;/code&gt;&lt;/strong&gt; est le backend par défaut — Avalonia 12, qui donne Windows, macOS etLinux pour le bureau sans aucune configuration. Référencez-le, et &lt;code&gt;Application.Run(new MyForm())&lt;/code&gt;fonctionne tout simplement. Il ne se limite pas au bureau, d’ailleurs : Avalonia fournit ses proprescibles Android, iOS et Browser (WASM), si bien que ce même backend constitue une seconde voie vers lemobile et le web, à côté du backend Uno dédié présenté ci-dessous.&lt;/p&gt;&lt;p&gt;&lt;strong&gt;&lt;code&gt;Majorsilence.Forms.Headless&lt;/code&gt;&lt;/strong&gt; est le backend le plus simple possible et sert aussi de modèle deréférence pour en écrire un nouveau : une boucle de messages à file de travail, un presse-papiers enmémoire, un écran virtuel et un rendu hors écran. Il n’a besoin d’aucun affichage ; c’est donc sur luique tourne la suite de tests unitaires, et il peut rendre l’exemple ControlGallery directement en PNGpour la comparaison pixel par pixel en CI :&lt;/p&gt;&lt;pre&gt;&lt;code&gt;dotnet run --project samples/ControlGallery -- --render-headless out.png 1100 750 --select-row 0&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;&lt;strong&gt;&lt;code&gt;Majorsilence.Forms.Uno&lt;/code&gt;&lt;/strong&gt; cible le moteur de rendu Skia d’Uno Platform, héberge un &lt;code&gt;SKXamlCanvas&lt;/code&gt;et atteint le bureau, iOS, Android et WebAssembly. Il a été vérifié de bout en bout sous macOS : l’hôteUno se lance, le backend crée la fenêtre et le &lt;code&gt;MainForm&lt;/code&gt; complet de la ControlGallery se rend dans lecanvas. Comme il a besoin d’une session interactive, il s’exécute via une tête d’application dédiée —&lt;a href=&quot;https://github.com/majorsilence/Majorsilence.Forms/tree/main/samples/Gallery.Uno&quot;&gt;&lt;code&gt;samples/Gallery.Uno&lt;/code&gt;&lt;/a&gt; — plutôt que par labuild CI headless.&lt;/p&gt;&lt;p&gt;Un détail mérite d’être souligné : Uno n’a pas d’API programmatique « commencer un déplacement defenêtre », si bien que le déplacement et le redimensionnement du chrome de fenêtre auto-dessiné deMajorsilence.Forms sont gérés de manière déclarative — un presenter sans bordure conserve gratuitementles marges de redimensionnement du système, et le glisser de la barre de titre s’appuie sur l’API dezone de légende (caption region) de WinUI sur la tête bureau Windows. Sous macOS, ce sont lesdécorations natives qui prennent en charge le déplacement et le redimensionnement.&lt;/p&gt;&lt;h2 id=&quot;adding-your-own&quot;&gt;Ajouter le vôtre&lt;/h2&gt;&lt;p&gt;Un nouveau backend n’est qu’un assembly de plus : référencez le cœur &lt;code&gt;Majorsilence.Forms&lt;/code&gt; et votretoolkit, implémentez &lt;code&gt;IPlatformBackend&lt;/code&gt; et &lt;code&gt;IWindowBackend&lt;/code&gt;, et calquez-vous sur le trioAvalonia/Headless/Uno — pilotez le dispatcher dans le backend de plateforme, et présentez une surfaceSkia et traduisez les entrées dans le backend de fenêtre. Voir&lt;a href=&quot;/fr/backends/&quot;&gt;Backends de plateforme&lt;/a&gt; pour la liste complète des interfaces.&lt;/p&gt;</content>
    <author><name>Majorsilence</name></author>
  </entry>
  <entry>
    <title>Migrer une application WinForms avec majorsilence-migrate</title>
    <id>https://forms.majorsilence.com/fr/blog/2026/07/21/migrating-with-majorsilence-migrate/</id>
    <link href="https://forms.majorsilence.com/fr/blog/2026/07/21/migrating-with-majorsilence-migrate/" rel="alternate" type="text/html"/>
    <published>2026-07-21T08:00:00+00:00</published>
    <updated>2026-07-21T08:00:00+00:00</updated>
    <summary type="text">Comment majorsilence-migrate automatise la migration d&apos;une solution WinForms vers .NET multiplateforme — un réécriveur délibérément textuel qui traite des milliers de fichiers en quelques secondes, même ceux qui ne compilent pas actuellement.</summary>
    <content type="html">&lt;p&gt;&lt;code&gt;majorsilence-migrate&lt;/code&gt; est l’outil en ligne de commande qui automatise le passage d’une solutionWinForms vers Majorsilence.Forms. Sa décision de conception centrale passe facilement inaperçue etmérite d’être dite explicitement : il ne construit &lt;strong&gt;pas&lt;/strong&gt; d’arbre syntaxique et ne résout pas lessymboles. C’est un &lt;strong&gt;réécriveur textuel à base d’expressions régulières&lt;/strong&gt;, en plusieurs passes, sur letexte source brut — et c’est voulu.&lt;/p&gt;&lt;h2 id=&quot;why-textual-not-roslyn&quot;&gt;Pourquoi textuel, et non Roslyn&lt;/h2&gt;&lt;p&gt;Extrait du commentaire présent dans le code source de l’outil : &lt;em&gt;« Il s’agit d’une transformationdélibérément textuelle — elle n’analyse pas l’arbre syntaxique — ce qui la garde rapide et toléranteaux fichiers qui ne compilent pas actuellement. »&lt;/em&gt;&lt;/p&gt;&lt;p&gt;Ce compromis apporte deux choses qu’un outil conscient des symboles ne peut pas offrir :&lt;/p&gt;&lt;ul&gt;  &lt;li&gt;&lt;strong&gt;Il fonctionne sur du code cassé.&lt;/strong&gt; Une solution à moitié migrée, un fichier qui référence un typeque personne n’a encore porté, un projet avec une référence manquante — rien de tout cela n’arrêtele réécriveur, parce qu’il n’a jamais besoin que le code compile, ni même qu’il soit entièrementanalysable. Un outil fondé sur Roslyn, avec une vraie résolution de symboles, refuserait de toucherà un projet tant qu’il ne se construit pas, ce qui va à l’encontre d’une &lt;em&gt;première passe&lt;/em&gt; sur unebase de code héritée.&lt;/li&gt;  &lt;li&gt;&lt;strong&gt;Il est rapide.&lt;/strong&gt; Pas de compilation, pas de &lt;code&gt;MSBuildWorkspace&lt;/code&gt;, pas de chargement du graphe deprojets — il traite des milliers de fichiers en quelques secondes.&lt;/li&gt;&lt;/ul&gt;&lt;p&gt;Le prix à payer : pas de véritable résolution de symboles entre projets. Le réécriveur ne peut pastoujours savoir si une référence nue à &lt;code&gt;Panel&lt;/code&gt; désigne &lt;code&gt;System.Windows.Forms.Panel&lt;/code&gt; ou votre propreclasse du même nom — il s’appuie à la place sur le préfixe d’espace de noms et sur le contexte des&lt;code&gt;using&lt;/code&gt;/&lt;code&gt;Imports&lt;/code&gt;. En pratique, c’est rarement ambigu (les noms de types WinForms et Telerik sontreconnaissables), et tout ce qu’il ne reconnaît pas est signalé pour revue manuelle plutôt que devinéen silence.&lt;/p&gt;&lt;h2 id=&quot;the-optional-roslyn-engine&quot;&gt;Le moteur Roslyn optionnel&lt;/h2&gt;&lt;p&gt;Pour le cas réellement ambigu — un type personnalisé partageant un nom nu avec un type WinForms/GDI+dans le même fichier — il existe un second moteur, à activer explicitement : &lt;code&gt;--engine roslyn&lt;/code&gt;. Ilutilise &lt;code&gt;MSBuildWorkspace&lt;/code&gt; et une vraie résolution de symboles au lieu d’expressions régulières,&lt;em&gt;par-dessus&lt;/em&gt; le moteur textuel plutôt qu’à sa place ; plusieurs passes restent textuelles même en modeRoslyn, parce qu’elles n’ont jamais été des problèmes de résolution de symboles.&lt;/p&gt;&lt;p&gt;Les compromis sont à l’inverse de ceux du moteur par défaut : il lui faut une solution ou un projetqui se charge réellement via MSBuild (un simple répertoire ou un fichier isolé retombe sur le moteurtextuel avec un avertissement), il est plus lent de plusieurs ordres de grandeur parce quel’évaluation MSBuild domine l’exécution, et si un projet échoue à se charger, seuls les fichiers de ceprojet retombent sur le moteur textuel — l’exécution ne s’interrompt pas. Si MSBuild lui-même estintrouvable, l’exécution entière échoue franchement plutôt que de se dégrader en silence.&lt;/p&gt;&lt;p&gt;&lt;strong&gt;Quand y recourir :&lt;/strong&gt; après une première passe avec le moteur par défaut &lt;code&gt;--engine text&lt;/code&gt;, sur unprojet qui se charge déjà proprement, si vous constatez dans le diff un cas précis et confirmé decollision de noms. Pour la passe initiale sur une grande base de code héritée, éventuellement à moitiécassée, le moteur textuel par défaut reste le bon outil.&lt;/p&gt;&lt;h2 id=&quot;whats-next&quot;&gt;La suite&lt;/h2&gt;&lt;p&gt;Voir &lt;a href=&quot;https://github.com/majorsilence/Majorsilence.Forms/blob/main/MIGRATION.md&quot;&gt;&lt;code&gt;MIGRATION.md&lt;/code&gt;&lt;/a&gt; dans le dépôt pour le détailpasse par passe, et&lt;a href=&quot;https://github.com/majorsilence/Majorsilence.Forms/blob/main/COMPATIBILITY_MATRIX.md&quot;&gt;&lt;code&gt;COMPATIBILITY_MATRIX.md&lt;/code&gt;&lt;/a&gt; pour ce qui estréellement implémenté une fois que votre code migré compile.&lt;/p&gt;</content>
    <author><name>Majorsilence</name></author>
  </entry>
</feed>
