dotnet / winforms

Windows Forms is a .NET UI framework for building Windows desktop applications.
MIT License
4.34k stars 963 forks source link

Make appearance of MenuStrip & ContextMenuStrip look native when RenderMode = System #2543

Open chylex opened 4 years ago

chylex commented 4 years ago

(split off from #2476)

Windows 7

See #2476 for screenshots if needed.

Windows 10

Native Strip (RenderMode = System)
NativeMenu10 StripSystemMenu10
NativeContext10 StripSystemContext10
a b
bb aa

List of Differences

It's probably not worth matching the look of Windows 7, so I will only consider differences from the Windows 10 look.

I have done measurements on 100% and 150% DPI, and marked those that change. I have not measured widths/heights of items, those seem mostly fine.

It's a lot ^.^ but it should make them almost completely visually indistinguishable from native controls.

(Updated) Test Project

winforms.zip

RussKie commented 4 years ago

Thank you for the detailed report

Tanya-Solyanik commented 4 years ago

FYI: setting supported OS in the manifest file does not fix this issue, most likely we are not getting there glyphs or colors from the theme data.

RussKie commented 4 years ago

While debugging another issues I was stepping through TooStrip implementations and observed that that it defaults to ProfessionalRendererType: https://github.com/dotnet/winforms/blob/62c17fe35b2f00f8156828148a5fbbb910cc52a1/src/System.Windows.Forms/src/System/Windows/Forms/ToolStripManager.cs#L46-L51 https://github.com/dotnet/winforms/blob/62c17fe35b2f00f8156828148a5fbbb910cc52a1/src/System.Windows.Forms/src/System/Windows/Forms/ToolStripManager.cs#L510-L516 On a separate note, it looks to me that InitializeThread should be relying on DefaultRendererType instead of using ProfessionalRendererType directly.

And I think at this point it is natural for one to wonder why we are not using SystemRendererType as the default. @merriemcgaw @Tanya-Solyanik any background on this?

Can/should we default to the "System" instead? Obviously such change has wider repercussions - all existing consumers migrating to .NET will be affected. Though one can argue the look and feel of the menus and toolbars will be more inline with the OS (once we address the theming issues).

RussKie commented 4 years ago
  • The menu background from top to bottom is (19px * DPI - 1px) of RGB(255, 255, 255), and then 1px bottom border of RGB(242, 242, 242)

I've looked at this, we do all the painting with standard predefined colours, e.g.: https://github.com/dotnet/winforms/blob/b666dc7a94d8ac87a7d300cfb4fa86332fb79bae/src/System.Windows.Forms/src/System/Windows/Forms/ToolStripSystemRenderer.cs#L233-L237

 SystemColors.MenuBar => {Name=Menu, ARGB=(255, 240, 240, 240)}

This is how the colours are read by the runtime: https://github.com/dotnet/runtime/blob/4f9ae42d861fcb4be2fcd5d3d55d5f227d30e723/src/libraries/Common/src/System/Drawing/KnownColorTable.cs#L175-L182 https://github.com/dotnet/runtime/blob/4f9ae42d861fcb4be2fcd5d3d55d5f227d30e723/src/libraries/Common/src/System/Drawing/KnownColorTable.cs#L228-L229 ...using these constants: https://github.com/dotnet/runtime/blob/4f9ae42d861fcb4be2fcd5d3d55d5f227d30e723/src/libraries/Common/src/Interop/Windows/User32/Interop.Win32SystemColors.cs#L9-L45 which are the same as defined here: https://docs.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-getsyscolor

Executed locally I get the same result: image

I'm not quite sure how native apps get the different colours (i.e. RGB(242, 242, 242)) Obviously Notepad has it differently: image

@JeremyKuhne @Tanya-Solyanik @weltkante any thoughts on this?

weltkante commented 4 years ago

I'm not entirely sure if SystemColors (and SystemRenderer) will properly reflect theming. Some colors may be reused by theming, but the general model I have in mind is that theming uses a lot of hardcoded colors and rendering code which you only can get by going through the theming API. From a quick look you have no renderer using the theming API for menus/toolbars/statusbars (but I may have missed something).

If I remember right the general idea is that

Its been a long time since Office had menus and the OS has caught up and now has its own theming and UI styling rules separate from Office. I don't know if there is much value maintaining the historic Office rendering styles beyond providing it for backward compatibility to existing WinForms users.

In my opinion the main goal should be to achieve parity with the OS, which obviously has been neglected in the menu/toolbar area because for a long time Office was seen as having the superior style. Using Office as reference for UI theming has no point anymore if you don't provide the kind of controls used in Office.

So someone will probably have to look into how the theming API is to be used for rendering menus/toolbars/statusbars. It may take more than just picking colors, you may have to call the theming rendering APIs (which I think for menus is done nowhere in WinForms currently)

PS: take everything I said here with a lot of caution, its driven by 10-15 year old memory and I didn't take a close look what WinForms does today in its menu rendering.

RussKie commented 4 years ago

PS: take everything I said here with a lot of caution, its driven by 10-15 year old memory and I didn't take a close look what WinForms does today in its menu rendering.

I think we're in real troubles now... πŸ˜„

Some colors may be reused by theming, but the general model I have in mind is that theming uses a lot of hardcoded colors and rendering code which you only can get by going through the theming API. From a quick look you have no renderer using the theming API for menus/toolbars/statusbars (but I may have missed something).

Windows Forms have only rudimentary theming support, and that is something we're planning to look at going forward. My OS is configured to use "dark" mode, and Notepad and Git Extensions are the only retina burning apps, so following the logic I guess I'd expect menus to be rendered in dark colours as well image (Outlook uses own theming, so for the most part irrelevant, though it uses the same colour palette as the OS, and in Git Extensions we use custom colours)

In my opinion the main goal should be to achieve parity with the OS, which obviously has been neglected in the menu/toolbar area because for a long time Office was seen as having the superior style. Using Office as reference for UI theming has no point anymore if you don't provide the kind of controls used in Office.

Agree πŸ’―

RussKie commented 4 years ago

We need to step back and agree on what we consider to be a "native Windows look and feel". I don't believe it is correct just to look at how .NET Framework MainMenu et al. used to look. It had been designed in a completely different world with completely different useability and accessibility requirements than what we have today.

Let's look at "native" Windows 10 1903 apps.

Windows default "light" mode Windows "dark" mode
Windows Explorer

It is used to possible to show menus,
however now they seem to be completely removed
even though the setting is still there πŸ˜’
image image
Internet Explorer 11 image image
Notepad image image
MMC image image
Control Panel image image
Visual Studio 2019

whilst technically VS is an owner-draw
included it for completeness
image image

There is some consistency in the light theme, however hardly any handle the dark theme correctly.

❗️ And that without the rabbit hole of the High Contrast (HC) themes, where we can truly immerse ourselves in the world of accessibility nightmares. Whilst the above apps do some form of HC theming, not all of them correctly implement all accessibility requirements. The Windows team has a backlog is accessibility bugs, and we need to be careful not to copy their bugs into the Windows Forms stack.

We can't arbitrary change colours and are bound to use the colours provided to us by the Runtime (i.e. SystemColours, etc.) because those colours meet accessibility requirements, and behave in the HC themes. We also need to investigate and bridge the theming gap, and see how that affects the available colour palette.

I'd argue that a Windows Forms application must use the same colours and theming parameters as Windows Explorer, after all it is the Windows shell. An app must also change colours similar to how Edge and Chrome change their colours in response to the underlying Windows color theme change (their colours are not even anywhere near the Explorer's colours but they look on par with the underlying OS):

Windows default "light" mode Windows "dark" mode
Windows Explorer image image
Edge image image
Chrome image image

With all being said, we are planning to modify the "System" renderer so that *-strip controls have more native look, once we agree on what that means.

@merriemcgaw @OliaG we likely need to get with in touch with someone from Windows UX team and discuss the approved colours.

@vatsan-madhavan how does WPF decide on the default colours for menus and alike?

weltkante commented 4 years ago

Not sure if you understood me correctly, so TLDR for my previous post: there are two APIs, SystemColors and theming API, using SystemColors may give you the colors from the non-themed UI in cases where the OS theming overrides colors, which is probably what is happening here.

What I'm suggesting is using the official theming API instead of starting to replicate code/colors. There are parts for menus/toolbars/statusbars (like MENU_BARBACKGROUND or SP_PANE) which I'd expect you to be able to use. Using the theming API is what most other "common controls" classes do in the WinForms codebase so why implement menus etc. differently from the approach you are taking with other controls?

That said, if you decide to roll your own implementation instead of calling the OS theming API thats of course a valid solution.

vatsan-madhavan commented 4 years ago

I'm not an expert in this, /cc @rladuca to comment in case I make substantive mistakes here.

--

Here is where the Style's for Menu are defined for various pre-defined themes:

For Aero theme (which was used in Windows Vista - WPF switched to Aero2 for Win8+), this is what we've got. You can see that it relies on SystemColors and SystemFonts.

    <Style x:Key="{x:Type Menu}"
           TargetType="{x:Type Menu}">
        <Setter Property="Background"
                Value="{StaticResource MenuBackground}"/>
        <Setter Property="FontFamily"
                Value="{DynamicResource {x:Static SystemFonts.MenuFontFamilyKey}}"/>
        <Setter Property="FontSize"
                Value="{DynamicResource {x:Static SystemFonts.MenuFontSizeKey}}"/>
        <Setter Property="FontStyle"
                Value="{DynamicResource {x:Static SystemFonts.MenuFontStyleKey}}"/>
        <Setter Property="FontWeight"
                Value="{DynamicResource {x:Static SystemFonts.MenuFontWeightKey}}"/>
        <Setter Property="Foreground"
                Value="{DynamicResource {x:Static SystemColors.MenuTextBrushKey}}"/>
        <Setter Property="Template">
            <Setter.Value>
                <ControlTemplate TargetType="{x:Type Menu}">
                    <Border Background="{TemplateBinding Background}"
                            BorderBrush="{TemplateBinding BorderBrush}"
                            BorderThickness="{TemplateBinding BorderThickness}"
                            Padding="{TemplateBinding Padding}"
                            SnapsToDevicePixels="true">
                        <ItemsPresenter SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}"/>
                    </Border>
                </ControlTemplate>
            </Setter.Value>
        </Setter>
    </Style>

Classic is defined this way, which is used in High Contrast modes. This also relies on SystemColors and SystemFonts.

    <Style x:Key="{x:Type Menu}"
           TargetType="{x:Type Menu}">
        <Setter Property="Background"
                Value="{DynamicResource {x:Static SystemColors.MenuBrushKey}}"/>
        <Setter Property="FontFamily"
                Value="{DynamicResource {x:Static SystemFonts.MenuFontFamilyKey}}"/>
        <Setter Property="FontSize"
                Value="{DynamicResource {x:Static SystemFonts.MenuFontSizeKey}}"/>
        <Setter Property="FontStyle"
                Value="{DynamicResource {x:Static SystemFonts.MenuFontStyleKey}}"/>
        <Setter Property="FontWeight"
                Value="{DynamicResource {x:Static SystemFonts.MenuFontWeightKey}}"/>
        <Setter Property="Foreground"
                Value="{DynamicResource {x:Static SystemColors.MenuTextBrushKey}}"/>
        <Setter Property="VerticalContentAlignment"
                Value="Center"/>
        <Setter Property="Template">
            <Setter.Value>
                <ControlTemplate TargetType="{x:Type Menu}">
                    <Border Background="{TemplateBinding Background}"
                            BorderBrush="{TemplateBinding BorderBrush}"
                            BorderThickness="{TemplateBinding BorderThickness}"
                            Padding="{TemplateBinding Padding}"
                            SnapsToDevicePixels="true">
                        <ItemsPresenter SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}"/>
                    </Border>
                </ControlTemplate>
            </Setter.Value>
        </Setter>
    </Style>

And Aero2 is defined like this, which is the default in WPF.

Now there is reliance on predefined colors (i.e., special theme-specific constants) in addition to SystemColors and SystemFonts. These constants were likely selected to match the look-and-feel of Windows 8 better than what would otherwise have been acheivable by relying solely on SystemColors.

<!-- [[Aero2.NormalColor]] -->

    <SolidColorBrush x:Key="Menu.Static.Background" Color="#FFF0F0F0" />
    <SolidColorBrush x:Key="Menu.Static.Border" Color="#FF999999" />
    <SolidColorBrush x:Key="Menu.Static.Foreground" Color="#FF212121" />

    <SolidColorBrush x:Key="Menu.Static.Separator" Color="#FFD7D7D7" />

    <SolidColorBrush x:Key="Menu.Disabled.Background" Color="#3DDADADA" />
    <SolidColorBrush x:Key="Menu.Disabled.Border" Color="#FFDADADA" />
    <SolidColorBrush x:Key="Menu.Disabled.Foreground" Color="#FF707070" />

    <SolidColorBrush x:Key="MenuItem.Selected.Background" Color="#3D26A0DA" />
    <SolidColorBrush x:Key="MenuItem.Selected.Border" Color="#FF26A0DA" />

    <SolidColorBrush x:Key="MenuItem.Highlight.Background" Color="#3D26A0DA" />
    <SolidColorBrush x:Key="MenuItem.Highlight.Border" Color="#FF26A0DA" />

    <SolidColorBrush x:Key="MenuItem.Highlight.Disabled.Background" Color="#0A000000" />
    <SolidColorBrush x:Key="MenuItem.Highlight.Disabled.Border" Color="#21000000" />

<!--=================================================================
        Menu
    ==================================================================-->

    <Style TargetType="{x:Type Menu}">
        <Setter Property="Background" Value="{StaticResource Menu.Static.Background}" />
        <Setter Property="FontFamily" Value="{DynamicResource {x:Static SystemFonts.MenuFontFamilyKey}}"/>
        <Setter Property="FontSize" Value="{DynamicResource {x:Static SystemFonts.MenuFontSizeKey}}"/>
        <Setter Property="FontStyle" Value="{DynamicResource {x:Static SystemFonts.MenuFontStyleKey}}"/>
        <Setter Property="FontWeight" Value="{DynamicResource {x:Static SystemFonts.MenuFontWeightKey}}"/>
        <Setter Property="Foreground" Value="{StaticResource Menu.Static.Foreground}" />
        <Setter Property="VerticalContentAlignment" Value="Center"/>
        <Setter Property="Template">
            <Setter.Value>
                <ControlTemplate TargetType="{x:Type Menu}">
                    <Border
                        Background="{TemplateBinding Background}"
                        BorderBrush="{TemplateBinding BorderBrush}"
                        BorderThickness="{TemplateBinding BorderThickness}"
                        Padding="{TemplateBinding Padding}"
                        SnapsToDevicePixels="true">
                        <ItemsPresenter
                            SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}" />
                    </Border>
                </ControlTemplate>
            </Setter.Value>
        </Setter>
    </Style>

note: The links above are to sources that act as inputs to a generator which eventually generates the actual theme xaml files like Aero2.NormalColor.xaml.

RussKie commented 4 years ago

Thank you @vatsan-madhavan, so is it fair to say WPF has colours hard-coded and relies on colours defined by the Runtime instead of loading the OS theme defined colours?

vatsan-madhavan commented 4 years ago

No, that's not a good generalization. It's more nuanced than that 😁

Normal operation (i.e., the OS is running a non-High Contrast theme): WPF uses a mix of self-defined and OS defined colors.

<<edited based on https://github.com/dotnet/winforms/issues/2543#issuecomment-582730461>> OS is running a High contrast theme: WPF uses OS defined colors by and large; there have been several accessibility related bug-fixes that have ~likely~ introduced <<edit>> rare deviations from this norm in the form of WPF defined colors ~as well~.

RussKie commented 4 years ago

πŸ‘ thank you for the clarification.

rladuca commented 4 years ago

@vatsan-madhavan that's pretty much on the money as far as I know. Recent high contrast fixes have generally been done with an effort to only use SystemColors wherever possible. I actually do not remember any fix that we made in the last few years that used anything else, aside from when accessibility standards demanded a specific color that was not provided by the SystemColors.

weltkante commented 4 years ago

In summary: For theme off and high Contrast WPF uses System Colors as does WinForms, themed colors are hardcoded like <SolidColorBrush x:Key="Menu.Static.Background" Color="#FFF0F0F0" /> Note that WPF has different styles for different OS releases - if themes differ the hardcoded colors can differ between OS versions, thats something WinForms would need to do as well if it choses to replicate colors instead of calling theming APIs.

chylex commented 4 years ago

I don't want to interfere too much, but here's my perspective as a developer using WinForms, and someone who cares about consistency:

We need to step back and agree on what we consider to be a "native Windows look and feel". Let's look at "native" Windows 10 1903 apps.

Notepad and MMC seem to just use the native control, which looks the most consistent today. If you're leaning towards Explorer to also support dark theme, it'd be good to know how those colors were chosen, whether the design is stable now, and how consistent it is with other modern Microsoft apps.

The Control Panel's (0, 120, 255) with black text is unreadable and to me it's horrifying that it's actually in the OS; at the same time, it's the only example of a MainMenu-style control with dark theme support, so maybe worth investigating.

The question I have is whether dark theme support is within the scope of this issue - if WinForms were to properly support dark theme, it would have to be applied to every control and not just the menus/tool strips, and provide proper colors to user controls that will also take time to implement.

Dark menus and light everything else looks very jarring, examples being the Control Panel and early versions of dark Explorer. IMO it's much better to have a consistent light theme instead, and give control to developers to decide whether their app is ready to respond to system-wide light/dark theme setting (unless the intention is to force all devs to implement dark theme for all new apps and apps ported from .NET Framework, but that seems extreme).

merriemcgaw commented 4 years ago

Notepad and MMC seem to just use the native control, which looks the most consistent today.

That is my assessment as well. And for now there is no support for dark theme, but they both support High Contrast. I think for this issue and the related ContextStrip/MenuStrip discussions I'm happy to consider them as our baseline, and move to Explorer for when we support Dark Theme. I'll work with @OliaG to see if we can find design guidance for the colors once it's time to implement a dark theme support.

The question I have is whether dark theme support is within the scope of this issue - if WinForms were to properly support dark theme, it would have to be applied to every control and not just the menus/tool strips, and provide proper colors to user controls that will also take time to implement.

I fully agree, but I think it's worth investigating and designing an approach that can then be extended to the other controls we own. We are considering putting the larger workitem on the roadmap and attempting to pick up things like the dark theme in addition to high contrast theming. Whatever we implement we won't have dark theme support without some sort of flag or property that turns it on.

Shadowblitz16 commented 4 years ago

the strip items should use the same renderer as the deprecated versions when using rendermode system

Then the native render should be updated to fit windows 10's current theme. (meaning a consistent look for winforms and wpf)

Shadowblitz16 commented 3 years ago

note I think this should support older versions of windows for backwards compatibility. literally just use the same renderer and the old versions

weltkante commented 3 years ago

You cannot use the theme rendering from older OS versions on a newer OS, its literally integrated into the OS, you can only use whatever is "current". WinForms would only call the provided OS function and not reimplement the theming from scratch. When running the code on older OS versions you obviously would get "their" version of the theme rendering.

Shadowblitz16 commented 3 years ago

Doesn't win32,mfc, or winforms have a native rendering class? if so just use that.

if not then the native render should be reimplemented for all os versions. WinForms might be able to be compiled to native code someday and it would be nice to be able to write native apps that are backwards compatible with win32 versions

mdtauk commented 3 years ago

Edge is probably the new bar Win32 and UXTheme should aim for.

With the "Sun Valley" UI Refresh being reported, the Windows 10 look should be updated to resemble WinUI and FluentUI * - so when this happens, the UXTheme should update, Dark Mode should be formalised and consistent for Win32 apps.

I would also expect the default system WPF Theme and WinForms controls should all match.

* Padding, Sizing, Margins, FontSizes, and other layout metrics - will probably be unchanged to not break existing UI

Shadowblitz16 commented 3 years ago

not on older systems. on older systems it should use the native win32 style of that os

Shadowblitz16 commented 3 years ago

@RussKie Here is a example of native menu bars on older versions of windows image I'm sure you can run the various versions of windows in a emulator to find out how the rest of the controls look This is only relevant to older versions of windows. Anyways anything that's is written in wpf, blend, winform's newer controls, uwp is not native. (at least not yet)

I'm not sure about windows 10 but I would assume a style needs to be agreed upon by the teams for win32 and other GUI frameworks need to have themes that match for their supported versions of windows

RussKie commented 3 years ago

@Shadowblitz16 thank you for the examples.

.NET supports only as far back as W7SP1 (which will probably too be dropped at some point in not too distant future). Theming has also significantly changed with each version of Windows, i.e. Windows 7 theming is very different from Windows 10 theming, both in terms of user experiences and API. 'Sun Valley' will likely throw a spanner into works redefining what the new Windows UX and UI are, and it is totally unclear at this stage what it'd mean for Win32 apps.

I totally agree that Win32 GUI SDKs need to have a shared set of UI, UX, a11y and styling guidelines, in reality it is almost unattainable. That's said, we're engaging with Windows teams to see how we can bridge the gap.

AEAEAEAE4343 commented 3 years ago

I think the name should be changed to something else. RenderMode System sounds like it was drawn by the system.

merriemcgaw commented 3 years ago

@AEAEAEAE4343 agreed the name could use some improvements, but given the number of apps out there in both Core and .NET Framework that would be broken with a name change, we simply can't do it. We are working with Windows to find ways to make WinForms look as native as possible, and since looking 'native' is undefined across Windows we have some work to do πŸ˜„ .

trucksmart commented 3 years ago

@merriemcgaw Another example which uses VisualStyleRenderer and UXTheme: https://github.com/AlexxEG/DropDownButton/blob/master/NativeToolStripRenderer.cs. This also includes styles from the windows media player, etc.

AraHaan commented 2 years ago

In summary: For theme off and high Contrast WPF uses System Colors as does WinForms, themed colors are hardcoded like <SolidColorBrush x:Key="Menu.Static.Background" Color="#FFF0F0F0" /> Note that WPF has different styles for different OS releases - if themes differ the hardcoded colors can differ between OS versions, thats something WinForms would need to do as well if it choses to replicate colors instead of calling theming APIs.

I would rather call GetThemeSysColor for the colors (after calling SetWindowTheme (from uxtheme.dll) to Explorer_Dark.

Oh which in my Winforms application I actually do today, the only problem is that Well, when it comes to the things like ContextMenuStrips, I am not sure what values to pass in to the GetThemeSysColor function to grap the actual dark variant of the "light" color used by default in winforms for each member of the ProfessionalColorTable class.

If there was at least documentations as to what "theme" part options that can be passed into those apis for various controls (ContextMenuStrip, Panel, TreeView, ListView, TextBox, Buttons, Labels, Window Background, etc) And yes those are mainly the controls I use and want to use the colors of what Windows Explorer uses at that time.

Currently I sadly have to do the interop and assigning them manually using TerraFX.Interop.Windows.

Shadowblitz16 commented 2 years ago

@Shadowblitz16 thank you for the examples.

.NET supports only as far back as W7SP1 (which will probably too be dropped at some point in not too distant future). Theming has also significantly changed with each version of Windows, i.e. Windows 7 theming is very different from Windows 10 theming, both in terms of user experiences and API. 'Sun Valley' will likely throw a spanner into works redefining what the new Windows UX and UI are, and it is totally unclear at this stage what it'd mean for Win32 apps.

I totally agree that Win32 GUI SDKs need to have a shared set of UI, UX, a11y and styling guidelines, in reality it is almost unattainable. That's said, we're engaging with Windows teams to see how we can bridge the gap.

as long as you can have the win32 team support a rendering back end for the new controls it should work all the way back as far as C# supports.

also I thought C# supported back to xp?

weltkante commented 2 years ago

also I thought C# supported back to xp?

no, XP is long out of support, see for example this page for .NET 5 supported platforms. XP and Vista are off the list, Win7 is only supported if its patched. In case of WinForms this means that version checks have for anything older than Win7 have been removed, in order to simplify code.

Shadowblitz16 commented 2 years ago

also I thought C# supported back to xp?

no, XP is long out of support, see for example this page for .NET 5 supported platforms. XP and Vista are off the list, Win7 is only supported if its patched. In case of WinForms this means that version checks have for anything older than Win7 have been removed, in order to simplify code.

but win32 still supports it. If the renderer is exposed from win32, winforms can just use that.

weltkante commented 2 years ago

No, you got it backwards, the win32 API doesn't "support" anything, it is a description of what is being supported under various operating system versions. XP had an implementation of the win32 API and it is still documented which parts of the API were available under XP.

However compiling C++ code with Visual Studio has no longer been supported for XP for a while, the compiler will emit CPU instructions and runtime libraries will use API calls that aren't guaranteed to be available under XP. Considering the .NET runtime is C++ code compiled with VS this means .NET will likely no longer run under XP. (Note that it doesn't even run under plain Win7, you need the service pack to fill in some missing APIs not implemented in original Win7. This is particularly noticeable when calling into WPF, which crashes immediately in this case.)

However we're drifting offtopic here, supporting XP APIs requires not using any API that is newer than XP, which is too late since the WinForms code already got refactored to assume Win7-SP1 APIs as minimum available set.