What’s new for the WinForms Visual Basic Application Framework
.NET from version .NET Core 3.1 up to .NET 7 has plenty of advantages over .NETFramework: it provides performance improvements in almost every area, and thoseimprovements were an ongoing effort over each .NET version. Thelatest improvements in .NET6 and.NET7 arereally worth checking out.
Migrating your Windows Forms (WinForms) Visual Basic Apps to .NET 6/7+ alsoallows to adopt modern technologies which are not (or are no longer) supported in .NETFramework. EFCore is one example: it isa modern Entity Framework data access technology that enables .NET developers towork with database backends using .NET objects. Although it is not nativelysupported for VB by Microsoft, it is designed in a way that it is easy for thecommunity to build up on it and provide code generation support for additionallanguages like Visual Basic. Inthat context there are also changes and improvements in the new WinFormsOut-of-Process Designer for .NET, especially around Object DataSources.For the WinForms .NET runtime, there are a series of improvements in differentareas which have been introduced with the latest releases of .NET:
.NET 5 introduced the
TaskDialog
control,a series ofListView
controlenhancements,FileDialog
classenhancementsand a noticeable performance and memory usage improvement aroundGDI+..NET (in .NET Core 3.1) also changed the default font for WinForms Formsand UserControls to Segoe UI, 9pt to let the typical WinForms UI have a moremodern look and feel..NET 6 built on that, and introduced the option to set the default font forthe whole WinForms Application to what ever font you like. In the VBApplication Framework, this is done now by an additional Application Eventwhich we introduced in the .NET 6 time frame called
ApplyApplicationDefaults
. This event allows to set values for theHighDpiMode,the application’s defaultfontand the minimum splash dialog displaytime.For more about the Application Events in the VB Application Framework see below..NET 7 introduces Command Binding forWinForms,which makes it easier to apply a UI Controller architecture based on the MVVMpattern for WinForms Apps, and introduce Unit Tests to WinForms App. Generalimprovements in WinForms in addition to that were rendering in HighDPI perMonitor V2scenariosand – counting for all versions from .NET 5 to .NET 7 – repeatedly improvedaccessibilitysupportwith Microsoft UI Automation pattern work better with accessibility tools likeNarrator, Jaws and NVDA.
The new Visual Basic Application Framework Experience
In contrast to the project property Application Framework Designer experience inearlier versions of Visual Studio and for .NET Framework, you will noticed thatthe project properties UI in Visual Studio has changed. It’s style is now inparity with the project properties experience for other .NET project types: wehave invested into modernizing the experience for developers, focusing onenhancing productivity and a modern look and feel.
We’ve added theming and search to the new experience. If this is your first timeyou’re working with the new project properties experience in Visual Studio, it’sa good idea to read up on the the introductoryblog.
In contrast to C# projects, Visual Basic Application Framework projects use aspecial file for storing the Application Framework project settings: theApplication.myapp file. We’ll talk more about the technical details of howthis file connects the project settings to the VB project specific codegeneration of the My
namespace later, but one thing to keep in mind is how theUI translates each property’s value to this file:
Windows Visual Styles is to determine if the application will use the mostcurrent version for the Control Library comctl.dll to provide controlrendering with modern visual styling. This setting translates to the value
EnableVisualStyles
of typeBoolean
inside of Application.myapp.Single-instance application is to determine if the application will preventusers from running multiple instances of the application. This setting isswitched off by default, which allows multiple instances of the application tobe run concurrently. This setting translates to the value
SingleInstance
oftypeBoolean
.Save user settings on exit is to determine if the application settings areautomatically saved when an app is about to shut down. The settings can bechanged with the settings editor. In contrast to .NET Framework, a new VisualBasic Application Framework App doesn’t contain a settings file by default,but you can easily insert one over the project properties, should you needone, and then manage the settingsinteractively.
Adding to the list of settings automatically generates respective code, whichcan be easily access over the
My
object in the Visual Basic ApplicationFramework atruntime.This settings translates to the valueSaveMySettingsOnExit
of typeBoolean
.High DPI mode is to identify the application-wide HighDpiMode for theapplication. Note that this setting can be programmatically overridden throughthe
HighDpiMode
propertyof theApplyApplicationDefaultsEventArgs
of theApplyApplicationDefaults
application event. Choose from the following setting:- DPI unaware (0): The application window does not scale for DPI changes andalways assumes a scale factor of 100%. For higher resolutions, this willmake text and fine drawings more blurry, but may impose the best setting forsome apps which demand a high backwards compatibility in rendering content.
- DPI unaware GDI scaled (4): similar to DPI unaware, but improves thequality of GDI/GDI+ based on content. Please note that this mode will notwork as expected, when you have enabled doublebufferingfor control rendering via
OnPaint
and related functionality. - Per monitor (2): Per-Monitor DPI allows individual displays to have theirown DPI scaling setting. WinForms doesn’t optimize for this mode, andPer-Monitor V2 should be used instead.
- Per monitor V2 (3): Per-Monitor V2 offers more advanced scaling featuressuch as improved support for mixed DPI environments, improved displayenumeration, and support for dynamically scaling on-client area of windows.In WinForms common controls are optimized for this high dpi mode. Pleasenote the eventsForm.DpiChange,Control.DpiChangedAfterParentandControl.DpiChangeBeforeParent,when your app need to scale up or down content based on a changed DPIenvironment, for example, when the user of your app has dragged a Form fromone monitor to another monitor with a different DPI setting.
- System aware (1): The application queries for the DPI of the primarymonitor once and uses this for the application on all monitors. When contentin Forms is dragged from one monitor to another with a different HighDPIsetting, content might become blurry. SystemAware is WinForm’s mostcompatible high-dpi rendering mode for all supported controls.
Authentication mode is to specify the method of identifying the logged-onuser, when needed. The setting translates to the value
AuthenticationMode
asan enum value of typeInteger
:- 0: The
WindowsFormsApplicationBase(AuthenticationMode)
constructor doesnot automatically initialize the principal for the application’s mainthread. It’s completely the developer’s task, to manage authentication forthe user. - 1: The
WindowsFormsApplicationBase(AuthenticationMode)
constructorinitializes the principal for the application’s main thread with the currentuser’s Windows user info.
- 0: The
Shutdown mode is to to indicate which condition causes the application toshut down. This setting translates to the value
ShutdownMode
as an enumvalue of typeInteger
(Note: Please also refer to the application eventShutDownand the further remarks down below.):- 0: When the main form closes.
- 1: Only after the last form closes.
Splash screen represents the name of the form to be used as a splash screenfor the application. Note that the file name does not need to include theextension (.vb). This setting translates to the value
SplashScreen
of typeString
.Note: you will may be missing the settings for the Splash dialog up toVisual Studio 2022 version 17.5. For a workaround, read the comments inthe section “A look behind the scenes”. To recap: a “Splash” dialog istypically displayed for a few seconds when an application is launched.Visual Basic has an item template which you can use to add a basic splashdialog to your project. It usually displays the logo or name of theapplication, along with some kind of animation or visual effects, to giveusers the impression that the application is loading or initializing. Theterm “splash” in this context is used because the dialog is designed tocreate a splash or impact on the user, drawing their attention to theapplication while it loads.
Application Framework is saved both in the Application.myapp file and the.vbproj file:
- Application.myapp saves the setting
MySubMain
of typeBoolean
toidentify if the Application Framework is enabled. - .vbproj uses the setting
MyType
for identifying the usage of theApplication Framework for a VB project. If the Application Framework isenabled, the value is WindowsForms; if the Application Framework isdisabled, the value is WindowsFormsWithCustomSubMain.
- Application.myapp saves the setting
Startup object is the name of the form that will be used as the entrypoint, without its filename extension. Note: this property is found in theproject property Settings under the General section, and not in theApplication Framework section. This setting translates to the value
MainForm
of typeString
, when the Application Framework is activated. The start object setting inthe .vbproj file is ignored in that case – see also the comments below on thistopic.
Custom constants new look
We are introducing a new custom constants-control in the modernized ProjectProperty Pages for VB Projects, that allows to encode the input to the formatkey=”value”. Our goal is that users will be able to input their custom constantsin a more streamlined key-value pair format, thus enhancing their productivity.Feedback is welcomed – if you have any comments or suggestions, feel free toreach out to the project systemteam by filing a new issue orcomment on existing ones.
A look behind the scenes of the WinForms VB Application Framework
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 appstarts with a static method called main
which can usually be found in a filecalled Program.cs, and in that main
method all the setting get applied.
That is different in Visual Basic. Since VB Apps in WinForms are based on theApplication Framework runtime, there are a few features, which aren’tintrinsically available to C# WinForms apps to begin with, like configuring toautomatically show Splash dialogs (see below) or ensure a single instanceapplication start. Since you configure most of the parts of your appinteractively in VB with the settings described above at design time, the actualcode which honors or ensures those settings later at runtime is mostlycode-generated and somewhat hidden behind the scenes. The starting point of a VBapp is therefore not so obvious. There are also a series of differences in .NETVisual Basic apps when it comes to hooking up event code which is supposed torun, for example when a VB WinForms app starts, ends, or runs into an unhandledexception – just to name a few examples.
That all said, technically Visual Basic doesn’t break any fundamental rules.Under the hood, there is of course a Shared Sub Main
when you activate theApplication Framework. You just do not write it yourself, and you don’t see it,because it is generated by the VB compiler and then automatically added to yourStart Form. This is done by activating the VB compiler switch/main
.
At the same time, when you are activating the Application Framework, a series ofconditional compiler constants are defined. One of the constants is called_mytype
. If that constant is defined as Windows
then the VB compilergenerates all the necessary infrastructure code to support the ApplicationFramework. If that constant is defined as WindowsFormsWithCustomSubMain
however, the VB compiler just generates the bare minimum infrastructure code anddoesn’t apply any settings to the WinForms app on startup. The latter happens,when you deactivate the Application Framework. This setting is stored in thevbproj project file, along with the Start Form. What’s important to knowthough in this context: only in the case of WindowsFormsWithCustomSubMain
, sowith the Application Framework deactivated, is the Start Form definitionactually taken from the vbproj file. When the Application Framework isactivated however then that is the case when the aforementionedApplication.myapp file is used as the settings container. Note, that bydefault you cannot find that file in the solution explorer.
You need to make sure first to show all files for that project (see screenshotabove). Then you can open the My Project-folder and show that setting file inthe editor by double-clicking it in the solution explorer. The content of thatfile looks something like this:
<?xml version="1.0" encoding="utf-16"?>
<MyApplicationData xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<MySubMain>true</MySubMain>
<MainForm>Form1</MainForm>
<SingleInstance>false</SingleInstance>
<ShutdownMode>0</ShutdownMode>
<EnableVisualStyles>true</EnableVisualStyles>
<AuthenticationMode>0</AuthenticationMode>
<SaveMySettingsOnExit>true</SaveMySettingsOnExit>
<HighDpiMode>3</HighDpiMode>
</MyApplicationData>
Note: Visual Studio 2022 before version 17.6 (Preview 3) won’t have theoption to pick a Splash Dialog interactively, as mentioned above. We will havean interactive designer for setting the splash form only from that version onon. Up to then, you can manually patch the Application.myapp file to triggerthe code generation for the Splash dialog. Insert the following line of code inthat file and save the changes.
<SplashScreen>SplashDialog</SplashScreen>
When you do this, make sure not to include the filename extension (.vb) inthat definition, because otherwise the required code does not get generated.
Application.myapp as the source for code generation
Now, if you take a closer look at that file’s properties in the propertybrowser, you’ll see that it is triggering a custom tool which is invokedwhenever that file is saved.
And that custom tool generates VB code which youcan find under the Application.myapp node in the Solution Explorer inApplication.Designer.vb. It does the following:
- It defines a
Friend Partial Class MyApplication
. With the ApplicationFramework enabled, that class is inherited fromWindowsFormsApplicationBase
.You don’t see thatInherits
statement here and the reason is that the majorpart of that Class’definitionis injected by the Visual Basic compiler based on the earlier definedconditional constant_myapp
. - It generates the code to apply all the settings which were saved inApplication.myapp file.
- It creates code for a method which overrides
OnCreateMainForm
.In that method, it assigns the Form, which is defined as the start form in theApplication.myapp file.
Warning: The Application.Designer.vb is not supposed to be edited, as it’sauto-generated. Any changes will be lost as soon as you make changes to Application.myapp. Instead, use the project properties UI.
Now, the class which is injected by the compiler is also responsible forgenerating everything which the Visual Basic Application Framework provides youvia the My
namespace. The My
namespace simplifies access to frequently usedinformation about your WinForms app, your system, or simplifies access tofrequently used APIs. Part of the My
namespace for an activated ApplicationFramework is the Application
property, and its return type is of exactly thattype which is defined by the class generated based on your Application Settingsand then merged with the injected Visual Basic compiler file mentioned earlier.So, if you access My.Application
you are basically accessing a single instanceof the My.MyApplication
type which the generated code defines.
With this context understood, we can move on to how two additional features ofthe Application Framework work and can be approached. The first one is extendingthe My
namespace with additional function areas. We won’t go too much intothem, because there are detailed docs about the My
namespace and how toextendit.
An even more important concept to understand are the Application Events which areprovided by the Application Framework. Since there isn’t a good way to interceptthe startup or shut down of an app (since that code gets generatedand sort of hidden inside the main Form) Application Events are the way to benotified of certain application-global occurrences.
Note in this context, that there is a small breaking change in the UI: while in.NET Framework, you had to insert a code file named ApplicationEvents.vb viathe Property Settings of the VB project, in a .NET Core App this file will bethere from the start when you’ve created a new Application Framework project.
To wire up the available Application events, you open that ApplicationEvent.vbcode file, and then you select ApplicationEvents from the Object drop-down list,and the application event you want to write up from the events list:
As you can see, the ApplicationEvent.vb code file again extends the MyApplication
class – this time by the events handler you place there on demand. The options you have here are:
Startup
: raised when the application starts, before the start form is created.Shutdown
: raised after all application forms are closed. This event is not raised if the application terminates abnormally.UnhandledException
: raised if the application encounters an unhandled exception.StartupNextInstance
: raised when launching a single-instance application and the application is already active.NetworkAvailabilityChanged
: raised when the network connection is connected or disconnected.ApplyApplicationDefaults
: raised when the application queries default values to be set for the application.
Note: More general information about the Visual Basic Application Model is provided through the Microsoft Learn Docs about this topic. Also note, that, on top of the extensibility of the My
namespace, this Application Model also has extensibility points which are also described in great detail by the respective docs.
Summary
With the new and modernized project properties pages, WinForm’s ApplicationFramework is ready for new, .NET 6,7,8+ based Visual Basic Apps to develop. It’salso the right time to think about modernizing your older .NET Framework basedVB Apps and bring them over to .NET 6,7,8+. WinForms and the .NET runtimedeliver countless new features and provide considerable performance improvementsfor your apps in almost every area. Visual Basic and the Visual BasicApplication Framework are and continue to be first class citizens and are fullysupported in WinForms. Our plans are to continue modernizing around the VB AppFramework in the future without breaking code for existing projects.
And, as always: Feedback about the subject matter is really important to us, soplease let us know your thoughts and additional ideas! Please also note that theWinForms .NET and the Visual Basic Application Framework runtime is open source,and you can contribute! If you have general feature ideas, encountered bugs, oreven want to take on existing issues around the WinForms runtime and submit PRs,have a look at the WinForms Github repo.If you have suggestions around the WinForms Designer feel free to file newissues there as well.
Happy coding!
6 comments
“Visual Basic and the Visual Basic Application Framework are and continue to be first class citizens and are fully supported in WinForms. Our plans are to continue modernizing around the VB App Framework in the future without breaking code for existing projects.” This is really important for us, also thank for the great explanation on how all those configurations relates to each other.
One thing I don’t fully undestand is that there is the ApplyApplicationDefaults event that allows you to configure a default font for the entire application, but if you create a new form or a new control in the designer, it stills defaults to Segoe UI 9px. Is is an intended behaviour? It is a little weird to have a default Segoe UI font in the designer but then, when you run the application, it shows a different default font.
We have been thinking about consolidating application.myapp into vbproj, although we have not yet a concrete timeline or an ETA for that. It’s early planning stages. That would bring VB for WinForms apps in parity with C#, which then means that the Out-Of-Process Designer could pick up the Font already defined at design-time.
That said, please keep in mind that in a world of HighDPI and Per Monitor V2 requirements, pixel-perfect layouts in WinForms are not a good idea to begin with. So, refactoring layouts to use more features like AutoSize and TableLayoutPanel-based Forms/UserControl is really a useful benefit for app users.
Thank you for the response.
I know that pixel perfect layouts nowadays are not a good idea, but in legacy applications ported to .Net 6 with around a thousand controls it will be a lot helpful if the Out-Of-Process Designer can pick the default font.
Looking forward for it 😉
Best regards!
Hey Klaus,
WinForm is not good aha – I know that because communication VB <=> C++/C like 1:1 example I use Ubuntu 22.04 with X11 but XDrawRectangles() doesn’t work for C# or VB because DllImport doesn’t know which pointer * or array []
Or Java can’t find where is closed 4. Lines of SDL2 that’s why 1:1 doesn’t exist everything. But C/C++ has not problems like 1:1. You understand that?
For Windows Api User32 from C#,F# or VB <=> C/C++ mean 1:1 but Gdi32 for C#,F# and VB are maybe 0:1 that’s why you say not perfect we need create wrapper for Gdi32 and unsafe libraries example not working to call back to C#,F# and VB
For Linux is really catastrophical for call back to C#,F# and VB. I need create wrapper with X11, Wayland, Cairo or other libraries.
I hope you understand me. Sorry my bad English!
Amazing stuff, thank you!