Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions src/System.Windows.Forms/PublicAPI.Unshipped.txt
Original file line number Diff line number Diff line change
Expand Up @@ -101,6 +101,7 @@ override System.Windows.Forms.RadioButton.OnPaint(System.Windows.Forms.PaintEven
override System.Windows.Forms.RadioButton.OnSystemColorsChanged(System.EventArgs! e) -> void
override System.Windows.Forms.RadioButton.OnVisualStylesModeChanged(System.EventArgs! e) -> void
override System.Windows.Forms.UpDownBase.OnVisualStylesModeChanged(System.EventArgs! e) -> void
override System.Windows.Forms.ToolStripControlHost.OnOwnerChanged(System.EventArgs! e) -> void
static System.Windows.Forms.Application.DefaultVisualStylesMode.get -> System.Windows.Forms.VisualStylesMode
static System.Windows.Forms.Application.SetDefaultVisualStylesMode(System.Windows.Forms.VisualStylesMode styleSetting) -> void
virtual System.Windows.Forms.Control.DefaultVisualStylesMode.get -> System.Windows.Forms.VisualStylesMode
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,9 @@ public partial class Control
/// shrink slightly. Prefer <see cref="TableLayoutPanel"/> or <see cref="FlowLayoutPanel"/> for adaptive layouts.
/// </para>
/// <para>
/// This setting is not applied to controls hosted through <see cref="ToolStripControlHost"/>.
/// </para>
/// <para>
/// High Contrast resolves the effective mode to classic rendering. See the
/// <see href="https://github.com/dotnet/winforms/blob/main/docs/net11-visualstyles-layout-guidance.md">
/// .NET 11 VisualStyles layout guidance</see> for migration patterns.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,9 @@ public partial class ToolStripControlHost : ToolStripItem
private int _suspendSyncSizeCount;
private ContentAlignment _controlAlign = ContentAlignment.MiddleCenter;
private bool _inSetVisibleCore;
private bool _isUpdatingHostedControlVisualStylesMode;
private bool _hostedControlVisualStylesModeForced;
private VisualStylesMode _hostedControlVisualStylesModeBeforeForce = VisualStylesMode.Inherit;

internal static readonly object s_gotFocusEvent = new();
internal static readonly object s_lostFocusEvent = new();
Expand Down Expand Up @@ -576,6 +579,16 @@ private void HandleResize(object? sender, EventArgs e)

private void HandleTextChanged(object? sender, EventArgs e) => OnTextChanged(e);

private void HandleVisualStylesModeChanged(object? sender, EventArgs e)
{
if (_isUpdatingHostedControlVisualStylesMode)
{
return;
}

ApplyHostedControlVisualStylesModePolicy();
}
Comment on lines +582 to +590

private void HandleControlVisibleChanged(object? sender, EventArgs e)
{
// check the STATE_VISIBLE flag rather than using Control.Visible.
Expand Down Expand Up @@ -684,6 +697,8 @@ protected override void OnParentChanged(ToolStrip? oldParent, ToolStrip? newPare
{
if (oldParent is not null && Owner is null && newParent is null && _control is not null)
{
RestoreHostedControlVisualStylesMode();

// if we've really been removed from the item collection,
// politely remove ourselves from the control collection
ReadOnlyControlCollection? oldControlCollection
Expand All @@ -698,6 +713,20 @@ protected override void OnParentChanged(ToolStrip? oldParent, ToolStrip? newPare
base.OnParentChanged(oldParent, newParent);
}

protected override void OnOwnerChanged(EventArgs e)
{
base.OnOwnerChanged(e);

if (Owner is null)
{
RestoreHostedControlVisualStylesMode();
}
else
{
ApplyHostedControlVisualStylesModePolicy();
}
}

/// <summary>
/// The events from the hosted control are subscribed here.
/// Override to add/prevent syncing of control events.
Expand Down Expand Up @@ -739,6 +768,7 @@ protected virtual void OnSubscribeControlEvents(Control? control)
control.RightToLeftChanged += HandleRightToLeftChanged;
control.TextChanged += HandleTextChanged;
control.VisibleChanged += HandleControlVisibleChanged;
control.VisualStylesModeChanged += HandleVisualStylesModeChanged;
control.Validating += HandleValidating;
control.Validated += HandleValidated;
}
Expand Down Expand Up @@ -784,6 +814,7 @@ protected virtual void OnUnsubscribeControlEvents(Control? control)
control.RightToLeftChanged -= HandleRightToLeftChanged;
control.TextChanged -= HandleTextChanged;
control.VisibleChanged -= HandleControlVisibleChanged;
control.VisualStylesModeChanged -= HandleVisualStylesModeChanged;
control.Validating -= HandleValidating;
control.Validated -= HandleValidated;
}
Expand All @@ -803,6 +834,52 @@ private void SyncControlParent()
{
ReadOnlyControlCollection? newControls = GetControlCollection(ParentInternal);
newControls?.AddInternal(_control);
ApplyHostedControlVisualStylesModePolicy();
}

private bool ShouldForceHostedControlClassicVisualStylesMode()
=> Owner is not null;

private void ApplyHostedControlVisualStylesModePolicy()
{
if (_control is null || !ShouldForceHostedControlClassicVisualStylesMode())
{
return;
}

VisualStylesMode mode = _control.VisualStylesMode;
if (mode is VisualStylesMode.Classic or VisualStylesMode.Disabled)
{
return;
}

_hostedControlVisualStylesModeBeforeForce = mode;
_hostedControlVisualStylesModeForced = true;
UpdateHostedControlVisualStylesMode(VisualStylesMode.Classic);
}

private void RestoreHostedControlVisualStylesMode()
{
if (!_hostedControlVisualStylesModeForced || _control is null)
{
return;
}

UpdateHostedControlVisualStylesMode(_hostedControlVisualStylesModeBeforeForce);
_hostedControlVisualStylesModeForced = false;
}

private void UpdateHostedControlVisualStylesMode(VisualStylesMode mode)
{
_isUpdatingHostedControlVisualStylesMode = true;
try
{
_control.VisualStylesMode = mode;
}
finally
{
_isUpdatingHostedControlVisualStylesMode = false;
}
}

protected virtual void OnHostedControlResize(EventArgs e)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,9 @@ public enum VisualStylesMode : short
/// Controls opt into the .NET 11 rendering changes they support. For example, support for
/// <see cref="Appearance.ToggleSwitch"/> depends on the control and its current state.
/// </para>
/// <para>
/// For controls hosted through <see cref="ToolStripControlHost"/>, this mode is not applied.
/// </para>
/// </remarks>
Net11 = 2,

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4557,6 +4557,52 @@ public void ToolStripControlHost_SetVisibleCore_InvokeWithHandler_CallsVisibleCh
Assert.Equal(2, callCount);
}

[WinFormsFact]
public void ToolStripControlHost_HostedControlVisualStylesMode_Net11_IsForcedToClassic()
{
using Control control = new()
{
VisualStylesMode = VisualStylesMode.Net11
};
using ToolStripControlHost host = new(control);
using ToolStrip toolStrip = new();

toolStrip.Items.Add(host);

Assert.Equal(VisualStylesMode.Classic, control.VisualStylesMode);
}

[WinFormsFact]
public void ToolStripControlHost_HostedControlVisualStylesMode_SetToNet11WhileHosted_RemainsClassic()
{
using Control control = new();
using ToolStripControlHost host = new(control);
using ToolStrip toolStrip = new();

toolStrip.Items.Add(host);
control.VisualStylesMode = VisualStylesMode.Net11;

Assert.Equal(VisualStylesMode.Classic, control.VisualStylesMode);
}

[WinFormsFact]
public void ToolStripControlHost_HostedControlVisualStylesMode_RemovingHost_RestoresRequestedMode()
{
using Control control = new()
{
VisualStylesMode = VisualStylesMode.Net11
};
using ToolStripControlHost host = new(control);
using ToolStrip toolStrip = new();

toolStrip.Items.Add(host);
Assert.Equal(VisualStylesMode.Classic, control.VisualStylesMode);

toolStrip.Items.Remove(host);

Assert.Equal(VisualStylesMode.Net11, control.VisualStylesMode);
}

private class SubControl : Control
{
public new void CreateControl() => base.CreateControl();
Expand Down
Loading