{"id":132347,"date":"2023-03-09T19:15:00","date_gmt":"2023-03-09T19:15:00","guid":{"rendered":"https:\/\/devblogs.microsoft.com\/dotnet\/?p=44695"},"modified":"2023-03-09T19:15:00","modified_gmt":"2023-03-09T19:15:00","slug":"whats-new-for-the-winforms-visual-basic-application-framework","status":"publish","type":"post","link":"https:\/\/sickgaming.net\/blog\/2023\/03\/09\/whats-new-for-the-winforms-visual-basic-application-framework\/","title":{"rendered":"What\u2019s new for the WinForms Visual Basic Application Framework"},"content":{"rendered":"<div class=\"row justify-content-center author-header\">\n<div class=\"col-md-4\">\n<div class=\"post-detail-avatar-section\">\n<div class=\"post-detail-avatar\"> <img loading=\"lazy\" decoding=\"async\" alt src=\"https:\/\/www.sickgaming.net\/blog\/wp-content\/uploads\/2023\/03\/whats-new-for-the-winforms-visual-basic-application-framework.jpg\" class=\"avatar avatar-58 photo avatar-default lazyload\" height=\"58\" width=\"58\"><\/div>\n<p>Klaus Loeffelmann<\/p>\n<\/div>\n<\/div>\n<div class=\"col-md-4\">\n<div class=\"post-detail-avatar-section\">\n<div class=\"post-detail-avatar\"> <img loading=\"lazy\" decoding=\"async\" width=\"58\" height=\"58\" src=\"https:\/\/www.sickgaming.net\/blog\/wp-content\/uploads\/2023\/03\/whats-new-for-the-winforms-visual-basic-application-framework-1.jpg\" class=\"avatar avatar-58 photo lazyload\" alt><\/div>\n<p>Melissa Trevino<\/p>\n<\/div>\n<\/div>\n<\/div>\n<div class=\"entry-meta entry-meta-layout\">\n<p> March 9th, 2023<span class=\"entry-meta-comment\"><a data-bi-name=\"jump-to-comments\" href=\"https:\/\/devblogs.microsoft.com\/dotnet\/update-to-winforms-vb-appframework\/#comments\" aria-label=\"click to comments\" title=\"Jump to comments\"><i class=\"fabric-icon fabric-icon--Message\"><\/i>3<\/a><\/span><span class=\"entry-meta-comment\"><span class=\"post-like\" id=\"postLike-44695\"><span class=\"icon-like-dislike\"><a class=\"x-hidden-focus\" aria-label=\"Login to like, vote count 4\" title=\"Login to like\" data-toggle=\"tooltip\" href=\"https:\/\/devblogs.microsoft.com\/dotnet\/wp-login.php?redirect_to=https%3A%2F%2Fdevblogs.microsoft.com%2Fdotnet%2Fupdate-to-winforms-vb-appframework%2F\" data-bi-id=\"body\" data-bi-name=\"Login to like\"><span> 4<\/span><\/a><\/span><\/span><\/span><\/p>\n<\/p><\/div>\n<p><!-- .entry-meta --> <\/p>\n<p>.NET from version .NET Core 3.1 up to .NET 7 has plenty of advantages over .NET<br \/>\nFramework: it provides performance improvements in almost every area, and those<br \/>\nimprovements were an ongoing effort over each .NET version. The<br \/>\nlatest improvements in <a href=\"https:\/\/devblogs.microsoft.com\/dotnet\/performance-improvements-in-net-6\/\">.NET<br \/>\n6<\/a> and<br \/>\n<a href=\"https:\/\/devblogs.microsoft.com\/dotnet\/performance_improvements_in_net_7\/\">.NET<br \/>\n7<\/a> are<br \/>\nreally worth checking out.<\/p>\n<p>Migrating your Windows Forms (WinForms) Visual Basic Apps to .NET 6\/7+ also<br \/>\nallows to adopt modern technologies which are not (or are no longer) supported in .NET<br \/>\nFramework. <a href=\"https:\/\/learn.microsoft.com\/ef\/core\/\">EFCore is one example<\/a>: it is<br \/>\na modern Entity Framework data access technology that enables .NET developers to<br \/>\nwork with database backends using .NET objects. Although it is not natively<br \/>\nsupported for VB by Microsoft, it is designed in a way that it is easy for the<br \/>\ncommunity to build up on it and provide <a href=\"https:\/\/github.com\/efcore\/EFCore.VisualBasic\">code generation support for additional<br \/>\nlanguages like Visual Basic<\/a>. In<br \/>\nthat context there are also changes and improvements in the new WinForms<br \/>\nOut-of-Process Designer for .NET, <a href=\"https:\/\/devblogs.microsoft.com\/dotnet\/databinding-with-the-oop-windows-forms-designer\/\">especially around Object Data<br \/>\nSources<\/a>.<br \/>\nFor the WinForms .NET runtime, there are a series of improvements in different<br \/>\nareas which have been introduced with the latest releases of .NET:<\/p>\n<h2 id=\"the-new-visual-basic-application-framework-experience\">The new Visual Basic Application Framework Experience<\/h2>\n<p>In contrast to the project property Application Framework Designer experience in<br \/>\nearlier versions of Visual Studio and for .NET Framework, you will noticed that<br \/>\nthe project properties UI in Visual Studio has changed. It\u2019s style is now in<br \/>\nparity with the project properties experience for other .NET project types: we<br \/>\nhave invested into modernizing the experience for developers, focusing on<br \/>\nenhancing productivity and a modern look and feel.<\/p>\n<p><img decoding=\"async\" src=\"https:\/\/www.sickgaming.net\/blog\/wp-content\/uploads\/2023\/03\/whats-new-for-the-winforms-visual-basic-application-framework.png\" alt=\"Screenshot of the new Visual Basic Application Framework project settings designer.\"><\/p>\n<p>We\u2019ve added theming and search to the new experience. If this is your first time<br \/>\nyou\u2019re working with the new project properties experience in Visual Studio, it\u2019s<br \/>\na good idea to read up on the <a href=\"https:\/\/devblogs.microsoft.com\/visualstudio\/revamped-project-properties-ui\/\">the introductory<br \/>\nblog<\/a>.<\/p>\n<p>In contrast to C# projects, Visual Basic Application Framework projects use a<br \/>\nspecial file for storing the Application Framework project settings: the<br \/>\n<em>Application.myapp<\/em> file. We\u2019ll talk more about the technical details of how<br \/>\nthis file connects the project settings to the VB project specific code<br \/>\ngeneration of the <code>My<\/code> namespace later, but one thing to keep in mind is how the<br \/>\nUI translates each property\u2019s value to this file:<\/p>\n<ul>\n<li>\n<p><strong>Windows Visual Styles<\/strong> is to determine if the application will use the most<br \/>\ncurrent version for the Control Library <em>comctl.dll<\/em> to provide control<br \/>\nrendering with modern visual styling. This setting translates to the value<br \/>\n<code>EnableVisualStyles<\/code> of type <code>Boolean<\/code> inside of <em>Application.myapp<\/em>.<\/p>\n<\/li>\n<li>\n<p><strong>Single-instance application<\/strong> is to determine if the application will prevent<br \/>\nusers from running multiple instances of the application. This setting is<br \/>\nswitched off by default, which allows multiple instances of the application to<br \/>\nbe run concurrently. This setting translates to the value <code>SingleInstance<\/code> of<br \/>\ntype <code>Boolean<\/code>.<\/p>\n<\/li>\n<li>\n<p><strong>Save user settings on exit<\/strong> is to determine if the application settings are<br \/>\nautomatically saved when an app is about to shut down. The settings can be<br \/>\nchanged with the settings editor. In contrast to .NET Framework, a new Visual<br \/>\nBasic Application Framework App doesn\u2019t contain a settings file by default,<br \/>\nbut you can easily insert one over the project properties, should you need<br \/>\none, and then <a href=\"https:\/\/learn.microsoft.com\/visualstudio\/ide\/managing-application-settings-dotnet?view=vs-2022\">manage the settings<br \/>\ninteractively<\/a>.<\/p>\n<p><img decoding=\"async\" src=\"https:\/\/www.sickgaming.net\/blog\/wp-content\/uploads\/2023\/03\/whats-new-for-the-winforms-visual-basic-application-framework-1.png\" alt=\"Screenshot of the Settings section in the Application Framework project's property pages\"><\/p>\n<p>Adding to the list of settings automatically generates respective code, which<br \/>\ncan be easily access over the <a href=\"https:\/\/learn.microsoft.com\/dotnet\/visual-basic\/language-reference\/objects\/my-settings-object\"><code>My<\/code> object in the Visual Basic Application<br \/>\nFramework at<br \/>\nruntime<\/a>.<br \/>\nThis settings translates to the value <code>SaveMySettingsOnExit<\/code> of type<br \/>\n<code>Boolean<\/code>.<\/p>\n<\/li>\n<li>\n<p><strong>High DPI mode<\/strong> is to identify the application-wide HighDpiMode for the<br \/>\napplication. Note that this setting can be programmatically overridden through<br \/>\nthe <a href=\"https:\/\/learn.microsoft.com\/dotnet\/api\/microsoft.visualbasic.applicationservices.applyapplicationdefaultseventargs.highdpimode?view=windowsdesktop-7.0\"><code>HighDpiMode<\/code><br \/>\nproperty<\/a><br \/>\nof the <code>ApplyApplicationDefaultsEventArgs<\/code> of the <a href=\"https:\/\/learn.microsoft.com\/dotnet\/api\/microsoft.visualbasic.applicationservices.windowsformsapplicationbase.applyapplicationdefaults?view=windowsdesktop-7.0\"><code>ApplyApplicationDefaults<\/code><\/a><br \/>\napplication event. Choose from the following setting:<\/p>\n<ul>\n<li><strong>DPI unaware (0):<\/strong> The application window does not scale for DPI changes and<br \/>\nalways assumes a scale factor of 100%. For higher resolutions, this will<br \/>\nmake text and fine drawings more blurry, but may impose the best setting for<br \/>\nsome apps which demand a high backwards compatibility in rendering content.<\/li>\n<li><strong>DPI unaware GDI scaled (4):<\/strong> similar to DPI unaware, but improves the<br \/>\nquality of GDI\/GDI+ based on content. Please note that this mode will <em>not<\/em><br \/>\nwork as expected, when you have enabled <a href=\"https:\/\/learn.microsoft.com\/dotnet\/api\/system.windows.forms.control.doublebuffered?view=windowsdesktop-7.0\">double<br \/>\nbuffering<\/a><br \/>\nfor control rendering via <a href=\"https:\/\/learn.microsoft.com\/dotnet\/api\/system.windows.forms.control.onpaint?view=windowsdesktop-7.0\"><code>OnPaint<\/code><\/a> and related functionality.<\/li>\n<li><strong>Per monitor (2):<\/strong> Per-Monitor DPI allows individual displays to have their<br \/>\nown DPI scaling setting. WinForms doesn\u2019t optimize for this mode, and<br \/>\nPer-Monitor V2 should be used instead.<\/li>\n<li><strong>Per monitor V2 (3):<\/strong> Per-Monitor V2 offers more advanced scaling features<br \/>\nsuch as improved support for mixed DPI environments, improved display<br \/>\nenumeration, and support for dynamically scaling on-client area of windows.<br \/>\nIn WinForms common controls are optimized for this high dpi mode. Please<br \/>\nnote the events<br \/>\n<a href=\"https:\/\/learn.microsoft.com\/dotnet\/api\/system.windows.forms.form.dpichanged?view=windowsdesktop-7.0\">Form.DpiChange<\/a>,<br \/>\n<a href=\"https:\/\/learn.microsoft.com\/dotnet\/api\/system.windows.forms.control.dpichangedafterparent?view=windowsdesktop-7.0\">Control.DpiChangedAfterParent<\/a><br \/>\nand<br \/>\n<a href=\"https:\/\/learn.microsoft.com\/dotnet\/api\/system.windows.forms.control.dpichangedbeforeparent?view=windowsdesktop-7.0\">Control.DpiChangeBeforeParent<\/a>,<br \/>\nwhen your app need to scale up or down content based on a changed DPI<br \/>\nenvironment, for example, when the user of your app has dragged a Form from<br \/>\none monitor to another monitor with a different DPI setting.<\/li>\n<li><strong>System aware (1):<\/strong> The application queries for the DPI of the primary<br \/>\nmonitor once and uses this for the application on all monitors. When content<br \/>\nin Forms is dragged from one monitor to another with a different HighDPI<br \/>\nsetting, content might become blurry. SystemAware is WinForm\u2019s most<br \/>\ncompatible high-dpi rendering mode for all supported controls.<\/li>\n<\/ul>\n<\/li>\n<li>\n<p><strong>Authentication mode<\/strong> is to specify the method of identifying the logged-on<br \/>\nuser, when needed. The setting translates to the value <code>AuthenticationMode<\/code> as<br \/>\nan enum value of type <code>Integer<\/code>:<\/p>\n<ul>\n<li>0: The <code>WindowsFormsApplicationBase(AuthenticationMode)<\/code> constructor does<br \/>\nnot automatically initialize the principal for the application\u2019s main<br \/>\nthread. It\u2019s completely the developer\u2019s task, to manage authentication for<br \/>\nthe user.<\/li>\n<li>1: The <code>WindowsFormsApplicationBase(AuthenticationMode)<\/code> constructor<br \/>\ninitializes the principal for the application\u2019s main thread with the current<br \/>\nuser\u2019s Windows user info.<\/li>\n<\/ul>\n<\/li>\n<li>\n<p><strong>Shutdown mode<\/strong> is to to indicate which condition causes the application to<br \/>\nshut down. This setting translates to the value <code>ShutdownMode<\/code> as an enum<br \/>\nvalue of type <code>Integer<\/code> (Note: Please also refer to the application event<br \/>\n<a href=\"https:\/\/learn.microsoft.com\/dotnet\/api\/microsoft.visualbasic.applicationservices.windowsformsapplicationbase.shutdown?view=windowsdesktop-7.0\">ShutDown<\/a><br \/>\nand the further remarks down below.):<\/p>\n<ul>\n<li>0: When the main form closes.<\/li>\n<li>1: Only after the last form closes.<\/li>\n<\/ul>\n<\/li>\n<li>\n<p><strong>Splash screen<\/strong> represents the name of the form to be used as a splash screen<br \/>\nfor the application. Note that the file name does not need to include the<br \/>\nextension (.vb). This setting translates to the value <code>SplashScreen<\/code> of type<br \/>\n<code>String<\/code>.<\/p>\n<blockquote>\n<p><strong>Note:<\/strong> you will may be missing the settings for the Splash dialog up to<br \/>\nVisual Studio 2022 version 17.5. For a workaround, read the comments in<br \/>\nthe section \u201cA look behind the scenes\u201d. To recap: a \u201cSplash\u201d dialog is<br \/>\ntypically displayed for a few seconds when an application is launched.<br \/>\nVisual Basic has an item template which you can use to add a basic splash<br \/>\ndialog to your project. It usually displays the logo or name of the<br \/>\napplication, along with some kind of animation or visual effects, to give<br \/>\nusers the impression that the application is loading or initializing. The<br \/>\nterm \u201csplash\u201d in this context is used because the dialog is designed to<br \/>\ncreate a splash or impact on the user, drawing their attention to the<br \/>\napplication while it loads.<\/p>\n<\/blockquote>\n<\/li>\n<li>\n<p><strong>Application Framework<\/strong> is saved both in the <em>Application.myapp<\/em> file and the<br \/>\n<em>.vbproj<\/em> file:<\/p>\n<ul>\n<li><em>Application.myapp<\/em> saves the setting <code>MySubMain<\/code> of type <code>Boolean<\/code> to<br \/>\nidentify if the Application Framework is enabled.<\/li>\n<li><em>.vbproj<\/em> uses the setting <code>MyType<\/code> for identifying the usage of the<br \/>\nApplication Framework for a VB project. If the Application Framework is<br \/>\nenabled, the value is <em>WindowsForms<\/em>; if the Application Framework is<br \/>\ndisabled, the value is <em>WindowsFormsWithCustomSubMain<\/em>.<\/li>\n<\/ul>\n<\/li>\n<li>\n<p><strong>Startup object<\/strong> is the name of the form that will be used as the entry<br \/>\npoint, without its filename extension. Note: this property is found in the<br \/>\nproject property Settings under the <em>General<\/em> section, and not in the<br \/>\nApplication Framework section. This setting translates to the value <code>MainForm<\/code> of type<br \/>\n<code>String<\/code>, when the Application Framework is activated. The start object setting in<br \/>\nthe <em>.vbproj<\/em> file is ignored in that case \u2013 see also the comments below on this<br \/>\ntopic.<\/p>\n<\/li>\n<\/ul>\n<h3 id=\"custom-constants-new-look\">Custom constants new look<\/h3>\n<p><img decoding=\"async\" src=\"https:\/\/www.sickgaming.net\/blog\/wp-content\/uploads\/2023\/03\/whats-new-for-the-winforms-visual-basic-application-framework-2.png\" alt=\"Screenshot of the new custom constants editor in the project properties UI.\"><\/p>\n<p>We are introducing a new custom constants-control in the modernized Project<br \/>\nProperty Pages for VB Projects, that allows to encode the input to the format<br \/>\nkey=\u201dvalue\u201d. Our goal is that users will be able to input their custom constants<br \/>\nin a more streamlined key-value pair format, thus enhancing their productivity.<br \/>\nFeedback is welcomed \u2013 if you have any comments or suggestions, feel free to<br \/>\nreach out to the <a href=\"https:\/\/github.com\/dotnet\/project-system\/\">project system<br \/>\nteam<\/a> by filing a new issue or<br \/>\ncomment on existing ones.<\/p>\n<h2 id=\"a-look-behind-the-scenes-of-the-winforms-vb-application-framework\">A look behind the scenes of the WinForms VB Application Framework<\/h2>\n<p>The way basic properties and behaviors of a WinForms app are controlled and configured is fundamentally different between C# and Visual Basic. In C#, every app<br \/>\nstarts with a static method called <code>main<\/code> which can usually be found in a file<br \/>\ncalled <em>Program.cs<\/em>, and in that <code>main<\/code> method all the setting get applied.<\/p>\n<p>That is different in Visual Basic. Since VB Apps in WinForms are based on the<br \/>\nApplication Framework runtime, there are a few features, which aren\u2019t<br \/>\nintrinsically available to C# WinForms apps to begin with, like configuring to<br \/>\nautomatically show Splash dialogs (see below) or ensure a single instance<br \/>\napplication start. Since you configure most of the parts of your app<br \/>\ninteractively in VB with the settings described above at design time, the actual<br \/>\ncode which honors or ensures those settings later at runtime is mostly<br \/>\ncode-generated and somewhat hidden behind the scenes. The starting point of a VB<br \/>\napp is therefore not so obvious. There are also a series of differences in .NET<br \/>\nVisual Basic apps when it comes to hooking up event code which is supposed to<br \/>\nrun, for example when a VB WinForms app starts, ends, or runs into an unhandled<br \/>\nexception \u2013 just to name a few examples.<\/p>\n<p>That all said, technically Visual Basic doesn\u2019t break any fundamental rules.<br \/>\nUnder the hood, there is of course a <code>Shared Sub Main<\/code> when you activate the<br \/>\nApplication Framework. You just do not write it yourself, and you don\u2019t see it,<br \/>\nbecause it is generated by the VB compiler and then automatically added to your<br \/>\nStart Form. This is done by activating the VB compiler switch<br \/>\n<a href=\"https:\/\/learn.microsoft.com\/dotnet\/visual-basic\/reference\/command-line-compiler\/main\"><code>\/main<\/code><\/a>.<\/p>\n<p>At the same time, when you are activating the Application Framework, a series of<br \/>\nconditional compiler constants are defined. One of the constants is called<br \/>\n<code>_mytype<\/code>. If that constant is defined as <code>Windows<\/code> then the VB compiler<br \/>\ngenerates all the necessary infrastructure code to support the Application<br \/>\nFramework. If that constant is defined as <code>WindowsFormsWithCustomSubMain<\/code><br \/>\nhowever, the VB compiler just generates the bare minimum infrastructure code and<br \/>\ndoesn\u2019t apply any settings to the WinForms app on startup. The latter happens,<br \/>\nwhen you deactivate the Application Framework. This setting is stored in the<br \/>\n<em>vbproj<\/em> project file, along with the Start Form. What\u2019s important to know<br \/>\nthough in this context: only in the case of <code>WindowsFormsWithCustomSubMain<\/code>, so<br \/>\nwith the Application Framework <em>deactivated<\/em>, is the Start Form definition<br \/>\nactually taken from the <em>vbproj<\/em> file. When the Application Framework <em>is<\/em><br \/>\nactivated however then that is the case when the aforementioned<br \/>\n<em>Application.myapp<\/em> file is used as the settings container. Note, that by<br \/>\ndefault you cannot find that file in the solution explorer.<\/p>\n<p><img decoding=\"async\" src=\"https:\/\/www.sickgaming.net\/blog\/wp-content\/uploads\/2023\/03\/whats-new-for-the-winforms-visual-basic-application-framework-3.png\" alt=\"Screenshot of solution explorer showing the Application.myapp file.\"><\/p>\n<p>You need to make sure first to show <em>all files<\/em> for that project (see screenshot<br \/>\nabove). Then you can open the <em>My Project<\/em>-folder and show that setting file in<br \/>\nthe editor by double-clicking it in the solution explorer. The content of that<br \/>\nfile looks something like this:<\/p>\n<pre><code class=\"language-xml\">&lt;?xml version=\"1.0\" encoding=\"utf-16\"?&gt;\n&lt;MyApplicationData xmlns:xsi=\"http:\/\/www.w3.org\/2001\/XMLSchema-instance\" xmlns:xsd=\"http:\/\/www.w3.org\/2001\/XMLSchema\"&gt; &lt;MySubMain&gt;true&lt;\/MySubMain&gt; &lt;MainForm&gt;Form1&lt;\/MainForm&gt; &lt;SingleInstance&gt;false&lt;\/SingleInstance&gt; &lt;ShutdownMode&gt;0&lt;\/ShutdownMode&gt; &lt;EnableVisualStyles&gt;true&lt;\/EnableVisualStyles&gt; &lt;AuthenticationMode&gt;0&lt;\/AuthenticationMode&gt; &lt;SaveMySettingsOnExit&gt;true&lt;\/SaveMySettingsOnExit&gt; &lt;HighDpiMode&gt;3&lt;\/HighDpiMode&gt;\n&lt;\/MyApplicationData&gt;<\/code><\/pre>\n<p><strong>Note:<\/strong> Visual Studio 2022 before version 17.6 (Preview 3) won\u2019t have the<br \/>\noption to pick a Splash Dialog interactively, as mentioned above. We will have<br \/>\nan interactive designer for setting the splash form only from that version on<br \/>\non. Up to then, you can manually patch the <em>Application.myapp<\/em> file to trigger<br \/>\nthe code generation for the Splash dialog. Insert the following line of code in<br \/>\nthat file and save the changes.<\/p>\n<pre><code class=\"language-xml\">&lt;SplashScreen&gt;SplashDialog&lt;\/SplashScreen&gt;<\/code><\/pre>\n<p>When you do this, make sure <em>not<\/em> to include the filename extension (.vb) in<br \/>\nthat definition, because otherwise the required code does not get generated.<\/p>\n<h3 id=\"application-myapp-as-the-source-for-code-generation\">Application.myapp as the source for code generation<\/h3>\n<p>Now, if you take a closer look at that file\u2019s properties in the property<br \/>\nbrowser, you\u2019ll see that it is triggering a custom tool which is invoked<br \/>\nwhenever that file is saved. <\/p>\n<p><img decoding=\"async\" src=\"https:\/\/www.sickgaming.net\/blog\/wp-content\/uploads\/2023\/03\/whats-new-for-the-winforms-visual-basic-application-framework-4.png\" alt=\"Screenshot of solution explorer showing the properties for the Application.myapp file.\"><\/p>\n<p>And that custom tool generates VB code which you<br \/>\ncan find under the <em>Application.myapp<\/em> node in the Solution Explorer in<br \/>\n<em>Application.Designer.vb<\/em>. It does the following:<\/p>\n<ul>\n<li>It defines a <code>Friend Partial Class MyApplication<\/code>. With the Application<br \/>\nFramework enabled, that class is inherited from<br \/>\n<a href=\"https:\/\/learn.microsoft.com\/dotnet\/api\/microsoft.visualbasic.applicationservices.windowsformsapplicationbase?view=windowsdesktop-7.0\"><code>WindowsFormsApplicationBase<\/code><\/a>.<br \/>\nYou don\u2019t see that <code>Inherits<\/code> statement here and the reason is that <a href=\"https:\/\/github.com\/dotnet\/roslyn\/blob\/main\/src\/Compilers\/VisualBasic\/Portable\/Symbols\/EmbeddedSymbols\/VbMyTemplateText.vb\">the major<br \/>\npart of that Class\u2019<br \/>\ndefinition<\/a><br \/>\nis injected by the Visual Basic compiler based on the earlier defined<br \/>\nconditional constant <code>_myapp<\/code>.<\/li>\n<li>It generates the code to apply all the settings which were saved in<br \/>\n<em>Application.myapp<\/em> file.<\/li>\n<li>It creates code for a method which overrides<br \/>\n<a href=\"https:\/\/learn.microsoft.com\/dotnet\/api\/microsoft.visualbasic.applicationservices.windowsformsapplicationbase.oncreatemainform?view=windowsdesktop-7.0\"><code>OnCreateMainForm<\/code><\/a>.<br \/>\nIn that method, it assigns the Form, which is defined as the start form in the<br \/>\n<em>Application.myapp<\/em> file.<\/li>\n<\/ul>\n<blockquote>\n<p><strong>Warning<\/strong>: The <em>Application.Designer.vb<\/em> is not supposed to be edited, as it\u2019s<br \/>\nauto-generated. Any changes will be lost as soon as you make changes to <em>Application.myapp<\/em>. Instead, use the project properties UI.<\/p>\n<\/blockquote>\n<p>Now, the class which is injected by the compiler is also responsible for<br \/>\ngenerating everything which the Visual Basic Application Framework provides you<br \/>\nvia the <code>My<\/code> namespace. The <code>My<\/code> namespace simplifies access to frequently used<br \/>\ninformation about your WinForms app, your system, or simplifies access to<br \/>\nfrequently used APIs. Part of the <code>My<\/code> namespace for an activated Application<br \/>\nFramework is the <code>Application<\/code> property, and its return type is of exactly that<br \/>\ntype which is defined by the class generated based on your Application Settings<br \/>\nand then merged with the injected Visual Basic compiler file mentioned earlier.<br \/>\nSo, if you access <code>My.Application<\/code> you are basically accessing a single instance<br \/>\nof the <code>My.MyApplication<\/code> type which the generated code defines.<\/p>\n<p>With this context understood, we can move on to how two additional features of<br \/>\nthe Application Framework work and can be approached. The first one is extending<br \/>\nthe <code>My<\/code> namespace with additional function areas. We won\u2019t go too much into<br \/>\nthem, because there are <a href=\"https:\/\/learn.microsoft.com\/dotnet\/visual-basic\/developing-apps\/customizing-extending-my\/extending-the-my-namespace\">detailed docs about the <code>My<\/code> namespace and how to<br \/>\nextend<br \/>\nit<\/a>.<\/p>\n<p>An even more important concept to understand are the Application Events which are<br \/>\nprovided by the Application Framework. Since there isn\u2019t a good way to intercept<br \/>\nthe startup or shut down of an app (since that code gets generated<br \/>\nand sort of hidden inside the main Form) Application Events are the way to be<br \/>\nnotified of certain application-global occurrences. <\/p>\n<p>Note in this context, that there is a small breaking change in the UI: while in<br \/>\n.NET Framework, you had to insert a code file named <em>ApplicationEvents.vb<\/em> via<br \/>\nthe Property Settings of the VB project, in a .NET Core App this file will be<br \/>\nthere from the start when you\u2019ve created a new Application Framework project.<\/p>\n<p>To wire up the available Application events, you open that <em>ApplicationEvent.vb<\/em><br \/>\ncode file, and then you select ApplicationEvents from the Object drop-down list,<br \/>\nand the application event you want to write up from the events list:<\/p>\n<p><img decoding=\"async\" src=\"https:\/\/www.sickgaming.net\/blog\/wp-content\/uploads\/2023\/03\/whats-new-for-the-winforms-visual-basic-application-framework.gif\" alt=\"Animated gif showing how to wire app Application Events in the ApplicationEvent.vb code file\"><\/p>\n<p>As you can see, the <em>ApplicationEvent.vb<\/em> code file again extends the <code>MyApplication<\/code> class \u2013 this time by the events handler you place there on demand. The options you have here are:<\/p>\n<ul>\n<li><a href=\"https:\/\/learn.microsoft.com\/dotnet\/api\/microsoft.visualbasic.applicationservices.windowsformsapplicationbase.startup?view=windowsdesktop-7.0\"><strong><code>Startup<\/code><\/strong><\/a>: raised when the application starts, before the start form is created.<\/li>\n<li><a href=\"https:\/\/learn.microsoft.com\/dotnet\/api\/microsoft.visualbasic.applicationservices.windowsformsapplicationbase.shutdown?view=windowsdesktop-7.0\"><strong><code>Shutdown<\/code><\/strong><\/a>: raised after all application forms are closed. This event is not raised if the application terminates abnormally.<\/li>\n<li><a href=\"https:\/\/learn.microsoft.com\/dotnet\/api\/microsoft.visualbasic.applicationservices.windowsformsapplicationbase.unhandledexception?view=windowsdesktop-7.0\"><strong><code>UnhandledException<\/code><\/strong><\/a>: raised if the application encounters an unhandled exception.<\/li>\n<li><a href=\"https:\/\/learn.microsoft.com\/dotnet\/api\/microsoft.visualbasic.applicationservices.windowsformsapplicationbase.startupnextinstance?view=windowsdesktop-7.0\"><strong><code>StartupNextInstance<\/code><\/strong><\/a>: raised when launching a single-instance application and the application is already active.<\/li>\n<li><a href=\"https:\/\/learn.microsoft.com\/dotnet\/api\/microsoft.visualbasic.applicationservices.windowsformsapplicationbase.networkavailabilitychanged?view=windowsdesktop-7.0\"><strong><code>NetworkAvailabilityChanged<\/code><\/strong><\/a>: raised when the network connection is connected or disconnected.<\/li>\n<li><a href=\"https:\/\/learn.microsoft.com\/dotnet\/api\/microsoft.visualbasic.applicationservices.windowsformsapplicationbase.applyapplicationdefaults?view=windowsdesktop-7.0\"><strong><code>ApplyApplicationDefaults<\/code><\/strong><\/a>: raised when the application queries default values to be set for the application.<\/li>\n<\/ul>\n<p><strong>Note:<\/strong> More general information about the <a href=\"https:\/\/learn.microsoft.com\/dotnet\/visual-basic\/developing-apps\/development-with-my\/overview-of-the-visual-basic-application-model\">Visual Basic Application Model<\/a> is provided through the Microsoft Learn Docs about this topic. Also note, that, on top of the extensibility of the <code>My<\/code> namespace, this <a href=\"https:\/\/learn.microsoft.com\/dotnet\/visual-basic\/developing-apps\/customizing-extending-my\/extending-the-visual-basic-application-model\">Application Model also has extensibility points<\/a> which are also described in great detail by the respective docs.<\/p>\n<h2 id=\"summary\">Summary<\/h2>\n<p>With the new and modernized project properties pages, WinForm\u2019s Application<br \/>\nFramework is ready for new, .NET 6,7,8+ based Visual Basic Apps to develop. It\u2019s<br \/>\nalso the right time to think about modernizing your older .NET Framework based<br \/>\nVB Apps and bring them over to .NET 6,7,8+. WinForms and the .NET runtime<br \/>\ndeliver countless new features and provide considerable performance improvements<br \/>\nfor your apps in almost every area. Visual Basic and the Visual Basic<br \/>\nApplication Framework are and continue to be first class citizens and are fully<br \/>\nsupported in WinForms. Our plans are to continue modernizing around the VB App<br \/>\nFramework in the future without breaking code for existing projects.<\/p>\n<p>And, as always: Feedback about the subject matter is really important to us, so<br \/>\nplease let us know your thoughts and additional ideas! Please also note that the<br \/>\nWinForms .NET and the <a href=\"https:\/\/github.com\/dotnet\/winforms\/tree\/main\/src\/Microsoft.VisualBasic.Forms\/src\/Microsoft\/VisualBasic\/ApplicationServices\">Visual Basic Application Framework runtime<\/a> is open source,<br \/>\nand you can contribute! If you have general feature ideas, encountered bugs, or<br \/>\neven want to take on existing issues around the WinForms runtime and submit PRs,<br \/>\nhave a look at the <a href=\"https:\/\/github.com\/dotnet\/winforms\">WinForms Github repo<\/a>.<br \/>\nIf you have suggestions around the WinForms Designer feel free to file new<br \/>\nissues there as well.<\/p>\n<p>Happy coding!<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Klaus Loeffelmann Melissa Trevino March 9th, 20233 4 .NET from version .NET Core 3.1 up to .NET 7 has plenty of advantages over .NET Framework: it provides performance improvements in almost every area, and those improvements were an ongoing effort over each .NET version. The latest improvements in .NET 6 and .NET 7 are really [&hellip;]<\/p>\n","protected":false},"author":2,"featured_media":132348,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[66],"tags":[103,1445,1446],"class_list":["post-132347","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-microsoft-webdev","tag-net","tag-visual-basic","tag-winforms"],"_links":{"self":[{"href":"https:\/\/sickgaming.net\/blog\/wp-json\/wp\/v2\/posts\/132347","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/sickgaming.net\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/sickgaming.net\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/sickgaming.net\/blog\/wp-json\/wp\/v2\/users\/2"}],"replies":[{"embeddable":true,"href":"https:\/\/sickgaming.net\/blog\/wp-json\/wp\/v2\/comments?post=132347"}],"version-history":[{"count":0,"href":"https:\/\/sickgaming.net\/blog\/wp-json\/wp\/v2\/posts\/132347\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/sickgaming.net\/blog\/wp-json\/wp\/v2\/media\/132348"}],"wp:attachment":[{"href":"https:\/\/sickgaming.net\/blog\/wp-json\/wp\/v2\/media?parent=132347"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/sickgaming.net\/blog\/wp-json\/wp\/v2\/categories?post=132347"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/sickgaming.net\/blog\/wp-json\/wp\/v2\/tags?post=132347"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}