Fix ComboBox dark mode theme on first TabPage
Proposed changes
- Modified
TabControl.StyleChildren()to only apply dark mode theme to direct children (TabPages), not descendant controls - Added parent check using
PInvoke.GetParent()to identify direct children - Preserved return value of
SetWindowTheme()for proper error handling
Customer Impact
- ComboBox controls on the first TabPage now correctly display in dark mode
- Affects applications using
Application.SetColorMode(SystemColorMode.Dark)with TabControl containing ComboBox controls
Regression?
- Yes (regression from .NET 9.0)
Risk
- Low. Surgical fix changes only theme application scope in TabControl
- Only affects dark mode rendering path
- Controls with specific dark mode themes (ComboBox, etc.) now preserve their themes
Screenshots
Before
After
Test methodology
- Code review completed
- CodeQL security scan passed
- Manual testing required on Windows to validate visual rendering
Test environment(s)
- .NET 10.0.100
Technical Details:
The issue occurred because TabControl.ApplyDarkModeOnDemand() calls EnumChildWindows() which recursively enumerates all descendant windows. The StyleChildren callback was applying the generic DarkMode_Explorer theme to every window, overwriting ComboBox's specific DarkMode_ComboBoxButton theme for its button component.
The fix restricts theme application to only TabPage windows (direct children of TabControl), allowing controls to maintain their specific themes:
private BOOL StyleChildren(HWND handle)
{
// Only apply theme to direct children (TabPages), not to controls within TabPages.
HWND parent = PInvoke.GetParent(handle);
if (parent == HWND)
{
return PInvoke.SetWindowTheme(handle, $"{DarkModeIdentifier}_{ExplorerThemeIdentifier}", null)
.Succeeded;
}
return true;
}
[!WARNING]
Firewall rules blocked me from connecting to one or more addresses (expand for details)
I tried to connect to the following addresses, but was blocked by firewall rules:
rcxvsblobprodcus328.vsblob.vsassets.io
- Triggering command:
/home/REDACTED/work/winforms/winforms/.dotnet/dotnet /home/REDACTED/work/winforms/winforms/.dotnet/dotnet msbuild /m /nologo /clp:Summary /v:minimal /nr:true /warnaserror /p:TreatWarningsAsErrors=true /p:ContinuousIntegrationBuild=false /home/REDACTED/work/winforms/winforms/artifacts/toolset/restore.proj /t:__WriteToolsetLocation /clp:ErrorsOnly;NoSummary /p:__ToolsetLocationOutputFile=/home/REDACTED/work/winforms/winforms/artifacts/toolset/11.0.0-beta.25609.108.txt(dns block)If you need me to access, download, or install something from one of these locations, you can either:
- Configure Actions setup steps to set up my environment, which run before the firewall is enabled
- Add the appropriate URLs or hosts to the custom allowlist in this repository's Copilot coding agent settings (admins only)
Original prompt
This section details on the original issue you should resolve
<issue_title>[Dark Mode] the combobox refuses dark theme when on first tabpage of a tabcontrol</issue_title> <issue_description>### .NET version
latest .NET 10.0 build
Did it work in .NET Framework?
No
Did it work in any of the earlier releases of .NET Core or .NET 5+?
This is a regression issue, not reproduce .NET 9.0
Issue description
The combobox refuses dark theme when on first tabpage of a tabcontrol Expected Results:
Actual Results:
Steps to reproduce
- Create a .NET winforms project with a TabCpntrol control
- Add a Combobox contorl in the tabPage1
- Set app under Dark mode in program.cs file
Application.SetColorMode(SystemColorMode.Dark);- Run the application
More info:
- The issue can reproduce when setting the DropDownStyle as DropDown/DropDownList, not reproduce when setting the DropDownStyle as Sample</issue_description>
Comments on the Issue (you are @copilot in this section)
- Fixes dotnet/winforms#14107
💡 You can make Copilot smarter by setting up custom instructions, customizing its development environment and configuring Model Context Protocol (MCP) servers. Learn more Copilot coding agent tips in the docs.
Microsoft Reviewers: Open in CodeFlow
Codecov Report
:x: Patch coverage is 0% with 8 lines in your changes missing coverage. Please review.
:white_check_mark: Project coverage is 77.15885%. Comparing base (ceb6911) to head (c0b6d94).
Additional details and impacted files
@@ Coverage Diff @@
## main #14128 +/- ##
===================================================
+ Coverage 77.15337% 77.15885% +0.00548%
===================================================
Files 3279 3279
Lines 645325 645331 +6
Branches 47720 47721 +1
===================================================
+ Hits 497890 497930 +40
+ Misses 143748 143713 -35
- Partials 3687 3688 +1
| Flag | Coverage Δ | |
|---|---|---|
| Debug | 77.15885% <0.00000%> (+0.00548%) |
:arrow_up: |
| integration | 18.99499% <0.00000%> (+0.00100%) |
:arrow_up: |
| production | 52.02862% <0.00000%> (+0.01280%) |
:arrow_up: |
| test | 97.40749% <ø> (ø) |
|
| unit | 49.47336% <0.00000%> (+0.01738%) |
:arrow_up: |
Flags with carried forward coverage won't be shown. Click here to find out more.
:rocket: New features to boost your workflow:
- :snowflake: Test Analytics: Detect flaky tests, report on failures, and find test suite problems.