Skip to content

Fix TabControl dark mode rendering for Left/Right alignment with vertical text rotation, dark tab strip, and dark border#14579

Open
SimonZhao888 wants to merge 1 commit into
dotnet:mainfrom
SimonZhao888:Fix_issue_14109
Open

Fix TabControl dark mode rendering for Left/Right alignment with vertical text rotation, dark tab strip, and dark border#14579
SimonZhao888 wants to merge 1 commit into
dotnet:mainfrom
SimonZhao888:Fix_issue_14109

Conversation

@SimonZhao888
Copy link
Copy Markdown
Member

@SimonZhao888 SimonZhao888 commented May 29, 2026

Fixes #14109

Proposed changes

  • Automatically enable owner-draw mode (TCS_OWNERDRAWFIXED) for vertical tabs (Left/Right alignment) when dark mode is enabled
  • Implement DrawDarkModeTab() method with proper vertical text rotation using Graphics.DrawString (GDI+) and very dark/black backgrounds
  • Modified OnDrawItem() to automatically render vertical tabs in dark mode when user hasn't set custom draw handler
  • Implement 90-degree text rotation for vertical tabs (Left alignment: -90°, Right alignment: +90°)
  • Add WM_ERASEBKGND message handling to paint tab strip background dark for vertical tabs
  • Add WM_PAINT message handling to fill thick dark border areas around TabPage content for vertical tabs
  • Horizontal tabs (Top/Bottom alignment) continue using DarkMode::FileExplorerBannerContainer theme
  • Only applies when DrawMode is not explicitly set to OwnerDrawFixed and no DrawItem event handler is attached

Root Cause: Windows standard themes (DarkMode::FileExplorerBannerContainer and DarkMode_Explorer) do not support dark mode rendering for tab controls with the TCS_VERTICAL style (Left/Right alignment). After testing multiple theme-based approaches, an owner-draw solution was implemented.

Technical Implementation: Uses Graphics.DrawString instead of TextRenderer.DrawText because TextRenderer is GDI-based and doesn't respect Graphics rotation transforms, while Graphics.DrawString uses GDI+ and properly honors rotation. Custom WM_PAINT handling fills 3-pixel thick border areas (top, bottom, left, right) around TabPage content area to completely cover the native Windows light border with dark color matching the tab strip background.

Customer Impact

  • TabControl tabs with Left/Right alignment now render completely in dark mode with very dark/black backgrounds, properly rotated vertical text, dark tab strip area, and dark border around TabPage content instead of remaining white with horizontal text and light borders
  • Affects applications using Application.SetColorMode(SystemColorMode.Dark) with vertically-aligned tab controls
  • Backward Compatible: User's explicit DrawMode.OwnerDrawFixed settings and custom DrawItem event handlers are preserved
  • Automatic dark mode rendering only activates when neither explicit draw mode nor custom handlers are set
  • TabPage content area maintains normal background color (not affected by tab button drawing, tab strip background, or border drawing)

Regression?

  • No

Risk

  • Low: Automatic owner-draw only activates under specific conditions (dark mode enabled, vertical alignment, no user customization)
  • Horizontal tab behavior unchanged - continues using standard theme approach
  • Preserves all existing user customization options
  • WM_ERASEBKGND and WM_PAINT handling includes safety checks (null validation, try-catch) to prevent crashes

Screenshots

Before

Left and Right alignments show white tabs in dark mode (highlighted in red boxes):

After

image

Manual testing on Windows required - Vertical tabs (Left/Right alignment) should now render with:

  • Very dark/black tab backgrounds: Selected tab #252526, Normal tab #1C1C1C, Border #333333
  • Dark tab strip background: #2D2D30 (the area where tabs are placed)
  • Dark border around TabPage content area: 3-pixel thick filled areas in #2D2D30 (matching tab strip color)
  • Light gray text: #F1F1F1
  • Text rotated vertically: -90° for Left alignment (bottom-to-top), +90° for Right alignment (top-to-bottom)
  • TabPage content area maintains normal background color

Test methodology

  • Manually

Accessibility testing

Test environment(s)

  • 11.0.0-alpha.1.25619.109
Microsoft Reviewers: Open in CodeFlow

…ical text rotation, dark tab strip, and dark border
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR updates TabControl dark-mode rendering for Left/Right (vertical) tab alignment by enabling automatic owner-draw and adding custom background/border painting paths, addressing a gap in Windows theming support for TCS_VERTICAL in dark mode (Fixes #14109).

Changes:

  • Automatically sets TCS_OWNERDRAWFIXED for vertical tabs when dark mode is enabled (unless explicitly owner-drawn by the user).
  • Adds default dark-mode vertical tab rendering with rotated text via Graphics.DrawString.
  • Adds WM_ERASEBKGND / WM_PAINT handling to darken the tab strip background and cover native light borders for vertical tabs.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines +2207 to +2211
g.FillRectangle(borderBrush,
displayRect.Right,
displayRect.Y - borderThickness,
0,
displayRect.Height + borderThickness * 2);
Comment on lines +2177 to +2179
if (Application.IsDarkModeEnabled &&
(_alignment is TabAlignment.Left or TabAlignment.Right) &&
_drawMode != TabDrawMode.OwnerDrawFixed)
Comment on lines +2223 to +2226
if (Application.IsDarkModeEnabled &&
(_alignment is TabAlignment.Left or TabAlignment.Right) &&
_drawMode != TabDrawMode.OwnerDrawFixed &&
m.WParamInternal != (WPARAM)0)
Comment on lines +1379 to +1382
using (Pen pen = new(borderColor))
{
e.Graphics.DrawRectangle(pen, e.Bounds.X, e.Bounds.Y, e.Bounds.Width, e.Bounds.Height);
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

area-DarkMode Issues relating to Dark Mode feature

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[Dark Mode] the tabPage is not in darkmode when setting the Alignment as Left/Right

2 participants