Windows Forms .NET 6
Windows Forms .NET 6
This article describes some of the new Windows Forms features and enhancements in .NET 6.
There are a few breaking changes you should be aware of when migrating from .NET Framework to .NET 6. For
more information, see Breaking changes in Windows Forms.
class Program
{
[STAThread]
static void Main()
{
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
Application.Run(new Form1());
}
}
In .NET 6, these templates have been modified to use the new bootstrap code, invoked by the
ApplicationConfiguration.Initialize method.
class Program
{
[STAThread]
static void Main()
{
ApplicationConfiguration.Initialize();
Application.Run(new Form1());
}
}
This method is automatically generated at compile time and contains the code to configure Windows Forms. The
project file can control these settings now too, and you can avoid configuring it in code. For example, the
generated method looks similar to the following code:
public static void Initialize()
{
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
Application.SetHighDpiMode(HighDpiMode.SystemAware);
}
The new bootstrap code is used by Visual Studio to configure the Windows Forms Visual Designer. If you opt-out
of using the new bootstrap code, by restoring the old code and bypassing the
ApplicationConfiguration.Initialize method, the Windows Forms Visual Designer won't respect the bootstrap
settings you set.
The settings generated in the Initialize method are controlled by the project file.
Project-level application settings
To complement the new application bootstrap feature of Windows Forms, a few Application settings previously
set in the startup code of the application should be set in the project file. The project file can configure the
following application settings:
The following example demonstrates a project file that sets these application-related properties:
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<OutputType>WinExe</OutputType>
<TargetFramework>net6.0-windows</TargetFramework>
<Nullable>enable</Nullable>
<UseWindowsForms>true</UseWindowsForms>
<ImplicitUsings>enable</ImplicitUsings>
<ApplicationVisualStyles>true</ApplicationVisualStyles>
<ApplicationUseCompatibleTextRendering>false</ApplicationUseCompatibleTextRendering>
<ApplicationHighDpiMode>SystemAware</ApplicationHighDpiMode>
<ApplicationDefaultFont>Microsoft Sans Serif, 8.25pt</ApplicationDefaultFont>
</PropertyGroup>
</Project>
The Windows Forms Visual Designer uses these settings. For more information, see the Visual Studio designer
improvements section.
IMPORTANT
This is the preferred way. Using the project to configure the new application bootstrap system allows Visual Studio
to use these settings in the designer.
In the following example, the project file configures Windows Forms to use the same font that .NET
Framework uses.
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<ApplicationDefaultFont>Microsoft Sans Serif, 8.25pt</ApplicationDefaultFont>
</PropertyGroup>
</Project>
- or -
Call the the Application.SetDefaultFont API in the old way (but with no designer support):
class Program
{
[STAThread]
static void Main()
{
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
Application.SetHighDpiMode(HighDpiMode.SystemAware);
Application.SetDefaultFont(new Font(new FontFamily("Microsoft Sans Serif"), 8.25f));
Application.Run(new Form1());
}
}
New APIs
System.Windows.Forms.Application.SetDefaultFont
System.Windows.Forms.Control.IsAncestorSiteInDesignMode
System.Windows.Forms.ProfessionalColors.StatusStripBorder
System.Windows.Forms.ProfessionalColorTable.StatusStripBorder
New Visual Basic APIs
Microsoft.VisualBasic.ApplicationServices.ApplyApplicationDefaultsEventArgs
Microsoft.VisualBasic.ApplicationServices.ApplyApplicationDefaultsEventHandler
Microsoft.VisualBasic.ApplicationServices.ApplyApplicationDefaultsEventArgs.MinimumSplashScreenDisplayTime
Microsoft.VisualBasic.ApplicationServices.ApplyApplicationDefaultsEventArgs.MinimumSplashScreenDisplayTime
Microsoft.VisualBasic.ApplicationServices.ApplyApplicationDefaultsEventArgs.Font
Microsoft.VisualBasic.ApplicationServices.ApplyApplicationDefaultsEventArgs.Font
Microsoft.VisualBasic.ApplicationServices.ApplyApplicationDefaultsEventArgs.HighDpiMode
Microsoft.VisualBasic.ApplicationServices.ApplyApplicationDefaultsEventArgs.HighDpiMode
Microsoft.VisualBasic.ApplicationServices.WindowsFormsApplicationBase.ApplyApplicationDefaults
Microsoft.VisualBasic.ApplicationServices.WindowsFormsApplicationBase.HighDpiMode
Microsoft.VisualBasic.ApplicationServices.WindowsFormsApplicationBase.HighDpiMode
Updated APIs
System.Windows.Forms.Control.Invoke now accepts System.Action and System.Func<TResult> as input
parameters.
System.Windows.Forms.Control.BeginInvoke now accepts System.Action as an input parameter.
System.Windows.Forms.DialogResult is extended with the following members:
TryAgain
Continue
Improved accessibility
Microsoft UI Automation patterns work better with accessibility tools like Narrator and Jaws.
See also
Breaking changes in Windows Forms
Tutorial: Create a new WinForms app
How to migrate a Windows Forms desktop app to .NET 6
What's new for .NET 5 (Windows Forms .NET)
9/23/2022 • 2 minutes to read • Edit Online
Windows Forms for .NET 5 adds the following features and enhancements over .NET Framework.
There are a few breaking changes you should be aware of when migrating from .NET Framework to .NET 5. For
more information, see Breaking changes in Windows Forms.
Enhanced features
Microsoft UI Automation patterns work better with accessibility tools like Narrator and Jaws.
Improved performance.
The VB.NET project template defaults to DPI SystemAware settings for high DPI resolutions such as 4k
monitors.
The default font matches the current Windows design recommendations.
Cau t i on
This may impact the layout of apps migrated from .NET Framework.
New controls
The following controls have been added since Windows Forms was ported to .NET Framework:
System.Windows.Forms.TaskDialog
A task dialog is a dialog box that can be used to display information and receive simple input from the
user. Like a message box, it's formatted by the operating system according to parameters you set. Task
dialog has more features than a message box. For more information, see the Task dialog sample.
Microsoft.Web.WebView2.WinForms.WebView2
A new web browser control with modern web support. Based on Edge (Chromium). For more
information, see Getting started with WebView2 in Windows Forms.
Enhanced controls
System.Windows.Forms.ListView
Supports collapsible groups
Footers
Group subtitle, task, and title images
System.Windows.Forms.FolderBrowserDialog
This dialog has been upgraded to use the modern Windows experience instead of the old Windows 7
experience.
System.Windows.Forms.FileDialog
Added support for ClientGuid.
ClientGuid enables a calling application to associate a GUID with a dialog's persisted state. A
dialog's state can include factors such as the last visited folder and the position and size of the
dialog. Typically, this state is persisted based on the name of the executable file. With ClientGuid ,
an application can persist different states of the dialog within the same application.
System.Windows.Forms.TextRenderer
Support added for ReadOnlySpan<T> to enhance performance of rendering text.
See also
Breaking changes in Windows Forms
Tutorial: Create a new WinForms app (Windows Forms .NET)
How to migrate a Windows Forms desktop app to .NET 5
Desktop Guide (Windows Forms .NET)
9/23/2022 • 6 minutes to read • Edit Online
Welcome to the Desktop Guide for Windows Forms, a UI framework that creates rich desktop client apps for
Windows. The Windows Forms development platform supports a broad set of app development features,
including controls, graphics, data binding, and user input. Windows Forms features a drag-and-drop visual
designer in Visual Studio to easily create Windows Forms apps.
IMPORTANT
The Desktop Guide documentation for .NET 6 and .NET 5 (including .NET Core 3.1) is under construction.
Introduction
Windows Forms is a UI framework for building Windows desktop apps. It provides one of the most productive
ways to create desktop apps based on the visual designer provided in Visual Studio. Functionality such as drag-
and-drop placement of visual controls makes it easy to build desktop apps.
With Windows Forms, you develop graphically rich apps that are easy to deploy, update, and work while offline
or while connected to the internet. Windows Forms apps can access the local hardware and file system of the
computer where the app is running.
To learn how to create a Windows Forms app, see Tutorial: Create a new WinForms app.
See also
Tutorial: Create a new WinForms app
How to add a form to a project
Add a control
Tutorial: Create a Windows Forms app with .NET
9/23/2022 • 4 minutes to read • Edit Online
In this short tutorial, you'll learn how to create a new Windows Forms app with Visual Studio. Once the initial
app has been generated, you'll learn how to add controls and how to handle events. By the end of this tutorial,
you'll have a simple app that adds names to a list box.
IMPORTANT
The Desktop Guide documentation for .NET 6 and .NET 5 (including .NET Core 3.1) is under construction.
Prerequisites
Visual Studio 2019 version 16.8 or later versions
Select the Visual Studio Desktop workload
Select the .NET 5 individual component
Visual Studio 2022 version 17.0 or later versions
Select the .NET desktop development workload
Select the .NET 6 individual component
IMPORTANT
Don't select the Windows Forms App (.NET Framework ) template.
6. In the Configure your new project window, set the Project name to Names and click Create .
You can also save your project to a different folder by adjusting the Location setting.
3. In the Search for templates box, type winforms , and wait for the search results to appear.
4. In the code language dropdown, choose C# or Visual Basic .
5. In the list of templates, select Windows Forms App and then click Next .
IMPORTANT
Don't select the Windows Forms App (.NET Framework ) template.
The following image shows both C# and Visual Basic .NET project templates. If you applied the code
language filter, you'll see the corresponding template.
6. In the Configure your new project window, set the Project name to Names and click Next .
You can also save your project to a different folder by adjusting the Location path.
7. Finally, in the Additional information window, select .NET 6.0 (Long-term suppor t) for the
Framework setting, and then click Create .
Once the app is generated, Visual Studio should open the designer pane for the default form, Form1. If the form
designer isn't visible, double-click on the form in the Solution Explorer pane to open the designer window.
Important parts of Visual Studio
Support for Windows Forms in Visual Studio has four important components that you'll interact with as you
create an app:
1. Solution Explorer
All of your project files, code, forms, resources, will appear in this pane.
2. Properties
This pane shows property settings you can configure based on the item selected. For example, if you
select an item from Solution Explorer , you'll see property settings related to the file. If you select an
object in the Designer , you'll see settings for the control or form.
3. Form Designer
This is the designer for the form. It's interactive and you can drag-and-drop objects from the Toolbox . By
selecting and moving items in the designer, you can visually compose the user interface (UI) for your app.
4. Toolbox
The toolbox contains all of the controls you can add to a form. To add a control to the current form,
double-click a control or drag-and-drop the control.
Text Names
Location 12, 27
Size 120, 94
Location 138, 26
Size 100, 23
Location 138, 55
Size 100, 23
You should have a form in the designer that looks similar to the following:
Handle events
Now that the form has all of its controls laid out, you need to handle the events of the controls to respond to
user input. With the form designer still open, perform the following steps:
1. Select the button control on the form.
2. In the Proper ties pane, click on the events icon to list the events of the button.
3. Find the Click event and double-click it to generate an event handler.
This action adds the following code to the the form:
End Sub
The code we'll put in this handler will add the name specified by the txtName textbox control to the
lstNames listbox control. However, we want there to be two conditions to adding the name: the name
provided must not be blank, and the name must not already exist.
4. The following code demonstrates adding a name to the lstNames control:
Next steps
Learn more about Windows Forms
How to migrate a Windows Forms desktop app to
.NET 5
9/23/2022 • 9 minutes to read • Edit Online
This article describes how to migrate a Windows Forms desktop app from .NET Framework to .NET 5 or later.
The .NET SDK includes support for Windows Forms applications. Windows Forms is still a Windows-only
framework and only runs on Windows.
Migrating your app from .NET Framework to .NET 5 generally requires a new project file. .NET 5 uses SDK-style
project files while .NET Framework typically uses the older Visual Studio project file. If you've ever opened a
Visual Studio project file in a text editor, you know how verbose it is. SDK-style projects are smaller and don't
require as many entries as the older project file format does.
To learn more about .NET 5, see Introduction to .NET.
Prerequisites
Visual Studio 2019 version 16.11 or later.
Select the Visual Studio Desktop workload.
Select the .NET 5 individual component.
Preview WinForms designer in Visual Studio.
To enable the designer, go to Tools > Options > Environment > Preview Features and select the Use
the preview Windows Forms designer for .NET Core apps option.
This article uses the Matching game sample app. If you want to follow along, download and open the
application in Visual Studio. Otherwise, use your own app.
Consider
When migrating a .NET Framework Windows Forms application, there are a few things you must consider.
1. Check that your application is a good candidate for migration.
Use the .NET Portability Analyzer to determine if your project will migrate to .NET 5. If your project has
issues with .NET 5, the analyzer helps you identify those problems. The .NET Portability Analyzer tool can
be installed as a Visual Studio extension or used from the command line. For more information, see .NET
Portability Analyzer.
2. You're using a different version of Windows Forms.
When .NET Core 3.0 was released, Windows Forms went open source on GitHub. The code for Windows
Forms for .NET 5 is a fork of the .NET Framework Windows Forms codebase. It's possible some
differences exist and your app will be difficult to migrate.
3. The Windows Compatibility Pack may help you migrate.
Some APIs that are available in .NET Framework aren't available in .NET 5. The Windows Compatibility
Pack adds many of these APIs and may help your Windows Forms app become compatible with .NET 5.
4. Update the NuGet packages used by your project.
It's always a good practice to use the latest versions of NuGet packages before any migration. If your
application is referencing any NuGet packages, update them to the latest version. Ensure your application
builds successfully. After upgrading, if there are any package errors, downgrade the package to the latest
version that doesn't break your code.
NuGet packages
If your project is referencing NuGet packages, you probably have a packages.config file in your project folder.
With SDK-style projects, NuGet package references are configured in the project file. Visual Studio project files
can optionally define NuGet packages in the project file too. .NET 5 doesn't use packages.config for NuGet
packages. NuGet package references must be migrated into the project file before migration.
To migrate the packages.config file, do the following steps:
1. In Solution explorer , find the project you're migrating.
2. Right-click on packages.config > Migrate packages.config to PackageReference .
3. Select all of the top-level packages.
A build report is generated to let you know of any issues migrating the NuGet packages.
Project file
The next step in migrating your app is converting the project file. As previously stated, .NET 5 uses SDK-style
project files and won't load the Visual Studio project files that .NET Framework uses. However, there's the
possibility that you're already using SDK-style projects. You can easily spot the difference in Visual Studio. Right-
click on the project file in Solution explorer and look for the Edit Project File menu option. If this menu item
is missing, you're using the old Visual Studio project format and need to upgrade.
Convert each project in your solution. If you're using the sample app previously referenced, both the
MatchingGame and MatchingGame.Logic projects would be converted.
To convert a project, do the following steps:
1. In Solution explorer , find the project you're migrating.
2. Right-click on the project and select Unload Project .
3. Right-click on the project and select Edit Project File .
4. Copy-and-paste the project XML into a text editor. You'll want a copy so that it's easy to move content into
the new project.
5. Erase the content of the file and paste the following XML:
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<OutputType>WinExe</OutputType>
<TargetFramework>net5.0-windows</TargetFramework>
<UseWindowsForms>true</UseWindowsForms>
<GenerateAssemblyInfo>false</GenerateAssemblyInfo>
</PropertyGroup>
</Project>
IMPORTANT
Libraries don't need to define an <OutputType> setting. Remove that entry if you're upgrading a library project.
This XML gives you the basic structure of the project. However, it doesn't contain any of the settings from the old
project file. Using the old project information you previously copied to a text editor, do the following steps:
1. Copy the following elements from the old project file into the <PropertyGroup> element in the new
project file:
<RootNamespace>
<AssemblyName>
Your project file should look similar to the following XML:
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<OutputType>WinExe</OutputType>
<TargetFramework>net5.0-windows</TargetFramework>
<UseWindowsForms>true</UseWindowsForms>
<GenerateAssemblyInfo>false</GenerateAssemblyInfo>
<RootNamespace>MatchingGame</RootNamespace>
<AssemblyName>MatchingGame</AssemblyName>
</PropertyGroup>
</Project>
2. Copy the <ItemGroup> elements from the old project file that contain <ProjectReference> or
<PackageReference> into the new file after the </PropertyGroup> closing tag.
Your project file should look similar to the following XML:
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
(contains settings previously described)
</PropertyGroup>
<ItemGroup>
<ProjectReference Include="..\MatchingGame.Logic\MatchingGame.Logic.csproj">
<Project>{36b3e6e2-a9ae-4924-89ae-7f0120ce08bd}</Project>
<Name>MatchingGame.Logic</Name>
</ProjectReference>
</ItemGroup>
<ItemGroup>
<PackageReference Include="MetroFramework">
<Version>1.2.0.3</Version>
</PackageReference>
</ItemGroup>
</Project>
The <ProjectReference> elements don't need the <Project> and <Name> children, so you can remove
those settings:
<ItemGroup>
<ProjectReference Include="..\MatchingGame.Logic\MatchingGame.Logic.csproj" />
</ItemGroup>
IMPORTANT
Visual Basic projects typically use the folder My Project while C# projects typically use the folder Properties for
the default project settings file.
Import the configuration for any resx file, such as the properties\Resources.resx file. Notice that the
Include attribute was set to Update on the <Compile> and <EmbeddedResource> element, and <SubType>
was removed from <EmbeddedResource> :
<ItemGroup>
<EmbeddedResource Update="Properties\Resources.resx">
<Generator>ResXFileCodeGenerator</Generator>
<LastGenOutput>Resources.Designer.cs</LastGenOutput>
</EmbeddedResource>
<Compile Update="Properties\Resources.Designer.cs">
<AutoGen>True</AutoGen>
<DependentUpon>Resources.resx</DependentUpon>
<DesignTime>True</DesignTime>
</Compile>
</ItemGroup>
IMPORTANT
Visual Basic projects typically use the folder My Project while C# projects typically use the folder Properties for
the default project resource file.
Visual Basic
Visual Basic language projects require extra configuration.
1. Import the configuration file My Project\Application.myapp setting. Notice that the <Compile> element
uses the Update attribute instead of the Include attribute.
<ItemGroup>
<None Include="My Project\Application.myapp">
<Generator>MyApplicationCodeGenerator</Generator>
<LastGenOutput>Application.Designer.vb</LastGenOutput>
</None>
<Compile Update="My Project\Application.Designer.vb">
<AutoGen>True</AutoGen>
<DependentUpon>Application.myapp</DependentUpon>
<DesignTime>True</DesignTime>
</Compile>
</ItemGroup>
2. Add the <MyType>WindowsForms</MyType> setting to the <PropertyGroup> element:
<PropertyGroup>
(contains settings previously described)
<MyType>WindowsForms</MyType>
</PropertyGroup>
This setting imports the My namespace members Visual Basic programmers are familiar with.
3. Import the namespaces defined by your project.
Visual Basic projects can automatically import namespaces into every code file. Copy the <ItemGroup>
elements from the old project file that contain <Import> into the new file after the </PropertyGroup>
closing tag.
<ItemGroup>
<Import Include="Microsoft.VisualBasic" />
<Import Include="System" />
<Import Include="System.Collections" />
<Import Include="System.Collections.Generic" />
<Import Include="System.Data" />
<Import Include="System.Drawing" />
<Import Include="System.Diagnostics" />
<Import Include="System.Windows.Forms" />
<Import Include="System.Linq" />
<Import Include="System.Xml.Linq" />
<Import Include="System.Threading.Tasks" />
</ItemGroup>
If you can't find any <Import> statements, or your project fails to compile, make sure you at least have
the following <Import> statements defined in your project:
<ItemGroup>
<Import Include="System.Data" />
<Import Include="System.Drawing" />
<Import Include="System.Windows.Forms" />
</ItemGroup>
4. From the original project, copy the <Option*> and <StartupObject> settings to the <PropertyGroup>
element:
<PropertyGroup>
(contains settings previously described)
<OptionExplicit>On</OptionExplicit>
<OptionCompare>Binary</OptionCompare>
<OptionStrict>Off</OptionStrict>
<OptionInfer>On</OptionInfer>
<StartupObject>MatchingGame.My.MyApplication</StartupObject>
</PropertyGroup>
Edit App.config
If your app has an App.config file, remove the <supportedRuntime> element:
There are some things you should consider with the App.config file. The App.config file in .NET Framework was
used not only to configure the app, but to configure runtime settings and behavior, such as logging. The
App.config file in .NET 5+ (and .NET Core) is no longer used for runtime configuration. If your App.config file has
these sections, they won't be respected.
<ItemGroup>
<PackageReference Include="Microsoft.Windows.Compatibility" Version="5.0.0" />
</ItemGroup>
Next steps
Try the .NET Upgrade Assistant to migrate your app.
Learn about breaking changes in Windows Forms.
Read more about the Windows Compatibility Pack.
Events overview (Windows Forms .NET)
9/23/2022 • 2 minutes to read • Edit Online
An event is an action that you can respond to, or "handle," in code. Events can be generated by a user action,
such as clicking the mouse or pressing a key, by program code, or by the system.
IMPORTANT
The Desktop Guide documentation for .NET 6 and .NET 5 (including .NET Core 3.1) is under construction.
Event-driven applications execute code in response to an event. Each form and control exposes a predefined set
of events that you can program against. If one of these events occurs and there's code an associated event
handler, that code is invoked.
The types of events raised by an object vary, but many types are common to most controls. For example, most
objects will handle a Click event. If a user clicks a form, code in the form's Click event handler is executed.
NOTE
Many events occur in conjunction with other events. For example, in the course of the DoubleClick event occurring, the
MouseDown, MouseUp, and Click events occur.
For information about how to raise and consume an event, see Handling and raising events.
See also
Handling and raising events
Automatic scaling (Windows Forms .NET)
9/23/2022 • 3 minutes to read • Edit Online
Automatic scaling enables a form and its controls, designed on one machine with a certain display resolution or
font, to be displayed appropriately on another machine with a different display resolution or font. It assures that
the form and its controls will intelligently resize to be consistent with native windows and other applications on
both the users' and other developers' machines. Automatic scaling and visual styles enable Windows Forms
applications to maintain a consistent look-and-feel when compared to native Windows applications on each
user's machine.
For the most part, automatic scaling works as expected in Windows Forms. However, font scheme changes can
be problematic.
IMPORTANT
The Desktop Guide documentation for .NET 6 and .NET 5 (including .NET Core 3.1) is under construction.
Arbitrary mixtures of DPI and font scaling modes are not supported. Although you may scale a user control
using one mode (for example, DPI) and place it on a form using another mode (Font) with no issues, but mixing
a base form in one mode and a derived form in another can lead to unexpected results.
See also
AutoScaleMode
Scale
PerformAutoScale
AutoScaleDimensions
How to add a form to a project (Windows Forms
.NET)
9/23/2022 • 2 minutes to read • Edit Online
Add forms to your project with Visual Studio. When your app has multiple forms, you can choose which is the
startup form for your app, and you can display multiple forms at the same time.
IMPORTANT
The Desktop Guide documentation for .NET 6 and .NET 5 (including .NET Core 3.1) is under construction.
2. In the Name box, type a name for your form, such as MyNewForm. Visual Studio will provide a default
and unique name that you may use.
Once the form has been added, Visual Studio opens the form designer for the form.
See also
How to position and size a form (Windows Forms .NET)
Events overview (Windows Forms .NET)
Position and layout of controls (Windows Forms .NET)
How to position and size a form (Windows Forms
.NET)
9/23/2022 • 4 minutes to read • Edit Online
When a form is created, the size and location is initially set to a default value. The default size of a form is
generally a width and height of 800x500 pixels. The initial location, when the form is displayed, depends on a
few different settings.
You can change the size of a form at design time with Visual Studio, and at run time with code.
IMPORTANT
The Desktop Guide documentation for .NET 6 and .NET 5 (including .NET Core 3.1) is under construction.
The second way you can resize the form while the designer is open, is through the properties pane. Select the
form, then find the Proper ties pane in Visual Studio. Scroll down to size and expand it. You can set the Width
and Height manually.
Resize in code
Even though the designer sets the starting size of a form, you can resize it through code. Using code to resize a
form is useful when something about your application determines that the default size of the form is
insufficient.
To resize a form, change the Size, which represents the width and height of the form.
Resize the current form
You can change the size of the current form as long as the code is running within the context of the form. For
example, if you have Form1 with a button on it, that when clicked invokes the Click event handler to resize the
form:
If the Size isn't manually set, the form's default size is what it was set to during design-time.
CenterParent The form is centered within the bounds of its parent form.
The CenterParent value only works with forms that are either a multiple document interface (MDI) child form, or
a normal form that is displayed with the ShowDialog method. CenterParent has no affect on a normal form that
is displayed with the Show method. To center a form ( form variable) to another form ( parentForm variable), use
the following code:
form.StartPosition = FormStartPosition.Manual;
form.Location = new Point(parentForm.Width / 2 - form.Width / 2 + parentForm.Location.X,
parentForm.Height / 2 - form.Height / 2 + parentForm.Location.Y);
form.Show();
form.StartPosition = Windows.Forms.FormStartPosition.CenterParent.Manual
form.Location = New Drawing.Point(parentForm.Width / 2 - form.Width / 2 + parentForm.Location.X,
parentForm.Height / 2 - form.Height / 2 + parentForm.Location.Y)
form.Show()
If the Location isn't set, the form's default position is based on what the StartPosition property was set to at
design-time.
See also
How to add a form to a project (Windows Forms .NET)
Events overview (Windows Forms .NET)
Position and layout of controls (Windows Forms .NET)
How to position and size a form (Windows Forms
.NET)
9/23/2022 • 4 minutes to read • Edit Online
When a form is created, the size and location is initially set to a default value. The default size of a form is
generally a width and height of 800x500 pixels. The initial location, when the form is displayed, depends on a
few different settings.
You can change the size of a form at design time with Visual Studio, and at run time with code.
IMPORTANT
The Desktop Guide documentation for .NET 6 and .NET 5 (including .NET Core 3.1) is under construction.
The second way you can resize the form while the designer is open, is through the properties pane. Select the
form, then find the Proper ties pane in Visual Studio. Scroll down to size and expand it. You can set the Width
and Height manually.
Resize in code
Even though the designer sets the starting size of a form, you can resize it through code. Using code to resize a
form is useful when something about your application determines that the default size of the form is
insufficient.
To resize a form, change the Size, which represents the width and height of the form.
Resize the current form
You can change the size of the current form as long as the code is running within the context of the form. For
example, if you have Form1 with a button on it, that when clicked invokes the Click event handler to resize the
form:
If the Size isn't manually set, the form's default size is what it was set to during design-time.
CenterParent The form is centered within the bounds of its parent form.
The CenterParent value only works with forms that are either a multiple document interface (MDI) child form, or
a normal form that is displayed with the ShowDialog method. CenterParent has no affect on a normal form that
is displayed with the Show method. To center a form ( form variable) to another form ( parentForm variable), use
the following code:
form.StartPosition = FormStartPosition.Manual;
form.Location = new Point(parentForm.Width / 2 - form.Width / 2 + parentForm.Location.X,
parentForm.Height / 2 - form.Height / 2 + parentForm.Location.Y);
form.Show();
form.StartPosition = Windows.Forms.FormStartPosition.CenterParent.Manual
form.Location = New Drawing.Point(parentForm.Width / 2 - form.Width / 2 + parentForm.Location.X,
parentForm.Height / 2 - form.Height / 2 + parentForm.Location.Y)
form.Show()
If the Location isn't set, the form's default position is based on what the StartPosition property was set to at
design-time.
See also
How to add a form to a project (Windows Forms .NET)
Events overview (Windows Forms .NET)
Position and layout of controls (Windows Forms .NET)
Overview of using controls (Windows Forms .NET)
9/23/2022 • 2 minutes to read • Edit Online
Windows Forms controls are reusable components that encapsulate user interface functionality and are used in
client-side, Windows-based applications. Not only does Windows Forms provide many ready-to-use controls, it
also provides the infrastructure for developing your own controls. You can combine existing controls, extend
existing controls, or author your own custom controls. For more information, see Types of custom controls.
IMPORTANT
The Desktop Guide documentation for .NET 6 and .NET 5 (including .NET Core 3.1) is under construction.
Adding controls
Controls are added through the Visual Studio Designer. With the Designer, you can place, size, align, and move
controls. Alternatively, controls can be added through code. For more information, see Add a control (Windows
Forms).
Layout options
The position a control appears on a parent is determined by the value of the Location property relative to the
top-left of the parent surface. The top-left position coordinate in the parent is (x0,y0) . The size of the control is
determined by the Size property and represents the width and height of the control.
Besides manual positioning and sizing, various container controls are provided that help with automatic
placement of controls.
For more information, see Position and layout of controls and How to dock and anchor controls.
Control events
Controls provide a set of common events through the base class: Control. Not every control responds to every
event. For example, the Label control doesn't respond to keyboard input, so the Control.PreviewKeyDown event
isn't raised. Most shared events fall under these categories:
Mouse events
Keyboard events
Property changed events
Other events
For more information, see Control events and How to handle a control event.
Control accessibility
Windows Forms has accessibility support for screen readers and voice input utilities for verbal commands.
However, you must design your UI with accessibility in mind. Windows Forms controls expose various
properties to handle accessibility. For more information about these properties, see Providing Accessibility
Information for Controls.
See also
Position and layout of controls
Label control overview
Control events
Types of custom controls
Painting and drawing on controls
Providing Accessibility Information for Controls
Position and layout of controls (Windows Forms
.NET)
9/23/2022 • 12 minutes to read • Edit Online
Control placement in Windows Forms is determined not only by the control, but also by the parent of the
control. This article describes the different settings provided by controls and the different types of parent
containers that affect layout.
IMPORTANT
The Desktop Guide documentation for .NET 6 and .NET 5 (including .NET Core 3.1) is under construction.
When a control is added to a parent that enforces automatic placement, the position and size of the control is
changed. In this case, the position and size of the control may not be manually adjusted, depending on the type
of parent.
The MaximumSize and MinimumSize properties help set the minimum and maximum space a control can use.
When a control is docked, the container determines the space it should occupy and resizes and places the
control. The width and height of the control are still respected based on the docking style. For example, if the
control is docked to the top, the Height of the control is respected but the Width is automatically adjusted. If a
control is docked to the left, the Width of the control is respected but the Height is automatically adjusted.
The Location of the control can't be manually set as docking a control automatically controls its position.
The Z-order of the control does affect docking. As docked controls are laid out, they use what space is available
to them. For example, if a control is drawn first and docked to the top, it will take up the entire width of the
container. If a next control is docked to the left, it has less vertical space available to it.
If the control's Z-order is reversed, the control that is docked to the left now has more initial space available.
The control uses the entire height of the container. The control that is docked to the top has less horizontal space
available to it.
As the container grows and shrinks, the controls docked to the container are repositioned and resized to
maintain their applicable positions and sizes.
If multiple controls are docked to the same side of the container, they're stacked according to their Z-order .
Anchor
Anchoring a control allows you to tie the control to one or more sides of the parent container. As the container
changes in size, any child control will maintain its distance to the anchored side.
A control can be anchored to one or more sides, without restriction. The anchor is set with the Anchor property.
Automatic sizing
The AutoSize property enables a control to change its size, if necessary, to fit the size specified by the
PreferredSize property. You adjust the sizing behavior for specific controls by setting the AutoSizeMode property.
Only some controls support the AutoSize property. In addition, some controls that support the AutoSize
property also supports the AutoSizeMode property.
Automatic sizing is a run-time feature. This means it never grows or shrinks a control and then has
no further effect.
If a control changes size, the value of its Location property When a control's contents cause it to grow, the control
always remains constant. grows toward the right and downward. Controls do not
grow to the left.
The Dock and Anchor properties are honored when AutoSize The value of the control's Location property is adjusted to
is true . the correct value.
The Label control is the exception to this rule. When you set
the value of a docked Label control's AutoSize property to
true , the Label control will not stretch.
A control's MaximumSize and MinimumSize properties are The MaximumSize and MinimumSize properties are not
always honored, regardless of the value of its AutoSize affected by the AutoSize property.
property.
There is no minimum size set by default. This means that if a control is set to shrink under AutoSize
and it has no contents, the value of its Size property is
(0x,0y) . In this case, your control will shrink to a point,
and it will not be readily visible.
If a control does not implement the GetPreferredSize This means that setting AutoSize to true will have no
method, the GetPreferredSize method returns last value effect.
assigned to the Size property.
A L WAY S T RUE B EH AVIO R DESC RIP T IO N
A control in a TableLayoutPanel cell always shrinks to fit in This size is enforced as a maximum size. This is not the case
the cell until its MinimumSize is reached. when the cell is part of an AutoSize row or column.
AutoSizeMode property
The AutoSizeMode property provides more fine-grained control over the default AutoSize behavior. The
AutoSizeMode property specifies how a control sizes itself to its content. The content, for example, could be the
text for a Button control or the child controls for a container.
The following list shows the AutoSizeMode values and its behavior.
AutoSizeMode.GrowAndShrink
The control grows or shrinks to encompass its contents.
The MinimumSize and MaximumSize values are honored, but the current value of the Size property is
ignored.
This is the same behavior as controls with the AutoSize property and no AutoSizeMode property.
AutoSizeMode.GrowOnly
The control grows as much as necessary to encompass its contents, but it will not shrink smaller than the
value specified by its Size property.
This is the default value for AutoSizeMode .
Controls that support the AutoSize property
The following table describes the level of auto sizing support by control:
Button ️
✔ ️
✔
CheckedListBox ️
✔ ️
✔
FlowLayoutPanel ️
✔ ️
✔
Form ️
✔ ️
✔
GroupBox ️
✔ ️
✔
Panel ️
✔ ️
✔
TableLayoutPanel ️
✔ ️
✔
CheckBox ️
✔ ❌
DomainUpDown ️
✔ ❌
Label ️
✔ ❌
LinkLabel ️
✔ ❌
MaskedTextBox ️
✔ ❌
C O N T RO L AUTOSIZE SUP P O RT ED AUTOSIZEMODE SUP P O RT ED
NumericUpDown ️
✔ ❌
RadioButton ️
✔ ❌
TextBox ️
✔ ❌
TrackBar ️
✔ ❌
CheckedListBox ❌ ❌
ComboBox ❌ ❌
DataGridView ❌ ❌
DateTimePicker ❌ ❌
ListBox ❌ ❌
ListView ❌ ❌
MaskedTextBox ❌ ❌
MonthCalendar ❌ ❌
ProgressBar ❌ ❌
PropertyGrid ❌ ❌
RichTextBox ❌ ❌
SplitContainer ❌ ❌
TabControl ❌ ❌
TabPage ❌ ❌
TreeView ❌ ❌
WebBrowser ❌ ❌
ScrollBar ❌ ❌
true Property not available. The user can't resize the control at
design time, except for the following
controls:
- TextBox
- MaskedTextBox
- RichTextBox
- TrackBar
false or AutoSize is hidden Not applicable. User can resize the control at design
time.
NOTE
To maximize productivity, the Windows Forms Designer in Visual Studio shadows the AutoSize property for the Form class.
At design time, the form behaves as though the AutoSize property is set to false , regardless of its actual setting. At
runtime, no special accommodation is made, and the AutoSize property is applied as specified by the property setting.
Container: Form
The Form is the main object of Windows Forms. A Windows Forms application will usually have a form
displayed at all times. Forms contain controls and respect the Location and Size properties of the control for
manual placement. Forms also respond to the Dock property for automatic placement.
Most of the time a form will have grips on the edges that allow the user to resize the form. The Anchor property
of a control will let the control grow and shrink as the form is resized.
Container: Panel
The Panel control is similar to a form in that it simply groups controls together. It supports the same manual and
automatic placement styles that a form does. For more information, see the Container: Form section.
A panel blends in seamlessly with the parent, and it does cut off any area of a control that falls out of bounds of
the panel. If a control falls outside the bounds of the panel and AutoScroll is set to true , scroll bars appear and
the user can scroll the panel.
Unlike the group box control, a panel doesn't have a caption and border.
The image above has a panel with the BorderStyle property set to demonstrate the bounds of the panel.
The image above has a table with the CellBorderStyle property set to demonstrate the bounds of each cell.
The image above has a split container to create a left and right pane. The right pane contains a second split
container with the Orientation set to Vertical. The BorderStyle property is set to demonstrate the bounds of each
panel.
Windows Forms Label controls are used to display text that cannot be edited by the user. They're used to identify
objects on a form and to provide a description of what a certain control represents or does. For example, you
can use labels to add descriptive captions to text boxes, list boxes, combo boxes, and so on. You can also write
code that changes the text displayed by a label in response to events at run time.
IMPORTANT
The Desktop Guide documentation for .NET 6 and .NET 5 (including .NET Core 3.1) is under construction.
See also
Use a label to focus a control (Windows Forms .NET)
How to: Set the text displayed by a control (Windows Forms .NET)
AutoScaleMode
Scale
PerformAutoScale
AutoScaleDimensions
Control events (Windows Forms .NET)
9/23/2022 • 3 minutes to read • Edit Online
Controls provide events that are raised when the user interacts with the control or when the state of the control
changes. This article describes the common events shared by most controls, events raised by user interaction,
and events unique to specific controls. For more information about events in Windows Forms, see Events
overview and Handling and raising events.
IMPORTANT
The Desktop Guide documentation for .NET 6 and .NET 5 (including .NET Core 3.1) is under construction.
For more information about how to add or remove a control event handler, see How to handle an event.
Common events
Controls provide a set of common events through the base class: Control. Not every control responds to every
event. For example, the Label control doesn't respond to keyboard input, so the Control.PreviewKeyDown event
isn't raised. Most shared events fall under these categories:
Mouse events
Keyboard events
Property changed events
Other events
Mouse events
Considering Windows Forms is a User Interface (UI) technology, mouse input is the primary way users interact
with a Windows Forms application. All controls provide basic mouse-related events:
MouseClick
MouseDoubleClick
MouseDown
MouseEnter
MouseHover
MouseLeave
MouseMove
MouseUp
MouseWheel
Click
For more information, see Using mouse events.
Keyboard events
If the control responds to user input, such as a TextBox or Button control, the appropriate input event is raised
for the control. The control must be focused to receive keyboard events. Some controls, such as the Label
control, can't be focused and can't receive keyboard events. The following is a list of keyboard events:
KeyDown
KeyPress
KeyUp
For more information, see Using keyboard events.
If the property set modifies the backing value, the OnFirstNameChanged method is called. The
FirstName
OnFirstNameChanged method raises the FirstNameChanged event.
Here are some of the common property changed events for a control:
For a full list of events, see the Events section of the Control Class.
Other events
Controls will also raise events based on the state of the control, or other interactions with the control. For
example, the HelpRequested event is raised if the control has focus and the user presses the F1 key. This event is
also raised if the user presses the context-sensitive Help button on a form, and then presses the help cursor on
the control.
Another example is when a control is changed, moved, or resized, the Paint event is raised. This event provides
the developer with the opportunity to draw on the control and change its appearance.
For a full list of events, see the Events section of the Control Class.
See also
How to handle an event
Events overview
Using mouse events
Using keyboard events
System.Windows.Forms.Control
System.Windows.Forms.Control.Click
System.Windows.Forms.Button
Types of custom controls (Windows Forms .NET)
9/23/2022 • 4 minutes to read • Edit Online
With Windows Forms, you can develop and implement new controls. You can create a new user control, modify
existing controls through inheritance, and write a custom control that does its own painting.
IMPORTANT
The Desktop Guide documentation for .NET 6 and .NET 5 (including .NET Core 3.1) is under construction.
Deciding which kind of control to create can be confusing. This article highlights the differences among the
various kinds of controls from which you can inherit, and provides you with information about how to choose a
particular type of control for your project.
IF . . . C REAT E A . . .
You want to combine the functionality of several Composite control by inheriting from
Windows Forms controls into a single reusable unit. System.Windows.Forms.UserControl.
Most of the functionality you need is already identical Extended control by inheriting from a specific Windows
to an existing Windows Forms control. Forms control.
You don't need a custom graphical user interface, or
you want to design a new graphical user interface for
an existing control.
Composite Controls
A composite control is a collection of Windows Forms controls encapsulated in a common container. This kind of
control is sometimes called a user control. The contained controls are called constituent controls.
A composite control holds all of the inherent functionality associated with each of the contained Windows
Forms controls and enables you to selectively expose and bind their properties. A composite control also
provides a great deal of default keyboard handling functionality with no extra development effort on your part.
For example, a composite control could be built to display customer address data from a database. This control
would include a DataGridView control to display the database fields, a BindingSource to handle binding to a
data source, and a BindingNavigator control to move through the records. You could selectively expose data
binding properties, and you could package and reuse the entire control from application to application.
To author a composite control, derive from the UserControl class. The UserControl base class provides keyboard
routing for child controls and enables child controls to work as a group.
Extended Controls
You can derive an inherited control from any existing Windows Forms control. With this approach, you can keep
all of the inherent functionality of a Windows Forms control, and then extend that functionality by adding
custom properties, methods, or other features. With this option, you can override the base control's paint logic,
and then extend its user interface by changing its appearance.
For example, you can create a control derived from the Button control that tracks how many times a user has
clicked it.
In some controls, you can also add a custom appearance to the graphical user interface of your control by
overriding the OnPaint method of the base class. For an extended button that tracks clicks, you can override the
OnPaint method to call the base implementation of OnPaint, and then draw the click count in one corner of the
Button control's client area.
Custom Controls
Another way to create a control is to create one substantially from the beginning by inheriting from Control. The
Control class provides all of the basic functionality required by controls, including mouse and keyboard
handling events, but no control-specific functionality or graphical interface.
Creating a control by inheriting from the Control class requires much more thought and effort than inheriting
from UserControl or an existing Windows Forms control. Because a great deal of implementation is left for you,
your control can have greater flexibility than a composite or extended control, and you can tailor your control to
suit your exact needs.
To implement a custom control, you must write code for the OnPaint event of the control, as well as any feature-
specific code you need. You can also override the WndProc method and handle windows messages directly. This
is the most powerful way to create a control, but to use this technique effectively, you need to be familiar with
the Microsoft Win32® API.
An example of a custom control is a clock control that duplicates the appearance and behavior of an analog
clock. Custom painting is invoked to cause the hands of the clock to move in response to Tick events from an
internal Timer component.
ActiveX Controls
Although the Windows Forms infrastructure has been optimized to host Windows Forms controls, you can still
use ActiveX controls. There's support for this task in Visual Studio.
Windowless Controls
The Microsoft Visual Basic® 6.0 and ActiveX technologies support windowless controls. Windowless controls
aren't supported in Windows Forms.
See also
Overview of Using Controls (Windows Forms .NET)
Painting and drawing on controls (Windows Forms
.NET)
9/23/2022 • 5 minutes to read • Edit Online
Custom painting of controls is one of the many complicated tasks made easy by Windows Forms. When
authoring a custom control, you have many options available to handle your control's graphical appearance. If
you're authoring a custom control, that is, a control that inherits from Control, you must provide code to render
its graphical representation.
IMPORTANT
The Desktop Guide documentation for .NET 6 and .NET 5 (including .NET Core 3.1) is under construction.
If you're creating a composite control, that is a control that inherits from UserControl or one of the existing
Windows Forms controls, you may override the standard graphical representation and provide your own
graphics code.
If you want to provide custom rendering for an existing control without creating a new control, your options
become more limited. However, there are still a wide range of graphical possibilities for your controls and
applications.
The following elements are involved in control rendering:
The drawing functionality provided by the base class System.Windows.Forms.Control.
The essential elements of the GDI graphics library.
The geometry of the drawing region.
The procedure for freeing graphics resources.
Graphics is a managed class that encapsulates drawing functionality, as described in the discussion of GDI later
in this article. The ClipRectangle is an instance of the Rectangle structure and defines the available area in which
a control can draw. A control developer can compute the ClipRectangle using the ClipRectangle property of a
control, as described in the discussion of geometry later in this article.
OnPaint
A control must provide rendering logic by overriding the OnPaint method that it inherits from Control. OnPaint
gets access to a graphics object and a rectangle to draw in through the Graphics and the ClipRectangle
properties of the PaintEventArgs instance passed to it.
The following code uses the System.Drawing namespace:
// Declare and instantiate a new pen that will be disposed of at the end of the method.
using var myPen = new Pen(Color.Aqua);
// Create a rectangle that represents the size of the control, minus 1 pixel.
var area = new Rectangle(new Point(0, 0), new Size(this.Size.Width - 1, this.Size.Height - 1));
' Create a rectangle that represents the size of the control, minus 1 pixel.
Dim area = New Rectangle(New Point(0, 0), New Size(Me.Size.Width - 1, Me.Size.Height - 1))
End Using
End Sub
The OnPaint method of the base Control class doesn't implement any drawing functionality but merely invokes
the event delegates that are registered with the Paint event. When you override OnPaint, you should typically
invoke the OnPaint method of the base class so that registered delegates receive the Paint event. However,
controls that paint their entire surface shouldn't invoke the base class's OnPaint, as this introduces flicker.
NOTE
Don't invoke OnPaint directly from your control; instead, invoke the Invalidate method (inherited from Control) or some
other method that invokes Invalidate. The Invalidate method in turn invokes OnPaint. The Invalidate method is
overloaded, and, depending on the arguments supplied to Invalidate e , redraws either some or all of its screen area.
The code in the OnPaint method of your control will execute when the control is first drawn, and whenever it is
refreshed. To ensure that your control is redrawn every time it is resized, add the following line to the
constructor of your control:
SetStyle(ControlStyles.ResizeRedraw, true);
SetStyle(ControlStyles.ResizeRedraw, True)
OnPaintBackground
The base Control class defines another method that is useful for drawing, the OnPaintBackground method.
OnPaintBackground paints the background (and in that way, the shape) of the window and is guaranteed to be
fast, while OnPaint paints the details and might be slower because individual paint requests are combined into
one Paint event that covers all areas that have to be redrawn. You might want to invoke the OnPaintBackground
if, for instance, you want to draw a gradient-colored background for your control.
While OnPaintBackground has an event-like nomenclature and takes the same argument as the OnPaint
method, OnPaintBackground is not a true event method. There is no PaintBackground event and
OnPaintBackground doesn't invoke event delegates. When overriding the OnPaintBackground method, a derived
class is not required to invoke the OnPaintBackground method of its base class.
GDI+ Basics
The Graphics class provides methods for drawing various shapes such as circles, triangles, arcs, and ellipses, and
methods for displaying text. The System.Drawing namespace contains namespaces and classes that encapsulate
graphics elements such as shapes (circles, rectangles, arcs, and others), colors, fonts, brushes, and so on.
See also
Types of custom controls
Providing Accessibility Information for Controls
(Windows Forms .NET)
9/23/2022 • 2 minutes to read • Edit Online
Accessibility aids are specialized programs and devices that help people with disabilities use computers more
effectively. Examples include screen readers for people who are blind and voice input utilities for people who
provide verbal commands instead of using the mouse or keyboard. These accessibility aids interact with the
accessibility properties exposed by Windows Forms controls. These properties are:
System.Windows.Forms.AccessibleObject
System.Windows.Forms.Control.AccessibleDefaultActionDescription
System.Windows.Forms.Control.AccessibleDescription
System.Windows.Forms.Control.AccessibleName
System.Windows.Forms.AccessibleRole
IMPORTANT
The Desktop Guide documentation for .NET 6 and .NET 5 (including .NET Core 3.1) is under construction.
AccessibilityObject Property
This read-only property contains an AccessibleObject instance. The AccessibleObject implements the
IAccessible interface, which provides information about the control's description, screen location, navigational
abilities, and value. The designer sets this value when the control is added to the form.
AccessibleDefaultActionDescription Property
This string describes the action of the control. It does not appear in the Properties window and may only be set
in code. The following example sets the AccessibleDefaultActionDescription property for a button control:
AccessibleDescription Property
This string describes the control. The AccessibleDescription property may be set in the Properties window, or in
code as follows:
AccessibleName Property
This is the name of a control reported to accessibility aids. The AccessibleName property may be set in the
Properties window, or in code as follows:
Button1.AccessibleName = "Order"
button1.AccessibleName = "Order";
AccessibleRole Property
This property, which contains an AccessibleRole enumeration, describes the user interface role of the control. A
new control has the value set to Default . This would mean that by default, a Button control acts as a Button .
You may want to reset this property if a control has another role. For example, you may be using a PictureBox
control as a Chart , and you may want accessibility aids to report the role as a Chart , not as a PictureBox . You
may also want to specify this property for custom controls you have developed. This property may be set in the
Properties window, or in code as follows:
PictureBox1.AccessibleRole = AccessibleRole.Chart
pictureBox1.AccessibleRole = AccessibleRole.Chart;
See also
Label control overview (Windows Forms .NET)
AccessibleObject
Control.AccessibilityObject
Control.AccessibleDefaultActionDescription
Control.AccessibleDescription
Control.AccessibleName
Control.AccessibleRole
AccessibleRole
Add a control to a form (Windows Forms .NET)
9/23/2022 • 2 minutes to read • Edit Online
Most forms are designed by adding controls to the surface of the form to define a user interface (UI). A control is
a component on a form used to display information or accept user input.
The primary way a control is added to a form is through the Visual Studio Designer, but you can also manage
the controls on a form at run time through code.
IMPORTANT
The Desktop Guide documentation for .NET 6 and .NET 5 (including .NET Core 3.1) is under construction.
Controls.Add(label1);
Controls.Add(field1);
Controls.Add(label1)
Controls.Add(field1)
See also
Set the Text Displayed by a Windows Forms Control
Add an access key shortcut to a control
System.Windows.Forms.Label
System.Windows.Forms.TextBox
System.Windows.Forms.Button
Add an access key shortcut to a control (Windows
Forms .NET)
9/23/2022 • 2 minutes to read • Edit Online
An access key is an underlined character in the text of a menu, menu item, or the label of a control such as a
button. With an access key, the user can "click" a button by pressing the Alt key in combination with the
predefined access key. For example, if a button runs a procedure to print a form, and therefore its Text
property is set to "Print," adding an ampersand (&) before the letter "P" causes the letter "P" to be underlined in
the button text at run time. The user can run the command associated with the button by pressing Alt.
Controls that cannot receive focus can't have access keys, except label controls.
IMPORTANT
The Desktop Guide documentation for .NET 6 and .NET 5 (including .NET Core 3.1) is under construction.
Designer
In the Proper ties window of Visual Studio, set the Text property to a string that includes an ampersand (&)
before the letter that will be the access key. For example, to set the letter "P" as the access key, enter &Print .
Programmatic
Set the Text property to a string that includes an ampersand (&) before the letter that will be the shortcut.
Display an ampersand
When setting the text or caption of a control that interprets an ampersand (&) as an access key, use two
consecutive ampersands (&&) to display a single ampersand. For example, the text of a button set to
"Print && Close" displays in the caption of Print & Close :
See also
Set the text displayed by a Windows Forms control
System.Windows.Forms.Button
System.Windows.Forms.Label
How to: Set the text displayed by a control
(Windows Forms .NET)
9/23/2022 • 2 minutes to read • Edit Online
Windows Forms controls usually display some text that's related to the primary function of the control. For
example, a Button control usually displays a caption indicating what action will be performed if the button is
clicked. For all controls, you can set or return the text by using the Text property. You can change the font by
using the Font property.
You can also set the text by using the designer.
IMPORTANT
The Desktop Guide documentation for .NET 6 and .NET 5 (including .NET Core 3.1) is under construction.
Designer
1. In the Proper ties window in Visual Studio, set the Text property of the control to an appropriate string.
To create an underlined shortcut key, include an ampersand (&) before the letter that will be the shortcut
key.
2. In the Proper ties window, select the ellipsis button ( ) next to the Font property.
In the standard font dialog box, adjust the font with settings such as type, size, and style.
Programmatic
1. Set the Text property to a string.
To create an underlined access key, include an ampersand (&) before the letter that will be the access key.
2. Set the Font property to an object of type Font.
NOTE
You can use an escape character to display a special character in user-interface elements that would normally
interpret them differently, such as menu items. For example, the following line of code sets the menu item's text to
read "& Now For Something Completely Different":
MPMenuItem.Text = "&& Now For Something Completely Different"
See also
Create Access Keys for Windows Forms Controls
System.Windows.Forms.Control.Text
How to set the tab order on Windows Forms
(Windows Forms .NET)
9/23/2022 • 2 minutes to read • Edit Online
The tab order is the order in which a user moves focus from one control to another by pressing the Tab key.
Each form has its own tab order. By default, the tab order is the same as the order in which you created the
controls. Tab-order numbering begins with zero and ascends in value, and is set with the TabIndex property.
You can also set the tab order by using the designer.
IMPORTANT
The Desktop Guide documentation for .NET 6 and .NET 5 (including .NET Core 3.1) is under construction.
Tab order can be set in the Proper ties window of the designer using the TabIndex property. The TabIndex
property of a control determines where it's positioned in the tab order. By default, the first control added to the
designer has a TabIndex value of 0, the second has a TabIndex of 1, and so on. Once the highest TabIndex has
been focused, pressing Tab will cycle and focus the control with the lowest TabIndex value.
Container controls, such as a GroupBox control, treat their children as separate from the rest of the form. Each
child in the container has its own TabIndex value. Because a container control can't be focused, when the tab
order reaches the container control, the child control of the container with the lowest TabIndex is focused. As
the Tab is pressed, each child control is focused according to its TabIndex value until the last control. When Tab
is pressed on the last control, focus resumes to the next control in the parent of the container, based on the next
TabIndex value.
Any control of the many on your form can be skipped in the tab order. Usually, pressing Tab successively at run
time selects each control in the tab order. By turning off the TabStop property, a control is passed over in the tab
order of the form.
Designer
Use the Visual Studio designer Proper ties window to set the tab order of a control.
1. Select the control in the designer.
2. In the Proper ties window in Visual Studio, set the TabIndex property of the control to an appropriate
number.
Programmatic
1. Set the TabIndex property to a numerical value.
Button1.TabIndex = 1
Button1.TabIndex = 1;
NOTE
A radio button group has a single tab stop at run-time. The selected button, the button with its Checked property set to
true , has its TabStop property automatically set to true . Other buttons in the radio button group have their
TabStop property set to false .
Button1.TabStop = false;
Button1.TabStop = False
See also
Add a control to a form
System.Windows.Forms.Control.TabIndex
System.Windows.Forms.Control.TabStop
How to dock and anchor controls (Windows Forms
.NET)
9/23/2022 • 3 minutes to read • Edit Online
If you're designing a form that the user can resize at run time, the controls on your form should resize and
reposition properly. Controls have two properties that help with automatic placement and sizing, when the form
changes size.
IMPORTANT
The Desktop Guide documentation for .NET 6 and .NET 5 (including .NET Core 3.1) is under construction.
Control.Dock
Controls that are docked fill the edges of the control's container, either the form or a container control.
For example, Windows Explorer docks its TreeView control to the left side of the window and its ListView
control to the right side of the window. The docking mode can be any side of the control's container, or
set to fill the remaining space of the container.
Controls are docked in reverse z-order and the Dock property interacts with the AutoSize property. For
more information, see Automatic sizing.
Control.Anchor
When an anchored control's form is resized, the control maintains the distance between the control and
the anchor positions. For example, if you have a TextBox control that is anchored to the left, right, and
bottom edges of the form, as the form is resized, the TextBox control resizes horizontally so that it
maintains the same distance from the right and left sides of the form. The control also positions itself
vertically so that its location is always the same distance from the bottom edge of the form. If a control
isn't anchored and the form is resized, the position of the control relative to the edges of the form is
changed.
For more information, see Position and layout of controls.
Dock a control
A control is docked by setting its Dock property.
NOTE
Inherited controls must be Protected to be able to be docked. To change the access level of a control, set its Modifier
property in the Proper ties window.
3. Select the button that represents the edge of the container where you want to dock the control. To fill the
contents of the control's form or container control, press the center box. Press (none) to disable docking.
The control is automatically resized to fit the boundaries of the docked edge.
Set Dock programmatically
1. Set the Dock property on a control. In this example, a button is docked to the right side of its container:
button1.Dock = DockStyle.Right;
button1.Dock = DockStyle.Right
Anchor a control
A control is anchored to an edge by setting its Anchor property to one or more values.
NOTE
Certain controls, such as the ComboBox control, have a limit to their height. Anchoring the control to the bottom of its
form or container cannot force the control to exceed its height limit.
Inherited controls must be Protected to be able to be anchored. To change the access level of a control, set its
Modifiers property in the Proper ties window.
See also
Position and layout of controls.
System.Windows.Forms.Control.Anchor
System.Windows.Forms.Control.Dock
How to display an image on a control (Windows
Forms .NET)
9/23/2022 • 2 minutes to read • Edit Online
Several Windows Forms controls can display images. These images can be icons that clarify the purpose of the
control, such as a diskette icon on a button denoting the Save command. Alternatively, the icons can be
background images to give the control the appearance and behavior you want.
IMPORTANT
The Desktop Guide documentation for .NET 6 and .NET 5 (including .NET Core 3.1) is under construction.
' Replace the image named below with your own icon.
PictureBox1.Image = Image.FromFile _
(System.Environment.GetFolderPath _
(System.Environment.SpecialFolder.MyPictures) _
& "\Image.gif")
See also
System.Drawing.Image.FromFile
System.Drawing.Image
System.Windows.Forms.Control.BackgroundImage
How to handle a control event (Windows Forms
.NET)
9/23/2022 • 4 minutes to read • Edit Online
Events for controls (and for forms) are generally set through the Visual Studio Visual Designer for Windows
Forms. Setting an event through the Visual Designer is known as handling an event at design-time. You can also
handle events dynamically in code, known as handling events at run-time. An event created at run-time allows
you to connect event handlers dynamically based on what your app is currently doing.
IMPORTANT
The Desktop Guide documentation for .NET 6 and .NET 5 (including .NET Core 3.1) is under construction.
End Sub
To run this code, do the following to a form with the Visual Studio Visual Designer:
1. Add a new button to the form and name it Button1 .
2. Change the Proper ties pane mode to Events by pressing the event button ( ).
3. Double-click the Click event to generate a handler. This action opens the code window and generates a blank
Button1_Click method.
4. Replace the method code with the previous code above.
For more information about C# events, see Events (C#) For more information about Visual Basic events, see
Events (Visual Basic)
Remove the handler
The Add a handler section used some code to demonstrate adding a handler. That code also contained a call to
remove a handler:
button1.Click -= button1_Click;
RemoveHandler Button1.Click, AddressOf Button1_Click
This syntax can be used to remove any event handler from any event.
For more information about C# events, see Events (C#) For more information about Visual Basic events, see
Events (Visual Basic)
See also
Control events
Events overview
Using mouse events
Using keyboard events
System.Windows.Forms.Button
How to make thread-safe calls to controls (Windows
Forms .NET)
9/23/2022 • 4 minutes to read • Edit Online
Multithreading can improve the performance of Windows Forms apps, but access to Windows Forms controls
isn't inherently thread-safe. Multithreading can expose your code to serious and complex bugs. Two or more
threads manipulating a control can force the control into an inconsistent state and lead to race conditions,
deadlocks, and freezes or hangs. If you implement multithreading in your app, be sure to call cross-thread
controls in a thread-safe way. For more information, see Managed threading best practices.
IMPORTANT
The Desktop Guide documentation for .NET 6 and .NET 5 (including .NET Core 3.1) is under construction.
There are two ways to safely call a Windows Forms control from a thread that didn't create that control. Use the
System.Windows.Forms.Control.Invoke method to call a delegate created in the main thread, which in turn calls
the control. Or, implement a System.ComponentModel.BackgroundWorker, which uses an event-driven model to
separate work done in the background thread from reporting on the results.
The Visual Studio debugger detects these unsafe thread calls by raising an InvalidOperationException with the
message, Cross-thread operation not valid. Control accessed from a thread other than the thread it
was created on. The InvalidOperationException always occurs for unsafe cross-thread calls during Visual
Studio debugging, and may occur at app runtime. You should fix the issue, but you can disable the exception by
setting the Control.CheckForIllegalCrossThreadCalls property to false .
Safe cross-thread calls
The following code examples demonstrate two ways to safely call a Windows Forms control from a thread that
didn't create it:
1. The System.Windows.Forms.Control.Invoke method, which calls a delegate from the main thread to call the
control.
2. A System.ComponentModel.BackgroundWorker component, which offers an event-driven model.
In both examples, the background thread sleeps for one second to simulate work being done in that thread.
End Sub
If (TextBox1.InvokeRequired) Then
TextBox1.Invoke(Sub()
WriteTextSafe($"{text} (THREAD2)")
End Sub)
Else
TextBox1.Text = text
End If
End Sub
End Sub
Dim counter = 0
Dim max = 10
BackgroundWorker1.ReportProgress(0, counter.ToString())
System.Threading.Thread.Sleep(1000)
counter += 1
End While
End Sub
In Windows Forms, user input is sent to applications in the form of Windows messages. A series of overridable
methods process these messages at the application, form, and control level. When these methods receive
keyboard messages, they raise events that can be handled to get information about the keyboard input. In many
cases, Windows Forms applications will be able to process all user input simply by handling these events. In
other cases, an application may need to override one of the methods that process messages in order to intercept
a particular message before it is received by the application, form, or control.
IMPORTANT
The Desktop Guide documentation for .NET 6 and .NET 5 (including .NET Core 3.1) is under construction.
Keyboard events
All Windows Forms controls inherit a set of events related to mouse and keyboard input. For example, a control
can handle the KeyPress event to determine the character code of a key that was pressed. For more information,
see Using keyboard events.
M ET H O D N OT ES
Types of keys
Windows Forms identifies keyboard input as virtual-key codes that are represented by the bitwise Keys
enumeration. With the Keys enumeration, you can combine a series of pressed keys to result in a single value.
These values correspond to the values that accompany the WM_KEYDOWN and WM_SYSKEYDOWN
Windows messages. You can detect most physical key presses by handling the KeyDown or KeyUp events.
Character keys are a subset of the Keys enumeration and correspond to the values that accompany the
WM_CHAR and WM_SYSCHAR Windows messages. If the combination of pressed keys results in a character,
you can detect the character by handling the KeyPress event.
Preprocessing keys
Like other messages, keyboard messages are processed in the WndProc method of a form or control. However,
before keyboard messages are processed, the PreProcessMessage method calls one or more methods that can
be overridden to handle special character keys and physical keys. You can override these methods to detect and
filter certain keys before the messages are processed by the control. The following table shows the action that is
being performed and the related method that occurs, in the order that the method occurs.
Preprocessing for a KeyDown event
A C T IO N REL AT ED M ET H O D N OT ES
Check for a command key such as an ProcessCmdKey This method processes a command
accelerator or menu shortcut. key, which takes precedence over
regular keys. If this method returns
true , the key message is not
dispatched and a key event does not
occur. If it returns false , IsInputKey
is called .
Check for a special key that requires IsInputKey If the method returns true , it means
preprocessing or a normal character the control is a regular character and a
key that should raise a KeyDown event KeyDown event is raised. If false ,
and be dispatched to a control. ProcessDialogKey is called. Note: To
ensure a control gets a key or
combination of keys, you can handle
the PreviewKeyDown event and set
IsInputKey of the
PreviewKeyDownEventArgs to true
for the key or keys you want.
A C T IO N REL AT ED M ET H O D N OT ES
Check for a navigation key (ESC, TAB, ProcessDialogKey This method processes a physical key
Return, or arrow keys). that employs special functionality
within the control, such as switching
focus between the control and its
parent. If the immediate control does
not handle the key, the
ProcessDialogKey is called on the
parent control and so on to the
topmost control in the hierarchy. If this
method returns true , preprocessing
is complete and a key event is not
generated. If it returns false , a
KeyDown event occurs.
Check to see the key is a normal IsInputChar If the character is a normal character,
character that should be processed by this method returns true , the
the control KeyPress event is raised and no further
preprocessing occurs. Otherwise
ProcessDialogChar will be called.
M ET H O D N OT ES
TA SK M ET H O D
Intercept a navigation key and raise a KeyDown event. For Override IsInputKey. Note: Alternatively, you can handle the
example you want TAB and Return to be handled in a text PreviewKeyDown event and set IsInputKey of the
box. PreviewKeyDownEventArgs to true for the key or keys
you want.
Intercept a navigation key and raise a KeyPress event. For Override IsInputChar.
example in a spin-box control you want multiple arrow key
presses to accelerate progression through the items.
Perform custom mnemonic handling; for example, you want Override ProcessMnemonic.
to handle mnemonics on owner-drawn buttons contained in
a toolbar.
See also
Keys
WndProc
PreProcessMessage
Using keyboard events (Windows Forms .NET)
How to modify keyboard key events (Windows Forms .NET)
How to Check for modifier key presses (Windows Forms .NET)
How to simulate keyboard events (Windows Forms .NET)
How to handle keyboard input messages in the form (Windows Forms .NET)
Add a control (Windows Forms .NET)
Using keyboard events (Windows Forms .NET)
9/23/2022 • 2 minutes to read • Edit Online
Most Windows Forms programs process keyboard input by handling the keyboard events. This article provides
an overview of the keyboard events, including details on when to use each event and the data that is supplied
for each event. For more information about events in general, see Events overview (Windows Forms .NET).
IMPORTANT
The Desktop Guide documentation for .NET 6 and .NET 5 (including .NET Core 3.1) is under construction.
Keyboard events
Windows Forms provides two events that occur when a user presses a keyboard key and one event when a user
releases a keyboard key:
The KeyDown event occurs once.
The KeyPress event, which can occur multiple times when a user holds down the same key.
The KeyUp event occurs once when a user releases a key.
When a user presses a key, Windows Forms determines which event to raise based on whether the keyboard
message specifies a character key or a physical key. For more information about character and physical keys, see
Keyboard overview, keyboard events.
The following table describes the three keyboard events.
KeyDown This event is raised when a user The handler for KeyDown receives:
presses a physical key.
A KeyEventArgs parameter,
which provides the KeyCode
property (which specifies a
physical keyboard button).
The Modifiers property (SHIFT,
CTRL, or ALT).
The KeyData property (which
combines the key code and
modifier). The KeyEventArgs
parameter also provides:
KeyPress This event is raised when the key or KeyPress is raised after KeyDown.
keys pressed result in a character. For
example, a user presses SHIFT and the The handler for KeyPress
lowercase "a" keys, which result in a receives:
capital letter "A" character. A KeyPressEventArgs
parameter, which contains the
character code of the key that
was pressed. This character
code is unique for every
combination of a character key
and a modifier key.
KeyUp This event is raised when a user The handler for KeyUp receives:
releases a physical key.
A KeyEventArgs parameter:
See also
Overview of using the keyboard (Windows Forms .NET)
How to modify keyboard key events (Windows Forms .NET)
How to Check for modifier key presses (Windows Forms .NET)
How to simulate keyboard events (Windows Forms .NET)
How to handle keyboard input messages in the form (Windows Forms .NET)
Overview of how to validate user input (Windows
Forms .NET)
9/23/2022 • 6 minutes to read • Edit Online
When users enter data into your application, you may want to verify that the data is valid before your
application uses it. You may require that certain text fields not be zero-length, that a field formatted as a
telephone number, or that a string doesn't contain invalid characters. Windows Forms provides several ways for
you to validate input in your application.
IMPORTANT
The Desktop Guide documentation for .NET 6 and .NET 5 (including .NET Core 3.1) is under construction.
MaskedTextBox Control
If you need to require users to enter data in a well-defined format, such as a telephone number or a part
number, you can accomplish this quickly and with minimal code by using the MaskedTextBox control. A mask is
a string made up of characters from a masking language that specifies which characters can be entered at any
given position in the text box. The control displays a set of prompts to the user. If the user types an incorrect
entry, for example, the user types a letter when a digit is required, the control will automatically reject the input.
The masking language that is used by MaskedTextBox is flexible. It allows you to specify required characters,
optional characters, literal characters, such as hyphens and parentheses, currency characters, and date
separators. The control also works well when bound to a data source. The Format event on a data binding can be
used to reformat incoming data to comply with the mask, and the Parse event can be used to reformat outgoing
data to comply with the specifications of the data field.
Event-driven validation
If you want full programmatic control over validation, or need complex validation checks, you should use the
validation events that are built into most Windows Forms controls. Each control that accepts free-form user
input has a Validating event that will occur whenever the control requires data validation. In the Validating
event-handling method, you can validate user input in several ways. For example, if you have a text box that
must contain a postal code, you can do the validation in the following ways:
If the postal code must belong to a specific group of zip codes, you can do a string comparison on the
input to validate the data entered by the user. For example, if the postal code must be in the set
{10001, 10002, 10003} , then you can use a string comparison to validate the data.
If the postal code must be in a specific form, you can use regular expressions to validate the data entered
by the user. For example, to validate the form ##### or #####-#### , you can use the regular expression
^(\d{5})(-\d{4})?$ . To validate the form A#A #A# , you can use the regular expression
[A-Z]\d[A-Z] \d[A-Z]\d . For more information about regular expressions, see .NET Regular Expressions
and Regular Expression Examples.
If the postal code must be a valid United States Zip code, you could call a Zip code Web service to validate
the data entered by the user.
The Validating event is supplied an object of type CancelEventArgs. If you determine that the control's data isn't
valid, cancel the Validating event by setting this object's Cancel property to true . If you don't set the Cancel
property, Windows Forms will assume that validation succeeded for that control and raise the Validated event.
For a code example that validates an email address in a TextBox, see the Validating event reference.
Event-driven validation data-bound controls
Validation is useful when you have bound your controls to a data source, such as a database table. By using
validation, you can make sure that your control's data satisfies the format required by the data source, and that
it doesn't contain any special characters such as quotation marks and back slashes that might be unsafe.
When you use data binding, the data in your control is synchronized with the data source during execution of
the Validating event. If you cancel the Validating event, the data won't be synchronized with the data source.
IMPORTANT
If you have custom validation that takes place after the Validating event, it won't affect the data binding. For example, if
you have code in a Validated event that attempts to cancel the data binding, the data binding will still occur. In this case,
to perform validation in the Validated event, change the control's Binding.DataSourceUpdateMode property from
DataSourceUpdateMode.OnValidation to DataSourceUpdateMode.Never, and add
your-control.DataBindings["field-name"].WriteValue() to your validation code.
ContainerControl Inherit
Form EnableAllowFocusChange
SplitContainer Inherit
UserControl EnableAllowFocusChange
NOTE
If you force the form to close in this manner, any data in the form's controls that has not already been saved is lost. In
addition, modal forms don't validate the contents of controls when they're closed. You can still use control validation to
lock focus to a control, but you don't have to be concerned about the behavior associated with closing the form.
See also
Using keyboard events (Windows Forms .NET)
Control.Validating
Form.FormClosing
System.Windows.Forms.FormClosingEventArgs
How to modify keyboard key events (Windows
Forms .NET)
9/23/2022 • 3 minutes to read • Edit Online
Windows Forms provides the ability to consume and modify keyboard input. Consuming a key refers to
handling a key within a method or event handler so that other methods and events further down the message
queue don't receive the key value. And, modifying a key refers to modifying the value of a key so that methods
and event handlers further down the message queue receive a different key value. This article shows how to
accomplish these tasks.
IMPORTANT
The Desktop Guide documentation for .NET 6 and .NET 5 (including .NET Core 3.1) is under construction.
Consume a key
In a KeyPress event handler, set the Handled property of the KeyPressEventArgs class to true .
-or-
In a KeyDown event handler, set the Handled property of the KeyEventArgs class to true .
NOTE
Setting the Handled property in the KeyDown event handler does not prevent the KeyPress and KeyUp events from
being raised for the current keystroke. Use the SuppressKeyPress property for this purpose.
The following example handles the KeyPress event to consume the A and a character keys. Those keys can't
be typed into the text box:
if (m.Msg == WM_KEYDOWN)
{
Keys keyCode = (Keys)m.WParam & Keys.KeyCode;
Return MyBase.PreProcessMessage(m)
End Function
See also
Overview of using the keyboard (Windows Forms .NET)
Using keyboard events (Windows Forms .NET)
Keys
KeyDown
KeyPress
How to check for modifier key presses (Windows
Forms .NET)
9/23/2022 • 2 minutes to read • Edit Online
As the user types keys into your application, you can monitor for pressed modifier keys such as the SHIFT, ALT,
and CTRL. When a modifier key is pressed in combination with other keys or even a mouse click, your
application can respond appropriately. For example, pressing the S key may cause an "s" to appear on the
screen. If the keys CTRL+S are pressed, instead, the current document may be saved.
IMPORTANT
The Desktop Guide documentation for .NET 6 and .NET 5 (including .NET Core 3.1) is under construction.
If you handle the KeyDown event, the KeyEventArgs.Modifiers property received by the event handler specifies
which modifier keys are pressed. Also, the KeyEventArgs.KeyData property specifies the character that was
pressed along with any modifier keys combined with a bitwise OR.
If you're handling the KeyPress event or a mouse event, the event handler doesn't receive this information. Use
the ModifierKeys property of the Control class to detect a key modifier. In either case, you must perform a
bitwise AND of the appropriate Keys value and the value you're testing. The Keys enumeration offers variations
of each modifier key, so it's important that you do the bitwise AND check with the correct value.
For example, the SHIFT key is represented by the following key values:
Keys.Shift
Keys.ShiftKey
Keys.RShiftKey
Keys.LShiftKey
The correct value to test SHIFT as a modifier key is Keys.Shift. Similarly, to test for CTRL and ALT as modifiers
you should use the Keys.Control and Keys.Alt values, respectively.
See also
Overview of using the keyboard (Windows Forms .NET)
Using keyboard events (Windows Forms .NET)
Keys
ModifierKeys
KeyDown
KeyPress
How to handle keyboard input messages in the
form (Windows Forms .NET)
9/23/2022 • 2 minutes to read • Edit Online
Windows Forms provides the ability to handle keyboard messages at the form level, before the messages reach
a control. This article shows how to accomplish this task.
IMPORTANT
The Desktop Guide documentation for .NET 6 and .NET 5 (including .NET Core 3.1) is under construction.
// Detect all numeric characters at the form level and consume 1,4, and 7.
// Form.KeyPreview must be set to true for this event handler to be called.
void Form1_KeyPress(object sender, KeyPressEventArgs e)
{
if (e.KeyChar >= 48 && e.KeyChar <= 57)
{
MessageBox.Show($"Form.KeyPress: '{e.KeyChar}' pressed.");
switch (e.KeyChar)
{
case (char)49:
case (char)52:
case (char)55:
MessageBox.Show($"Form.KeyPress: '{e.KeyChar}' consumed.");
e.Handled = true;
break;
}
}
}
' Detect all numeric characters at the form level and consume 1,4, and 7.
' Form.KeyPreview must be set to true for this event handler to be called.
Private Sub Form1_KeyPress(sender As Object, e As KeyPressEventArgs)
If e.KeyChar >= Chr(48) And e.KeyChar <= Chr(57) Then
MessageBox.Show($"Form.KeyPress: '{e.KeyChar}' pressed.")
End Sub
See also
Overview of using the keyboard (Windows Forms .NET)
Using keyboard events (Windows Forms .NET)
Keys
ModifierKeys
KeyDown
KeyPress
How to simulate keyboard events (Windows Forms
.NET)
9/23/2022 • 3 minutes to read • Edit Online
Windows Forms provides a few options for programmatically simulating keyboard input. This article provides
an overview of these options.
IMPORTANT
The Desktop Guide documentation for .NET 6 and .NET 5 (including .NET Core 3.1) is under construction.
Use SendKeys
Windows Forms provides the System.Windows.Forms.SendKeys class for sending keystrokes to the active
application. There are two methods to send keystrokes to an application: SendKeys.Send and
SendKeys.SendWait. The difference between the two methods is that SendWait blocks the current thread when
the keystroke is sent, waiting for a response, while Send doesn't. For more information about SendWait , see To
send a keystroke to a different application.
Cau t i on
If your application is intended for international use with a variety of keyboards, the use of SendKeys.Send could
yield unpredictable results and should be avoided.
Behind the scenes, SendKeys uses an older Windows implementation for sending input, which may fail on
modern Windows where it's expected that the application isn't running with administrative rights. If the older
implementation fails, the code automatically tries the newer Windows implementation for sending input.
Additionally, when the SendKeys class uses the new implementation, the SendWait method no longer blocks the
current thread when sending keystrokes to another application.
IMPORTANT
If your application relies on consistent behavior regardless of the operating system, you can force the SendKeys class to
use the new implementation by adding the following application setting to your app.config file.
<appSettings>
<add key="SendKeys" value="SendInput"/>
</appSettings>
To force the SendKeys class to only use the previous implementation, use the value "JournalHook" instead.
[DllImport("USER32.DLL")]
public static extern bool SetForegroundWindow(IntPtr hWnd);
if (SetForegroundWindow(calcWindow))
SendKeys.Send("10{+}10=");
}
<Runtime.InteropServices.DllImport("USER32.DLL", CharSet:=Runtime.InteropServices.CharSet.Unicode)>
Public Shared Function FindWindow(lpClassName As String, lpWindowName As String) As IntPtr : End Function
<Runtime.InteropServices.DllImport("USER32.DLL")>
Public Shared Function SetForegroundWindow(hWnd As IntPtr) As Boolean : End Function
If SetForegroundWindow(hCalcWindow) Then
SendKeys.Send("10{+}10=")
End If
End Sub
For more information about these events, see Using keyboard events (Windows Forms .NET).
See also
Overview of using the keyboard (Windows Forms .NET)
Using keyboard events (Windows Forms .NET)
Using mouse events (Windows Forms .NET)
SendKeys
Keys
KeyDown
KeyPress
Overview of using the mouse (Windows Forms
.NET)
9/23/2022 • 4 minutes to read • Edit Online
Receiving and handling mouse input is an important part of every Windows application. You can handle mouse
events to carry out an action in your application, or use mouse location information to perform hit testing or
other actions. Also, you can change the way the controls in your application handle mouse input. This article
describes these mouse events in detail, and how to obtain and change system settings for the mouse.
IMPORTANT
The Desktop Guide documentation for .NET 6 and .NET 5 (including .NET Core 3.1) is under construction.
In Windows Forms, user input is sent to applications in the form of Windows messages. A series of overridable
methods process these messages at the application, form, and control level. When these methods receive mouse
messages, they raise events that can be handled to get information about the mouse input. In many cases,
Windows Forms applications can process all user input simply by handling these events. In other cases, an
application may override one of the methods that process messages to intercept a particular message before it's
received by the application, form, or control.
Mouse Events
All Windows Forms controls inherit a set of events related to mouse and keyboard input. For example, a control
can handle the MouseClick event to determine the location of a mouse click. For more information on the
mouse events, see Using mouse events.
DoubleClickSize Gets the dimensions, in pixels, of the area in which the user
must click twice for the operating system to consider the
two clicks a double-click.
MouseButtonsSwapped Gets a value indicating whether the functions of the left and
right mouse buttons have been swapped.
MouseHoverTime Gets the time, in milliseconds, that the mouse pointer has to
stay in the hover rectangle before a mouse hover message is
generated.
MouseWheelScrollLines Gets the number of lines to scroll when the mouse wheel is
rotated.
M ET H O D N OT ES
See also
Using mouse events (Windows Forms .NET)
Drag-and-drop mouse behavior overview (Windows Forms .NET)
Manage mouse pointers (Windows Forms .NET)
Using mouse events (Windows Forms .NET)
9/23/2022 • 6 minutes to read • Edit Online
Most Windows Forms programs process mouse input by handling the mouse events. This article provides an
overview of the mouse events, including details on when to use each event and the data that is supplied for each
event. For more information about events in general, see Events overview (Windows Forms .NET).
IMPORTANT
The Desktop Guide documentation for .NET 6 and .NET 5 (including .NET Core 3.1) is under construction.
Mouse events
The primary way to respond to mouse input is to handle mouse events. The following table shows the mouse
events and describes when they're raised.
MouseClick This event occurs when the user clicks the control with the
mouse. The handler for this event receives an argument of
type MouseEventArgs. Handle this event when you need to
get information about the mouse when a click occurs.
MouseDoubleClick This event occurs when the user double-clicks the control
with the mouse. The handler for this event receives an
argument of type MouseEventArgs. Handle this event when
you need to get information about the mouse when a
double-click occurs.
MouseDown This event occurs when the mouse pointer is over the
control and the user presses a mouse button. The handler
for this event receives an argument of type
MouseEventArgs.
MouseEnter This event occurs when the mouse pointer enters the border
or client area of the control, depending on the type of
control. The handler for this event receives an argument of
type EventArgs.
MouseHover This event occurs when the mouse pointer stops and rests
over the control. The handler for this event receives an
argument of type EventArgs.
M O USE EVEN T DESC RIP T IO N
MouseLeave This event occurs when the mouse pointer leaves the border
or client area of the control, depending on the type of the
control. The handler for this event receives an argument of
type EventArgs.
MouseMove This event occurs when the mouse pointer moves while it is
over a control. The handler for this event receives an
argument of type MouseEventArgs.
MouseUp This event occurs when the mouse pointer is over the
control and the user releases a mouse button. The handler
for this event receives an argument of type
MouseEventArgs.
MouseWheel This event occurs when the user rotates the mouse wheel
while the control has focus. The handler for this event
receives an argument of type MouseEventArgs. You can use
the Delta property of MouseEventArgs to determine how far
the mouse has scrolled.
Mouse information
A MouseEventArgs is sent to the handlers of mouse events related to clicking a mouse button and tracking
mouse movements. MouseEventArgs provides information about the current state of the mouse, including the
location of the mouse pointer in client coordinates, which mouse buttons are pressed, and whether the mouse
wheel has scrolled. Several mouse events, such as those that are raised when the mouse pointer has entered or
left the bounds of a control, send an EventArgs to the event handler with no further information.
If you want to know the current state of the mouse buttons or the location of the mouse pointer, and you want
to avoid handling a mouse event, you can also use the MouseButtons and MousePosition properties of the
Control class. MouseButtons returns information about which mouse buttons are currently pressed. The
MousePosition returns the screen coordinates of the mouse pointer and is equivalent to the value returned by
Position.
7. MouseDoubleClick event.
8. MouseUp event.
Individual controls
The following controls don't conform to the standard mouse click event behavior:
Button
CheckBox
ComboBox
RadioButton
NOTE
For the ComboBox control, the event behavior detailed later occurs if the user clicks on the edit field, the button,
or on an item within the list.
NOTE
The event behavior detailed later occurs when the user clicks anywhere within these controls.
NOTE
The event behavior detailed later occurs only when the user clicks on the items themselves or to the right of the
items in the TreeView control. No events are raised for clicks anywhere else on the control. In addition to those
described later, there are the BeforeCheck, BeforeSelect, BeforeLabelEdit, AfterSelect, AfterCheck, and
AfterLabelEdit events, which may be of interest to you if you want to use validation with the TreeView control.
NOTE
If the user moves the pointer out of the toggle control while the mouse button is down (such as moving the
mouse off the Button control while it is pressed), the toggle control will paint in the raised state and only the
MouseUp event occurs. The Click or MouseClick events will not occur in this situation.
See also
Overview of using the mouse (Windows Forms .NET)
Manage mouse pointers (Windows Forms .NET)
How to simulate mouse events (Windows Forms .NET)
System.Windows.Forms.Control
Drag-and-drop mouse behavior overview
(Windows Forms .NET)
9/23/2022 • 3 minutes to read • Edit Online
Windows Forms includes a set of methods, events, and classes that implement drag-and-drop behavior. This
topic provides an overview of the drag-and-drop support in Windows Forms.
IMPORTANT
The Desktop Guide documentation for .NET 6 and .NET 5 (including .NET Core 3.1) is under construction.
Drag-and-drop events
There are two categories of events in a drag and drop operation: events that occur on the current target of the
drag-and-drop operation, and events that occur on the source of the drag and drop operation. To perform drag-
and-drop operations, you must handle these events. By working with the information available in the event
arguments of these events, you can easily facilitate drag-and-drop operations.
The DragEventArgs class provides the location of the mouse pointer, the current state of the mouse buttons and
modifier keys of the keyboard, the data being dragged, and DragDropEffects values that specify the operations
allowed by the source of the drag event and the target drop effect for the operation.
The QueryContinueDragEventArgs class provides the current state of the mouse buttons and modifier keys of
the keyboard, a value specifying whether the ESC key was pressed, and a DragAction value that can be set to
specify whether the drag-and-drop operation should continue.
Performing drag-and-drop
Drag-and-drop operations always involve two components, the drag source and the drop target . To start a
drag-and-drop operation, designate a control as the source and handle the MouseDown event. In the event
handler, call the DoDragDrop method providing the data associated with the drop and the a DragDropEffects
value.
Set the target control's AllowDrop property set to true to allow that control to accept a drag-and-drop
operation. The target handles two events, first an event in response to the drag being over the control, such as
DragOver. And a second event which is the drop action itself, DragDrop.
The following example demonstrates a drag from a Label control to a TextBox. When the drag is completed, the
TextBox responds by assigning the label's text to itself.
// Set the effect filter and allow the drop on this control
private void textBox1_DragOver(object sender, DragEventArgs e) =>
e.Effect = DragDropEffects.All;
' Set the effect filter and allow the drop on this control
Private Sub TextBox1_DragOver(sender As Object, e As DragEventArgs)
e.Effect = DragDropEffects.All
End Sub
See also
Overview of using the mouse (Windows Forms .NET)
Control.DragDrop
Control.DragEnter
Control.DragLeave
Control.DragOver
How to distinguish between clicks and double-clicks
(Windows Forms .NET)
9/23/2022 • 4 minutes to read • Edit Online
Typically, a single click initiates a user interface action and a double-click extends the action. For example, one
click usually selects an item, and a double-click edits the selected item. However, the Windows Forms click
events do not easily accommodate a scenario where a click and a double-click perform incompatible actions,
because an action tied to the Click or MouseClick event is performed before the action tied to the DoubleClick or
MouseDoubleClick event. This topic demonstrates two solutions to this problem.
IMPORTANT
The Desktop Guide documentation for .NET 6 and .NET 5 (including .NET Core 3.1) is under construction.
One solution is to handle the double-click event and roll back the actions in the handling of the click event. In
rare situations you may need to simulate click and double-click behavior by handling the MouseDown event and
by using the DoubleClickTime and DoubleClickSize properties of the SystemInformation class. You measure the
time between clicks and if a second click occurs before the value of DoubleClickTime is reached and the click is
within a rectangle defined by DoubleClickSize, perform the double-click action; otherwise, perform the click
action.
End Class
The following code demonstrates how a form changes the style of border based on a click or double-click of the
new button control:
public partial class Form1 : Form
{
private FormBorderStyle _initialStyle;
private bool _isDoubleClicking;
public Form1()
{
InitializeComponent();
}
Controls.Add(button1);
}
_initialStyle = FormBorderStyle
Controls.Add(button1)
End Sub
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Drawing;
using System.Windows.Forms;
namespace project
{
public partial class Form2 : Form
{
private DateTime _lastClick;
private bool _inDoubleClick;
private Rectangle _doubleClickArea;
private TimeSpan _doubleClickMaxTime;
private Action _doubleClickAction;
private Action _singleClickAction;
private Timer _clickTimer;
public Form2()
{
InitializeComponent();
_doubleClickMaxTime = TimeSpan.FromMilliseconds(SystemInformation.DoubleClickTime);
return;
}
_singleClickAction();
}
}
}
Imports System.Drawing
Imports System.Windows.Forms
_singleClickAction = Sub()
MessageBox.Show("Single click")
End Sub
_doubleClickAction = Sub()
MessageBox.Show("Double click")
End Sub
End Sub
_inDoubleClick = False
Return
End If
Call _singleClickAction()
End Sub
End Class
See also
Overview of using the mouse (Windows Forms .NET)
Using mouse events (Windows Forms .NET)
Manage mouse pointers (Windows Forms .NET)
How to simulate mouse events (Windows Forms .NET)
Control.Click
Control.MouseDown
Control.SetStyle
Manage mouse pointers (Windows Forms .NET)
9/23/2022 • 2 minutes to read • Edit Online
The mouse pointer, which is sometimes referred to as the cursor, is a bitmap that specifies a focus point on the
screen for user input with the mouse. This topic provides an overview of the mouse pointer in Windows Forms
and describes some of the ways to modify and control the mouse pointer.
IMPORTANT
The Desktop Guide documentation for .NET 6 and .NET 5 (including .NET Core 3.1) is under construction.
button2.Cursor = System.Windows.Forms.Cursors.Hand;
Button2.Cursor = System.Windows.Forms.Cursors.Hand
To display the wait pointer, which resembles an hourglass, whenever the mouse pointer is on the control, use the
UseWaitCursor property of the Control class.
See also
Overview of using the mouse (Windows Forms .NET)
Using mouse events (Windows Forms .NET)
How to distinguish between clicks and double-clicks (Windows Forms .NET)
How to simulate mouse events (Windows Forms .NET)
System.Windows.Forms.Cursor
Cursor.Position
How to simulate mouse events (Windows Forms
.NET)
9/23/2022 • 2 minutes to read • Edit Online
Simulating mouse events in Windows Forms isn't as straight forward as simulating keyboard events. Windows
Forms doesn't provide a helper class to move the mouse and invoke mouse-click actions. The only option for
controlling the mouse is to use native Windows methods. If you're working with a custom control or a form, you
can simulate a mouse event, but you can't directly control the mouse.
IMPORTANT
The Desktop Guide documentation for .NET 6 and .NET 5 (including .NET Core 3.1) is under construction.
Events
Most events have a corresponding method that invokes them, named in the pattern of On followed by
EventName , such as OnMouseMove . This option is only possible within custom controls or forms, because these
methods are protected and can't be accessed from outside the context of the control or form. The disadvantage
to using a method such as OnMouseMove is that it doesn't actually control the mouse or interact with the control,
it simply raises the associated event. For example, if you wanted to simulate hovering over an item in a ListBox,
OnMouseMove and the ListBox doesn't visually react with a highlighted item under the cursor.
For more information about these events, see Using mouse events (Windows Forms .NET)
Invoke a click
Considering most controls do something when clicked, like a button calling user code, or checkbox change its
checked state, Windows Forms provides an easy way to trigger the click. Some controls, such as a combobox,
don't do anything special when clicked and simulating a click has no effect on the control.
PerformClick
The System.Windows.Forms.IButtonControl interface provides the PerformClick method which simulates a click
on the control. Both the System.Windows.Forms.Button and System.Windows.Forms.LinkLabel controls
implement this interface.
button1.PerformClick();
Button1.PerformClick()
InvokeClick
With a form a custom control, use the InvokeOnClick method to simulate a mouse click. This is a protected
method that can only be called from within the form or a derived custom control.
For example, the following code clicks a checkbox from button1 .
<Runtime.InteropServices.DllImport("USER32.DLL", EntryPoint:="SetCursorPos")>
Public Shared Function SetCursorPos(x As Integer, y As Integer) As Boolean : End Function
See also
Overview of using the mouse (Windows Forms .NET)
Using mouse events (Windows Forms .NET)
How to distinguish between clicks and double-clicks (Windows Forms .NET)
Manage mouse pointers (Windows Forms .NET)
PrintDialog component overview (Windows Forms
.NET)
9/23/2022 • 3 minutes to read • Edit Online
Printing in Windows Forms consists primarily of using the PrintDocument component to enable the user to
print. The PrintPreviewDialog control, PrintDialog and PageSetupDialog components provide a familiar
graphical interface to Windows operating system users.
The PrintDialog component is a pre-configured dialog box used to select a printer, choose the pages to print,
and determine other print-related settings in Windows-based applications. It's a simple solution for printer and
print-related settings instead of configuring your own dialog box. You can enable users to print many parts of
their documents: print all, print a selected page range, or print a selection. By relying on standard Windows
dialog boxes, you create applications whose basic functionality is immediately familiar to users. The PrintDialog
component inherits from the CommonDialog class.
Typically, you create a new instance of the PrintDocument component and set the properties that describe what
to print using the PrinterSettings and PageSettings classes. Call to the Print method actually prints the
document.
PrintDialog1.Document = PrintDocument1
printDialog1.Document = printDocument1;
4. The user's printing choices from the dialog will be copied to the PrinterSettings property of the
PrintDocument component.
You may also want to write code for the BeginPrint and EndPrint events. It will help to include an integer
representing the total number of pages to print that is decremented as each page prints.
NOTE
You can add a PrintDialog component to your form to provide a clean and efficient user interface (UI) to your users.
Setting the Document property of the PrintDialog component enables you to set properties related to the print
document you're working with on your form.
For more information about the specifics of Windows Forms print jobs, including how to create a print job
programmatically, see PrintPageEventArgs.
printDocument1.DocumentName = "SamplePrintApp";
It's common for Windows-based applications to print text. The Graphics class provides methods for drawing
objects (graphics or text) to a device, such as a screen or printer. The following section describes in detail the
process to print text file. This method doesn't support printing non-plain text files, such as an Office Word
document or a PDF file.
NOTE
The DrawText methods of TextRenderer are not supported for printing. You should always use the DrawString methods of
Graphics, as shown in the following code example, to draw text for printing purposes.
To print text
1. In Visual Studio, double-click the form you want to print from, in the Solution Explorer pane. This opens
the Visual Designer.
2. From the Toolbox , double-click the PrintDocument component to add it to the form. This should create a
PrintDocument component with the name printDocument1 .
3. Either add a Button to the form, or use a button that is already on the form.
4. In the Visual Designer of the form, select the button. In the Proper ties pane, select the Event filter
button and then double-click the Click event to generate an event handler.
5. The Click event code should be visible. Outside the scope of the event handler, add a private string
variable to the class named stringToPrint .
6. Back in the Click event handler code, set the DocumentName property to the name of the document.
This information is sent to the printer. Next, read the document text content and store it in the
stringToPrint string. Finally, call the Print method to raise the PrintPage event. The Print method is
highlighted below.
private void button1_Click(object sender, EventArgs e)
{
string docName = "testPage.txt";
string docPath = @"C:\";
string fullPath = System.IO.Path.Combine(docPath, docName);
printDocument1.DocumentName = docName;
stringToPrint = System.IO.File.ReadAllText(fullPath);
printDocument1.Print();
}
PrintDocument1.DocumentName = docName
stringToPrint = System.IO.File.ReadAllText(fullPath)
PrintDocument1.Print()
End Sub
7. Go back to the Visual Designer of the form and select the PrintDocument component. On the Proper ties
pane, select the Event filter and then double-click the PrintPage event to generate an event handler.
8. In the PrintPage event handler, use the Graphics property of the PrintPageEventArgs class and the
document contents to calculate line length and lines per page. After each page is drawn, check if it's the
last page, and set the HasMorePages property of the PrintPageEventArgs accordingly. The PrintPage
event is raised until HasMorePages is false .
In the following code example, the event handler is used to print the contents of the "testPage.txt" file in
the same font as it's used on the form.
' Remove the portion of the string that has been printed.
stringToPrint = stringToPrint.Substring(charactersOnPage)
End Sub
See also
Graphics
Brush
PrintDialog component overview
How to print a Form (Windows Forms .NET)
9/23/2022 • 2 minutes to read • Edit Online
As part of the development process, you typically will want to print a copy of your Windows Form. The following
code example shows how to print a copy of the current form by using the CopyFromScreen method.
In the following example, a button named Button1 is added to the form. When the Button1 button is clicked, it
saves the form to an image in memory, and then sends it to the print object.
Example
namespace Sample_print_win_form1
{
public partial class Form1 : Form
{
Bitmap memoryImage;
public Form1()
{
InitializeComponent();
}
printDocument1.Print();
}
private void PrintDocument1_PrintPage(System.Object sender,
System.Drawing.Printing.PrintPageEventArgs e) =>
e.Graphics.DrawImage(memoryImage, 0, 0);
}
}
Public Class Form1
e.Graphics.DrawImage(memoryImage, 0, 0)
End Sub
PrintDocument1.Print()
End Sub
End Class
Robust programming
The following conditions may cause an exception:
You don't have permission to access the printer.
There's no printer installed.
.NET security
To run this code example, you must have permission to access the printer you use with your computer.
See also
PrintDocument
How to: Render Images with GDI+
How to: Print Graphics in Windows Forms
Print using print preview (Windows Forms .NET)
9/23/2022 • 4 minutes to read • Edit Online
It's common in Windows Forms programming to offer print preview in addition to printing services. An easy
way to add print preview services to your application is to use a PrintPreviewDialog control in combination with
the PrintPage event-handling logic for printing a file.
6. Back in the Click event handler code, set the DocumentName property to the document you wish to
print, and open and read the document's contents to the string you added previously.
PrintDocument1.DocumentName = docName
stringToPrint = System.IO.File.ReadAllText(fullPath)
7. As you would for printing the document, in the PrintPage event handler, use the Graphics property of the
PrintPageEventArgs class and the file contents to calculate lines per page and render the document's
contents. After each page is drawn, check to see if it's the last page, and set the HasMorePages property
of the PrintPageEventArgs accordingly. The PrintPage event is raised until HasMorePages is false . When
the document has finished rendering, reset the string to be rendered. Also, ensure that the PrintPage
event is associated with its event-handling method.
NOTE
If you have implemented printing in your application, you may have already completed step 5 and 6.
In the following code example, the event handler is used to print the "testPage.txt" file in the same font
used on the form.
' Remove the portion of the string that has been printed.
stringToPrint = StringToPrint.Substring(charactersOnPage)
End Sub
8. Set the Document property of the PrintPreviewDialog control to the PrintDocument component on the
form.
printPreviewDialog1.Document = printDocument1;
PrintPreviewDialog1.Document = PrintDocument1
9. Call the ShowDialog method on the PrintPreviewDialog control. Note the highlighted code given below,
you would typically call ShowDialog from the Click event-handling method of a button. Calling
ShowDialog raises the PrintPage event and renders the output to the PrintPreviewDialog control. When
the user selects the print icon on the dialog, the PrintPage event is raised again, sending the output to
the printer instead of the preview dialog. Hence, the string is reset at the end of the rendering process in
step 4.
The following code example shows the Click event-handling method for a button on the form. The event-
handling method calls the methods to read the document and show the print preview dialog.
printPreviewDialog1.Document = printDocument1;
printPreviewDialog1.ShowDialog();
}
Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
PrintDocument1.DocumentName = docName
stringToPrint = System.IO.File.ReadAllText(fullPath)
PrintPreviewDialog1.Document = PrintDocument1
PrintPreviewDialog1.ShowDialog()
End Sub
See also
PrintDialog component overview
Print a multi-page text file
More Secure Printing in Windows Forms
Data binding overview (Windows Forms .NET)
9/23/2022 • 15 minutes to read • Edit Online
In Windows Forms, you can bind to not just traditional data sources, but also to almost any structure that
contains data. You can bind to an array of values that you calculate at run time, read from a file, or derive from
the values of other controls.
In addition, you can bind any property of any control to the data source. In traditional data binding, you typically
bind the display property—for example, the Text property of a TextBox control—to the data source. With .NET,
you also have the option of setting other properties through binding. You might use binding to perform the
following tasks:
Setting the graphic of an image control.
Setting the background color of one or more controls.
Setting the size of controls.
Essentially, data binding is an automatic way of setting any run-time accessible property of any control on a
form.
IBindingList interface
A class that implements the IBindingList interface provides a much higher level of data-binding
functionality. This implementation offers you basic sorting capabilities and change notification. Both are
useful when the list items change, and when the list itself changes. Change notification is important if you
plan to have multiple controls bound to the same data. It helps you to make data changes made in one of
the controls to propagate to the other bound controls.
NOTE
Change notification is enabled for the IBindingList interface through the SupportsChangeNotification property
which, when true , raises a ListChanged event, indicating the list changed or an item in the list changed.
NOTE
The BindingList<T> provides a generic implementation of the IBindingList interface.
IBindingListView interface
A class that implements the IBindingListView interface provides all the functionality of an implementation
of IBindingList, along with filtering and advanced sorting functionality. This implementation offers string-
based filtering, and multi-column sorting with property descriptor-direction pairs.
IEditableObject interface
A class that implements the IEditableObject interface allows an object to control when changes to that
object are made permanent. This implementation supports the BeginEdit, EndEdit, and CancelEdit
methods, which enable you to roll back changes made to the object. Following is a brief explanation of
the functioning of the BeginEdit , EndEdit , and CancelEdit methods and how they work with one
another to enable a possible rollback of changes made to the data:
The BeginEdit method signals the start of an edit on an object. An object that implements this
interface will need to store any updates after the BeginEdit method call in such a way that the
updates can be discarded if the CancelEdit method is called. In data binding Windows Forms, you
can call BeginEdit multiple times within the scope of a single edit transaction (for example,
BeginEdit , BeginEdit , EndEdit). Implementations of IEditableObject should keep track of whether
BeginEdit has already been called and ignore subsequent calls to BeginEdit . Because this
method can be called multiple times, it's important that subsequent calls to it are nondestructive.
Subsequent BeginEdit calls can't destroy the updates that have been made or change the data
that was saved on the first BeginEdit call.
The EndEdit method pushes any changes since BeginEdit was called into the underlying object, if
the object is currently in edit mode.
The CancelEdit method discards any changes made to the object.
For more information about how the BeginEdit, EndEdit, and CancelEdit methods work, see Save data
back to the database.
This transactional notion of data functionality is used by the DataGridView control.
ICancelAddNew interface
A class that implements the ICancelAddNew interface usually implements the IBindingList interface and
allows you to roll back an addition made to the data source with the AddNew method. If your data source
implements the IBindingList interface, you should also have it implement the ICancelAddNew interface.
IDataErrorInfo interface
A class that implements the IDataErrorInfo interface allows objects to offer custom error information to
bound controls:
The Error property returns general error message text (for example, "An error has occurred").
The Item[] property returns a string with the specific error message from the column (for example,
"The value in the State column is invalid").
IEnumerable interface
A class that implements the IEnumerable interface is typically consumed by ASP.NET. Windows Forms
support for this interface is only available through the BindingSource component.
NOTE
The BindingSource component copies all IEnumerable items into a separate list for binding purposes.
ITypedList interface
A collections class that implements the ITypedList interface provides the feature to control the order and
the set of properties exposed to the bound control.
NOTE
When you implement the GetItemProperties method, and the PropertyDescriptor array is not null, the last entry
in the array will be the property descriptor that describes the list property that is another list of items.
ICustomTypeDescriptor interface
A class that implements the ICustomTypeDescriptor interface provides dynamic information about itself.
This interface is similar to ITypedList but is used for objects rather than lists. This interface is used by
DataRowView to project the schema of the underlying rows. A simple implementation of
ICustomTypeDescriptor is provided by the CustomTypeDescriptor class.
NOTE
To support design-time binding to types that implement ICustomTypeDescriptor, the type must also implement
IComponent and exist as an instance on the Form.
IListSource interface
A class that implements the IListSource interface enables list-based binding on non-list objects. The
GetList method of IListSource is used to return a bindable list from an object that doesn't inherit from
IList. IListSource is used by the DataSet class.
IRaiseItemChangedEvents interface
A class that implements the IRaiseItemChangedEvents interface is a bindable list that also implements the
IBindingList interface. This interface is used to indicate if your type raises ListChanged events of type
ItemChanged through its RaisesItemChangedEvents property.
NOTE
You should implement the IRaiseItemChangedEvents if your data source provides the property to list event
conversion described previously and is interacting with the BindingSource component. Otherwise, the
BindingSource will also perform property to list event conversion resulting in slower performance.
ISupportInitialize interface
A component that implements the ISupportInitialize interface takes advantages of batch optimizations for
setting properties and initializing co-dependent properties. The ISupportInitialize contains two
methods:
BeginInit signals that object initialization is starting.
EndInit signals that object initialization is finishing.
ISupportInitializeNotification interface
A component that implements the ISupportInitializeNotification interface also implements the
ISupportInitialize interface. This interface allows you to notify other ISupportInitialize components that
initialization is complete. The ISupportInitializeNotification interface contains two members:
IsInitialized returns a boolean value indicating whether the component is initialized.
Initialized occurs when EndInit is called.
INotifyPropertyChanged interface
A class that implements this interface is a type that raises an event when any of its property values
change. This interface is designed to replace the pattern of having a change event for each property of a
control. When used in a BindingList<T>, a business object should implement the
INotifyPropertyChanged interface and the BindingList`1 will convert PropertyChanged events to
ListChanged events of type ItemChanged.
NOTE
For change notification to occur in a binding between a bound client and a data source, your bound data-source
type should either implement the INotifyPropertyChanged interface (preferred) or you can provide propertyName
Changed events for the bound type, but you shouldn't do both.
ICurrencyManagerProvider interface
A class that implements the ICurrencyManagerProvider interface is a component that provides its own
CurrencyManager to manage the bindings associated with this particular component. Access to the
custom CurrencyManager is provided by the CurrencyManager property.
NOTE
A class that inherits from Control manages bindings automatically through its BindingContext property, so cases
in which you need to implement the ICurrencyManagerProvider are fairly rare.
Simple data binding The ability of a control to bind to a single data element, such
as a value in a column in a dataset table. Simple data binding
is the type of binding typical for controls such as a TextBox
control or Label control, which are controls that typically
only display a single value. In fact, any property on a control
can be bound to a field in a database. There's extensive
support for this feature in Visual Studio.
Complex data binding The ability of a control to bind to more than one data
element, typically more than one record in a database.
Complex binding is also called list-based binding. Examples
of controls that support complex binding are the
DataGridView, ListBox, and ComboBox controls. For an
example of complex data binding, see How to: Bind a
Windows Forms ComboBox or ListBox Control to Data.
See also
Binding
Data binding overview
Design great data sources with change notification
Create a simple-bound control (Windows Forms .NET)
BindingSource Component
How to: Bind the Windows Forms DataGrid Control to a Data Source
Design great data sources with change notification
(Windows Forms .NET)
9/23/2022 • 10 minutes to read • Edit Online
One of the most important concepts of Windows Forms data binding is the change notification. To ensure that
your data source and bound controls always have the most recent data, you must add change notification for
data binding. Specifically, you want to ensure that bound controls are notified of changes that were made to
their data source. The data source is notified of changes that were made to the bound properties of a control.
There are different kinds of change notifications, depending on the kind of data binding:
Simple binding, in which a single control property is bound to a single instance of an object.
List-based binding, which can include a single control property bound to the property of an item in a list
or a control property bound to a list of objects.
Additionally, if you're creating Windows Forms controls that you want to use for data binding, you must apply
the PropertyNameChanged pattern to the controls. Applying pattern to the controls results in changes to the
bound property of a control are propagated to the data source.
public CustomerControl()
{
this.dataGridView1 = new System.Windows.Forms.DataGridView();
this.label1 = new System.Windows.Forms.Label();
this.dataGridView1.ColumnHeadersHeightSizeMode =
System.Windows.Forms.DataGridViewColumnHeadersHeightSizeMode.AutoSize;
this.dataGridView1.ImeMode = System.Windows.Forms.ImeMode.Disable;
this.dataGridView1.Location = new System.Drawing.Point(100, 100);
this.dataGridView1.Size = new System.Drawing.Size(500,500);
this.dataGridView1.TabIndex = 1;
this.label1.AutoSize = true;
this.label1.Location = new System.Drawing.Point(50, 50);
this.label1.Name = "label1";
this.label1.Size = new System.Drawing.Size(76, 13);
this.label1.TabIndex = 2;
this.label1.Text = "Customer List:";
this.Controls.Add(this.label1);
this.Controls.Add(this.dataGridView1);
this.Size = new System.Drawing.Size(450, 250);
}
}
' This class implements a simple user control
' that demonstrates how to apply the propertyNameChanged pattern.
<ComplexBindingProperties("DataSource", "DataMember")>
Public Class CustomerControl
Inherits UserControl
Private dataGridView1 As DataGridView
Private label1 As Label
Private lastUpdate As DateTime = DateTime.Now
End Sub
public Form3()
{
InitializeComponent();
set
{
if (value != this.customerNameValue)
if (value != this.customerNameValue)
{
this.customerNameValue = value;
NotifyPropertyChanged();
}
}
}
set
{
if (value != this.phoneNumberValue)
{
this.phoneNumberValue = value;
NotifyPropertyChanged();
}
}
}
}
}
Imports System.Collections.Generic
Imports System.ComponentModel
Imports System.Drawing
Imports System.Runtime.CompilerServices
Imports System.Windows.Forms
' These fields hold the values for the public properties.
Private idValue As Guid = Guid.NewGuid()
Private customerNameValue As String = String.Empty
Private phoneNumberValue As String = String.Empty
Synchronize bindings
During implementation of data binding in Windows Forms, multiple controls are bound to the same data
source. In some cases, it may be necessary to take extra steps to ensure that the bound properties of the
controls remain synchronized with each other and the data source. These steps are necessary in two situations:
If the data source doesn't implement IBindingList, and therefore generate ListChanged events of type
ItemChanged.
If the data source implements IEditableObject.
In the former case, you can use a BindingSource to bind the data source to the controls. In the latter case, you
use a BindingSource and handle the BindingComplete event and call EndCurrentEdit on the associated
BindingManagerBase.
For more information on implementing this concept, see the BindingComplete API reference page.
See also
Data Binding
BindingSource
INotifyPropertyChanged
BindingList<T>
Navigate data (Windows Forms .NET)
9/23/2022 • 6 minutes to read • Edit Online
The easiest way to navigate through records in a data source is to bind a BindingSource component to the data
source and then bind controls to the BindingSource . You can then use the built-in navigation method of the
BindingSource , such as MoveNext, MoveLast, MovePrevious, and MoveFirst. Using these methods will adjust the
Position and Current properties of the BindingSource appropriately. You can also find a record and set it as the
current record by setting the Position property.
NOTE
Setting the Position property to a value beyond the first or last record does not result in an error, as Windows Forms
won't set the position to a value outside the bounds of the list. If it's important to know whether you have gone past the
first or last record, include logic to test whether you'll exceed the data element count.
If customersBindingSource.Position =
customersBindingSource.Count - 1 Then
nextButton.Enabled = False
Else
nextButton.Enabled = True
End If
End Sub
NOTE
Be aware that, if you change the list you are navigating in code, you should re-enable the Next button so that users
might browse the entire length of the new list. Additionally, be aware that the above PositionChanged event for the
specific BindingSource you are working with needs to be associated with its event-handling method.
2. Handle the ListChanged event for the binding's CurrencyManager and check for a ListChangedType of
Reset.
3. Check the current position of the CurrencyManager. If it's greater than the first entry in the list (typically
0), save it to a variable.
End Sub
4. Handle the parent list's CurrentChanged event for the parent currency manager. In the handler, set the
Boolean value to indicate it isn't a caching scenario. If the CurrentChanged occurs, the change to the
parent is a list position change and not an item value change.
End Sub
See also
Data binding overview
Data sources supported by Windows Forms
Change Notification in Windows Forms Data Binding
How to synchronize multiple controls to the same data source
BindingSource Component
Create a simple-bound control (Windows Forms
.NET)
9/23/2022 • 3 minutes to read • Edit Online
With simple data binding, you can display a single data element, such as a column value from a dataset table to
a control on a form. You can simple-bind any property of a control to a data value.
To simple-bind a control
1. Connect to a data source.
2. In Visual Studio, select the control on the form and display the Proper ties window.
3. Expand the DataBindings property.
The properties that are bound are displayed under the DataBindings property. For example, in most
controls, the Text property is frequently bound.
4. If the property you want to bind isn't one of the commonly bound properties, select the Ellipsis button (
) in the Advanced box to display the Formatting and Advanced Binding dialog with a complete
list of properties for that control.
5. Select the property you want to bind and select the drop-down arrow under Binding . A list of available
data sources is displayed.
6. Expand the data source you want to bind to until you find the single data element you want. For example,
if you're binding to a column value in a dataset table, expand the name of the dataset, and then expand
the table name to display column names.
7. Select the name of an element to bind to.
8. If you're working in the Formatting and Advanced Binding dialog, select OK to return to the
Proper ties window.
9. If you want to bind more properties of the control, repeat steps 3 to 7.
NOTE
As simple-bound controls show only a single data element, it's typical to include navigation logic in a Windows
Form with simple-bound controls.
F O RM AT T Y P E F O RM AT T IN G O P T IO N
No Formatting No options.
Date Time Choose how the date and time should be displayed by
selecting one of the items in the Type selection box.
8. Select OK to close the Formatting and Advanced Binding dialog and return to the Proper ties
window.
See also
Binding
Data Binding
User Input Validation in Windows Forms
Synchronize multiple controls to the same data
source (Windows Forms .NET)
9/23/2022 • 2 minutes to read • Edit Online
During the implementation of data binding in Windows Forms, multiple controls are bound to the same data
source. In the following situations, it's necessary to ensure that the bound properties of the control remain
synchronized with each other and the data source:
If the data source doesn't implement IBindingList, and therefore generates ListChanged events of type
ItemChanged.
If the data source implements IEditableObject.
In the former case, you can use a BindingSource to bind the data source to the controls. In the latter case, you
use a BindingSource and handle the BindingComplete event and call EndCurrentEdit on the associated
BindingManagerBase.
' Check if the data source has been updated, and that no error has occurred.
If e.BindingCompleteContext = BindingCompleteContext.DataSourceUpdate _
AndAlso e.Exception Is Nothing Then
See also
Design great data sources with change notification
Data Binding
How to: Share Bound Data Across Forms Using the BindingSource Component
Obsolete Windows Forms features in .NET 7+
9/23/2022 • 2 minutes to read • Edit Online
Starting in .NET 7, some Windows Forms APIs are marked as obsolete (or otherwise produce a warning) with
custom diagnostic IDs of the format WFDEVXXX .
If you encounter build warnings or errors due to usage of an obsolete API, follow the specific guidance provided
for the diagnostic ID listed in the Reference section. Warnings or errors for these obsoletions can't be
suppressed using the standard diagnostic ID (CS0618) for obsolete types or members; use the custom
WFDEVXXX diagnostic ID values instead. For more information, see Suppress warnings.
Reference
The following table provides an index to the WFDEVXXX obsoletions and warnings in .NET 7+.
Suppress warnings
It's recommended that you use an available workaround whenever possible. However, if you cannot change your
code, you can suppress warnings through a #pragma directive or a <NoWarn> project setting. If you must use the
obsolete APIs and the WFDEVXXX diagnostic does not surface as an error, you can suppress the warning in code
or in your project file.
To suppress the warnings in code:
NOTE
Suppressing warnings in this way only disables the obsoletion warnings you specify. It doesn't disable any other warnings,
including obsoletion warnings with different diagnostic IDs.
See also
Obsolete .NET features in .NET 5+
WFDEV001: WParam, LParam, and Message.Result
are obsolete
9/23/2022 • 2 minutes to read • Edit Online
To reduce the risk of cast and overflow exceptions associated with IntPtr on different platforms, the Windows
Forms SDK disallows direct use of Message.WParam, Message.LParam, and Message.Result. Projects that use the
DEBUG build of the Windows Forms SDK and that reference WParam, LParam, or Result will fail to compile due
to warning WFDEV001 .
Workarounds
Update your code to use the new internal properties, either WParamInternal , LParamInternal , or ResultInternal
depending on the situation.
Suppress a warning
If you must use the obsolete APIs, you can suppress the warning in code or in your project file.
To suppress only a single violation, add preprocessor directives to your source file to disable and then re-enable
the warning.
To suppress all the WFDEV001 warnings in your project, add a <NoWarn> property to your project file.
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
...
<NoWarn>$(NoWarn);WFDEV001</NoWarn>
</PropertyGroup>
</Project>
Workarounds
Update your code to use AccessibleObject instead of DomainUpDown.DomainUpDownAccessibleObject.
If you suppress the warning, your code will continue to compile and run in .NET 7.
Suppress a warning
If you must use the obsolete API, you can suppress the warning in code or in your project file.
To suppress only a single violation, add preprocessor directives to your source file to disable and then re-enable
the warning.
To suppress all the WFDEV002 warnings in your project, add a <NoWarn> property to your project file.
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
...
<NoWarn>$(NoWarn);WFDEV002</NoWarn>
</PropertyGroup>
</Project>
Workarounds
Remove invocations of the public constructor for the DomainUpDown.DomainItemAccessibleObject type. Use
System.Windows.Forms.AccessibleObject instead.
Suppress a warning
If you must use the obsolete APIs, you can suppress the warning in code or in your project file.
To suppress only a single violation, add preprocessor directives to your source file to disable and then re-enable
the warning.
To suppress all the WFDEV003 warnings in your project, add a <NoWarn> property to your project file.
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
...
<NoWarn>$(NoWarn);WFDEV003</NoWarn>
</PropertyGroup>
</Project>