Thread Rating:
  • 0 Vote(s) - 0 Average
  • 1
  • 2
  • 3
  • 4
  • 5
What’s new for the WinForms Visual Basic Application Framework
What’s new for the WinForms Visual Basic Application Framework

<div style="margin: 5px 5% 10px 5%;"><img src="" width="96" height="96" title="" alt="" /></div><div><div class="row justify-content-center author-header">
<div class="col-md-4">
<div class="post-detail-avatar-section">
<div class="post-detail-avatar"> <img decoding="async" alt src="" class="avatar avatar-58 photo avatar-default lazyload" height="58" width="58"></div>
<p>Klaus Loeffelmann</p>
<div class="col-md-4">
<div class="post-detail-avatar-section">
<div class="post-detail-avatar"> <img decoding="async" width="58" height="58" src="" class="avatar avatar-58 photo lazyload" alt></div>
<p>Melissa Trevino</p>
<div class="entry-meta entry-meta-layout">
<p> March 9th, 2023<span class="entry-meta-comment"><a data-bi-name="jump-to-comments" href="" 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="" data-bi-id="body" data-bi-name="Login to like"><span> 4</span></a></span></span></span></p>
<p><!-- .entry-meta --> </p>
<p>.NET from version .NET Core 3.1 up to .NET 7 has plenty of advantages over .NET<br />
Framework: it provides performance improvements in almost every area, and those<br />
improvements were an ongoing effort over each .NET version. The<br />
latest improvements in <a href="">.NET<br />
6</a> and<br />
<a href="">.NET<br />
7</a> are<br />
really worth checking out.</p>
<p>Migrating your Windows Forms (WinForms) Visual Basic Apps to .NET 6/7+ also<br />
allows to adopt modern technologies which are not (or are no longer) supported in .NET<br />
Framework. <a href="">EFCore is one example</a>: it is<br />
a modern Entity Framework data access technology that enables .NET developers to<br />
work with database backends using .NET objects. Although it is not natively<br />
supported for VB by Microsoft, it is designed in a way that it is easy for the<br />
community to build up on it and provide <a href="">code generation support for additional<br />
languages like Visual Basic</a>. In<br />
that context there are also changes and improvements in the new WinForms<br />
Out-of-Process Designer for .NET, <a href="">especially around Object Data<br />
Sources</a>.<br />
For the WinForms .NET runtime, there are a series of improvements in different<br />
areas which have been introduced with the latest releases of .NET:</p>
<h2 id="the-new-visual-basic-application-framework-experience">The new Visual Basic Application Framework Experience</h2>
<p>In contrast to the project property Application Framework Designer experience in<br />
earlier versions of Visual Studio and for .NET Framework, you will noticed that<br />
the project properties UI in Visual Studio has changed. It’s style is now in<br />
parity with the project properties experience for other .NET project types: we<br />
have invested into modernizing the experience for developers, focusing on<br />
enhancing productivity and a modern look and feel.</p>
<p><img decoding="async" src="" alt="Screenshot of the new Visual Basic Application Framework project settings designer."></p>
<p>We’ve added theming and search to the new experience. If this is your first time<br />
you’re working with the new project properties experience in Visual Studio, it’s<br />
a good idea to read up on the <a href="">the introductory<br />
<p>In contrast to C# projects, Visual Basic Application Framework projects use a<br />
special file for storing the Application Framework project settings: the<br />
<em>Application.myapp</em> file. We’ll talk more about the technical details of how<br />
this file connects the project settings to the VB project specific code<br />
generation of the <code>My</code> namespace later, but one thing to keep in mind is how the<br />
UI translates each property’s value to this file:</p>
<p><strong>Windows Visual Styles</strong> is to determine if the application will use the most<br />
current version for the Control Library <em>comctl.dll</em> to provide control<br />
rendering with modern visual styling. This setting translates to the value<br />
<code>EnableVisualStyles</code> of type <code>Boolean</code> inside of <em>Application.myapp</em>.</p>
<p><strong>Single-instance application</strong> is to determine if the application will prevent<br />
users from running multiple instances of the application. This setting is<br />
switched off by default, which allows multiple instances of the application to<br />
be run concurrently. This setting translates to the value <code>SingleInstance</code> of<br />
type <code>Boolean</code>.</p>
<p><strong>Save user settings on exit</strong> is to determine if the application settings are<br />
automatically saved when an app is about to shut down. The settings can be<br />
changed with the settings editor. In contrast to .NET Framework, a new Visual<br />
Basic Application Framework App doesn’t contain a settings file by default,<br />
but you can easily insert one over the project properties, should you need<br />
one, and then <a href="">manage the settings<br />
<p><img decoding="async" src="" alt="Screenshot of the Settings section in the Application Framework project's property pages"></p>
<p>Adding to the list of settings automatically generates respective code, which<br />
can be easily access over the <a href=""><code>My</code> object in the Visual Basic Application<br />
Framework at<br />
runtime</a>.<br />
This settings translates to the value <code>SaveMySettingsOnExit</code> of type<br />
<p><strong>High DPI mode</strong> is to identify the application-wide HighDpiMode for the<br />
application. Note that this setting can be programmatically overridden through<br />
the <a href=""><code>HighDpiMode</code><br />
property</a><br />
of the <code>ApplyApplicationDefaultsEventArgs</code> of the <a href=""><code>ApplyApplicationDefaults</code></a><br />
application event. Choose from the following setting:</p>
<li><strong>DPI unaware (0):</strong> The application window does not scale for DPI changes and<br />
always assumes a scale factor of 100%. For higher resolutions, this will<br />
make text and fine drawings more blurry, but may impose the best setting for<br />
some apps which demand a high backwards compatibility in rendering content.</li>
<li><strong>DPI unaware GDI scaled (4):</strong> similar to DPI unaware, but improves the<br />
quality of GDI/GDI+ based on content. Please note that this mode will <em>not</em><br />
work as expected, when you have enabled <a href="">double<br />
buffering</a><br />
for control rendering via <a href=""><code>OnPaint</code></a> and related functionality.</li>
<li><strong>Per monitor (2):</strong> Per-Monitor DPI allows individual displays to have their<br />
own DPI scaling setting. WinForms doesn’t optimize for this mode, and<br />
Per-Monitor V2 should be used instead.</li>
<li><strong>Per monitor V2 (3):</strong> Per-Monitor V2 offers more advanced scaling features<br />
such as improved support for mixed DPI environments, improved display<br />
enumeration, and support for dynamically scaling on-client area of windows.<br />
In WinForms common controls are optimized for this high dpi mode. Please<br />
note the events<br />
<a href="">Form.DpiChange</a>,<br />
<a href="">Control.DpiChangedAfterParent</a><br />
and<br />
<a href="">Control.DpiChangeBeforeParent</a>,<br />
when your app need to scale up or down content based on a changed DPI<br />
environment, for example, when the user of your app has dragged a Form from<br />
one monitor to another monitor with a different DPI setting.</li>
<li><strong>System aware (1):</strong> The application queries for the DPI of the primary<br />
monitor once and uses this for the application on all monitors. When content<br />
in Forms is dragged from one monitor to another with a different HighDPI<br />
setting, content might become blurry. SystemAware is WinForm’s most<br />
compatible high-dpi rendering mode for all supported controls.</li>
<p><strong>Authentication mode</strong> is to specify the method of identifying the logged-on<br />
user, when needed. The setting translates to the value <code>AuthenticationMode</code> as<br />
an enum value of type <code>Integer</code>:</p>
<li>0: The <code>WindowsFormsApplicationBase(AuthenticationMode)</code> constructor does<br />
not automatically initialize the principal for the application’s main<br />
thread. It’s completely the developer’s task, to manage authentication for<br />
the user.</li>
<li>1: The <code>WindowsFormsApplicationBase(AuthenticationMode)</code> constructor<br />
initializes the principal for the application’s main thread with the current<br />
user’s Windows user info.</li>
<p><strong>Shutdown mode</strong> is to to indicate which condition causes the application to<br />
shut down. This setting translates to the value <code>ShutdownMode</code> as an enum<br />
value of type <code>Integer</code> (Note: Please also refer to the application event<br />
<a href="">ShutDown</a><br />
and the further remarks down below.):</p>
<li>0: When the main form closes.</li>
<li>1: Only after the last form closes.</li>
<p><strong>Splash screen</strong> represents the name of the form to be used as a splash screen<br />
for the application. Note that the file name does not need to include the<br />
extension (.vb). This setting translates to the value <code>SplashScreen</code> of type<br />
<p><strong>Note:</strong> you will may be missing the settings for the Splash dialog up to<br />
Visual Studio 2022 version 17.5. For a workaround, read the comments in<br />
the section “A look behind the scenes”. To recap: a “Splash” dialog is<br />
typically displayed for a few seconds when an application is launched.<br />
Visual Basic has an item template which you can use to add a basic splash<br />
dialog to your project. It usually displays the logo or name of the<br />
application, along with some kind of animation or visual effects, to give<br />
users the impression that the application is loading or initializing. The<br />
term “splash” in this context is used because the dialog is designed to<br />
create a splash or impact on the user, drawing their attention to the<br />
application while it loads.</p>
<p><strong>Application Framework</strong> is saved both in the <em>Application.myapp</em> file and the<br />
<em>.vbproj</em> file:</p>
<li><em>Application.myapp</em> saves the setting <code>MySubMain</code> of type <code>Boolean</code> to<br />
identify if the Application Framework is enabled.</li>
<li><em>.vbproj</em> uses the setting <code>MyType</code> for identifying the usage of the<br />
Application Framework for a VB project. If the Application Framework is<br />
enabled, the value is <em>WindowsForms</em>; if the Application Framework is<br />
disabled, the value is <em>WindowsFormsWithCustomSubMain</em>.</li>
<p><strong>Startup object</strong> is the name of the form that will be used as the entry<br />
point, without its filename extension. Note: this property is found in the<br />
project property Settings under the <em>General</em> section, and not in the<br />
Application Framework section. This setting translates to the value <code>MainForm</code> of type<br />
<code>String</code>, when the Application Framework is activated. The start object setting in<br />
the <em>.vbproj</em> file is ignored in that case – see also the comments below on this<br />
<h3 id="custom-constants-new-look">Custom constants new look</h3>
<p><img decoding="async" src="" alt="Screenshot of the new custom constants editor in the project properties UI."></p>
<p>We are introducing a new custom constants-control in the modernized Project<br />
Property Pages for VB Projects, that allows to encode the input to the format<br />
key=”value”. Our goal is that users will be able to input their custom constants<br />
in a more streamlined key-value pair format, thus enhancing their productivity.<br />
Feedback is welcomed – if you have any comments or suggestions, feel free to<br />
reach out to the <a href="">project system<br />
team</a> by filing a new issue or<br />
comment on existing ones.</p>
<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>
<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 />
starts with a static method called <code>main</code> which can usually be found in a file<br />
called <em>Program.cs</em>, and in that <code>main</code> method all the setting get applied.</p>
<p>That is different in Visual Basic. Since VB Apps in WinForms are based on the<br />
Application Framework runtime, there are a few features, which aren’t<br />
intrinsically available to C# WinForms apps to begin with, like configuring to<br />
automatically show Splash dialogs (see below) or ensure a single instance<br />
application start. Since you configure most of the parts of your app<br />
interactively in VB with the settings described above at design time, the actual<br />
code which honors or ensures those settings later at runtime is mostly<br />
code-generated and somewhat hidden behind the scenes. The starting point of a VB<br />
app is therefore not so obvious. There are also a series of differences in .NET<br />
Visual Basic apps when it comes to hooking up event code which is supposed to<br />
run, for example when a VB WinForms app starts, ends, or runs into an unhandled<br />
exception – just to name a few examples.</p>
<p>That all said, technically Visual Basic doesn’t break any fundamental rules.<br />
Under the hood, there is of course a <code>Shared Sub Main</code> when you activate the<br />
Application Framework. You just do not write it yourself, and you don’t see it,<br />
because it is generated by the VB compiler and then automatically added to your<br />
Start Form. This is done by activating the VB compiler switch<br />
<a href=""><code>/main</code></a>.</p>
<p>At the same time, when you are activating the Application Framework, a series of<br />
conditional compiler constants are defined. One of the constants is called<br />
<code>_mytype</code>. If that constant is defined as <code>Windows</code> then the VB compiler<br />
generates all the necessary infrastructure code to support the Application<br />
Framework. If that constant is defined as <code>WindowsFormsWithCustomSubMain</code><br />
however, the VB compiler just generates the bare minimum infrastructure code and<br />
doesn’t apply any settings to the WinForms app on startup. The latter happens,<br />
when you deactivate the Application Framework. This setting is stored in the<br />
<em>vbproj</em> project file, along with the Start Form. What’s important to know<br />
though in this context: only in the case of <code>WindowsFormsWithCustomSubMain</code>, so<br />
with the Application Framework <em>deactivated</em>, is the Start Form definition<br />
actually taken from the <em>vbproj</em> file. When the Application Framework <em>is</em><br />
activated however then that is the case when the aforementioned<br />
<em>Application.myapp</em> file is used as the settings container. Note, that by<br />
default you cannot find that file in the solution explorer.</p>
<p><img decoding="async" src="" alt="Screenshot of solution explorer showing the Application.myapp file."></p>
<p>You need to make sure first to show <em>all files</em> for that project (see screenshot<br />
above). Then you can open the <em>My Project</em>-folder and show that setting file in<br />
the editor by double-clicking it in the solution explorer. The content of that<br />
file looks something like this:</p>
<pre><code class="language-xml">&lt;?xml version="1.0" encoding="utf-16"?&gt;
&lt;MyApplicationData xmlns:xsi="" xmlns:xsd=""&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;
<p><strong>Note:</strong> Visual Studio 2022 before version 17.6 (Preview 3) won’t have the<br />
option to pick a Splash Dialog interactively, as mentioned above. We will have<br />
an interactive designer for setting the splash form only from that version on<br />
on. Up to then, you can manually patch the <em>Application.myapp</em> file to trigger<br />
the code generation for the Splash dialog. Insert the following line of code in<br />
that file and save the changes.</p>
<pre><code class="language-xml">&lt;SplashScreen&gt;SplashDialog&lt;/SplashScreen&gt;</code></pre>
<p>When you do this, make sure <em>not</em> to include the filename extension (.vb) in<br />
that definition, because otherwise the required code does not get generated.</p>
<h3 id="application-myapp-as-the-source-for-code-generation">Application.myapp as the source for code generation</h3>
<p>Now, if you take a closer look at that file’s properties in the property<br />
browser, you’ll see that it is triggering a custom tool which is invoked<br />
whenever that file is saved. </p>
<p><img decoding="async" src="" alt="Screenshot of solution explorer showing the properties for the Application.myapp file."></p>
<p>And that custom tool generates VB code which you<br />
can find under the <em>Application.myapp</em> node in the Solution Explorer in<br />
<em>Application.Designer.vb</em>. It does the following:</p>
<li>It defines a <code>Friend Partial Class MyApplication</code>. With the Application<br />
Framework enabled, that class is inherited from<br />
<a href=""><code>WindowsFormsApplicationBase</code></a>.<br />
You don’t see that <code>Inherits</code> statement here and the reason is that <a href="">the major<br />
part of that Class’<br />
definition</a><br />
is injected by the Visual Basic compiler based on the earlier defined<br />
conditional constant <code>_myapp</code>.</li>
<li>It generates the code to apply all the settings which were saved in<br />
<em>Application.myapp</em> file.</li>
<li>It creates code for a method which overrides<br />
<a href=""><code>OnCreateMainForm</code></a>.<br />
In that method, it assigns the Form, which is defined as the start form in the<br />
<em>Application.myapp</em> file.</li>
<p><strong>Warning</strong>: The <em>Application.Designer.vb</em> is not supposed to be edited, as it’s<br />
auto-generated. Any changes will be lost as soon as you make changes to <em>Application.myapp</em>. Instead, use the project properties UI.</p>
<p>Now, the class which is injected by the compiler is also responsible for<br />
generating everything which the Visual Basic Application Framework provides you<br />
via the <code>My</code> namespace. The <code>My</code> namespace simplifies access to frequently used<br />
information about your WinForms app, your system, or simplifies access to<br />
frequently used APIs. Part of the <code>My</code> namespace for an activated Application<br />
Framework is the <code>Application</code> property, and its return type is of exactly that<br />
type which is defined by the class generated based on your Application Settings<br />
and then merged with the injected Visual Basic compiler file mentioned earlier.<br />
So, if you access <code>My.Application</code> you are basically accessing a single instance<br />
of the <code>My.MyApplication</code> type which the generated code defines.</p>
<p>With this context understood, we can move on to how two additional features of<br />
the Application Framework work and can be approached. The first one is extending<br />
the <code>My</code> namespace with additional function areas. We won’t go too much into<br />
them, because there are <a href="">detailed docs about the <code>My</code> namespace and how to<br />
extend<br />
<p>An even more important concept to understand are the Application Events which are<br />
provided by the Application Framework. Since there isn’t a good way to intercept<br />
the startup or shut down of an app (since that code gets generated<br />
and sort of hidden inside the main Form) Application Events are the way to be<br />
notified of certain application-global occurrences. </p>
<p>Note in this context, that there is a small breaking change in the UI: while in<br />
.NET Framework, you had to insert a code file named <em>ApplicationEvents.vb</em> via<br />
the Property Settings of the VB project, in a .NET Core App this file will be<br />
there from the start when you’ve created a new Application Framework project.</p>
<p>To wire up the available Application events, you open that <em>ApplicationEvent.vb</em><br />
code file, and then you select ApplicationEvents from the Object drop-down list,<br />
and the application event you want to write up from the events list:</p>
<p><img decoding="async" src="" alt="Animated gif showing how to wire app Application Events in the ApplicationEvent.vb code file"></p>
<p>As you can see, the <em>ApplicationEvent.vb</em> code file again extends the <code>MyApplication</code> class – this time by the events handler you place there on demand. The options you have here are:</p>
<li><a href=""><strong><code>Startup</code></strong></a>: raised when the application starts, before the start form is created.</li>
<li><a href=""><strong><code>Shutdown</code></strong></a>: raised after all application forms are closed. This event is not raised if the application terminates abnormally.</li>
<li><a href=""><strong><code>UnhandledException</code></strong></a>: raised if the application encounters an unhandled exception.</li>
<li><a href=""><strong><code>StartupNextInstance</code></strong></a>: raised when launching a single-instance application and the application is already active.</li>
<li><a href=""><strong><code>NetworkAvailabilityChanged</code></strong></a>: raised when the network connection is connected or disconnected.</li>
<li><a href=""><strong><code>ApplyApplicationDefaults</code></strong></a>: raised when the application queries default values to be set for the application.</li>
<p><strong>Note:</strong> More general information about the <a href="">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="">Application Model also has extensibility points</a> which are also described in great detail by the respective docs.</p>
<h2 id="summary">Summary</h2>
<p>With the new and modernized project properties pages, WinForm’s Application<br />
Framework is ready for new, .NET 6,7,8+ based Visual Basic Apps to develop. It’s<br />
also the right time to think about modernizing your older .NET Framework based<br />
VB Apps and bring them over to .NET 6,7,8+. WinForms and the .NET runtime<br />
deliver countless new features and provide considerable performance improvements<br />
for your apps in almost every area. Visual Basic and the Visual Basic<br />
Application Framework are and continue to be first class citizens and are fully<br />
supported in WinForms. Our plans are to continue modernizing around the VB App<br />
Framework in the future without breaking code for existing projects.</p>
<p>And, as always: Feedback about the subject matter is really important to us, so<br />
please let us know your thoughts and additional ideas! Please also note that the<br />
WinForms .NET and the <a href="">Visual Basic Application Framework runtime</a> is open source,<br />
and you can contribute! If you have general feature ideas, encountered bugs, or<br />
even want to take on existing issues around the WinForms runtime and submit PRs,<br />
have a look at the <a href="">WinForms Github repo</a>.<br />
If you have suggestions around the WinForms Designer feel free to file new<br />
issues there as well.</p>
<p>Happy coding!</p>

Forum Jump:

Users browsing this thread: 1 Guest(s)